Hacking Node.js with buffer overflows

Hacking Node.js with buffer overflows

hacking nodejs space


Nodejs is a relatively new candidate
in the programming world.
It allows JavaScript(which is normally only executed and used in web browsers) to be executed outside the browser.
A popular example of an application that is currently using Nodejs is the programming framework Electron which is used
by WhatsApp, Twitch, Microsoft Teams, Slack, Discord and several other applications, even NASA is using nodejs to export data from the Extravehicular activity aka eva spacesuits.
A security researcher by the name of Tobias Nie├čen discovered a Buffer overflow vulnerability in several of Nodejs built-in functions.


On Jan 27th 2020, Tobias noticed that Nodejs napi_get_value_string_latin1,
napi_get_value_string_utf8, napi_get_value_string_utf16 functions was not
properly handling the input data resulting in memory corruption.
He quickly reported it using Nodejs public bug bounty program and was rewarded
with 250 USD by the Internet Bug Bounty for his discoveries.
The internet bug bounty is an organization that hands out various bounties to security
researcher when a security vulnerability is found in a piece of software code that is
used by a larger amount of people, in order to make the internet a more secure place.
A day later the discovered vulnerabilities were reported and
gained the Common Vulnerability and Exposure id of CVE-2020-8174.

The dangers of exploitation

Buffer overflows are very common software vulnerabilities that
in many cases lead to security holes in a program
that a third party could use to corrupt memory and
manipulate the program to execute malicious code.

Tobias describes the vulnerability as:

1,  If the output pointer is NULL, return.

2,  Write min(string_length, bufsize - 1) bytes to the output buffer.   
Note that bufsize is an unsigned type, so this leads to an integer underflow for bufsize == 0.     
Since this is a size_t, the underflow will cause the entire string     
to be written to memory, no matter how long the string is.  

3,  Finally, write to buf[copied], where copied is the number    
of bytes previously written.   
Even if step 2 hadn't written out of bounds, this would (for bufsize == 0).   

Security advisory

The OpenJS foundation which is the responsible legal entity behind
Nodejs published a security advisory in June 2020
acknowledging Tobias’s findings as a high severity
vulnerability, “napi_get_value_string_() allows various kinds of memory corruption (High) (CVE-2020-8174)”.
Advising everyone to upgrade their nodejs instances, because
versions 10.x, 12.x, and 14.x of Nodejs contains the vulnerable functions.
No one has yet published a piece of code to exploit this vulnerability as of writing this.
A proof of concept exploit is likely going to be developed and perhaps come out publicly or remain private.
Since Nodejs is being used by a large chunk of software the demand for dangerous software exploits.

A Crash proof of consept is provided by the author:

Napi::Value Test(const Napi::CallbackInfo& info) {
  char buf[1];
  // This should be a valid call, e.g., due to a malloc(0).
  napi_get_value_string_latin1(info.Env(), info[0], buf, 0, nullptr);
  return info.Env().Undefined();

const binding = require('bindings')('validation');
console.log(binding.test('this could be code that might later be executed'));

What can you do?

Update all your nodejs instances to run the latest version which you can find at https://nodejs.org/en/.