I am writing a PHP script designed to run an executable file (ffmpeg.exe) via the exec() function. The problem is that I have read that using the exec() function can be a security risk and should be avoided if possible. I have been doing some research into how to run the exec() function securely, and the only thing that I keep coming across is to filter the command string with escapeshellcmd or escapeshellarg. What I want to know is if it is possible to further increase security when using the exec() function or if there is a secure alternative to exec(). Any help would be appreciated.
Here is my code;
define('FFMPEG_LIBRARY', 'c:\\ffmpeg7\\ffmpeg\\bin\\ffmpeg ');
$transcode_string = FFMPEG_LIBRARY." -i " . $srcFile . " -acodec libmp3lame -ab 64k -ar 22050 -ac 1 -vcodec libx264 -b:v 250k -r 30 -f flv -y " . $destFile;
$transcode_string = escapeshellcmd($transcode_string);
exec($transcode_string);
$srcFile is basically the video for transcoding while $destFile is the output file I wish to create.
That’s a bit of a generalization – it is perfectly possible to build a secure solution using
exec(). But it’s indeed hard: there are many pitfalls in executing external programs, especially if you are passing outside parameters to them.The first step, as you say, is to escape everything using
escapeshellarg()to prevent the injection of other, possibly harmful commands.Then the question is what damage entering wrong values could cause in the program that is being called. For example,
running a ffmpeg operation on a 200000 x 200000 pixels large video may well cause a server hangup because the call tries to allocate an impossible amount of memory. So you have to sanitize the size values the user can enter, and exit if they are too large, or not numbers.
a malicious user could tell ffmpeg to use a configuration file and try to create a video from that, possibly resulting in the configuration file to be used as output, so you need to limit the range of file paths users can specify.
And so on and so on.
Also, you need to think about the possibility of killing the server through the mere number of requests. What if I send 50 requests a second to a PHP script that in turn calls a complex ffmpeg command? The server may easily break under the burden, and you may want to protect against that.
So: there is no inherent security problem in using
exec(), but every incoming parameter that gets passed to it needs to be looked at very carefully.