PyPI packages ‘keep,’ ‘pyanxdns,’ ‘api-res-py’ were found to be containing a backdoor due to the presence of malicious ‘request’ dependency within some versions.
For example, while most versions of ‘keep’ project use the legitimate Python module requests for making HTTP requests, ‘keep’ v.1.2 contains ‘request’ (without s) which is malware.
BleepingComputer reached out to the authors of each of these packages to understand if this was caused by a mere typographical error, self-sabotage, or by maintainer accounts getting hijacked.
PyPI package ‘keep’ uses malicious ‘request’
Some versions of PyPI packages, ‘keep,’ ‘pyanxdns,’ and ‘api-res-py’ were caught using a malicious dependency, ‘request,’
Back in May, GitHub user duxinglin1 noticed the vulnerable versions contained the misspelled ‘request’ dependency, as opposed to the legitimate requests library.
As such, the following CVEs have been assigned this week with regards to the vulnerable versions:
- CVE-2022-30877 – ‘keep’ version 1.2 contains the backdoor ‘request’, contrary to what the advisory implies.
- CVE-2022-30882 – ‘pyanxdns’ version 0.2 impacted
- CVE-2022-31313 – ‘api-res-py’ version 0.1 impacted
Although ‘pyanxdns’ and ‘api-res-py’ might be small scale projects, the ‘keep’ package, in particular, gets downloaded over 8,000 times in a week on average—with its version 1.2 using the malicious dependency:
Back in 2020, Tencent Onion Anti-Intrusion System discovered a malicious typosquat ‘request’ uploaded to the PyPI registry which impersonated the requests HTTP library but instead dropped malicious info-stealers.
“We found a malicious backdoor in version 1.2 of this project, and its malicious backdoor is the request package. Even if the request package was removed by PyPI, many mirror sites did not completely delete this package, so it could still be installed,” writes GitHub user duxinglin1.
The malicious code inside the counterfeit ‘request’ is highlighted below:
Line 57 contains a base64-encoded URL to the ‘check.so’ malware shown below. Threat intel analyst blackorbird additionally identified another URL (x.pyx), also shown below, associated with the counterfeit ‘request’ dependency:
http://dexy[.]top/request/check.so
http://dexy[.]top/x.pyx
The file ‘check.so’ delivers a Remote Access Trojan (RAT), whereas ‘x.pyx’ obtained by BleepingComputer contains info-stealing malware that steals cookies and personal information from web browsers such as Chrome, Firefox, Yandex, Brave, and many more:
The info-stealing trojan will attempt to steal login names and passwords stored in web browsers.
After obtaining access to user credentials, threat actors can then attempt to compromise other accounts used by the developer, potentially leading to even further supply-chain attacks.
Hijack or a genuine typo?
The presence of a malicious dependency in multiple PyPI packages does raise a crucial question—how did this occur?
BleepingComputer reached out to the authors of each of these packages to understand if this was caused by a mere typographical error, self-sabotage, or by maintainer accounts getting hijacked.
We heard back from the author and maintainer of ‘pyanxdns’, Marky Egebäck, who confirms this is resulting from a typographical error rather than an account compromise.
And, from the looks of it, it appears the authors of other two packages also inadvertently introduced ‘request’ as opposed to the legitimate ‘requests’ due to an innocent typing mistake.
“Sorry to say by a simple typo in the setup.py file since git history shows that this was added when the install_requires was added by me,” Egebäck told BleepingComputer.
The developer has since reuploaded a new version to PyPI and deleted the version referencing the malicious “request” dependency.
“This was [an] honest mistake based on a typo in the setup.py. I generally don’t publish things on PyPI but I made this quickly for a friend and myself. Not sure if he as promoted this but the purpose was mainly for personal use in [an] internal docker project,” says Egebäck.
Egebäck appreciated GitHub user duxinglin1 for highlighting the presence of the malicious dependency in his project and explained how he hasn’t spent much time in maintaining the contributed Python project lately:
“What can of course have been done a lot better would have been to have fixed this earlier but did not understand the severity of it and since I put very little time sadly [nowadays] with coding it took a long time,” says Egebäck.
When coding applications, innocent typing mistakes on the developer’s part can inadvertently lend success to typosquatting attacks that count on such exact slip ups to compromise the broader software supply chain.
Although in this case, the malicious ‘request’ dependency has long been removed from the PyPI registry, anybody using a vulnerable version of the PyPI packages and relying on a mirror to fetch dependencies can end up with malicious info-stealers on their system.