Checkmarx Security Research Team The world runs on code. We secure it. Sun, 24 Nov 2024 16:33:02 +0000 en-US hourly 1 https://wordpress.org/?v=6.6.1 https://checkmarx.com/wp-content/uploads/2024/06/cropped-cx_favicon-32x32.webp Checkmarx Security Research Team 32 32 Dozens of Machines Infected: Year-Long NPM Supply Chain Attack Combines Crypto Mining and Data Theft https://checkmarx.com/blog/dozens-of-machines-infected-year-long-npm-supply-chain-attack-combines-crypto-mining-and-data-theft/ Mon, 25 Nov 2024 12:00:44 +0000 https://checkmarx.com/?p=99242 Through our continuous monitoring of software supply chain threats, the Checkmarx Research team identified a supply chain attack that has remained active for over a year. The package, @0xengine/xmlrpc, began its life as a “legitimate” XML-RPC implementation in October 2023, but strategically transformed into a malicious tool in later versions and has remained active through November of 2024. This discovery serves as a stark reminder that a package’s longevity and consistent maintenance history do not guarantee its safety. Whether initially malicious packages or legitimate ones becoming compromised through updates, the software supply chain requires constant vigilance – both during initial vetting and throughout a package’s lifecycle.

Key Findings

  • A malicious NPM package masquerading as an XML-RPC implementation has maintained an unusually long presence on the NPM registry from October 2023 to November 2024, receiving 16 updates during this period.
  • The package started as a “legitimate” XML-RPC implementation and strategically introduced malicious code in later versions.
  • The malware steals sensitive data (SSH keys, bash history, etc..) every 12 hours while mining cryptocurrency on infected systems. Data is exfiltrated through Dropbox and file.io.
  • The attack achieved distribution through multiple vectors: direct NPM installation and as a hidden dependency in a legitimate-looking repository.
  • Evasion techniques include system monitoring detection and activity-based mining
  • At the time of investigation, it appeared that up to 68 compromised systems were actively mining cryptocurrency through the attacker’s Monero wallet.

Package History and Evolution

The malicious package “@0xengine/xmlrpc” first appeared on the NPM registry on October 2nd, 2023, presenting itself as a pure JavaScript XML-RPC server and client implementation for Node.js.

malicious package “@0xengine/xmlrpc” screenshot in NPM registry

What makes this package particularly interesting is its strategic evolution from legitimate to malicious code. The initial release (version 1.3.2) and its immediate follow-up appeared to be legitimate implementations of XML-RPC functionality. However, starting from version 1.3.4, the package underwent a significant transformation with the introduction of malicious code in the form of heavily obfuscated code within the “validator.js” file.

XML-RPC functionality code snippet
Part of the obfuscated code

Over its year-long presence on NPM, the package has received 16 updates, with the latest version (1.3.18) published on October 4th, 2024. This consistent update pattern helped maintain an appearance of legitimate maintenance while concealing the malicious functionality.

Distribution Strategy

Our research uncovered a calculated supply chain attack involving two distribution vectors. The first involves direct installation of @0xengine/xmlrpc from NPM. The second, more sophisticated approach, involves a GitHub repository named “yawpp” (hxxps[:]//github[.]com/hpc20235/yawpp), which presents itself as a WordPress posting tool.

The yawpp repository appears legitimate, offering functionality for WordPress credential checking and content posting. It requires @0xengine/xmlrpc as a dependency, claiming to use it for XML-RPC communication with WordPress sites. This dependency is automatically installed when users set up the yawpp tool through standard npm installation.

This strategy is particularly effective as it exploits the trust developers place in package dependencies, potentially leading to inadvertent installation of the malicious package through what appears to be a legitimate project dependency.

The combination of regular updates, seemingly legitimate functionality, and strategic dependency placement has contributed to the package’s unusual longevity in the NPM ecosystem, far exceeding the typical lifespan of malicious packages that are often detected and removed within days.

Attack Flow

attack flow diagram

The attack orchestrated through @0xengine/xmlrpc operates through a sophisticated multi-stage approach that combines cryptocurrency mining with data exfiltration capabilities. The malicious functionality, concealed within validator.js, remains dormant until executed through one of two vectors:

  • Direct package users execute any command with the ‘–targets’ or ‘-t’ flag. This activation occurs when running the package’s validator functionality, which masquerades as an XML-RPC parameter validation feature.
  • Users installing the “yawpp” WordPress tool from GitHub automatically receive the malicious package as a dependency. The malware activates when running either of yawpp’s main scripts (checker.js or poster.js), as both require the ‘–targets’ parameter for normal operation.

This implementation ensures the malware activates through legitimate-looking tool usage, making detection more difficult.

Initial Compromise

Once triggered, the malware begins gathering system information:

Deobfuscated version of the system information gathering code
Deobfuscated version of the system information gathering code

Following the initial data collection phase, the malware deploys its cryptocurrency mining component with a particular focus on Linux systems. The deployment process involves downloading additional payloads from a Codeberg repository disguised as system authentication services. The mining operation utilizes XMRig to mine Monero cryptocurrency, directing all mining rewards to a predetermined wallet address while connecting to the mining pool.

Deobfuscated configuration revealing the attacker's Codeberg repository URLs used to fetch mining components
Deobfuscated configuration revealing the attacker’s Codeberg repository URLs used to fetch mining components

These downloaded components include:

  • XMRig: The actual cryptocurrency mining software
  • xprintidle: Used to detect user activity
  • Xsession.sh: The main script that orchestrates the mining operation

The mining operation is configured with specific parameters targeting Monero:

Monero mining configuration found in the downloaded Xsession.sh script
Monero mining configuration found in the downloaded Xsession.sh script

At the time of our investigation, we observed 68 miners actively connected to this wallet address through the hashvault.pro mining pool, indicating a possible significant number of compromised systems actively mining cryptocurrency for the attacker.

Monero mining Pool page screenshot

Sophisticated Evasion Mechanisms

The malware implements an advanced process monitoring system to avoid detection. It maintains a list of monitoring tools and continuously checks for their presence.

Deobfuscated version of the process monitoring evasion logic found in Xsession.sh
Deobfuscated version of the process monitoring evasion logic found in Xsession.sh – checks for and terminates mining when system monitoring tools are detected

The malware also carefully monitors user activity through the xprintidle utility. It only initiates mining operations after a specified period of inactivity (default: 1 minute) and immediately suspends operations when user activity is detected. This behavior is controlled by the INACTIVITY_IN_MINS parameter.

INACTIVITY_IN_MINS parameter code

Maintaining Persistence

To ensure long-term survival on infected systems, the malware establishes persistence through systemd, disguising itself as a legitimate session authentication service named “Xsession.auth”. This service is configured to automatically start with the system, ensuring the mining operation resumes after system reboots. The malware also implements a daily check-in mechanism, regularly sending system status updates and potentially receiving new commands or configurations.

Deobfuscated systemd service configuration from Xsession.sh used for maintaining persistence
Deobfuscated systemd service configuration from Xsession.sh used for maintaining persistence

Data Exfiltration Pipeline

The malware implements a comprehensive data collection and exfiltration system that operates continuously. Every 12 hours, it performs a systematic collection of sensitive system information through a “daily_tasks” function found in Xsession.sh:

"daily_tasks" function found in Xsession.sh

During each collection cycle, the malware systematically gathers a wide range of sensitive data including:

  • SSH keys and configurations from ~/.ssh
  • Command history from ~/.bash_history
  • System information and configurations
  • Environment variables and user data
  • Network and IP information through ipinfo.io
Dropbox API code execution

The stolen data is exfiltrated through two channels. One, using the Dropbox API with hardcoded credentials.

Consnt dropboxConfig code execution

Additionally, the malware employs file.io as a secondary exfiltration channel, using a bearer token for authentication and setting automatic file deletion after download to minimize detection risks.

const token code execution

Conclusion

This year-long campaign serves as a stark reminder of the critical importance of thoroughly vetting open-source projects before incorporation into any software development process. Projects can be malicious from the start, maintaining a long-term presence while hiding their true nature, or legitimate projects can later become compromised and introduce malicious code through updates.

This dual threat emphasizes why developers and organizations must remain vigilant not only during initial vetting but also in monitoring package updates, implementing robust security measures, and conducting regular audits of their dependencies to mitigate the risks associated with supply chain attacks.

As part of the Checkmarx Supply Chain Security solution, our research team continuously monitors suspicious activities in the open-source software ecosystem. We track and flag “signals” that may indicate foul play, including suspicious entry points, and promptly alert our customers to help protect them from potential threats.

Checkmarx One customers are protected from this attack.

Packages

  • @0xengine/xmlrpc

IOC

  • hxxps[:]//codeberg[.]org/k0rn66/xmrdropper/raw/branch/master/xprintidle
  • hxxps[:]//codeberg[.]org/k0rn66/xmrdropper/raw/branch/master/xmrig
  • hxxps[:]//codeberg[.]org/k0rn66/xmrdropper/raw/branch/master/Xsession.sh
  • Wallet Address: 45J3v3ooxT335ENFjJBB3s7WS7xGekEKiBW4Z6sRSTUa5Kbn8fbqwgC47SLUDdKsri7haj7PBi5Wvf3xLmrX9CEZ3MGEVJU
]]>
npm package obfuscated code Attack Flow system gather downloading crypto minor wallet data Miners checking for monitoring processes checking for inactivity Persistence daily task data Collection dropbox file io
“Free Hugs” – What to be Wary of in Hugging Face – Part 2  https://checkmarx.com/blog/free-hugs-what-to-be-wary-of-in-hugging-face-part-2/ Thu, 21 Nov 2024 12:00:48 +0000 https://checkmarx.com/?p=99009 Enjoy Threat Modeling? Try Threats in Models! 


Previously… 
In part 1 of this 4-part blog, we discussed Hugging Face, the potentially dangerous trust relationship between Hugging Face users and the ReadMe file, exploiting users who trust ReadMe and provided a glimpse into methods of attacking users via malicious models. 
In part 2, we explore dangerous model protocols more in-depth– going into the technical reasons as to why exactly are models running code. 

Angry pickle


Introduction to Model Serialization  

A model is a program that was trained on vast datasets to either recognize or generate content based on statistical conclusions derived from those datasets.  
To oversimplify, they’re just data results of statistics. However, do not be misled – models are code, not plain data. This is often stressed in everything ML, particularly in the context of security. Without going into too much detail – it is inherent for many models to require logic and functionality which is custom or specific, rather than just statistical data.  
Historically (and unfortunately) that requirement for writable and transmittable logic encouraged ML developers to use complex object serialization as a means of model storage – in this case types of serialization which could pack code. The quickest solution to this problem is the notoriously dangerous pickle, used by PyTorch to store entire Torch objects, or its more contextual and less volatile cousin marshal, used by TensorFlow’s lambda layer to store lambda code. 

Pickle code snippet

Please stop using this protocol for things. Please. 

While simple serialization involves data (numbers, strings, bytes, structs), more complex serialization can contain objects, functions and even code – and that significantly raises the risk of something malicious lurking inside the models.

Browser warning on Pickle module

Writing’s on the wall there, guys

Protecting these dangerous deserializers while still using them is quite a task. For now, let’s focus on exploitation. This is quite well documented at this point, though there have been some curious downgrades exposed during this research. 

Exploiting PyTorch 

PyTorch is a popular machine learning library – extremely popular on Hugging Face andthe backbone of many ML frameworks supported on HF. We’ll have more on those (and how to exploit them) in a future blog. 
PyTorch relies on pickling to save its output, which can contain an arbitrary method with arbitrary variables invoked upon deserialization with the load function; this works the same for PyTorch: 

Import torch commend code snippet

If this looks identical to the previous Pickle example to you then that’s because it is. 

Note that the source code for BadTorch doesn’t need to be in scope – the value of __reduce__ is packed into the pickle, and its contents will execute on any pickle.load action. 
To combat this, PyTorch added a weights_only flag. This flag detects anything outside of a very small allowlist as malicious and rejects it, severely limiting if not blocking exploitation. It is used internally by Hugging Face’s transformers, which explains why it can safely load torches even when dangerous and starting version 2.4 This flag is encouraged via a warning where it is stated that in the future this will be a default behavior.  

Hugging face transformers warring text

At the time of writing, PyTorch does not yet enable weights_only mode by default. Seeing how the rampant use of torch.load in various technologies is (this will be discussed in part 3), it would be safer to believe this change when we see it, because it is likely to be a breaking change. It would then be up to the maintainers whose code this change breaks to either adapt to this change or disable this security feature. 

TensorFlow to Code Execution 

TensorFlow, is a different machine learning library that offers various ways to serialize objects as well. 
Of particular interest to us are serialized TensorFlow objects in protocols that may contain serialized lambda code. Since lambdas are code, they get executed after being unmarshled from Keras’, being a high-level interface library for TensorFlow.
Newer versions of TensorFlow do not generate files in the older Keras format (TF1, which uses several protobuf files or as h5). 
To observe this, we can look at the older TensorFlow to 2.15.0, which allows generating a model that would be loaded using the malicious code (credit to Splinter0 for this particular exploit): 

Import tensortflow commend code snippet

Note that the functionality to serialize lambdas has been removed in later versions of the protocol. For Keras, which supports Lambdas, these are now relying on annotations to link lambdas to your own code, removing arbitrary code from the process. 
This could have been a great change if it eliminated support for the old dangerous formats, but it does not – it only removes serialization (which creates the payload) but not execution after deserialization (which consumes it). 
Simply put – just see for yourself: if you generate a payload like the above model in an h5 format using the dangerous tensorflow 2.15.0, and then update your tensorflow: 

Import tensortflow commend code snippet

Exploit created on tensorflow 2.15.0, exploit pops like a champ on 2.18.0

In other words – this is still exploitable. It’s not really a Keras vulnerability (in the same vein torch.load “isn’t vulnerable”), though, but rather it’s a matter of how you end up using it – we’ve disclosed it amongst several other things to Hugging Face in August 2024, but more on that in a later write-up.

SafeTensors

Currently, Hugging Face is transferring models from a pickle format to SafeTensors, which use a more secure deserialization protocol that is not as naïve (but not as robust) as pickles.

SafeTensors simply use a completely different language (Rust) and a much simpler serialization protocol (Serde), which requires customization for any sort of automatic behavior post-deserialization.

Moving from Torch to SafeTensors

However, there is a fly in the SafeTensors ointment – importing. It makes sense that the only way to import from another format is to open it using legacy libraries, but it’s also another vulnerable way to invoke Torches. convert.py, a part of the SafeTensors library intended to convert torches to the SafeTensors format. However, the conversion itself is simply a wrapper for torch.load:
https://github.com/huggingface/safetensors/blob/main/bindings/python/convert.py#L186
The HF Devs are aware of this and have added a prompt – but that can be bypassed with a -y flag:

python convert code result

Model will run whoami on conversion. Disclaimer: image manipulated to exclude a bunch of passive warnings that might warn you, right after it’s way too late

The problem here is the very low trust barrier to cross – since, as discussed, most configuration is derived from ReadMe commands. This flag can simply be hidden between other values in instructions, which makes convert.py not just a conversion tool but also another vector to look out for.

There are many more conversion scripts in the transformers library that still contain dangerous calls to torch.load and can be found on the Transformers’ Github.

Conclusion

It’s interesting to see how what’s old is new again. Old serialization protocols which are easier to implement and use, are making a comeback through new, complex technology – particularly when security was never a concern during experimentation, and again becoming deeply ingrained in relatively new technology. The price for that speed is still being paid, with the entire ecosystem struggling to pivot to a secure and viable service by slugging through this tech debt.

There are several recommendations to be made when judging models by their format:

  • With serialization mechanisms baked into the ecosystem, you should avoid the legacy ones, and review those that are middle-of-the-way and historically vulnerable.
  • Consider a transition to SafeTensor or other protocols that are identified as secure and do not execute code or functions on deserialization and reject older potentially dangerous protocols.
    • BUT never trust conversion tools to safely defuse suspicious models (without reviewing them first).
  • And – as always – make sure you trust the maintainer of the Model.

On The Next Episode…  

Now that we’ve discussed a couple of vulnerable protocols, we’ll demonstrate how they can be exploited in practice against Hugging Face integrated libraries. 

]]>
Pickle codesnippet1 url pic codesnippet2 textsnippet codesnippet3 codesnippet4 code5
Falling Stars https://checkmarx.com/blog/falling-stars/ Mon, 18 Nov 2024 14:39:23 +0000 https://checkmarx.com/?p=98880 Intro

The number of the open-source packages is constantly rising, complicating how developers choose a package that fits their needs and is secure. Package repositories offer various metrics to help developers choose the right package, like the number of downloads, GitHub statistics, and user ratings. Package repositories offer various metrics to help developers choose the right package, like the number of downloads, GitHub statistics, and user ratings. Nevertheless, popularity continues to be one of the most influential factors in package selection. When we see a popular package, we assume it’s well-maintained and reliable. This common assumption led to the emergence of starjacking two years ago.

Starjacking is a technique that artificially inflates a package’s apparent popularity by exploiting how package repositories display information about associated GitHub repositories. After the technique became public, several major repositories, including npm and Yarn, were found to allow package publications with links to GitHub repositories not owned by the package publisher. We recently conducted comprehensive research across more than 20 package repositories to evaluate the current state of starjacking, and the findings show promising developments in security measures.

Researched package repositories

Our research encompassed 21 separate package repositories, Ranging from the big ones like npm, maven, and PyPI to smaller ones like CPAN, LuaRocks, and Hackage. The table below lists each repository and its primary programming language, included in the research.

Repo Name Language
npm JS
Maven Central java
Pypi python
NuGet csharp
pkg.go.dev go
Packagist PHP
Rubygems Ruby
crates.io Rust
CocoaPods ObjC/Swift
Pub.dev dart
CPAN perl
CRAN R
Clojars JS
Yarn JS
anaconda python, r
LuaRocks lua
Hackage haskell
Opam ocaml
Hex erlang
Meteor JS
Swift package index Swift

These repositories fall into two primary categories based on their artifact management approaches:
  • Some store the artifacts created during building, compiling, or packaging the code.
  • Others simply provide references to GitHub repositories containing the necessary files for package installation.

Package managers that exclusively reference GitHub repositories, such as pkg.go.dev and RubyGems, are inherently protected against starjacking since they display data directly from GitHub repositories. This direct integration eliminates the possibility of linking to one repository while serving code from another.

GitHub repositories pkg.go.dev web image

While such package repositories are not susceptible to Starjacking, the displayed GitHub statistics can still be misleading. They can be manipulated using more sophisticated techniques. For example, Swift Package Index and Packagist display comprehensive GitHub repository details, which can trick the users, if the stats are spoofed.

Packagist index web screen shot
Swift index web screen shot

Results

Most repositories do not display the GitHub repository statistics referred to by the package. While PyPI and Yarn previously showed these stats, they’ve since modified their approaches: Yarn has completely removed the statistics while PyPI implemented a more sophisticated metadata display system.   Yet some package repos still display GitHub statistics; for example, npm continues to show the number of issues and pull requests from the GitHub repository specified in the package metadata.

npn index web screenshot

Moreover, the CPAN Perl package repository displays the GitHub stats.

CPAN Perl package repository screenshot

Pypi’s Transformation of GitHub Statistics Display

PyPI slowly but steadily added verification of the package metadata.

Initially, PyPI displayed GitHub repository statistics without any verification mechanism. This approach made the platform vulnerable to starjacking attempts, as any package could claim association with any GitHub repository. PyPI’s first security improvement divided package information into two distinct sections: unverified and verified details.

While this division helped users identify trusted information, statistics of arbitrary GitHub repositories were still shown in the unverified details section. This was a good step towards informing the user which data they can trust. However, this was not enough since most people don’t carefully distinguish between verified and unverified information.

PyPI made a crucial advancement by implementing a comprehensive verification system through the Trusted Publisher Management feature. Starting from August 2024, the platform now ensures GitHub statistics appear exclusively in the verified details section and are only displayed for packages uploaded through the Trusted Publisher Management feature. This system utilizes OpenID Connect to enable secure publishing through trusted services like GitHub Actions.

The new publishing process works as follows: A PyPI project maintainer specifies a workflow in their GitHub repository for automatic package publishing. When triggered, the workflow authenticates with PyPI, proving that the code comes from the intended source. Only after verification can the package be published. Under this new system, PyPI displays GitHub repository statistics only when the links point to verified code repositories that have been authenticated through the trusted publishing workflow.

The evolution of PyPI’s security measures against Starjacking can be seen in three distinct phases (left to right):

  1. Initial phase: GitHub statistics were displayed without any verification or indication of their authenticity.

2. Second phase: Separation of verified and unverified details, with GitHub statistics specifically placed
in the unverified details section.

3. Current phase: GitHub statistics are now only displayed in the verified details section and appear
exclusively for packages uploaded through the Trusted Publisher Management feature.

This progression demonstrates PyPI’s commitment to maintaining security while providing valuable repository information to users.

GitHub project description page screenshot

Conclusion

While npm and CPAN continue to display unverified GitHub statistics, the risk of Starjacking has significantly decreased over the past two years. This improvement stems from most repositories either removing GitHub statistics entirely or implementing more robust verification systems, as exemplified by PyPI. It’s worth noting that most repositories (with PyPI being the exception) still display package metadata links without verification. While this vulnerability could potentially be exploited by malicious actors, it poses a substantially lower risk of misleading users compared to the original Starjacking technique.

]]>
GO package repo packigist package repo swift package repo npm package repo meta cpan package repo Pypi verified details
“Free Hugs” – What To Be Wary of in Hugging Face – Part 1  https://checkmarx.com/blog/free-hugs-what-to-be-wary-of-in-hugging-face-part-1/ Thu, 14 Nov 2024 12:00:00 +0000 https://checkmarx.com/?p=98796 Introduction 

GenAI has taken the world by storm. To meet the needs for development of LLM/GenAI technology through open-source, various vendors have risen to meet the need to spread this technology. 

One well-known platform is Hugging Face – an open-source platform that hosts GenAI models. It is not unlike GitHub in many ways – it’s used for serving content (such as models, datasets and code), version control, issue tracking, discussions and more. It also allows running GenAI-driven apps in online sandboxes. It’s very comprehensive and at this point a mature platform chock full of GenAI content, from text to media. 

In this series of blog posts, we will explore the various potential risks present in the Hugging Face ecosystem. 

Championing logo design Don’ts (sorry not sorry opinions my own) 

Hugging Face Toolbox and Its Risks 

Beyond hosting models and associated code, Hugging Face is a also maintainer of multiple libraries for interfacing with all this goodness – libraries for uploading, downloading and executing models to the Hugging Face platform. From a security standpoint – this offers a HUGE attack surface to spread malicious content through. On that vast attack surface a lot has already been said and many things have been tested in the Hugging Face ecosystem, but many legacy vulnerabilities persist, and bad security practices still reign supreme in code and documentation;  these can bring an organization to its knees (while being practiced by major vendors!) and known issues are shrugged off because “that’s just the way it is” – while new solutions suffer from their own set of problems.. 

ReadMe.md? More Like “TrustMe.md” 

The crux of all potentially dangerous behavior around marketplaces and repositories is trust – trusting the content’s host, trusting the content’s maintainer and trusting that no one is going to pwn either. This is also why environments that allow obscuring malicious code or ways to execute it are often more precarious for defenders. 

While downloading things from Hugging Face is trivial, actually using them is finnicky – in that there is no one global definitive way to do so and trying to do it any other way than the one recommended by the vendor will likely end in failure. Figuring out how to use a model always boils down to RTFM – the ReadMe. 

But can ReadMe files be trusted? Like all code, there are good and bad practices – even major vendors fall for that. For example, Apple actively uses dangerous flags when instructing users on loading their models: 

trust_remote_code sounds like a very reasonable flag to set to True 

There are many ways to dangerously introduce code into the process, simply because users are bound to trust what the ReadMe presents to them. They can load malicious code, load malicious models in a manner that is both dangerous and very obscure. 

Configuration-Based Code Execution Vectors 

Let’s start by examining the above configurations in its natural habitat.

 Transformers is one of the many tools Hugging Face provides users with, and its purpose is to normalize the process of loading models, tokenizers and more with the likes of AutoModel and AutoTokenizer. It wraps around many of the aforementioned technologies and mostly does a good job only utilizing secure calls and flags. 

However – all of that security goes out the window once code execution for custom models that load as Python code behind a flag, “trust_remote_code=True”, which allows loading classes for models and tokenizers which require additional code and a custom implementation to run. 

While it sounds like a terrible practice that should be rarely used, this flag is commonly set to True. Apple was already mentioned, so here’s a Microsoft example: 

why wouldn’t you trust remote code from Microsoft? What are they going to do, force install Window 11 on y- uh oh it’s installing Windows 11 

Using these configurations with an unsecure model could lead to unfortunate results. 

Code loads dangerous config à config loads code module à code loads OS command 

  • Code will attempt to load an AutoModel from a config with the trust_remote_code flag 
  • Config will then attempt to load a custom class model from “exploit.SomeTokenizer” which will import “exploit” first, and then look for “SomeTokenizer” in that module 
  • SomeTokenizer class doesn’t exist but exploit.py has already been loaded, and executing malicious commands 

This works for auto-models and auto-tokenizers, and in transformer pipelines: 

in this case the model is valid, but the tokenizer is evil. Even easier to hide behind! 

Essentially this paves the way to malicious configurations – ones that seem secure but aren’t. There are plenty of ways to hide a True flag looking like a False flag in plain sight: 

  • False is False 
  • {False} is True – it’s a dict 
  • “False” is True – it’s a str 
  • False < 1 – is True, just squeeze it to the side: 

This flag is set as trust_remote_code=False……………………………………………………………………………….………….n’t 

While these are general parlor tricks to hide True statements that are absolutely not exclusive to any of the code we’ve discussed – hiding a dangerous flag in plain sight is still rather simple. However, the terrible practice by major vendors to have this flag be popular and expected means such trickery might not even be required – it can just be set to True. 

Of course, this entire thing can be hosted on Hugging Face – models are uploaded to repos in profiles. Providing the name of the profile and repo will automatically download and unpack the model, only to load arbitrary code. 

import transformers 

yit = transformers.AutoTokenizer.from_pretrained(“dortucx/unkindtokenizer”, trust_remote_code=True)    

print(yit) 

Go on, try it. You know you want to. What’s the worst that can happen? Probably nothing. Right? Nothing whatsoever. 

Dangerous Coding Practices in ReadMes 

Copy-pasting from ReadMes isn’t just dangerous because they contain configurations in their code, though – ReadMes contain actual code snippets (or whole scripts) to download and run models. 

We will discuss many examples of malicious model loading code in subsequent write-ups but to illustrate the point let’s examine the huggingface_hub library, a Hugging Face client. The hub has various methods for loading models automatically from the online hub, such as “huggingface_hub.from_pretrained_keras”. Google uses it in some of its models: 

And if it’s good enough for Google, it’s good enough for everybody! 

But this exact method also supports dangerous legacy protocols that can execute arbitrary code. For example, here’s a model that is loaded using the exact same method using the huggingface_hub client and running a whoami command: 

A TensorFlow model executing a “whoami” command, as one expects! 

Conclusions 

The Hugging Face ecosystem, like all marketplaces and open-source providers, suffers from issues of trust, and like many of its peers – has a variety of blindspots, weaknesses and practices the empower attackers to easily obscure malicious activity. 

There are plenty of things to be aware of – for example if you see the trust_remote_code flag being set to True – tread carefully. Validate the code referenced by the auto configuration.  

Another always-true recommendation is to simply avoid untrusted vendors and models. A model configured incorrectly from a trusted model is only trustworthy until that vendor’s account is compromised, but any model from any untrusted vendor is always highly suspect. 

As a broader but more thorough methodology, however, a user who wants to securely rely on Hugging Face as a provider should be aware of many things – hidden evals, unsafe model loading frameworks, hidden importers, fishy configuration and many, many more.  It’s why one should read the rest of these write-ups on the matter. 

On The Next Episode… 

Now that we’ve discussed the very basics of setting up a model – we’ve got exploit deep-dives, we’ve got scanner bypasses, and we’ve also got more exploits. Stay tuned. 

]]>
image image image image image image image
October 2024 in Software Supply Chain Security https://checkmarx.com/blog/october-2024-in-software-supply-chain-security/ Tue, 12 Nov 2024 16:02:41 +0000 https://checkmarx.com/?p=98734 October 2024 heralded a new chapter in supply chain security challenges, characterized by innovative attack techniques and cryptocurrency-focused threats. A groundbreaking entry point exploitation technique affecting multiple package ecosystems was unveiled, while the NPM ecosystem witnessed the first-ever use of Ethereum smart contracts for malware C2 infrastructure. The month also saw multiple sophisticated attacks on cryptocurrency wallets through PyPI packages and a notable compromise of the popular lottie-player package, despite 2FA protections, highlighting the increasing complexity of supply chain security threats.

Let’s delve into some of the most striking events of October:

This New Supply Chain Attack Technique Can Trojanize All Your CLI Commands

A new supply chain attack technique exploits entry points in various programming ecosystems, allowing attackers to trojanize CLI commands. This stealthy method poses risks to developers and enterprises, bypassing traditional security checks. (Link to report).

With 2FA Enabled: NPM Package lottie-player Taken Over by Attackers

NPM package lottie-player compromised via leaked automation token, bypassing 2FA. Malicious versions injected code to trick users into connecting crypto wallets. Swift response: safe version released, compromised versions unpublished. (Link to report).

Crypto-Stealing Code Lurking in Python Package Dependencies

A sophisticated cyber attack on PyPI targeted cryptocurrency wallets through malicious packages. The attack used deceptive strategies, distributed malicious code across dependencies, and only activated when specific functions were called, making detection challenging. (Link to report).

Crypto-Stealing Code Lurking in Python Package Dependencies attack flow

Cryptocurrency Enthusiasts Targeted in Multi-Vector Supply Chain Attack

A malicious PyPI package “cryptoaitools” targeted cryptocurrency enthusiasts through a multi-vector supply chain attack. It used deceptive GUI, multi-stage infection, and comprehensive data exfiltration to steal crypto-related information from Windows and macOS users. (Link to report).

Cryptocurrency Enthusiasts Targeted in Multi-Vector Supply Chain Attack image

Supply Chain Attack Using Ethereum Smart Contracts to Distribute Multi-Platform Malware

A sophisticated NPM supply chain attack uses Ethereum smart contracts for C2 distribution. The cross-platform malware, targeting popular testing packages, affects Windows, Linux, and macOS through Typosquatting and preinstall scripts. (Link to report)

Ethereum Smart Contracts attack flow

*   *   *

Our team will continue to hunt, squash attacks, and remove malicious packages in our effort to keep the open-source ecosystem safe.

I encourage you to stay up to date with the latest trends and tactics in software supply chain security by tuning into our future posts and learning how to defend against potential threats.

Stay tuned…

Working to Keep the Open Source Ecosystem Safe

]]>
Crypto-Stealing Code Lurking in Python Package Dependencies – image Cryptocurrency Enthusiasts Targeted in Multi-Vector Supply Chain Attack image Ethereum Smart Contracts – image
Supply Chain Attack Using Ethereum Smart Contracts to Distribute Multi-Platform Malware https://checkmarx.com/uncategorized/supply-chain-attack-using-ethereum-smart-contracts-to-distribute-multi-platform-malware/ Mon, 04 Nov 2024 09:47:48 +0000 https://checkmarx.com/?p=98670 As part of our ongoing security efforts, we continuously monitor and detect malicious packages within various software ecosystems. Recently, we uncovered a unique supply chain attack through the NPM package “jest-fet-mock,” which implements a different approach using Ethereum smart contracts for command-and-control operations. The package masquerades as a popular testing utility while distributing malware across Windows, Linux, and macOS platforms. This discovery represents a notable difference in supply chain attack methodologies, combining blockchain technology with traditional attack vectors in a way not previously observed in npm. jest-fet-mock was the first package identified in a larger ongoing campaign targeting the npm ecosystem. Additional packages connected to this campaign were later reported by security firms Phylum and Socket.

Key Findings

  • First observed instance of malware utilizing Ethereum smart contracts for C2 server address distribution in the NPM ecosystem.
  • Typosquatting attack targeting developers by impersonating two legitimate, popular testing packages.
  • Cross-platform malware targeting Windows, Linux, and macOS development environments.
  • Uses NPM preinstall scripts to execute malicious code during package installation.
  • Performs info-stealing actions while establishing persistence mechanisms across infected systems.

The Art of Impersonation

jest-fet-mock package screenshot

The malicious package “jest-fet-mock”, published in mid-October, was designed to impersonate two legitimate and widely used JavaScript testing utilities.

The first, “fetch-mock-jest” (~200K weekly downloads), is a wrapper around fetch-mock that enables HTTP request mocking in Jest environments.

The second, “Jest-Fetch-Mock” (~1.3M weekly downloads), provides similar functionality through Jest’s native mocking capabilities.

Both legitimate packages are tools for testing HTTP requests in JavaScript applications. The attacker used a classic typosquatting technique by misspelling “fetch” as “fet” while maintaining the key terms “jest” and “mock”. Given that the legitimate packages are primarily used in development environments where developers typically have elevated system privileges, and are often integrated into CI/CD pipelines, we believe this attack specifically targets development infrastructure through the compromise of testing environments.

Attack Flow

Ethereum Smart Contracts Supply Chain Attack Flow Diagram

Blockchain-Based Command & Control

Etherscan transaction Screenshot
Etherscan transaction details showing the smart contract’s getString method returning the C2 server address

The most distinctive aspect of this attack is how it leverages the Ethereum blockchain for its command-and-control infrastructure. When executed, the malware interacts with a smart contract at address “0xa1b40044EBc2794f207D45143Bd82a1B86156c6b“. Specifically, it calls the contract’s “getString” method, passing “0x52221c293a21D8CA7AFD01Ac6bFAC7175D590A84” as a parameter to retrieve its C2 server address.

By using the blockchain in this way, the attackers gain two key advantages: their infrastructure becomes virtually impossible to take down due to the blockchain’s immutable nature, and the decentralized architecture makes it extremely difficult to block these communications.

Understanding the Smart Contract Mechanism

Think of a smart contract on the Ethereum blockchain as a public bulletin board – anyone can read what’s posted, but only the owner has the ability to update it. The attackers in this case deployed such a contract, using it to store their C2 server address. Every time the malicious package is installed on a new system, it checks this bulletin board to find out where to download the actual malware. What makes this approach particularly effective is its flexibility. Instead of hardcoding server addresses in their malware, the attackers can simply update their smart contract whenever they need to point to a new server. This means that even if defenders successfully block one C2 server, the attackers can quickly switch to a new one by updating their contract, and all new infections will automatically connect to the new location.

 Ethereum code screenshot

Initial Execution

The attack chain begins during the npm package installation process through the preinstall script. This script determines the host operating system and constructs a platform-specific URL to download the appropriate payload. The malware then spawns a detached process, ensuring the malicious code continues running independently of the installation process.

Multi-Platform Malware

Our analysis revealed distinct malware variants designed for:

Windows (SHA-256: df67a118cacf68ffe5610e8acddbe38db9fb702b473c941f4ea0320943ef32ba),

Linux (SHA-256: 0801b24d2708b3f6195c8156d3661c027d678f5be064906db4fefe74e1a74b17),

and macOS (SHA-256: 3f4445eaf22cf236b5aeff5a5c24bf6dbc4c25dc926239b8732b351b09698653).

Notably, as of this writing, none of these files have been flagged as malicious by any security vendors on VirusTotal.

The malware variants demonstrated various capabilities including system reconnaissance, credential theft, and establishing persistence through platform-specific mechanisms – using AutoStart files in Linux and Launch Agent configuration (~/Library/LaunchAgents/com.user.startup.plist) in macOS.

Throughout their operation, all variants maintain consistent communication with the attacker’s C2 server, showcasing a coordinated cross-platform attack strategy aimed at compromising development environments.

Impact

By targeting development tools and testing utilities, attackers gain potential access to not only individual developer machines but also CI/CD pipelines and build systems. The use of blockchain technology for C2 infrastructure represents a different approach to supply chain attacks in the npm ecosystem, making the attack infrastructure more resilient to takedown attempts while complicating detection efforts.

The cross-platform nature of the malware, coupled with the fact that no security vendors have flagged these files as malicious on VirusTotal at the time of writing, makes this an actively dangerous threat to development environments.

Conclusion

The discovery of “jest-fet-mock” reveals how threat actors are finding different ways to compromise the software supply chain. This case serves as an important reminder for development teams to implement strict security controls around package management and carefully verify the authenticity of testing utilities, especially those requiring elevated privileges.

This campaign is ongoing, with additional packages connected to the same campaign reported later in the month by Phylum and Socket.

As part of the Checkmarx Supply Chain Security solution, our research team continuously monitors suspicious activities in the open-source software ecosystem. We track and flag “signals” that may indicate foul play, including suspicious entry points, and promptly alert our customers to help protect them from potential threats.

Packages

For the full list of packages related to this campaign see this link:

https://gist.github.com/masteryoda101/d4e90eb8004804d062bc04cf1aec4bc0

IOCs

  • hxxp[:]//193[.]233[.]201[.]21:3001
  • hxxp[:]//193[.]233[.]201[.]21:3001/node-win.exe
  • hxxp[:]//193[.]233[.]201[.]21:3001/node-linux
  • hxxp[:]//193[.]233[.]201[.]21:3001/node-macos
  • df67a118cacf68ffe5610e8acddbe38db9fb702b473c941f4ea0320943ef32ba
  • 0801b24d2708b3f6195c8156d3661c027d678f5be064906db4fefe74e1a74b17
  • 3f4445eaf22cf236b5aeff5a5c24bf6dbc4c25dc926239b8732b351b09698653

]]>
jest-fet-mock npm packages jest-fet-mock attack flow Ethernet smar contract example jest-fet-mock code
Pwn3D: Abusing 3D Models for Code Execution  https://checkmarx.com/blog/pwn3d-abusing-3d-models-for-code-execution/ Mon, 04 Nov 2024 09:44:47 +0000 https://checkmarx.com/?p=98468

Preface 

Back in 2016, I was a passionate mechanical engineering student. Though I never graduated and eventually pivoted into AppSec, my love for engineering never faded. Fast forward to 2023, I bought a 3D printer – playing around with mechanics again. Naturally, I began merging this hobby with my security background, leading me to seek out vulnerabilities in 3D printing software. 

During one of our in-company white hat hacking activities, I took the opportunity to examine several 3D printing open source products. One of them was UltiMaker Cura, a popular slicer that according to UltiMaker’s website is trusted by millions (more on slicers soon). After scanning Cura with Checkmarx SAST, I uncovered a potential lead for code injection vulnerability, now tracked as CVE-2024-8374

In this blog post, we’ll examine the vulnerable flow and exploitation of CVE-2024-8374. We’ll also share insights into the impact of such vulnerabilities on the open source 3D printing community. Finally, we’ll highlight key takeaways from UltiMaker’s excellent response. 

annomyos

Introduction 

Slicers 

First things first, what exactly is a slicer? 

Simply put, a slicer is a program that is responsible for transforming a 3D model into a set of instructions (i.e. a gcode file) that the 3D printer can follow to physically print the model.  

Slicing is a vital part of the 3D printing process, and it cannot be skipped. As the name suggests, the slicer divides the 3D model into layers and provides a set of instructions for each one, such as temperature, speed, and more. The printer then processes these instructions, layer by layer, when printing. 

A typical flow of printing a 3D model is: 

  1. Obtaining a model (e.g., download from a public model database or design it yourself) 
  1. Slicing the model (e.g., with UltiMaker Cura) 
  1. Hit PRINT 
  1. Enjoy the 3D print 

3D Models Formats 

Before diving into Cura’s source code, we need to take a step back and first discuss the file formats used in 3D printing. There are different 3D models formats, each with different properties and purposes.  

The most popular format for 3D printing is called STL. Another popular format is the 3MF that is essentially a ZIP archive with the `.3mf`extension holding the model data in XML along with a collection of metadata files.  

The popularity of 3MF is rapidly growing because it adds capabilities that the well-known STL format doesn’t provide, such as color printing. It’s also gained popularity because it is backed by industry leaders including Autodesk and Dassault Systèmes. All of these make it one of the most widely used formats for 3D printing. 

Most importantly, it serves as our payload entry point. 

The Vulnerability 

Our journey to Cura’s source code starts in the `_read` method of the `3MFReader.py` plugin, which is responsible for loading 3MF models into Cura before slicing. 

Let’s start by examining this method (the important lines are highlighted in yellow): 

code text image
  1. The function accepts a `file_name` parameter, which is the path to the 3MF model we want to slice (line of code). 
  1. The 3MF model is then parsed by a ZIP reader (as mentioned earlier, a 3MF file is a ZIP archive) (line of code). 
  1. The file `3dmodel.model` is read from the archive. This file contains the actual model data in the XML format. Note that Cura stores this information in a variable called `scene_3mf` (line of code). 
  1. Transforming each node from our 3MF file into an UltiMaker format. Note that the `node` is passed in the first parameter of `_convertSavitarNodeToUMNode` (line of code). 

Examining the flow further, we can move forward to `_convertSavitarNodeToUMNode`. This function is quite long, and most of it is not relevant to us, so we’ll only focus on the specific lines which our input flows to: 

The `node` variable passed by the `_read` function is now called `savitar_node` inside the function `_convertSavitarNodeToUMNode` (line of code

  1. Settings are extracted from the `savitar_node` (line of code
  1. If `settings` is defined, Cura tries to add them (line of code
  1. While iterating each setting, Cura may find that the `drop_to_buildplate` is defined (line of code
  1. Once that happens, the value of this setting will end up in a call to `eval` which results in code execution (line of code). 

Exploitation 

By now it seems that we have a weakness because we didn’t see any kind of sanitization in the execution flow.  

To exploit it, we need to verify that we can control the `drop_to_buildplate` property and, if so, to understand the valid XML structure in which we can place the payload. 

Searching for known information about the 3MF format didn’t reveal much about the `drop_to_buildplate` property. However, it looked like this is a feature that is specific to Cura and not used by other slicers, which makes finding this setting in publicly available models quite challenging. Guessing the correct XML format also doesn’t seem to be the best approach in this case. Another alternative is to dive deeper into the source code to learn the appropriate format for setting Cura configurations. But fortunately, I found an easier way:  

Since we know that this property is unique to Cura, we may be able to use it to create a valid XML model that contains the `drop_to_buildplate` property for the payload. 

Let’s try that by downloading any 3MF model from a public model database. Note that we don’t care about anything else but the format (.3mf) of the file. For example, in the image below you can see that the specific model that I downloaded was created by OnShape (line #9), which is a 3D design software, but soon this metadata will be overridden. 

Now, let’s load this 3MF file into Cura and export it back to a 3MF format. The metadata will be converted to the format used by Cura. 

Extracting `3dmodel.model` from the 3MF archive we have just exported confirms our success, revealing a valid 3MF model with Cura’s metadata, including the `drop_to_buildplate` property (line #6): 

Let’s replace the value of `drop_to_buildplate` with Python code that spawns a calculator: 

 
The only thing left to do now is to open our crafted model with Cura- 

Let’s highlight a few things about the exploitation: 

  1. The code is executed with the default Cura configuration. 
  1. The code runs immediately, even before the model is loaded. There’s no need to slice or perform any action in Cura. 
  1. The model remains completely valid after tampering, making it appear legitimate from the user’s perspective. 
  1. The only way to identify this model as malicious is by examining the XML data. 

This allows a malicious actor to easily download, modify, and redistribute popular models for exploitation. 

But that’s not all – yet. 

A Note About Supply Chain Attacks 

We know already that this vulnerability is quite simple to exploit. Additionally, beyond model databases like Printables and Thingiverse, which are popular among makers and hobbyists, there are also open source repositories for engineering-focused projects, often used by sensitive sectors such as national security contractors, healthcare engineers, and others. The engineers use basic models in several ways, such as building blocks for their own designs or testing purposes. The open source nature of the 3D printing industry makes such vulnerabilities a potential target for supply chain attacks. 

The Fix 

The fix is straightforward: the maintainers removed the unnecessary eval call and replaced it with strict Boolean parsing, as shown here: 

  1. Removing eval 
  1. Boolean parsing 

Another thing to note is that UltiMaker didn’t reveal any information about the vulnerability in their commit’s comment: 

This is important because malicious actors frequently scan GitHub for vulnerabilities that were fixed but not yet released. 

UltiMaker’s Response 

UltiMaker responded and acted quickly, implementing a fix within less than 24 hours. The fix was released in the next beta release `5.8.0-beta.1` on 16 Jul. UltiMkaer’s security team was very responsive and gave all the required information for a smooth disclosure process. 

All in all, working with UltiMaker to address this issue was a great experience, and they’ve certainly earned Checkmarx’s Seal of Approval. 

References 

  1. 3D Models – Clean 3MF Model & PoC for Code Execution 
  1. NVD CVE Database 
  1. Commit of the fix 
  1. CWE 94 – Code Injection 

Timeline 

  • 15 June 2024 – Initial contact made with the UltiMaker’s Security team via security@ultimaker.com, providing a comprehensive report on the vulnerability. 
  • 16 June 2024 – UltiMaker responded, confirming the vulnerability. A fix was subsequently implemented and committed on the same day. 
  • 16 July 2024 – Version 5.8.0-beta.1, containing the fix, was released. 
  • 1 August 2024 – Stable version 5.8.0, containing the fix, was released. 
  • 3 September 2024 – CVE number assigned. 

]]>
image code text image 2_code 3_code 4_code 5_code 6_cura_calc 7_commit Seal_of_approval_logo (002)
With 2FA Enabled: NPM Package lottie-player Taken Over by Attackers https://checkmarx.com/blog/with-2fa-enabled-npm-package-lottie-player-taken-over-by-attackers/ Thu, 31 Oct 2024 13:13:26 +0000 https://checkmarx.com/?p=98641 The popular NPM package @lottiefiles/lottie-player enables developers to seamlessly integrate Lottie animations into websites and applications.

On October 30, the community reported existence of malicious code within versions 2.0.5, 2.0.6, and 2.0.7 of the npm package.

The package maintainers replied and confirmed the attackers were able to take over the NPM package using a leaked automation token which was used to automate publications of NPM packages.

The malicious code displays a UI overlay, asking to connect the crypto wallets by clicking or scanning a QR. By doing so, this prevent usage of the infected website

This is yet another reminder on how sensitive the software supply chain is

Would MFA Have Prevented This?

Multifactor authentication is designed to challenge humans. There are three authentication factors that can be used and 2FA requires two:

  1. something you know (like a password)
  2. something you have (like a one-time-use token)
  3. something you are (a biometric identity like a fingerprint or a speech pattern)

Going back two years ago – NPM decided to enforce 2FA on all users. Great move on NPM side as we witnessed many account takeover incidents happening.

Sounds Great, Doesn’t Work (?)

While this does secure NPM account takeover attacks from the interactive login page, enforcing 2FA on all accounts comes with a side-effect:

  • non-human identities can’t answer 2FA challenges.

So, when you define an NPM automation token — whoever gets your long-auto generated password is able to bypass your 2FA controls to make new version releases.

Back to @lottiefiles/lottie-player , even with 2FA configured, the threat actors somehow got the NPM automation token set in the CI/CD pipeline to automate version releases to publish the malicious versions 2.0.5, 2.0.6, and 2.0.7 of the npm package

The Malicious Code

All it does is displaying a UI overlay to steer the victim’s focus on connecting its crypto wallets to the malicious interface.

Conclusion

Kudus to the package maintainers for quickly releasing an incident response report

Freeze your deps tightly. Don’t rush to update to the latest if it’s not a security update and it’s a new release.

Check and make sure you don’t have the malicious versions 2.0.52.0.6, and 2.0.7 of lottie-player npm package.

The incident highlighted limitations of 2FA in automation environments, as automation tokens bypass these controls. This can happen to any major project.

]]>
With 2FA Enabled: NPM Package lottie-player Taken Over by Attackers Malicious code by the Lottie-player found in the NPM package, Multifactor authentication - 2FA couldn't prevent the attack. Checkmarx Security Research Team,NPM Package Take-over Attack image image
Cryptocurrency Enthusiasts Targeted in Multi-Vector Supply Chain Attack https://checkmarx.com/blog/cryptocurrency-enthusiasts-targeted-in-multi-vector-supply-chain-attack/ Wed, 30 Oct 2024 10:00:00 +0000 https://checkmarx.com/?p=98515 Cryptocurrency enthusiasts have been the target of another sophisticated and invasive malware campaign. This campaign was orchestrated through multiple attack vectors, including a malicious Python package named “cryptoaitools” on PyPI and deceptive GitHub repositories. This multi-stage malware, masquerading as a suite of cryptocurrency trading tools, aims to steal a wide range of sensitive data and drain victims’ crypto wallets. 

Key Findings

  • A malicious package “cryptoaitools” was uploaded to PyPI, impersonating legitimate cryptocurrency trading tools, complete with a seemingly functional trading bot implementation. 
  • The malware activated automatically upon installation, targeting both Windows and macOS operating systems. 
  • The attacker also distributed the malware through GitHub repositories, expanding the attack surface. 
  • A deceptive graphical user interface (GUI) was used to distract victims while the malware performed its malicious activities in the background. 
  • The malware employed a multi-stage infection process, utilizing a fake website that appeared legitimate to host and deliver second-stage payloads. 
  • The malware displayed extensive data theft capabilities focused on cryptocurrency-related information, including wallet data, browser data, and sensitive system files. 

Attack Flow

Initial Infection Vector 

The CryptoAITools malware campaign began with the upload of a malicious package named “cryptoaitools” to PyPI. This package contained code for a seemingly legitimate cryptocurrency trading bot, including functions for automated trading on DEXs, price monitoring, and liquidity management. This legitimate-looking code served to disguise the malware’s true nature. 

The malware activates automatically upon installation through the package’s __init__.py file. This file imports and executes the run_base() function from  base.py: 

The run_base() function determines the victim’s operating system and executes the appropriate malware variant: 


The malware employs platform-specific helper functions to execute different versions for Windows and macOS systems. While the Windows version (basec_helper.py) is less obfuscated, the macOS variant (base_helper.py) is more heavily disguised. Despite these differences, both versions perform similar malicious activities, including data theft and cryptocurrency-related operations. These helper functions are responsible for downloading and executing additional malicious payloads, thus initiating subsequent stages of the attack. 

Multi-Stage Infection Process 

The CryptoAITools malware employs a sophisticated multi-stage infection process, leveraging a fake website to deliver its secondary payloads. 

After the initial infection via the PyPI package, the malware’s second stage begins with the execution of base_helper.py (for macOS) or basec_helper.py (for Windows). These scripts are responsible for downloading additional malicious components from a deceptive website. 

The malware uses a domain that appears legitimate: https://coinsw.app. This domain hosts a convincing appearance of a cryptocurrency trading bot service, complete with fake user reviews, subscriber counts, and detailed descriptions of AI-driven trading features. This elaborate disguise attempts to add credibility if a curious user investigates the domain. 

The helper script decodes a base64-encoded URL and a list of filenames: 

It then downloads these files from the fake website. 

These downloaded files constitute the secondary payloads, expanding the malware’s capabilities. Notable among these is MHTBot.py, which is executed immediately after download (For MAC a different set of files are downloaded and the main.py file is then executed immediately after download) 

This multi-stage approach allows the malware to: 

  • Maintain a small initial footprint in the PyPI package 
  • Evade detection during the initial installation 
  • Flexibly update and expand its capabilities post-infection 
  • Use a legitimate-looking website as a hosting platform for malicious payloads 

Deceptive GUI 

A unique aspect of this attack, compared to many malicious packages we have seen in the past, is that the CryptoAITools malware incorporates a graphical user interface (GUI) as a key component of its social engineering strategy. This GUI appears the moment the second-stage malware is activated and presents itself as an “AI Bot Starter” application. It is designed to distract users and collect sensitive information while the malware operates covertly. The interface’s role is straightforward: it begins by prompting users to create a password “to start using the bot securely.” Once a new password is added, a fake setup process is displayed, featuring a progress bar and loading animations. While users are engaged and focused on this seemingly legitimate interface and its fake setup process, the malware continues its malicious operations in the background, including data theft and system manipulation. 

Data Heist 

The CryptoAITools malware conducts an extensive data theft operation, targeting a wide range of sensitive information on the infected system. The primary goal is to gather any data that could aid the attacker in stealing cryptocurrency assets. The malware’s data collection capabilities are implemented across several modules, each focusing on specific types of data or system areas. 

Types of Data Targeted 

  • Cryptocurrency wallet data from various applications (Bitcoin, Ethereum, Exodus, Atomic, Electrum, etc.) 
  • Browser data: saved passwords, cookies, and browsing history 
  • Data from a wide range of browser extensions related to cryptocurrency 
  • Sensitive system files, including SSH keys and configuration files 
  • Files from user directories (Downloads, Documents, Desktop) containing keywords related to cryptocurrencies, passwords, and financial information 
  • Telegram application data, including configuration files and message databases 
  • System terminal history 
  • Data from Apple Notes and Stickies applications on macOS systems 

Data Exfiltration Method 

The malware’s exfiltration process begins with the collected data stored in a hidden .temp directory in the user’s home folder. For each file, the exfiltration script changes the file extension to ‘.minecraft’. It then uploads the file to gofile.io using their API. Upon successful upload, gofile.io returns a download link, which is then sent to a Telegram bot of the attacker. After transmission, the local copy of the exfiltrated file is deleted. The process also includes error handling to prevent disruptions to the malware’s operation. 

The Attacker 

Our continued investigation into this campaign revealed the attacker was employing multiple infection vectors and social engineering tactics. The attack is not limited to the malicious Python package on PyPI, but extends to other platforms and methods: 

  1. PyPI Package: The initial discovery of the malicious “cryptoaitools” package on PyPI. 
  1. GitHub Repository: The attacker also distributes the malware through a GitHub repository named “Meme-Token-Hunter-Bot”. This repository contains similar malicious code, potentially infecting users who clone and run the code directly from GitHub. 
  1. Fake Website: The attacker operates a fake website at https://coinsw.app/, which mimics a legitimate cryptocurrency trading bot service. 
  1. Telegram Channel: The website’s “Buy” page leads to a Telegram chat named “Pancakeswap prediction bot”, where the attacker directly engages with potential victims. 

In the Telegram chat, the attacker employs various tactics to lure potential victims. They offer “bot support” to establish credibility and trust. To entice users, they promote their GitHub repository as hosting their “most powerful bot,” appealing to those seeking advanced trading tools. The attacker then proposes an attractive offer: a free trial period followed by a monthly subscription model, making the proposition seem both risk-free and professional. To further personalize the experience and maintain ongoing engagement, they offer customized configuration options and continuous support, which creates a facade of a legitimate, customer-focused service. 

This multi-platform approach allows the attacker to cast a wide net, potentially reaching victims who might be cautious about one platform but trust another. 

Analysis of the GitHub repository interactions suggests that the scope of the attack may be larger than initially thought. Users who have starred or forked the malicious repository could potentially be victims, though further investigation would be needed to confirm this. 

Impact 

The CryptoAITools malware campaign has severe consequences for victims and the broader cryptocurrency community. Individuals face immediate financial losses through cryptocurrency theft, along with long-term risks of identity theft and privacy breaches due to extensive data exfiltration. 

The true scope of the attack may be larger than initially thought, particularly given the GitHub repository interactions. Users who starred or forked the malicious “Meme-Token-Hunter-Bot” repository are potential victims, significantly expanding the attack’s reach. 

On a larger scale, this attack erodes trust in cryptocurrency tools and platforms, potentially slowing adoption and innovation in the cryptocurrency space. 

Conclusion 

This cryptobot malware serves as a potent reminder that the stakes – and the risks – are high in the world of cryptocurrency. As digital assets continue to gain value and popularity, we can expect to see more sophisticated threats targeting this space. 

As part of the Checkmarx Supply Chain Security solution, our research team continuously monitors suspicious activities in the open-source software ecosystem. We track and flag “signals” that may indicate foul play, including suspicious entry points, and promptly alert our customers to help protect them from potential threats. 

Packages 

cryptoaitools 

IOC 

  • hxxps[:]//coinsw[.]app/basecw/main[.]py 
  • hxxps[:]//coinsw[.]app/basecw/upd[.]py 
  • hxxps[:]//coinsw[.]app/basec/loading[.]gif 
  • hxxps[:]//coinsw[.]app/basecw/tad[.]py 
  • hxxps[:]//coinsw[.]app/basecw/ciz[.]py 
  • hxxps[:]//coinsw[.]app/basecw/ps[.]py 
  • hxxps[:]//coinsw[.]app/basecw/cat_dance[.]gif 
  • hxxps[:]//api[.]telegram[.]org/bot7337910559:AAF3fBlgDrcT9R07QpnqUWQ7_eKmnD_1QMc/sendMessage 
  • hxxps[:]//coinsw[.]app/basecw/firstpage[.]py 
  • hxxps[:]//tryenom[.]com/active-addon/nkbihfbeogaeaoehlefnkodbefgpgknn/bulo[.]php?pass= 
  • hxxps[:]//coinsw[.]app/basec/tx[.]py 
  • hxxps[:]//coinsw[.]app/basec/AiBotPro[.]py 
  • hxxps[:]//coinsw[.]app/basec/tg[.]py 
  • hxxps[:]//coinsw[.]app/basecw/security[.]py 
  • hxxps[:]//coinsw[.]app/basec/password_creation[.]py 
  • hxxps[:]//coinsw[.]app/basec/MHTBot[.]py 
  • hxxps[:]//coinsw[.]app/basec/one[.]py 
  • hxxps[:]//coinsw[.]app/basec/ArbitrageBot[.]py 
  • hxxps[:]//coinsw[.]app/basec/ph[.]py 
  • hxxps[:]//coinsw[.]app/basecw/ss[.]py 
  • hxxps[:]//coinsw[.]app/basecw/ara[.]py 
  • hxxps[:]//coinsw[.]app/basecw/cat[.]py 
  • hxxps[:]//coinsw[.]app/basecw/cf[.]py 
  • hxxps[:]//coinsw[.]app/basecw/local[.]py 
  • hxxps[:]//coinsw[.]app/basec/updel[.]py 
  • hxxps[:]//coinsw[.]app/basec/password_creation_advanced[.]py 
  • hxxps[:]//coinsw[.]app/basec/addonal[.]py 
  • hxxps[:]//coinsw[.]app 
  • hxxps[:]//github[.]com/CryptoAiBots 

]]>
init checking os fake site second stage Gui Slide 16_9 – 74 telegram attacker
This New Supply Chain Attack Technique Can Trojanize All Your CLI Commands https://checkmarx.com/blog/this-new-supply-chain-attack-technique-can-trojanize-all-your-cli-commands/ Mon, 14 Oct 2024 11:00:00 +0000 https://checkmarx.com/?p=98284 The open source ecosystem, due to its widespread adoption, has become a prime target for supply chain attacks. Malicious actors often exploit built-in features of open source packages to automatically distribute and execute harmful code. They particularly favor two techniques: Automatic, preinstall scripts that execute upon package installation, and seemingly innocent packages that import malicious dependencies.

As these tactics have become more recognizable, current security tools and vigilant developers have improved at detecting them quickly. However, an often overlooked yet potentially dangerous feature remains: Entry points.

This blog post explores how attackers can leverage entry points across multiple programming ecosystems with an emphasis on Pypi to trick victims into running malicious code. While this method doesn’t allow for immediate system compromise like automatic scripts or malicious dependencies, it offers a subtler approach for patient attackers to infiltrate systems, potentially evading standard security measures.

By understanding this lesser-known vector, we can better defend against the evolving landscape of Open source supply chain attacks.

Key Points

  • Entry points, a powerful feature for exposing package functionality, are vulnerable to exploitation across various ecosystems including PyPI (Python), npm (JavaScript), Ruby Gems, NuGet (.NET), Dart Pub, and Rust Crates.
  • Attackers can leverage these entry points to execute malicious code when specific commands are run, posing a widespread risk in the open-source landscape.
  • Attack methods include command-jacking—impersonating popular third-party tools and system commands—and targeting various stages of the development process through malicious plugins and extensions. Each approach carries varying levels of potential success and detection risk.
  • Entry point attacks, while requiring user interaction, offer attackers a more stealthy and persistent method of compromising systems, potentially bypassing traditional security checks.
  • This attack vector poses risks to both individual developers and enterprises, highlighting the need for more comprehensive Python package security measures.

Understanding Python Entry Points

Entry points are a powerful feature of the packaging system that allows developers to expose specific functionality as a cli command without requiring users to know the exact import path or structure of the package.

Entry points serve several purposes which include:

  • Creating command-line scripts that users can run after installing a package.
  • Defining plugin systems where third-party packages can extend the functionality of a core package.

The most popular kind of entry point is console_scripts, which points to a function that you want to be made available as a command-line tool to whoever installs your package.

While primarily designed to enhance modularity and plugin systems, entry points can, if misused, become a vector for malicious actors to embed and execute harmful code. To understand how attackers can leverage Python entry points in their favor, let’s first understand how entry points were originally meant to work.

How Entry Points are Defined in Package Metadata

The location and format of entry point definitions can vary depending on the package format (wheel or source distribution).

Source Distributions (.tar.gz)

For source distributions, entry points are typically defined in a package’s setup configuration. This can be in setup.py, setup.cfg for traditional setups, or pyproject.toml for more modern packaging approaches.

Here’s an example of how entry points might be defined in setup.py:

Wheel Files (.whl)

In a wheel file, which is a built package format, entry points are defined in the entry_points.txt file within the .dist-info directory.

Here’s how the entry_points.txt file might look for the above example:

The syntax for entry points follows this pattern:

  • name: The name of the entry point (e.g., the command name for console scripts)
  • package.module: The Python module path
  • object: The object (function, class, etc.) within the module to be used

In the above examples, my_command is a console script that will be created during installation. Anytime after the package installation, when a user types my_command in their terminal, it will execute the my_function from mypackage.module.

The plugin_name is a custom entry point that could be used by my_package to discover plugins. It points to PluginClass in my_package.plugins.

When a package is installed, these entry points are recorded in the package’s metadata. Other packages or tools can then query this metadata to discover and use the defined entry points.

If an attacker can manipulate a legitimate package’s metadata or convince a user to install a malicious package, they can potentially execute arbitrary code on the user’s system whenever the defined command or plugin is invoked. In the following section, I will provide multiple methods an attacker could use to trick someone into executing their malicious code through entry points.

Understanding CLI Commands in Operating Systems

Command-line interface (CLI) commands are the primary means by which users interact with an operating system through a text-based interface. These commands are interpreted and executed by the shell, which acts as an intermediary between the user and the operating system.

When a user enters a command, the shell follows a specific resolution mechanism to locate and execute the corresponding program. The exact order can vary slightly between different shells. However, the process typically begins by checking in order the directories listed in the PATH environment variable and runs the first matching executable it finds. Users can view their current PATH by entering the command “echo $PATH” in their terminal (the exact command will differ between operating systems), which displays the list of directories the shell searches for executables.

This resolution process ensures that when a user types a command, the appropriate action is taken. Understanding this process is crucial when considering how Python entry points, which can create new CLI commands, might interact with or potentially interfere with existing system commands.

Terminal output on an Ubuntu system showing the ‘ls’ command execution, its PATH location using ‘which ls’, and the system’s PATH environment variable, displaying the ‘ls’ PATH priority.

How Attackers Can Abuse Entry Points to Execute Malicious Code

Malicious actors can exploit Python entry points in several ways to trick users into executing harmful code. We’ll explore a number of tactics, including Command-Jacking, Malicious Plugins and Malicious Extensions.

Command-Jacking

Impersonating Popular Third-Party Commands

Malicious packages can use entry points to masquerade as widely-used third-party tools. This tactic is particularly effective against developers who frequently use these tools in their workflows.

For instance, an attacker might create a package with a malicious ‘aws’ entry point. When unsuspecting developers who regularly use AWS services install this package and later execute the aws command, the fake ‘aws’ command could exfiltrate their AWS access keys and secrets. This attack could be devastating in CI/CD environments, where AWS credentials are often stored for automated deployments—potentially giving the attacker access to entire cloud infrastructures.

Another example could be a malicious package impersonating the ‘docker’ command, targeting developers working with containerized applications. The fake ‘docker’ command might secretly send images or container specifications to the attacker’s server during builds or deployments. In a microservices architecture, this could expose sensitive service configurations or even lead to the exfiltration of proprietary container images.

Other popular third-party commands that could be potential targets for impersonation include but not limited to:

  1. npm (Node.js package manager)
  2. pip (Python package installer)
  3. git (Version control system)
  4. kubectl (Kubernetes command-line tool)
  5. terraform (Infrastructure as Code tool)
  6. gcloud (Google Cloud command-line interface)
  7. heroku (Heroku command-line interface)
  8. dotnet (Command-line interface for .NET Core)

Each of these commands is widely used in various development environments, making them attractive targets for attackers looking to maximize the impact of their malicious packages.

Impersonating System Commands

By using common system command names as entry points, attackers can impersonate fundamental system utilities. Commands like ‘touch,’ ‘curl,’ ‘cd’, ‘ls’, and ‘mkdir’ just to name a few, could be hijacked, leading to severe security breaches when users attempt to use these fundamental tools.

While this method potentially provides the highest chances of the victim accidentally executing the malicious code, it also carries the highest risk of failure for the attacker. The success of this approach primarily depends on the PATH order. If the directory containing the malicious entry points appears earlier in the PATH than the system directories, the malicious command will be executed instead of the system command. This is more likely to occur in development environments where local package directories are prioritized.

Another thing to keep in mind is that globally installed packages (requiring root/admin privileges) might override system commands for all users, while user-installed packages would only affect that specific user’s environment.

Comparison of Ubuntu terminal outputs before and after installation of a malicious package. An ‘ls’ command is added to the PATH /home/ubuntu/.local/bin/ls, which takes priority over the PATH of the legitimate ls command.

Enhancing Attacks with Command Wrapping

In each of these Command-Jacking tactics, while it’s simpler for an attacker to merely override CLI commands, the chances of remaining undetected are quite low. The moment victims can’t execute a command, they’ll likely become suspicious immediately. However, these attacks can be made much more effective and stealthy through a technique called “command wrapping.” Instead of simply replacing a command, wrapping involves creating an entry point that acts as a wrapper around the original command. Here’s how it works:

  1. The malicious entry point is triggered when the user calls the command (whether it’s an impersonated third-party tool or an attempt to impersonate a system command).
  2. In addition to silently executing the attacker’s malicious code, it calls the original, legitimate command with all the user’s arguments.
  3. Finally, it returns the output and exit code of the legitimate command to the user.

This method of command wrapping is particularly dangerous as it executes malicious code without the user’s knowledge while maintaining the appearance of normal operation. Since the legitimate command still runs and its output and behavior are preserved, there’s no immediate sign of compromise, making the attack extremely difficult to detect through normal use. This stealthy approach allows attackers to maintain long-term access and potentially exfiltrate sensitive information without raising suspicion.

However, implementing command wrapping requires additional research by the attacker. They need to understand the correct paths for the targeted commands on different operating systems and account for potential errors in their code. This complexity increases with the diversity of systems the attack targets.

An alternative approach, depending on the command being hijacked, is for the malicious package to not only perform its covert operations but also replicate some or all of the functionality of the original command. Instead of calling the real command, the wrapper simulates its behavior. This method could further decrease suspicion, especially for simpler commands, but it requires more effort from the attacker to accurately mimic the original command’s behavior across various scenarios.

The success of these attacks ultimately depends on the malicious package being installed and its scripts directory being prioritized in the system’s PATH.

Malicious Plugins & Extensions

Another powerful technique for abusing entry points is through the creation of malicious plugins for popular Python tools and frameworks. This approach can be particularly dangerous as it targets the development and testing process itself.

Manipulating pytest

As an example, let’s consider how an attacker might target pytest, a widely-used testing framework in the Python ecosystem. By creating a malicious pytest plugin, an attacker could potentially compromise the integrity of the entire testing process.

Here’s how such an attack could work:

  1. The attacker creates a plugin that uses pytest’s entry point system to inject malicious code.
  2. This plugin is distributed as a seemingly helpful testing utility.
  3. Once installed, the plugin can manipulate various aspects of the testing process such as assertion handling.

The malicious plugin could then stealthily run malicious code in the background during testing. The malicious plugin could also override pytest’s assertion comparison, causing, for example, all equality checks to pass regardless of their actual values, leading to false positives in test results, allowing buggy or vulnerable code to pass quality checks unnoticed.

In the following video demonstration, we showcase how such a malicious plugin can target pytest’s assertion handling, allowing an attacker to manipulate test results without alerting the developers. In this example, a developer was attempting a simple test scan of a basic calculator package.

Manipulating Flake8

Attackers can also target popular development tools, manipulating them to run malicious extensions. Flake8, a widely-used linting tool in the Python ecosystem, is one such example. Since Flake8 uses entry points to discover and load extensions, it becomes a potential target for malicious actors.

An attacker might exploit Flake8 by creating a malicious extension disguised as helpful linting rules. This extension would be defined as an entry point in the package’s setup configuration. For example, the setup file might specify an entry point named ‘MCH’, pointing to a malicious checker class within the package.

Supply Chain Attack Technique code snippet example

The malicious checker’s implementation could include functionality to perform harmful actions on the victim’s system, inject malicious “fixes” into the code, or manipulate linting results to hide or create issues. When a user runs Flake8 on their codebase, this malicious extension would activate, allowing the attacker to execute their harmful code.

This attack is particularly dangerous because linting tools often run on entire codebases, giving the attacker broad access to the source code. Moreover, the attack can be perpetrated through seemingly helpful linting rules, making it less likely to raise suspicion. It could serve as part of a larger supply chain attack to gather intelligence or introduce vulnerabilities into the target’s codebase.

Working around .whl File Limitations

Python wheels (.whl files) have become increasingly prevalent due to their performance benefits in package installation. However, they present a unique challenge for attackers

While both .tar.gz and .whl files may contain a setup.py file, .whl files don’t execute setup.py during installation. This characteristic has traditionally made it more difficult for attackers to achieve arbitrary code execution during the installation process when using .whl files.

However, the entry point attack method we’ve discussed provides a workaround for this limitation. By manipulating entry points, attackers can ensure their code is executed when specific commands are run, even if the package is distributed as a .whl file. This is particularly significant because when developers build a Python package using commands like “pip -m build”, newer pip versions automatically create both .tar.gz and .whl files. Additionally, pip prioritizes delivering the .whl file to users during installation

This shift in package format and installation behavior presents a new opportunity for attackers. Many security tools focus on analyzing execution of preinstall scripts during installation, which are typically associated with .tar.gz files. As a result, they may miss malicious code in packages distributed as .whl files, especially when the malicious behavior is triggered through entry points rather than immediate execution.

Entry Points in Other Ecosystems

While this blog primarily focuses on Python, the exploitation of entry points for malicious purposes extends beyond the Python ecosystem. Through our research, we have confirmed that this type of attack vector exists in several other major ecosystems, including:

npm (JavaScript), Ruby Gems, NuGet (.NET), Dart Pub, and Rust Crates, though the vulnerability may not be limited to these alone.

Understanding how entry points function across various programming languages and package managers is crucial for grasping the widespread nature of this potential security risk and for developing comprehensive defensive strategies.

Conclusion

Entry points, while a powerful and useful feature for legitimate package development, can also be manipulated to deliver malicious code across multiple programming ecosystems

Attackers could exploit this mechanism through various methods, including Command-Jacking and the creation of malicious plugins and extensions for popular development tools.

Moving forward, it’s crucial to develop comprehensive security measures that account for entry point exploitation. By understanding and addressing these risks, we can work towards a more secure Python packaging environment, safeguarding both individual developers and enterprise systems against sophisticated supply chain attacks.

As part of the Checkmarx Supply Chain Security solution, our research team continuously monitors suspicious activities in the open-source software ecosystem. We track and flag “signals” that may indicate foul play, including suspicious entry points, and promptly alert our customers to help protect them from potential threats.

]]>
Command-Jacking: The New Supply Chain Attack Technique Malicious actors can exploit Python entry points in several ways to trick users into executing harmful code. We'll explore Command-Jacking. AppSec,Checkmarx Security Research Team,Open Source Security,Supply Chain Security,Supply Chain Attack Technique ComandJacking 1 ComandJacking 2 ComandJacking 3 ComandJacking 4 ComandJacking 5 ComandJacking 6 ComandJacking 7