【天问】PyPI模块替代攻击
/ / 点击 / 阅读耗时 14 分钟2024年12月24号,天问Python供应链威胁监测模块发现PyPI中出现了许多利用模块替代攻击的恶意包,这些恶意包采用伪装包名诱骗用户下载。在安装过程中,包中内置的第三方模块(例如requests)会替代用户主机原有同名模块,导致用户被攻击。模块替代攻击已经成为了PyPI中一个不可忽视的威胁。
天问供应链威胁监测模块是奇安信技术研究星图实验室研发的“天问”软件供应链安全分析平台的子模块,”天问“分析平台对Python、npm等主流的开发生态进行了长期、持续的监测,发现了大量的恶意包和攻击行为。
1. 伪造包名攻击(TypoSquatting)
2024年12月24日,天问Python供应链威胁监测模块发现了PyPI出现了许多伪造包名的软件包,如reqesst
。这些恶意包通过构建与流行软件包requests
(日均下载量超过1000万[1])极其相近的拼写,来诱导用户下载。
这些恶意包的版本均为2.32.3
,观察流行包requests
的发布情况,我们发现其目前的版本也是2.32.3
。由此可以确定,这是有针对性的伪造包名攻击。
由上图可知,恶意包和正常包的代码文件结构一致。我们分析了常见的攻击入口,setup.py
和__init__.py
并未发现直接的攻击代码。但鉴于包名和包的内容基本都在刻意伪装成正常代码,因此我们对所有的代码进行了细致分析,最终在reqesst-2.32.3/src/requests/models.py
的第312行、313行发现了藏匿的恶意代码。
其使用了base64编码来隐藏恶意代码的真实意图,通过解码可得如下的url
1 | https[:]//www.dropbox.com/scl/fi/o5sege0jphqd9gjxgeiia/asd2.exe?rlkey=44p2rf6h6i55z74hsj9p682cj&st=1p1np9nx&dl=1 |
asd2.exe
是Windows下流行的反恶意软件工具Anvi Smart Defender关联的可执行文件。攻击者尝试将从dropbox.com中下载恶意的asd2.exe
来替代用户机器上原有的asd2.exe
来进行攻击。目前该文件已无法下载。
我们细致分析了models.py
中恶意代码的触发方式,在reqesst-2.32.3/src/requests/__init__.py
中models
会被导入,如下所示。
因此,当用户尝试在代码中import requests
,就会触发攻击代码。至于为什么攻击者的恶意模块requests
能够替代用户原有的良性requests
模块,这与Python包安装的特性有关。此类攻击我们称之为模块替代攻击。我们在之前的文章中也讨论过此类攻击事件[2]。
2. 模块替代攻击
在这一节,我们会讲解Python模块替代攻击的具体原理并展示其实际攻击效果。
2.1 攻击原理
当用户使用pip
下载第三方Python包时,这些包会默认安装在site-packages
目录之中。Python包中会包含一个或多个模块,这些模块会被统一放置在site-packages
目录下。虽然不同的用户无法在PyPI软件源中发布相同名称的软件包,但包中的模块可以同名。因此,包含相同模块名的不同包在安装时,会发生模块冲突问题。目前pip默认安装策略是使用后安装的模块覆盖替代原有同名模块。如下图所示,利用这个特性,攻击者可以完成模块替代攻击。
2.2 攻击效果展示
为了更好地展示这种攻击效果,我们设计了两个简单的示例python包,pkg_good
和pkg_bad
。他们均包含相同的模块test_module
。
我们首先安装
pkg_good
,包的结构如下所示核心代码如下所示
__init__.py
1
from .demo import test
demo.py
1
2
3def test():
print('demo for test')
print('hello world!')实际导入效果如下所示,虽然我们只导入了
test
函数,但是print('hello world!')
在demo.py
的全局作用域下,所以导入时会默认执行。这种触发方式与上面实际攻击案例一致。然后我们安装
pkg_bad
,两个包的核心差异在于demo.py
文件,如下所示demo.py
1
2
3def test():
print('demo for test')
print('You are hacked!')安装执行效果如下所示。
从上图我们可以观察到,
test_module
已被替换为了恶意的模块。这种攻击对于普通用户难以察觉,极易受到攻击影响。
模块替代攻击本质上是利用了Python设计中固有的特性,所以可以预见这类攻击在未来一段时间将会不断出现。现在PyPI及GitHub中的许多包都存在模块冲突的问题,会影响用户的正常使用甚至威胁用户安全[3]。对于用户而言,要尽量避免下载不可信的第三方软件包。Python的包名和模块名并不一致,所以在代码编写过程中出现模块缺少问题,要确认好实际对应的包名,避免误下载恶意软件包。
3. 大模型分析测试
通过对当前恶意包的分析,我们发现人工去校验查看此类攻击非常繁琐。恶意代码隐藏在大量正常代码之中,因此我们尝试使用天穹沙箱的TQ-GPT[4]来辅助我们的分析。
提示词如下所示:
1 | 判断下面python代码是否包含潜在恶意代码,是则输出可疑代码,并给出理由。 否,直接回复"否" |
结果如下所示:
从上图可知,TQ-GPT能很好地辅助我们查找恶意代码的位置。这对于繁琐的代码分析无疑提供了有力的支持,大大减少了安全分析人员的工作负担。天问监测系统正在逐步尝试与TQ-GPT结合,更加快速高效地识别定位开源生态中的恶意代码。
4. 总结
模块替代攻击利用了Python软件包安装的特性,使得攻击者可以将恶意篡改后的模块替换用户主机中的同名模块。当用户正常导入该模块时,就会触发恶意代码,从而遭受攻击。此类攻击极其难以防范,从上文分析可知,攻击者只需要在大量正常代码中插入少量恶意代码即可完成攻击,而且对于用户完全透明。虽然,本文的例子结合了伪造包名来实施攻击,会引起安全分析人员的察觉。但攻击者也可以发布正常的软件包,并在其中先嵌入正常的第三方模块,通过日常维护积累大量用户后实施模块替代攻击。
目前这类攻击没有非常好的防护手段,需要用户提高警惕,不要轻易下载不可信第三方库。天问Python供应链威胁监测模块[5]也会对PyPI进行持续监测,并及时发布相关报告。
恶意包列表
包名 | 版本 | 上传时间 |
---|---|---|
reqesst | 2.32.2 | 2024-12-24 |
requeszs | 2.32.2 | 2024-12-24 |
reqest | 2.32.2 | 2024-12-24 |
rreqest | 2.32.2 | 2024-12-24 |
reqeuts | 2.32.2 | 2024-12-25 |
reqzest | 2.32.2 | 2024-12-25 |
reqiest | 2.32.2 | 2024-12-25 |
requesr | 2.32.2 | 2024-12-25 |
参考链接
[1] requests包下载量统计 https://pypistats.org/packages/requests
[2] 【天问】PyPI “特洛伊木马” https://tianwen.qianxin.com/blog/2024/02/05/pypi-trojan
[3] ModuleGuard: Understanding and Detecting Module Conflicts in Python Ecosystem. https://arxiv.org/pdf/2401.02090
[4] 【天穹】TQ-GPT沙箱智能助理,样本分析新体验! https://tianwen.qianxin.com/blog/2024/04/11/tq-sandbox-TQGPT-online/
[5] “天问”软件供应链安全分析平台 https://tianwen.qianxin.com/