SpringSecurityOauthRCE(CVE-2016-4977)分析与复现
⽬录
影响版本:
2.0.0-2.0.9
error parse new1.0.0-1.0.5
0x00 前⾔
这个漏洞与之前那个SpringBoot的SpEL表达式注⼊漏洞点基本⼀样,⽽且漏洞爆出来的时间点也差不多,可是没有到那个漏洞的CVE编号,不知道是什么原因。
这个漏洞的触发点也是对⽤户传的参数的递归解析,从⽽导致SpEL注⼊,可是两者的补丁⽅式⼤不相同。Springboot的修复⽅法是创建⼀个NonRecursive 类,使解析函数不进⾏递归。⽽SpringSecurityOauth的修复⽅法则是在前缀${前⽣成⼀个六位的字符串,只有六位字符串与之相同才会对其作为表达式进⾏解析。然⽽如果请求⾜够多,这种补丁也是会失效的。
0x01 调试分析
payload:
localhost:8080/oauth/authorize?response_type=token&client_id=acme&redirect_uri=${new%20java.lang.ProcessBuilder(new%20java.lang.String(new%20byte[]{99,97,108,99})).start()}⾸先,这个漏洞是在错误页触发的,所以这⾥在错误页的控制器打个断点。可以看到,最后渲染视图的时候使⽤了SpelView,并传⼊⼀个模板字符串,跟springboot的洞类似。
然后跟到render⽅法,接收模板字符串之后,接着使⽤replacePlaceholders⽅法,对模板进⾏解析。
跟进⼀下replacePlaceholders⽅法
跟进parseStringValue⽅法,这个⽅法与springboot中的⽅法基本相同,简单看⼀下。
72⾏进⾏⼀次递归,⽤于解析模板中类似于${${}}的结构。由于这⾥的模板只是⼀个单纯的${errorSummary},故不跟进这⾥。
73⾏是将errorSummary作为参数传⼊SpEL模板解析引擎
可以看到,35⾏将errorSummary转换成了⼀个字符串,注意看这个值,其中包含我们的payload:${xxxx}。
return之后回到parseStringValue函数,将返回值赋值给propVal。
继续跟进,到87⾏,这⾥对propVal⼜进⾏了⼀次递归解析。⽽propVal的值中刚好包含我们的payload(即包含“${}”)
跟进递归,到66⾏成功将我们的payload从${}中提取出来,马上就到触发点了
跟进到73⾏,将payload传⼊resolvePlaceholder,继续跟进
成功在35⾏将payload作为SpEL表达式解析,弹出了计算器。
0x02 补丁分析
可以看到,这⾥在${前加了个
RandomValueStringGenerator().generate(),⽤于⽣成⼀个随机字符串。可是正如前⾯说的,如果可以发出⾜够多的请求,那么这个补丁依旧是可以被利⽤的。
0x03 参考
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论