Spring Beans RCE分析

    渗透测试 lz520520 2年前 (2022-04-29) 1197次浏览

    漏洞介绍

    Spring MVC 框架的参数绑定功能提供了将请求中的参数绑定控制器方法中参数对象的成员变量,攻击者通过构造恶意请求获取AccessLogValve 对象并注入恶意字段值触发 pipeline 机制可写入任意路径下的文件。
    简答来说就是参数绑定造成的变量覆盖漏洞,漏洞点spring-beans包中。

    漏洞编号

    影响范围

    JDK>=9
    springMVC 全版本

    漏洞分析

    属性注入分析

    根据之前的漏洞分析
    http://rui0.cn/archives/1158,其中一个点在于获取BeanInfo,位置在CachedIntrospectionResults构造方法,下个断点,发送请求断下
    Spring Beans RCE分析

    之前的补丁是把classLoader等危险属性过滤掉了。
    Spring Beans RCE分析

    跟踪如上堆栈发现,新版本和旧版本参数绑定的类有所不一样,具体位置如下,setPropertyValue也叫属性注入
    org\springframework\beans\AbstractNestablePropertyAccessor.class#setPropertyValue
    Spring Beans RCE分析
    补充:AbstractNestablePropertyAccessor 类通过其成员属性提供了一种支持嵌套属性的数据结构

    这段的理解参考 https://www.cnblogs.com/binarylei/p/10267928.html

    getPropertyAccessorForPropertyPath 根据属性(propertyPath)获取所在 bean 的包装对象 beanWrapper。如果是类似 director.info.name 的嵌套属性,则需要递归获取。真正获取指定属性的包装对象则由方法 getNestedPropertyAccessor 完成。
    可以看到getPropertyAccessorForPropertyPath的递归调用

    也就是bean属性的递归获取,比如我这个环境中,最外层BeanWrapperImpl封装的是UserInfo,我传参是
    Spring Beans RCE分析
    对应的就是我controller中的入参类
    Spring Beans RCE分析

    我传参class.module.classLoader.resources.context.parent.appBase
    第一次获取class对应的BeanWrapperImpl

    利用链分析

    UserInfo除了基础的四个属性以外,还有一个class
    Spring Beans RCE分析
    并且在嵌套属性nestedPropertyAccessors(这个是缓存后有的,直接在beanInfo里也能看)中也直观看到class
    Spring Beans RCE分析
    展开可以看到套娃一样的嵌套属性
    Spring Beans RCE分析

    class.module.classLoader.resources.context 用对象如何获取呢,对应代码如下,也就是多个getter串起来

    获取到的就是StandardContext,是不是在内存马也见过。
    Spring Beans RCE分析
    进一步获取appBase也就顺理成章,最终聚焦下parent,也就是StandardHost
    class.module.classLoader.resources.context.parent

    Spring Beans RCE分析

    公开的利用链也就是pipeline下的AccessLogValue的利用,这个类用来设置日志存储参数,包括路径、后缀,修改参数即可达到写入任意文件的目的。
    Spring Beans RCE分析[

    ](https://tomcat.apache.org/tomcat-8.5-doc/config/valve.html)

    AccessLogValue构造

    AccessLogValue的属性可参考tomcat官方文档
    https://tomcat.apache.org/tomcat-8.5-doc/config/valve.html
    通过属性注入修改AccessLogValue的几个属性如下

    由于%会被过滤,pattern里通过引用头部来实现构造。
    PS: 注意每次写新的文件,需要修改suffix、prefix以及fileDateFormat,否则文件路径不会修改。
    fileDataFormat:默认是.yyyy-MM-dd,尽量只用数字,因为字母会被解析格式化
    suffix:只要有后缀即可
    prefix:可任意
    pattern:格式一般是%h %l %u %t "%r" %s %b ,所以%会被格式化,但通过%{xxx}i可引用请求头字段,即可保证任意字符写入,并且可以实现字符拼接,绕过webshell检测。

    http://xiaobaoqiu.github.io/blog/2014/12/30/tomcat-access-logpei-zhi/
    [

    ](http://xiaobaoqiu.github.io/blog/2014/12/30/tomcat-access-logpei-zhi/)

    bypass原因分析

    JDK1.8下测试,class bean下没有module bean,导致后续无法利用,如果是class.classLoader则会被黑名单拦截。
    Spring Beans RCE分析

    查了下module对应的类是java.lang.Module,是JDK9引入的,JDK9引入了模块系统。
    https://blog.csdn.net/charles_neil/article/details/114460702

    补充下:
    黑名单判断逻辑,beanClass非Class或者属性name非(classLoader|protectionDomain),满意一个即可,而jdk8中没有module,只能用class.classLoader调用,而这样两个条件都不满足,导致无法绕过。

    jdk9为什么能绕过呢,因为他多了一个module,如class.module.classLoader,这样module就满足第一个条件,而不去判断第二个条件,从而绕过黑名单。
    Spring Beans RCE分析

    如何遍历嵌套属性

    之前struts2出过类似漏洞,有人编写了一个jsp来遍历
    https://cs.github.com/julianvilas/rooted2k15/blob/a00055f906502dd038b908a84907b74b38e26b20/struts-tester/struts-tester.jsp
    细节看代码,主要把这个替换成自己的模型类,也就是控制器方法的入参类,以此为起点来获取gettersetter
    Spring Beans RCE分析
    效果如下,其他嵌套属性有啥用,就待大家自行摸索了。
    Spring Beans RCE分析

    做了属性值的获取,通过getPropertyAccessorForPropertyPath获取即可,示例代码如下

    Spring Beans RCE分析

    再看一下JDK9 springboot下的,和springMVC的classloader不一样,是AppClassLoader,没有getResources()。
    springMVC是ParallelWebappClassLoader
    Spring Beans RCE分析

    然后看下JDK8的springMVC,如下所示,protectionDomain是在黑名单内,所以连属性值都获取不到。
    Spring Beans RCE分析

    PS: 没有解析到值的,说明那个属性是错误的,不是bean的属性。
    这里是打印的存在setter的属性,不打印只有getter的属性。

    利用条件

    所以总结下

    • =JDK9。

    • springMVC。
    • 请求接口对应的是控制器方法。
    • 方法入参是非基础类,不能是String,int等
    • 请求方法要和控制器方法对应上,否则无法访问。

    修复建议

    官方补丁
    https://github.com/spring-projects/spring-framework/commit/afbff391d8299034cd98af968981504b6ca7b38c

    临时方案
    (一)WAF防护
    在WAF等网络防护设备上,根据实际部署业务的流量情况,实现对“class.”“Class.”“.class.”“.Class.”等字符串的规则过滤,并在部暑过滤规则后,对业务运行情况进行测试,避免产生额外影响。

    (二)临时修复措施
    需同时按以下两个步骤进行漏涧的临时修复:
    1.在应用中全局搜索@InitBinder注解,看看方法体内是否调用dataBinder.setDisallowedFields方法,如果发现此代码片段的引入,则在原来的黑名单中,添加{"class.","Class. ",". class.", ".Class."}。 (注:如果此代码片段使用较多,需要每个地方都追加)

    1. 在应用系统的项目包下新建以下全局类,并保证这个类被Spring 加载到(推荐在Controller 所在的包中添加).完成类添加后,需对项目进行重新编译打包和功能验证测试。并重新发布项目。

    补丁分析

    https://github.com/spring-projects/spring-framework/commit/afbff391d8299034cd98af968981504b6ca7b38c
    2022年3月31日18:31:58
    Refine PropertyDescriptor filtering
    补丁很简单,当beanClass是class.Class时,只允许添加name属性。
    并且如果属性是ClassLoaderProtectionDomain,也会被忽略。
    Spring Beans RCE分析

    参考链接

    class.classLoader.resources.dirCon想·text.docBase
    CVE-2010-1622 http://rui0.cn/archives/1158
    http://xiaobaoqiu.github.io/blog/2014/12/30/tomcat-access-logpei-zhi/
    https://tomcat.apache.org/tomcat-8.5-doc/config/valve.html
    https://spring.io/blog/2022/03/31/spring-framework-rce-early-announcement

    其他注意事项

    利用需要找控制器方法入参是一个非基础类,比如入参是String则无法触发参数绑定。
    Spring Beans RCE分析


    Security , 版权所有丨如未注明 , 均为原创丨
    转载请注明原文链接:Spring Beans RCE分析
    喜欢 (79)