Poison Packages in Python

Speeling is hard, yeah?

Python quiz: What’s the difference between these two packages?

  • urllib3
  • urlib3

Answer: urllib3, with two l’s is the one you meant to use. urlib3 with one l is a poison package that replicates the functionality you were looking for, but with a malicious install script.

As it happens, this install script sends only a modest amount of information to the attacker: Your username, your hostname, the package version. But it could have been worse. You can read the full report for yourself. The good news is that these packages have been removed from PyPi. But more will appear, certainly.

Back in August, a similar poison package was found in the Node ecosystem, one that exfiltrated environment variables, in a bid to discover service passwords and tokens. Ouch.

What can I do today?

Check that you don’t rely on any poison packages. In this one case, you can run this command to check if your Python app has malicious dependencies:

pip list --format=legacy | egrep '^(acqusition|apidev-coop|bzip|crypt|django-server|pwd|setup-tools|telnet|urlib3|urllib)$ '

(Yes, that space at the end is very important 😉 )

If you find that you have one of these poison packages installed, you can use pip to uninstall them. But in general you should manually delete it from your Python installation to preclude the chance of trigger more malicious code in the uninstall script.

Thankfully, forensic analysis hasn’t turned up anything genuinely nasty in these packages, but clearly this is just the first shot in a coming war.

What can you do in the future?

First, double-check package names. Yeah, it’s a pain, but because many existing poison packages rely on you making common speeling mistakes, extra vigilance is required.

Second, install a security tool that will alert you to the presence of poison packages. Sqreen—we’re biased of course—can detect not only malicious packages but legitimate packages that have known vulnerabilities, to help you keep your code safe.

Third, if you discover that you’ve used a poison package in one of your projects, well, it’s time to rotate your credentials. You should assume that the poison package had full access to anything you app had access to:

  • You’ll need to identify the credentials accessed by your app, be it in environment variables or configuration files (you’re not hard-coding them, are you?), and change them out for fresh ones.
  • You’ll also need to consider the possibilities that the attacked has exfiltrated your database. A forensic analysis of poison packages will tell you what could have been exfiltrated, but you should strongly consider using strong hashes with salts for storing passwords, just in case. Other kinds of data are much harder to keep out of others’ hands in case of a database leak, so it is better to have strong preventative measures in place.
  • Attackers could also gain shell access through their poison packages, so you’ll need to consider the possibility that the host itself has been compromised. Always make sure that your web application is running in a host that is isolated from your admin panel or other elevated-privilege processes or tools. Keep backups of anything that an attacker could delete, and store them on isolated systems that the web application has no access to.