Malicious PyPI Package Hijacks MEXC Orders, Steals Crypto Tokens

Malicious Pypi_863x300

The JFrog Security Research team regularly monitors open source software repositories using advanced automated tools, in order to detect malicious packages. In cases of potential supply chain security threats, our research team reports any malicious packages that were discovered to the repository’s maintainers in order to have them removed. This blog provides an analysis of the ccxt-mexc-futures malicious package which aims to leak crypto currency trading credentials.

ccxt-mexc-futures claims to extend the capabilities of crypto trading via the CryptoCurrency eXchange Trading (ccxt) PyPI package, which is a legitimate commonly used crypto trading Python package, with over 93M downloads on PyPI. Moreover, its GitHub repository has 35K stars and 7.8k forks.

PyPi Steals Crypto - image6

The GitHub repository of the CCXT package

The original CCXT PyPI package supports trading on many cryptocurrency exchanges, including the MEXC exchange, as mentioned in their readme on GitHub:

“The CCXT library is used to connect and trade with cryptocurrency exchanges and payment processing services worldwide. It provides quick access to market data for storage, analysis, visualization, indicator development, algorithmic trading, strategy backtesting, bot programming, and related software engineering.”

The authors of the malicious ccxt-mexc-futures package, claim in its README file that it extends the CCXT package to support “futures” trade on MEXC:

Readme of the malicious package ccxt-mext-futures

In cryptocurrency trading, as in normal trading, “futures” are a contract between two parties to buy or sell an asset at a predetermined price and time in the future. Traders can go “long” or “short” when purchasing futures contracts. If a trader goes long, then they expect the price to rise, whereas when they go short, they expect the price to fall.

Normal usage of the CCXT package

A user of the CCXT package may place an order using operations known as “entries”. Specifying their API key and secret, each entry defines a trading operation that a user may perform, such as buying or selling.

PyPi Steals Crypto - image14Placing an order using CCXT

The original CCXT Python package indicates the API entries in a specific format, it specifies which API endpoint to use when sending a trading request, which HTTP method to use, the cost of the action and the section such as ‘contract’, ‘private’, ‘public’ etc. The MEXC exchange’s original implementation decides by the entry to what URL the trading request would be sent to.

The MEXC interface in CCXT defines a wide set of APIs to support different types of trading, such as spot (buyer-seller) and contracts trading. Two of such APIs were the target of this malicious campaign: contract_private_post_order_submit and contract_private_post_order_cancel.

PyPi Steals Crypto - image7aOriginal entries from the CCXT MEXC interface

Technical analysis of the malicious package

The malicious ccxt-mexc-futures package overrides the two aforementioned APIs, and adds a third one, spot4_private_post_order_place. Every time a user utilizes these entries, instead of using the CCXT defined entries, they will use the attacker’s entries, specifying futures trading in the request.

PyPi Steals Crypto - image4aCCXT API entries overridden by the ccxt-mexc-futures

By overriding these APIs, the attackers expect the users to create, cancel or place a trading order through the APIs they provided, which impersonate the legitimate APIs of the CCXT library. At first glance, these endpoints look legitimate. As it turns out, they are not what they seem to be.

In the malicious package’s files we found that it extends the existing functionalities of the original CCXT library for MEXC, by overriding the following functions:

  1. ֵdescribe
  2. sign
  3. prepare_request_headers

 

By overriding the describe function, it is possible to edit the MEXC exchange settings implementations. The deep_extend method allows users to extend the settings of the exchange provided by the CCXT package, so a user can edit and add any setting they desire when implementing an exchange. We can see the method being used in the original MEXC exchange code:

PyPi Steals Crypto - image13MEXC exchange implementation in the CCXT library, using the “deep_extend” method as settings

Obfuscation technique

The malicious package got our research team’s attention since it appeared to be utilizing suspicious obfuscation techniques, which vary between its versions.

The initial 0.1.4 version was using a simple base64 encoded compiled Python code, which is presented as a variable named salt. Afterwards, in version 0.1.8 it was replaced by nested calls to eval in order to execute arbitrary code encoded as hexadecimal string, also presented as salt.

PyPi Steals Crypto - image2Nested calls to eval in version 0.1.8

PyPi Steals Crypto - image2Executing decoded base64 string in version 0.1.4

Both versions of the package use different ways to hide and run arbitrary code on the local machine that installed the package. Both methods are very common ways for attackers to hide and run malicious payloads.

Payload analysis – Hijack MEXC orders to a malicious exchange

Resolving this obfuscated parts for both versions revealed the following code execution, which imports the Python requests library, and utilizes it to get a json file from a domain that pretends to be related to MEXC, https[://]v3[.]mexc[.]workers[.]dev.

PyPi Steals Crypto - image11Decoded payload of the malicious package

The domain is not owned by MEXC. However, when monitoring outgoing requests, this domain could be mistaken for the legitimate MEXC domain.

 

The JSON payload that was retrieved from the URL reveals a set of settings that the attackers used to direct the overridden APIs to a malicious 3rd party platform, instead of the legitimate MEXC website.

PyPi Steals Crypto - image2The JSON settings downloaded by the malicious package

Every time the user sends an order using the aforementioned API entries, the order will be directed to the APIs listed in the settings downloaded by the malicious package.

Further investigation revealed that the original MEXC integration had similar settings in its describe function, and that the “deep_extend” method extends the settings used by the original CCXT package.

PyPi Steals Crypto - image10aDefault settings of the MEXC exchange in the CCXT package

The malicious package configures more URLS in the API to allegedly support futures trading, changes the unavailable contracts settings to be “False”, meaning the contacts are “available”, and configures error “-2011” instead of being “BadRequest” to “OrderFilled”.

By doing this, the attackers made sure that when a user places an order through the overridden entries, even if the request was meant to get a “BadRequest” response, it will actually get an “OrderFilled” response, tricking the user to believe their order went through.

If we conclude the findings, the package creates entries in the API for MEXC integration, using an API that directs requests to the domain greentreeone[.]com, and not the MEXC site mexc.com. All requests are redirected to the domain set up by the attackers, allowing them to hijack all of the victim’s crypto tokens and sensitive information transferred in the request, including API keys and secrets.

PyPi Steals Crypto - image1The site “greentreeone[.]com” posing as mexc.com

When using the original CCXT Python package, every request to an exchange results in activating the “sign” function, whose purpose is to sign the request details using the API key and secret key, for authentication with the exchange. It is implemented differently for each exchange but according to the documentation it is already supplied and should happen automatically: “The authentication is already handled for you, so you don’t need to perform any of those steps manually unless you are implementing a new exchange class. The only thing you need for trading is the actual API key pair.”

However, the malicious package overrides the sign function. Inspection of the code reveals that if a user tries to communicate with the MEXC exchange using the malicious ccxt-mexc-futures, every request they send using the new entries defined by the malicious package in order to create, cancel or place an order, (“futures” in particular), is sent to the malicious greentreeone[.]com domain, sending the user token in the request header to the attackers, otherwise it will use the original MEXC sign method.

PyPi Steals Crypto - image5Sign function implementation in the malicious package

If the user token is not supplied, the package will throw an exception, requesting the user to add it in order to make order operations in the exchange. If it is not a future related entry, the package directs the flow to the original MEXC exchange implementation of the CCXT package.

IOCs

  1. https://v3[.]mexc[.]workers[.]dev/describe.json
  2. https://www[.]greentreeone[.]com/api/platform/spot/v4
  3. https://futures[.]greentreeone[.]com/api/v1
  4. https://futures[.]greentreeone[.]com/api/v1/private
  5. https://pypi.org/user/mexc/
  6. https://www[.]greentreeone[.]com

Improved Detection and remediation with JFrog Xray

As a response to this incident, we have added the malicious Python packages to JFrog Xray, to allow customers to detect them immediately. JFrog Xray’s database of regularly curated packages currently contains more than 300K malicious packages across all relevant ecosystems, and is continuously growing.

Click to enlarge

 

If the malicious ccxt-mexc-futures package was identified in your dependencies, we suggest revoking any API keys and crypto tokens used for trading on the MEXC platform using the CCXT package, as well as removing the malicious package completely.

Conclusion

The “ccxt-mexc-futures” package poses a significant threat by relying on the legitimate CCXT library and redirecting user trading requests to a malicious server.

This allows attackers to steal API keys and secrets, compromising cryptocurrency trading accounts. The use of obfuscation techniques and a fake MEXC website further demonstrates the sophistication of this phishing campaign.

Users are strongly advised to revoke any potentially compromised tokens and remove the malicious package immediately. JFrog Xray has been updated to detect this malicious package, providing an added layer of security for users.

Make sure to check out the JFrog Security Research center for more information about the latest CVEs, vulnerabilities and fixes.