Spring处理参数值出错时会将参数中${}
中的内容当作SPEL
解析实现,造成RCE
漏洞
当使用JSON PATCH
对数据修改时,传入的PATH
参数会解析SPEL
在Model
的数据绑定上存在漏洞,但漏洞出发条件比较苛刻
由于没有明确指定相关Model
的具体属性,导致从表单可以提交恶意的表达式SPEL
被执行
其中的STOMP
模块发送订阅命令时,支持选择器标头,该选择器充当基于内容路由的筛选器
这个筛选器selector
属性的值会解析SPEL
导致RCE
请求参数中如何包含SPEL
会被解析,参考下方Payload
username[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("calc.exe")]
本质还是SPEL
表达式,本来这是一个需要修改配置文件导致的鸡肋RCE
漏洞
但因为Gateway
提供了Actuator
相关的API
可以动态地注册Filter
,而在注册的过程中可以设置SPEL
表达式
实战利用程度可能不高,目标未必开着Actuator
接口,就算开放也不一定可以正常访问注册Filter
的接口
P牛在漏洞爆出的凌晨就发布了相关的环境和POC
参考P牛的回显代码:在相应头里面添加一个新的头,利用工具类把执行回显写入
xxxxxxxxxx
{
"name": "AddResponseHeader",
"args": {
"value": "#{new java.lang.String(T(org.springframework.util.StreamUtils).copyToByteArray(T(java.lang.Runtime).getRuntime().exec(new String[]{\"whoami\"}).getInputStream()))}",
"name": "cmd123"
}
}
参考很多SPEL
漏洞的修复手段,默认情况使用StandardContext
可以执行Runtime.getRuntime().exec()
这样的危险方法
修复是重写一个GatewayContext
用来执行SPEL
,这个context
的底层是SimpleEvaluationContext
只能执行有限的操作
这也是Spring Cloud
种的一个组件,不过并不常用
利用方式是某个请求头支持SpEL
的格式并且会执行
xxxxxxxxxx
POST / HTTP/1.1
...
spring.cloud.function.routing-expression: SPEL
修复方案比较简单,使用SimpleEvaluationContext
即可
参考先知社区4ra1n
师傅的文章:https://xz.aliyun.com/t/11114
危害不大,但影响较广,所有能够执行SpEL
的框架,都可以通过初始化巨大的数组造成拒绝服务漏洞
修复方案是限制SpEL
种数组初始化的长度(一般业务也不可能在SpEL
种初始化很大的数组)
该漏洞与很久以前的SpringMVC
对象绑定漏洞有关,曾经的修复方案是:如果攻击者尝试以class.classloader
获取任意class
对象的loader
时跳过
这里的对象绑定是指将请求中的参数绑定到控制器(Controller)方法中的参数对象的成员变量,例如通过username
和password
等参数绑定到User
对象
由于在JDK9
中加入了模块module
功能,可以通过class.module.classLoader
得到某class
对应的classloader
进而利用
在Tomcat
环境下拿到的classloader
对象中包含了context
,进而通过pipeline
拿到AccessLogValue
对象,该类用于处理Tomcat
访问日志相关。通过修改其中的字段信息,可以将webshell
写入指定目录下的指定文件中,以达到RCE
的目的
module
功能)Classloader
对象)String
和int
等基本类型参数则不生效
因为在SpringBoot
中拿到的classloader
是AppClassloader
类,该类不存在无参的getResources
方法且没有其他可操作的空间,所以无法利用
当beanClass
为Class
时只允许参数名为name
并以Name
结尾且属性返回类型不能为Classloader
及Classloader
子类
由于SpringBoot
是FarJar
形式的一个Jar
包,因此无法在其运行的时候往classpath
中增加文件,另外SpringBoot
的应用通常不解析JSP
等模板文件,所以传统的上传webshell
以RCE
的思路是无效的
思路是覆盖了JAVA_HOME
中没有被加载的系统Jar
文件,例如charsets.jar
文件,然后想办法在运行中加载该jar
文件
难点在于可控的主动类初始化,主要的两种实际利用是:
Accept: text/html;charset=GBK
请求头触发Spring
中的Charset.forName
方法Fastjson
的1.2.76
版本通过普通的JSON
即可触发Charset.forName
方法