Loading HuntDB...

Remote Command Execution vulnerability in pullit

Critical
N
Node.js third-party modules
Submitted None
Reported by lirantal

Vulnerability Details

Technical details and impact analysis

Command Injection - Generic
I would like to report Remote Command Execution vulnerability in pullit It allows remote command execution such as reading or writing to the file system, and executing other programs under the current user running the pullit node executable. ## Module pullit https://www.npmjs.com/package/pullit version: 1.3.0 ### Description Display and pull branches from GitHub pull requests ### Module Stats Stats 1 downloads in the last day 26 downloads in the last week 64 downloads in the last month ~768 estimated downloads per year ## Description The pullit npm package makes insecure use of shell execution API (i.e: `exec()` or `execSync()`) which is vulnerable to a malicious user input based on a remote branch name on the GitHub platform, that can be set by a 3rd party, hence luring an innocent user to use the pullit module on the target branch and result in remote command execution exploit. ## Steps To Reproduce: The pullit project has a set of exec() calls to git commands which may end up in originating from user input in terms of a carefully created remote branch name on GitHub, which pullit pulls branch names from. Re-construct of a flow that results in a remote command execution on the user running pullit:  1. Create a branch that could potentially terminate an exec() command and concatenate to it a new command: 1. `git checkout -b ";{echo,hello,world}>/tmp/c”` 2. Push it to GitHub and create a pull request with this branch name 3. Run pullit from command line, select the relevant pull request to checkout locally 4. Read the contents of `/tmp/c` ## Patch See below for patch to fix the problem: pullit-security-rce.patch: ``` diff --git a/src/index.js b/src/index.js index 3a34831..9bffd0d 100644 --- a/src/index.js +++ b/src/index.js @@ -1,7 +1,7 @@ const GitHubApi = require('github'); const Menu = require('terminal-menu'); const { - execSync + execFileSync } = require('child_process'); const parse = require('parse-github-repo-url'); @@ -12,7 +12,7 @@ class Pullit { } init() { - const url = execSync(`git config --get remote.origin.url`, { + const url = execFileSync('git', ['config', '--get', 'remote.origin.url'], { encoding: 'utf8' }).trim(); @@ -34,8 +34,11 @@ class Pullit { }) .then(res => { const branch = res.data.head.ref; - execSync( - `git fetch origin pull/${id}/head:${branch} && git checkout ${branch}` + execFileSync( + 'git', ['fetch', 'origin', `pull/${id}/head:${branch}`] + ); + execFileSync( + 'git', ['checkout', branch] ); }) .catch(err => { ``` ## Supporting Material/References: - MacOS Sierra 10.12.6 - Node.js 8.9.4 - npm 5.6.0 ## Wrap up > Select Y or N for the following statements: - [Y] I contacted the maintainer to let him know - [N] I opened an issue in the related repository ## Impact -

Report Details

Additional information and metadata

State

Closed

Substate

Resolved

Submitted

Weakness

Command Injection - Generic