Last Updated: 2022-05-24 17:57:44 UTC
by Yee Ching Tok (Version: 1)
Python is a prevalent programming language and has a vast collection of packages on Python Package Index (pypi.org) that allow developers to build their code conveniently. Many of these packages can be installed and updated by the well-known “pip install” command. However, many developers may take the updating and installation process for granted and may neglect to check what might have changed in the packages. I was recently alerted to such a particular post on Reddit , , and I decided to dive deeper to investigate the issue.
The package in question was the ctx Python package that was last uploaded to pypi.org on December 19 2014 (with reference to Figure 1). It provides the additional Ctx class, a subclass of the python ‘dict’ object . However, when we browse the release history tab, we can see various versions of ctx uploaded within the past few days (with reference to Figure 2). A check on the author’s GitHub repository also showed that the ctx package did not receive any updates .
Figure 1: Original ctx Release History (Retrieved from Archive.org )
Figure 2: Current ctx Release History (Retrieved from pypi.org )
It was undoubtedly weird that the original package that was uploaded on December 19, 2014, would be replaced by something identical on May 21, 2022 and have subsequent version updates (and skipping a few releases too).
Next, I wanted to verify what were the package changes. There were a few packages to consider:
1) The original ctx version 0.1.2
2) The “new” ctx version 0.1.2
3) ctx version 0.2.2
4) ctx version 0.2.6
I executed a diff command on the original ctx 0.1.2 and the “new” ctx 0.1.2, and observed something that caught my attention immediately (Figure 3).
Figure 3: Linux diff command executed on original ctx 0.1.2 Package and the “new” ctx 0.1.2 Package
In the “new” ctx 0.1.2.py code, there was code added to attempt to retrieve the AWS access key ID, computer name and the AWS secret access key when a dictionary is created. What an extra feature!
I then compared the “new” ctx 0.1.2 version with the ctx 0.2.2 version, and found no significant code changes. However, ctx 0.2.6 had a different feature (Figure 4).
Figure 4: Linux diff command executed on original ctx 0.1.2 Package and ctx 0.2.6 Package
In this case, it appears that the perpetrator is trying to obtain all the environment variables, encode them in Base64, and forward the data to a web app under the perpetrator’s control.
There were also some other notable artifacts in the newly uploaded ctx packages. For example, there was also a separate Python code “test_ctx.py” that was ostensibly used for testing the new package code, along with a “tox.ini” file (also likely used for testing the python package).
We can safely determine that the current Python ctx package on pypi.org should not be used as it has been tampered with. One possibility is that the original author’s account was compromised and used to upload the new packages. If one was using the original version 0.1.2 (SHA1 hash of ed9ef913ee7d4044992142306038c8a647b00b77) that was installed prior to sometime before May 14, 2022, it is unlikely that you would be using the tampered version of ctx (note that version 0.2.2 was uploaded on May 14, 2022). However, if one had installed the ctx package after May 14, 2022, you would likely be running an unsafe version of the ctx Python package.
With such an occurrence, it would be good for developers to closely scrutinise the packages that one uses for coding and verify that no extra features are lurking within the packages. This also highlights the importance of regularly checking source code, libraries and packages for irregularities, having a secure infrastructure for software development, and proper configuration management.
Update #1: It appears that the original maintainer's domain name had expired, and the perpetrator registered it on May 14, 2022 (same date where version 0.2.2 of ctx was uploaded). With control over the original domain name, creating a corresponding e-mail to receive a password reset e-mail would be trivial. After gaining access to the account, the perpetrator could remove the old package and upload the new backdoored versions.
Update #2: Searching for the malicious domain (hxxps://anti-theft-web.herokuapp.com) shows that another GitHub repository (hxxps://github.com/hautelook/phpass) has the same malicious domain embedded within the PHP code (please replace hxxps with https). It is recommended that the code in this repository not be used.
Update #3: As of 1011hrs (UTC time), a contact from the Python Software Foundation has indicated that the "project has been removed and prohibited from re-registration without admin intervention". Browsing to the ctx project page also resulted in a HTTP 404 response.
Update #4: The incident report on the malicious takeover of the ctx package on pypi.org has been published .
Indicators of Compromise (IOCs):
37129d145a310d64369e7d2741b4d51eb3a85193 (SHA1 hash of backdoored ctx-0.1.2.tar.gz)
f98204e2bfceef20c85f26e0f5c6661a8639e56d (SHA1 hash of backdoored ctx-0.2.2.tar.gz)
a73d3d7f1a57d61d17763747a7eaf8b24332c5b6 (SHA1 hash of backdoored ctx-0.2.6.tar.gz)