It’s very easy, and it’s the ultimate simple one.
You only need to create fake pip and npm software packages to easily break the servers of dozens of technology companies such as Microsoft, Apple, Tesla, PayPal, Yelp, etc.
That’s right, these are the installation commands that we are all familiar with.
This is a huge vulnerability recently discovered by a hacker named Alex Birsan: As long as uploading a “Lee Ghost” with the same name as the internal software package of a technology company, they can be infected with malware unknowingly.
The wide coverage and the simple attack methods are staggering.
As a result, Birsan discovered vulnerabilities in more than 30 technology companies, and two companies have rewarded him with a bug bounty of $30,000.
What’s the matter
It started in the summer of 2020.
Another hacker shared an interesting Node.js source code on GitHub. This code was originally for PayPal internal use only.
Birsan found that the package.json file lists various dependencies required to install the software:
There are public packages from npm and private packages (red) within PayPal. The latter is hosted internally by PayPal. These packages are not searchable in the public npm registry.
Birsan therefore had a lot of questions:
What happens if someone fakes the name of a PayPal private software package and uploads malicious code to npm?
Is it possible for PayPal’s internal projects to use fake software packages instead of the original private software packages?
Will the system run malicious code because of the installation of fake software packages?
If this attack method works, can you get bug bounties from technology companies?
Will this attack still work against other companies?
With these thoughts in mind, Birsan uploaded the “malicious” Node package with the same name to the npm registry, so that PayPal programmers would be deceived and replaced by fake software if they installed their proprietary software package.
Of course, Birsan’s “malware” does not contain destructive components. It has only one function. When the other party uses npm to install the “Li Gui” with the same name as the original software, it will send a message to notify Birsan.
“Malware” will return user name, host name, installation path and other information. On the one hand, it can help the company’s security team determine the system that may be attacked based on this information, and it can also prevent Birsan’s test from being mistaken for an actual attack.
However, it is not easy for the server that installs the fake software to send a message to itself. Because the company’s internal computers are protected by a firewall, DNS penetration is the solution.
Birsan sends the information to his server through the DNS protocol. Birsan data is hexadecimal encoded, disguising the data as part of the DNS query, and the DNS query reaches his custom server directly or through an intermediate resolver.
Through this method of attack, he recorded the records of each computer downloading software packages.
Find the target
With the basic plan of the attack, Birsan decided to find more possible targets.
The first is to expand the software ecosystem of the attack. In addition to Node.js, he also ported the code to Python and Ruby, so that companies using PyPI and RubyGems would also be affected.
The next step is to find the names of private software packages of major companies.
After searching for several days, Birsan found that it can be found on GitHub and major package hosting services, as well as through posts on various Internet forums.
This is similar to finding dependencies in package.json earlier. Similarly, internal paths or calls leaked in these files of require() may also contain the names of dependencies.
Apple, Yelp and Tesla can all be found this way. Below are the dependencies found on the Yelp website.
Next, it began to “attack”.
What was the result of the attack?
“The success rate is simply amazing.”
After Brisan attacked according to the above method, he couldn’t help expressing such emotion.
He called such bugs dependency confusion and said that they have been found in more than 35 organizations in all three test programming languages:
One thing is very clear: illegally occupying a valid internal package name has almost become a foolproof method of attack.
Most of the companies affected by this have more than 1,000 employees, which probably reflects the high utilization rate of large-scale internal libraries.
In fact, although only 8 organizations’ internal Ruby gem names can be identified in my search, 4 of them are prone to “dependency confusion” because of RubyGems.
Brisan also gave an example.
The Canadian e-commerce giant Shopify was caught, and in order to fix this bug, they set up a $30,000 bounty.
Coincidentally, in August last year, he produced a Node package to npm. The code of this package was executed on multiple computers inside Apple.
Apple also set up a reward of $30,000 for this purpose, but when the hacker reported to Apple that “this vulnerability may allow threat actors to inject a “backdoor” into Apple ID”, Apple did not think so:
A more complex sequence of events is required to implement “backdoors” in operational services.
But at the same time, Apple has indeed confirmed that by using npm package technology, remote code execution on Apple servers can be achieved.
Finally, Birsan advises everyone not to try randomly, because the 35 companies he studied all have public bug bounty programs or allow security testing through private agreements.
If you are not authorized by the company, please do not try this test!
Why are large companies frequently recruited?
Seeing this, you may also have questions:
Why does this happen?
Why are large companies so vulnerable when faced with such an attack?
Brisan said that large companies are reluctant to disclose the details of their “repair” process, but in the process of communicating with the security team, he discovered some interesting things.
For example, the culprit of Python “dependency confusion” seems to be the wrong use of a “design by insecure” command line parameter called extra-index-url.
When you use this parameter together with pip install library to specify your own package index, although the effect is almost as expected, what pip actually does behind the scenes is this:
Check if the library exists on the specified (internal) package index.
Check if the library exists in the Public Package Index (PyPI).
Install based on the version found. If both versions of the software package exist, the source code with the higher version number will be installed by default.
Therefore, uploading a package named library 9000.0.0 to PyPI will cause the dependency in the above example to be “hijacked”.
Although this kind of thing is widely known, if you search for “extra-index-url” on GitHub, you can find some vulnerable scripts belonging to large organizations-including a bug that affects Microsoft’s .NET Core components.
This vulnerability may allow the addition of “backdoors” to .NET Core, but unfortunately, Microsoft did not include this vulnerability in the scope of the “.NET bug bounty program.”
There will be new attack methods
In this regard, Brisan believes that although many large companies are now aware of the existence of this bug and have also fixed it in their infrastructure, there are still more things that need to be discovered.
Specifically, he believes that if there is a smarter new method to leak internal package names, it will expose more systems that are more vulnerable to attack.
If you are looking for alternative programming languages and repositories as targets, you will find some additional attack surfaces for “dependency confusion” bugs.
From this point of view, large companies need to work harder on this seemingly basic vulnerability.