Calling Programs from Node.js for Fun... and Risk
Node.js consists of a small and stable core runtime and a set of built-in modules providing basic building blocks. The built-in modules are robust, well tested, and performant.
Unfortunately, they do not cover all the needs of Web application developers. Sometimes we need to use programs outside of Node.js to implement the functionality we are working on.
If we are not careful and call programs in a way that adversaries can control, the effects of a successful attack may range from disclosing sensitive information, through denial of service, all the way up to complete server takeover.
One of the built-in Node.js modules is
If the command to be executed is composed from input data controlled by the attacker may lead to changes to the structure of the executed command.
This type of security vulnerability is called command injection. We can use this technique to exfiltrate the content of any file on the server that the application has access to, including configuration files. Attackers can also read the values of environment variables.
Technically sophisticated attackers seek to gain control not only over the application but over the entire server. This allows them to gain persistent access to the compromised machine.
How to Fix It?
exec function from the
child_process module that we used passes the commands it received in the first parameter directly to the shell to execute. This is very flexible but leads to vulnerabilities. A better option is to use the
execFile function from the same module.
For cases where we need the flexibility afforded by the
exec function, we need to resort to strict input validation and output sanitisation.
Where to Learn More
Learn more about how such attacks can occur and how to prevent them from my article "Preventing Command Injection Attacks in Node.js Apps" on the Auth0 blog.