This article is based on my talk, which I read at ZeroNights 2018, but for various reasons (including Nvidia's requests to wait until the next patch), the article's release was delayed. I could have forgotten about this topic altogether if antivirus companies hadn't found malware that uses techniques similar to the one I described in my report.
If you want to quickly run through my findings, take a look presentation slides, and in the article I will consider the problem in more detail. Why did it happen that the creators of the malware were more interested in my discovery than the developers of the software?
The phrase NPM Package Hijacking may have already occurred to you in researchwhich was published by Nathan Johnson in 2016. However, I will talk about a different technique, and the coincidence here is mainly in the name.
This story began when I was still conducting monthly exploit reviews in Hacker. To use all the delights of the Markdown format, I wrote articles in one then fashionable editor and accidentally discovered an XSS vulnerability in the article preview module. I just forgot to add the quotes to frame the code of the next exploit, and soon I got to the bottom of RCE!
I sent the developers information about the vulnerability several times, but apparently they never got their hands on this bug. Once again, I remembered this problem when I came across article the person who found the same vulnerability in the Atom editor.
This inspired me to keep researching and looking for similar programs. After all, Node.js in general and the Electron engine in particular are gaining more and more popularity and are used in many common applications. Here you can find Adobe products, and various game updaters, code and text editors, messengers (including "protected" ones) and other software. Node.js is often used to create installers and updaters – that's how Adobe made my list. Or you can think of Nvidia GeForce Experience, a utility that monitors other Nvidia software for updates. It is also written in the now fashionable Node.js.
Electron applications include a Chromium-based browser, which is usually accessed by a local web server, which is also included in the program and runs with it. So it turns out that a bunch of server software is suddenly spinning on your work computer. But this software does not have sysadmins, and vulnerabilities or weaknesses in protection can still be a problem. We will talk about the exploitation of one of these weaknesses.
NPM Hijacking (Planting)
Hacker has already written about DLL Hijacking, aka DLL / Binary Planting or Preloading. This technique works like this. If the developer has not explicitly specified the path for loading DLLs in his executable file, then the operating system will search for these libraries in the paths listed in the variable
PATH (including Windows, for more details see official documentation). By placing a malicious library clone in one of these folders, an attacker can execute arbitrary code.
When loading modules, Node.js looks for a folder
node_modules all the paths above the parent directory of the called script, checking them until it finds the module you want. It turns out something like
../, where there can be any number of pointers to the parent folder. This is shown more clearly in the picture below.
I think you have already guessed why I dubbed this attack NPM Hijacking by analogy with DLL Hijacking. On the machines I studied, I noticed numerous attempts to load scripts from the directories listed in the variable
PATH, or the home directory of the current user. This folder is already accessible without any elevated rights, which is what malware can use. Actually, such tricks are already being practiced with might and main in attacks on web servers with "Noda", but there the protection is generally at a higher level than on the desktop, so this problem is less dangerous.
Let's now see how this feature is exploited in different applications, inside which servers with Node.js. We'll look at three examples:
The Discord chat is famous for its ability to communicate by voice, and it is made on Electron. It is not surprising that it is vulnerable to NPM Hijacking – I discovered the problem at the time of version 0.0.300, and notified the developers about it. When Discord starts, it looks for the following scripts, going up the directories:
The search and loading of the script itself from the point of view of the OS looks like a sequential search of the following folders:
Users User AppData Roaming discord 0. 0. 300 modules discord_desktop_core node_modules
Users User AppData Roaming discord 0. 0. 300 modules node_modules
Users User AppData Roaming discord 0. 0. 300 node_modules
Users User AppData Roaming discord node_modules
Users User AppData Roaming node_modules
Users User AppData node_modules
Users User node_modules
Users User AppData Roaming discord 0. 0. 300 modules discord_voice. js
By default, from the first to the ninth points, the operating system will not find anything if you do not have such folders, and only then (at point 10) Node.js will start searching for a script that is not in
node_modules, but separately, as done in Discord. If the user's folder is available for writing, then we can put our library so that it is loaded, for example, at point 7.