针对PyPI维护者的钓鱼攻击与Python软件供应链安全防护机制研究

1 引言

近年来,开源软件在现代软件开发中的基础性地位日益凸显。作为全球最广泛使用的编程语言之一,Python的包生态系统以Python Package Index(PyPI)为核心,承载了超过50万个公开项目和数百万开发者。然而,这一开放协作模式在提升开发效率的同时,也暴露出显著的安全隐患。2023年至2025年间,Python软件基金会(Python Software Foundation, PSF)多次披露针对PyPI账户持有者,尤其是高影响力包维护者的定向钓鱼攻击事件。攻击者通过伪造官方通信、注册仿冒域名(如pypi.mirror.org、pypi-verify.net等),诱导用户在虚假登录页面输入凭证,进而窃取账户控制权。

此类攻击并非孤立事件,而是构成对软件供应链上游节点的系统性威胁。一旦攻击者获得合法维护者权限,即可在不触发常规安全检测机制的前提下,向依赖广泛的软件包中注入恶意代码。由于下游应用通常直接或间接依赖这些包,攻击效果将沿依赖链迅速扩散,形成“一击多传”的供应链污染效应。SC Media与乌克兰技术媒体dev.ua均援引PSF安全工程师Seth Larson的分析指出,该钓鱼活动具有高度组织化特征,攻击者持续更换基础设施、模仿官方UI,并已尝试扩展至其他开源仓库平台。

本文聚焦于此次钓鱼攻击的技术特征、攻击路径及其对Python软件供应链造成的实际风险,系统梳理现有防御机制的局限性,并提出涵盖个体维护者、组织部署者与社区治理三个层面的纵深防御策略。文章结构如下:第二节分析攻击手法与技术细节;第三节评估其对供应链安全的影响;第四节从实践角度提出可落地的缓解措施,包括硬件密钥认证、包签名、依赖冻结等;第五节通过代码示例展示关键防护技术的实施方式;第六节讨论社区协同响应机制;第七节总结全文并指出未来研究方向。

2 攻击手法与技术特征分析

2.1 钓鱼邮件的社会工程学设计

攻击者发送的钓鱼邮件通常伪装为来自“PyPI Support”或“PSF Security Team”的官方通知,主题行多采用“Urgent: Your PyPI Account Requires Verification”或“Action Required: Prevent Account Suspension”等措辞,制造紧迫感。邮件正文声称用户账户存在异常登录行为或违反社区政策,若不在24–48小时内完成“安全验证”,账户将被永久停用。此类话术精准利用了维护者对项目中断的担忧心理。

值得注意的是,部分邮件甚至包含真实的PyPI项目名称、最近上传时间等元数据,表明攻击者可能通过公开API或历史数据集对目标进行预侦察。这种“半定制化”钓鱼(semi-spear phishing)显著提升了欺骗成功率。

2.2 仿冒域名与前端克隆

攻击者注册的仿冒域名在视觉上高度接近官方pypi.org,例如:

pypi.mirror.org

pypi-secure-login.com

verify-pypi.net

pypi-support.org

这些域名虽未使用HTTPS证书中的扩展验证(EV),但多数配置了由Let’s Encrypt签发的有效TLS证书,使得浏览器地址栏显示锁形图标,进一步增强可信度。前端页面则通过静态克隆PyPI登录页(/account/login/)实现,包括相同的Logo、配色方案、表单结构及错误提示逻辑。部分高级变体甚至动态加载官方CSS资源,仅替换表单提交的action URL至攻击者控制的后端。

2.3 凭证窃取与会话劫持

用户在仿冒站点输入用户名与密码后,凭证被发送至攻击者服务器。部分攻击样本还尝试窃取双因素认证(2FA)代码,通过实时中继(real-time relay)机制将用户输入的TOTP一次性密码立即用于真实PyPI登录,实现会话劫持。尽管PyPI自2023年起强制要求新账户启用2FA,但大量历史账户仍仅依赖密码或SMS验证,后者易受SIM交换攻击影响。

一旦获得账户访问权限,攻击者通常执行以下操作:

添加新的API token(权限设为“Upload only”以规避审计注意);

修改项目描述或README文件,插入看似无害的更新日志;

在后续版本中嵌入隐蔽的后门代码,如通过setup.py中的post_install钩子下载远程payload;

利用项目已有信任关系,诱导CI/CD系统自动构建并发布恶意包。

3 对软件供应链的安全影响评估

3.1 单点失效引发级联风险

PyPI生态中存在典型的“长尾依赖”结构:少数核心包(如requests、urllib3、numpy)被数十万个项目直接或间接引用。若其中任一维护者账户失陷,攻击者即可通过发布新版本(如1.2.4 → 1.2.5)注入恶意逻辑。由于大多数开发者默认信任语义化版本号(SemVer)的向后兼容性,此类更新常被自动拉取,导致恶意代码在无感知情况下部署至生产环境。

2024年曾发生一起真实案例:某流行CLI工具的维护者因点击钓鱼链接导致账户被盗,攻击者在v2.3.1版本中加入一段Base64编码的混淆脚本,该脚本在首次运行时向攻击者C2服务器回传主机名、当前用户及AWS凭证(若存在)。该版本在48小时内被下载超12万次,波及金融、医疗等多个行业。

3.2 现有安全机制的局限性

尽管PyPI已实施多项安全措施,如强制2FA、API token细粒度权限、可疑活动告警等,但在面对社会工程攻击时仍显不足:

2FA依赖软令牌:多数用户使用Google Authenticator等基于时间的一次性密码(TOTP)应用,无法抵御实时中继攻击;

缺乏发布签名:PyPI目前不要求包发布时附带数字签名,无法验证发布者身份真实性;

依赖解析无完整性校验:pip默认仅校验SHA256哈希(若提供),但该哈希由维护者自行声明,可被篡改;

监控滞后:恶意包通常在数小时甚至数天后才被社区举报下架,期间已造成广泛传播。

上述缺陷共同构成了“信任链断裂点”,使得攻击者只需突破最薄弱环节(即人的判断)即可绕过所有技术防线。

4 多层次防御体系构建

为应对上述威胁,需建立覆盖个体、组织与社区的三层防御体系。

4.1 个体维护者层面:强化身份认证与发布控制

启用FIDO2硬件安全密钥

FIDO2标准(含WebAuthn与CTAP)提供防钓鱼的强认证机制。与TOTP不同,FIDO2密钥在注册时绑定特定RP ID(Relying Party Identifier),仅当访问真实pypi.org时才会响应认证请求。即使用户误入仿冒站点,密钥亦不会激活,从根本上阻断凭证窃取。

PyPI自2023年Q4起支持FIDO2注册。维护者应优先使用YubiKey、SoloKey等合规设备,并禁用SMS及基于APP的2FA。

实施最小权限API Token

维护者应避免使用主账户密码进行自动化发布,而应创建具有明确作用域的API token。例如:

# .pypirc

[distutils]

index-servers = pypi

[pypi]

repository: https://upload.pypi.org/legacy/

username: __token__

password: pypi-AgEIcHlwaS5vcmc... # 仅限上传指定项目

Token应限制为单一项目、仅允许上传操作,并定期轮换。

启用多维护者审查机制

对于高影响力项目,建议设置至少两名独立维护者,并通过GitHub/GitLab的Protected Branches + Pull Request Review策略,确保任何发布前代码变更需经第二人审核。PyPI本身不提供此功能,但可通过外部CI流程实现。

4.2 组织部署层面:依赖治理与运行时防护

锁定内部镜像与依赖冻结

企业应部署私有PyPI镜像(如devpi、bandersnatch),并配置为仅同步经安全团队审核的包版本。同时,在项目中使用requirements.txt或pyproject.toml明确指定依赖的精确版本与哈希值:

# requirements.txt

requests==2.31.0 \

--hash=sha256:7d7b7a86fbc5d9c9e8b8b1e8a8e8a8e8a8e8a8e8a8e8a8e8a8e8a8e8a8e8a8e8 \

--hash=sha256:9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f

配合pip install --require-hashes可强制校验,防止版本漂移。

集成SLSA与in-toto验证

软件供应链层级(Supply-chain Levels for Software Artifacts, SLSA)框架为构建过程提供完整性保障。结合in-toto工具链,可在构建阶段生成布局(layout)与链接(link)元数据,记录谁、在何时、使用何种材料生成了制品。运行时可通过in-toto-verify校验发布包是否符合预期构建策略。

4.3 社区治理层面:品牌保护与快速响应

PSF应加强域名监控,对包含“pypi”“python”“psf”等关键词的新注册域名进行主动扫描与异议申诉。同时,建立自动化钓鱼站点识别系统,结合WHOIS、SSL证书指纹、页面相似度等特征训练分类模型。

此外,需完善恶意包快速下架机制。当前PyPI依赖人工举报,响应周期长。可引入基于行为分析的自动检测模块,例如:

新版本中突然引入网络请求或文件系统写入;

setup.py包含exec()、eval()或base64解码;

与历史版本代码相似度低于阈值。

一旦触发警报,自动暂停发布并通知维护者二次确认。

5 关键防护技术代码示例

5.1 使用FIDO2注册PyPI账户(维护者操作)

维护者需在PyPI账户安全设置中选择“Add security key”,浏览器将调用WebAuthn API。以下为简化流程示意(实际由PyPI前端处理):

// 浏览器端(PyPI网站)

const credential = await navigator.credentials.create({

publicKey: {

rp: { name: "PyPI", id: "pypi.org" },

user: { id: new Uint8Array([1,2,3,...]), name: "user@example.com" },

challenge: new Uint8Array([...]), // 来自服务器

pubKeyCredParams: [{ type: "public-key", alg: -7 }] // ES256

}

});

// 发送credential.response至PyPI后端注册

此后登录时,仅当访问pypi.org且用户提供物理密钥触碰,认证方可成功。

5.2 依赖哈希锁定与安装验证

项目根目录下requirements.txt:

click==8.1.7 \

--hash=sha256:ae74fb96c2a36130c8b9a1e8a8e8a8e8a8e8a8e8a8e8a8e8a8e8a8e8a8e8a8e8 \

--hash=sha256:bf9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f

安装命令:

pip install --require-hashes -r requirements.txt

若任一包哈希不匹配或版本被篡改,pip将拒绝安装。

5.3 in-toto构建验证示例

假设使用in-toto-run执行构建:

# 创建布局(由项目所有者签名)

in-toto layout create --layout layout.json \

--key owner.priv \

--steps '[{"name": "build", "expected_materials": [["MATCH", "src/*", "WITH", "PRODUCTS"]]}]'

# 执行构建步骤(生成链接元数据)

in-toto run --step-name build \

--materials "src/**" \

--products "dist/*.whl" \

--key builder.priv \

-- python setup.py bdist_wheel

# 验证(部署前)

in-toto verify --layout layout.json \

--layout-key owner.pub \

--link-dir .

若构建过程中引入未声明的外部依赖或修改了受保护材料,验证将失败。

6 社区协同响应机制建设

除技术手段外,有效的社区治理是遏制供应链攻击的关键。PSF可联合GitHub、GitLab等平台建立“高风险维护者”标识系统,对管理超过10万周下载量项目的账户,强制要求FIDO2认证与多因素审核。同时,推动PyPI原生支持发布签名(如PEP 458/480所提TUF框架),使客户端能验证包来源真实性。

此外,应建立跨仓库威胁情报共享机制。鉴于攻击者已尝试将钓鱼手法复制到npm、RubyGems等平台,各开源基金会可共建钓鱼域名黑名单,并通过DNS RPZ(Response Policy Zones)实现全网阻断。

教育亦不可忽视。PSF应在PyPI账户创建流程中嵌入安全引导,明确告知钓鱼风险及FIDO2优势,而非仅提供选项。开发者社区亦需培养“零信任”思维:即便来自熟识维护者的更新,也应通过哈希、签名或SBOM(软件物料清单)进行验证。

7 结论

针对PyPI维护者的钓鱼攻击揭示了开源软件供应链中“人”这一最脆弱环节的严重风险。攻击者通过精心设计的社会工程与基础设施伪装,绕过传统认证机制,直接威胁上游包的完整性。本文分析表明,单一防御措施难以奏效,必须构建涵盖强身份认证、依赖锁定、构建验证与社区协同的纵深防御体系。

FIDO2硬件密钥可有效阻断凭证窃取;依赖哈希与SLSA/in-toto机制保障制品完整性;而社区层面的品牌保护与快速响应则能压缩攻击窗口。未来工作应聚焦于推动PyPI全面采纳TUF(The Update Framework)以实现自动化签名验证,并探索基于区块链的不可篡改发布日志。唯有技术、流程与文化三者协同演进,方能在开放协作与安全保障之间取得可持续平衡。

编辑:芦笛(公共互联网反网络钓鱼工作组) 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

芦熙霖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值