pypa/abi3audit
GitHub: pypa/abi3audit
扫描 Python 扩展包的 abi3 稳定 ABI 合规性,检测版本声明与实际符号使用的不一致和违规。
Stars: 121 | Forks: 16
# abi3audit
[](https://github.com/pypa/abi3audit/actions/workflows/tests.yml)
[](https://pypi.org/project/abi3audit)
[](https://repology.org/project/python:abi3audit/versions)
*[阅读 Trail of Bits 关于使用 `abi3audit` 发现漏洞的博客文章!](https://blog.trailofbits.com/2022/11/15/python-wheels-abi-abi3audit/)*
`abi3audit` 扫描 Python 扩展以查找 `abi3` 违规和不一致情况。
它可以扫描单个(未打包的)共享对象、打包的 wheel 或整个
包版本历史。

该项目由 [Trail of Bits](https://trailofbits.com) 创建,
现作为 Python Packaging Authority (PyPA) 的一部分进行维护。
这不是 Trail of Bits 的官方产品。
## 目录
* [动机](#motivation)
* [安装](#installation)
* [用法](#usage)
* [示例](#examples)
* [局限性](#limitations)
* [许可](#licensing)
## 动机
CPython(Python 的参考实现)定义了一个稳定的 API 和相应的
ABI(“`abi3`”)。原则上,任何 CPython 扩展都可以针对此
API/ABI 构建,并保持与未来 CPython 次版本的向前兼容性。
换句话说:如果您针对 Python 3.5 的稳定 ABI 进行构建,您的
扩展无需修改即可在 Python 3.9 上运行。
稳定 ABI 简化了 CPython 扩展的打包,因为打包者
只需构建一个针对最低支持 Python 版本的 `abi3` wheel。
为了表明 Python wheel 包含 `abi3` 兼容的扩展,
Python 打包生态系统使用 `abi3` wheel 标签,例如:
```
pyrage-1.0.1-cp37-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.whl
```
不幸的是,在安装或运行时,对 Python 扩展的 `abi3` 合规性**没有实际强制措施**:一个被标记为 `abi3` 的 wheel(或独立的
共享对象)被假定是 `abi3` 的,但
不会以任何方式进行验证。
更糟糕的是,控制 wheel 标记的标志
([`--py-limited-api`](https://setuptools.pypa.io/en/latest/userguide/ext_modules.html#setuptools.Extension))
与实际上将 Python 扩展锁定到特定 `abi3` 版本的构建宏
([`Py_LIMITED_API`](https://docs.python.org/3/c-api/stable.html#c.Py_LIMITED_API))
之间**没有正式关联**。
结果就是:很容易将 Python 扩展编译为错误的 `abi3`
版本,或者将 Python wheel 标记为 `abi3` 而实际上并未将其编译为
`abi3` 兼容。
这具有严重的安全性和可靠性影响:CPython ABI 的非稳定部分
可能在次版本之间发生变化,当
Python 扩展错误地假设函数的参数
或结构的布局时,会导致崩溃、
不可预测的行为或潜在的利用内存损坏。
## 安装
`abi3audit` 可通过 `pip` 获取:
```
pip install abi3audit
```
## 用法
您可以将 `abi3audit` 作为独立程序运行,或通过 `python -m abi3audit` 运行:
```
abi3audit --help
python -m abi3audit --help
```
### 示例
审核单个共享对象、wheel 或 PyPI 包:
```
# 审核 abi3 扩展的本地副本
abi3audit procmaps.abi3.so
# 审核 abi3 wheel 的本地副本
abi3audit procmaps-0.5.0-cp36-abi3-manylinux2010_x86_64.whl
# 审核 PyPI 上 'procmaps' 包的每个 abi3 wheel
abi3audit procmaps
```
在审核时显示额外详细信息(漂亮的表格和个别违规):
```
abi3audit procmaps --verbose
```
输出结果:
```
[17:59:46] 👎 procmaps:
procmaps-0.5.0-cp36-abi3-manylinux2010_x86_64.whl: procmaps.abi3.so
uses the Python 3.10 ABI, but is tagged for the Python 3.6 ABI
┏━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━┓
┃ Symbol ┃ Version ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━┩
│ PyUnicode_AsUTF8AndSize │ 3.10 │
└─────────────────────────┴─────────┘
[17:59:47] 💁 procmaps: 2 extensions scanned; 1 ABI version mismatches and 0
ABI violations found
```
为每个输入生成 JSON 报告:
```
abi3audit procmaps --report | python -m json.tool
```
输出结果:
```
{
"specs": {
"procmaps": {
"kind": "package",
"package": {
"procmaps-0.5.0-cp36-abi3-manylinux2010_x86_64.whl": [
{
"name": "procmaps.abi3.so",
"result": {
"is_abi3": true,
"is_abi3_baseline_compatible": false,
"baseline": "3.6",
"computed": "3.10",
"non_abi3_symbols": [],
"future_abi3_objects": {
"PyUnicode_AsUTF8AndSize": "3.10"
}
}
}
],
"procmaps-0.6.1-cp37-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.whl": [
{
"name": "procmaps.abi3.so",
"result": {
"is_abi3": true,
"is_abi3_baseline_compatible": true,
"baseline": "3.7",
"computed": "3.7",
"non_abi3_symbols": [],
"future_abi3_objects": {}
}
}
]
}
}
}
}
```
## 局限性
`abi3audit` 是一个*尽力而为*的工具,具有与
[`auditwheel`](https://github.com/pypa/auditwheel) 相同的一些局限性。特别是:
* `abi3audit` 无法检查*动态* abi3 违规,例如扩展
调用 [`dlsym(3)`](https://man7.org/linux/man-pages/man3/dlsym.3.html)
以在运行时调用非 abi3 函数。
* `abi3audit` 可以确认存在 abi3 兼容符号,但没
有详尽的 abi3 *不兼容*符号列表。相反,它通过查找不在 abi3 兼容列表中以 `Py_` 或 `_Py_` 开头的符号
来寻找违规。这*不太可能*导致误报,
但如果扩展错误地使用了那些保留前缀,则*可能*
发生。
* 在审核“裸”共享对象(例如 `foo.abi3.so`)时,`abi3audit` 无法
对最低*预期* abi3 版本做任何假设。相反,它
默认为最低已知 abi3 版本(`abi3-cp32`)并警告任何
版本不匹配(例如,仅在 3.6 中稳定的符号)。
这可能导致误报,因此鼓励用户审核整个
wheel 或包(因为它们包含足够的元数据)。
* `abi3audit` 考虑的是符号*稳定*时的 abi3 版本,
而不是*引入*时的版本。换句话说:即使
函数是在 3.6 中引入的,如果 `abi3-cp36` 扩展包含在 3.7 中稳定的函数,`abi3audit` 也会产生警告。这*不是*误报
(这是 ABI 版本不匹配),但*通常*不是漏洞的来源。
* `abi3audit` 检查每个扩展的“本地”和“外部”符号,
针对支持这两种符号的格式。这样做是为了捕获已内联的符号,
例如 `_Py_DECREF`。但是,如果扩展的符号表
已被剥离,这些可能会被遗漏。
## 许可
`abi3audit` 根据 MIT 许可证授权。
`abi3audit` 包含根据
[Kaitai Struct](https://kaitai.io/) 项目提供的定义生成的 ASN.1 和 Mach-O 解析器。
这些内嵌的解析器由 Kaitai Struct 作者根据 MIT
许可证授权。
标签:abi3, CPython, DLL, ELF, PyPA, Python, Shared Object, wheel, 二进制分析, 云安全监控, 云安全运维, 云资产清单, 兼容性检查, 威胁情报, 安全合规, 开发者工具, 扩展模块, 文档结构分析, 无后门, 网络代理, 软件供应链安全, 远程方法调用, 逆向工具, 逆向工程, 静态分析