Ryazan, Russia - April 29, 2018: Homepage of Python website on the display of PC, url - Python.org
Image: sharafmaksumov/Adobe Stock

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

Image: Archive.org. Original ctx page on pypi.org showing v0.1.2 from 2014/12/19.

The new ctx page at pypi.org reveals new changes, with v0.2.6 released May 21 this year (Figure B).

Figure B

Image: pypi.org. The new ctx package page with updates in May 2022.
Image: pypi.org. The new ctx package page with updates in May 2022.

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

Image: TechRepublic. Code addition in the ctx.py source code file.
Image: TechRepublic. Code addition in the ctx.py source code file.

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

Image: TechRepublic. Code sending data to a web app controlled by the attacker, extracted from the latest ctx package.
Image: TechRepublic. Code sending data to a web app controlled by the attacker, extracted from the latest ctx package.

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

Image: TechRepublic. Malicious code added to a PHP script.
Image: TechRepublic. Malicious code added to a PHP script.

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

Image: TechRepublic. Header of ctx.py script showing the maintainer’s email address.
Image: TechRepublic. Header of ctx.py script showing the maintainer’s email address.

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.

Learn from more than one dozen of TechRepublic Academy’s online training courses for beginning Python developers now.

Disclosure: I work for Trend Micro, but the views expressed in this article are mine.

Subscribe to the Cybersecurity Insider Newsletter

Strengthen your organization's IT security defenses by keeping abreast of the latest cybersecurity news, solutions, and best practices. Delivered every Monday, Tuesday and Thursday

Subscribe to the Cybersecurity Insider Newsletter

Strengthen your organization's IT security defenses by keeping abreast of the latest cybersecurity news, solutions, and best practices. Delivered every Monday, Tuesday and Thursday