Old Python package comes back to life and delivers malicious payload
A recently spotted supply chain attack abused an old but legitimate Python package to deliver a malicious payload. Read more on how the attacker managed to do it and how to protect yourself from it.
Python packages are generally updated often as their developers add new functionalities or features, remove bugs or increase stability.
An old Python package named “ctx,” not updated since 2014, suddenly came back to life with new updates. But as discovered by Yee Ching Tok, ISC Handler at the SANS.edu Internet Storm Center, the new package contained malicious content delivered by a threat actor.
What was the malicious payload?
Python packages can be updated using the “pip” command very easily in the command line. Those needing to update Python packages – be they system administrators, developers, IT staff or end users – generally take it for granted and consider it free from risk.
SEE: Password breach: Why pop culture and passwords don’t mix (free PDF) (TechRepublic)
Ctx is a Python library for accessing Python dictionaries using dot notation. The original ctx package stopped being updated in December 2014 with version 0.1.2 (Figure A).
Figure A
The new ctx page at pypi.org reveals new changes, with v0.2.6 released May 21 this year (Figure B).
Figure B
Weird version changes should be a first warning regarding the page. Any usual developer would probably use good versioning and not skip from 0.1.2 to 0.2.6.
As can be seen in Figure B, the update from May 2022 consisted of little more than the one from 2014, though a careful analysis of the two files revealed that a few lines of code had been added (Figure C).
Figure C
According to Tok, that additional code attempts “to retrieve the AWS access key ID, computer name and the AWS secret access key when a dictionary is created”.
The ISC handler reports 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” (Figure D).
Figure D
Python Security estimates that 27,000 malicious versions of this software have been downloaded from PyPI, with the majority of “overage” downloads being driven by mirrors.
Was this an isolated incident?
Research done on the fraudulent web app domain led the researcher to another piece of code, this time not in Python but in PHP hosted on GitHub (Figure E).
Figure E
Given that this code also attempts to steal AWS access key IDs, it seems highly plausible that this attack was done by the same attackers.
How did it happen?
The original maintainer of the ctx package used a custom email address which can be seen in the code (Figure F).
Figure F
The domain registered by that person expired recently and was registered by the attacker on May 14. This allowed the attacker to create the same email address and do a password reset before taking full control of the package repository and pushing malicious code.
How can people protect themselves?
Package maintainers should always check their credentials are safe, and they should enable multi-factor authentication. If an attacker gains access to valid credentials for package maintenance, if MFA is enabled then they would be unable to update the repository with malicious content.
System administrators, IT employees and developers should not blindly accept updated packages. Differences in code should be analyzed before deploying any update.
While this may sound difficult when differences may be spread across hundreds or thousands of lines of code, focus should be put on a few selected functions that would be certainly used by attackers. Code involving network communications, or parts of code being obfuscated, should raise alarms.
New updates should be tested with behavioral content checks in a safe testing environment. A tool that has no business communicating on a network that suddenly does should raise red flags.
Disclosure: I work for Trend Micro, but the views expressed in this article are mine.