Discovered by: Dor Dali; Written by Dan Shallom, Cybersecurity experts at OP Innovate.
- Before using any open-source library, verify that it still being actively maintained
- Look for security issues using Github search
- The security ecosystem is not that eco – it lacks synchronization
- Case in point: we share details of a shell command injection vulnerability we found in the ‘Traceroute’ NPM package.
- We provide a POC & recommendations for mitigation
- https://www.npmjs.com/advisories/1465 ; https://snyk.io/vuln/npm:traceroute:20160311
The far-reaching hand of open-source code
People like open-source code. They use it in the form of packages, libraries, modules, and plugins, for all sorts of reasons. This code is publicly available, fully accessible, and is the polar opposite of proprietary software – EVERYBODY is the owner of the code. That’s fantastic, right?! Well not always…
Open-source is almost perfect at doing what it was intended to do: provide extreme efficiency by saving the developer community time and resources developing their product.
Thing is, it’s often implemented without security in mind which allows potential attackers to take advantage of the flaws. The scary part is that once a software repository is published, it is not subjected to any further security testing. Picture the ever-growing stream of downloads and you see how quickly vulnerable software can spread across continents and integrate into software, programs, and commercial products.
NPM (Node Package Manager) is one great way of managing open-source packages. It’s a big software repository that contains Node.js projects, one of them is Traceroute.
Here are some quick facts about the Traceroute package
- Traceroute is a simple NPM package used as a wrapper for the native traceroute command.
- The package has a download rate of approximately 700 downloads per week.
- The Traceroute.js file is really small – approx. 2500 characters long, 125 lines of code.
- The last version was released on Feb. 2016; the last GitHub commit was on Mar. 2016
Let’s get technical for a bit
We will now embark on a deep inspection of the vulnerable lines of code in order to explain the source, vector, and possible impact of the script.
Since the code is fairly short and simple, we can spot the issue right away. Let’s look at the main part of the code which takes the “host” parameter and issues the traceroute command towards that host.
As you can see the flow is:
- Check what OS is running the server (Windows or UNIX-based)
- Take the “host” param
- Based on the result of the OS check in step 1, use node.JS built-in exec command and run the OS native traceroute command as follows –
- if the running system is UNIX-based, the command will be:
command = 'traceroute -q 1 -n ' + host
- if the system is Windows-based, the command value will change to:
command = 'tracert -d ' + host
- if the running system is UNIX-based, the command will be:
In either case, the command value will be concatenated with the string value of the host
Variable which is likely to be based on user-input, representing a remote host.
The designated value is supposed to be an IP address or a hostname, but unfortunately, it can contain anything, especially malicious shell commands. The reason it can contain all sorts of commands is that the variable doesn’t get filtered or parsed before being executed. There is no instruction that is set to enforce a masked value of hostname or IP address.
Exec vs Spawn
The main caveat here is the use of child_process.exec instead of child_process.spawn. These functions might sound similar but one is way more secure than the other.
By looking at the documentation (https://nodejs.org/api/child_process.html) of the 2 functions we can see that exec doesn’t have an “args” argument whereas spawn has this argument. This means that if you want to pass an argument to a command run by an exec function you do it as part of the command whereas in the spawn function it has a designated place. The fix is easy – just switch the exec to spawn and move the host argument to the argument section.
The way spawn handles arguments is similar to SQL prepared statements, which essentially make sure that you’re unable to inject any more commands using supplied arguments.
So now that we understand the issue and how to fix it, we can create a quick POC for this issue
By altering the ‘host’ variable and supplying IP/hostname with a newline (value of %0a) followed by a malicious command. The server will run both the traceroute and the malicious command which, in this POC, will create a file called malicious in the /tmp directory.
Enough with the tech, let’s get to the juicy stuff
Why is the open-source security ecosystem flawed?
This security flaw was reported to Snyk 3 years ago by Dor Dali, at the time a researcher at OP Innovate. You’d think a reported flaw would cause users to abandon the use of the package. But sadly this is not how the story goes. Most users are not using Snyk to scan their libraries and rely on the NPM audit. NPM was not aware of the issue until Dor reported it to them directly.
This is a serious flaw in the world of vulnerability reporting. These two major players, who publish security advisories on open-source packages (along with other features), aren’t always synced regarding registered vulnerabilities. This lack of synchronization, along with the fact that researchers usually only report to one of them, is a genuine issue that affects all of us and shouldn’t be taken lightly.
Avoiding these cases in the future
In order to avoid this in the future, we recommend you ask yourselves the following questions –
- Is this package being actively maintained?
By looking at the GitHub page of the traceroute package you can see that the last commit was over 4 years ago, in March 2016. Moreover, if you try to look for the vulnerable lines of code we describe above, you see that they are not available in the “master” branch. That’s because the developer of this package has fixed the security issue, but didn’t release a new version and didn’t publish it to NPM repo.
So we can deduce that this package is no longer maintained and therefore is at higher risk of containing vulnerabilities.
- Does this package have known-vulnerabilities?
This one might sound obvious since no one wants to use a vulnerable application, but this one is also a bit tricky. As the number of security applications that promise to notify you about security vulnerabilities in your open-source applications grows, so does the lack of sync between them. Moreover, some of the security issues are handled directly in GitHub without alerting any of these apps.
A good approach would be to search the Github issues of the application for the term “security” and look for open/closed issues. It is also recommended to search the big two major indexes – Snyk and NPM – separately, for open-source security vulnerabilities.
Wrapping up: It’s important to remember that open-source code is built and designed to do a job, often without security best practice in mind. We recommend adopting a habit of manually testing any open-source code that is integrated into your solutions, for vulnerabilities it could sneak into your solution. Manually reviewing the code is always the best solution.
Contact us and learn more about how to secure your code!
OP Innovate was established in 2014 to defend global enterprises from the increasing challenges of reducing organizational cybersecurity risk. Our team has unmatched expertise in cyber research, penetration testing & vulnerability assessment, incident response, training, and forensics. Our team members are exposed to cutting-edge responses to today’s most critical cybersecurity concerns allowing us and our partners to remain ahead of the bad guys.