Reputation: 305
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.
Upvotes: 4
Views: 474
Reputation: 22019
exec itself is not the problem, the problem is that you should most definitely not be accepting user input when it comes to putting it into exec(). You should always be using escapeshellarg() but if you do need to accept user input, you should be doing your own sanitisation and manipulation first, in all cases.
What exactly is your code? Without seeing that there is no more to say on this matter.
If $srcFile is the name of an uploaded file, then you should change it.. @preinheimer's comment contains a good idea, you could call uniqid(); and rename $srcFile to that, then you know you have an alphanumeric filename regardless of what they uploaded. Change $srcFile to that new uniqid()'d filename and you're good to go.
With regards to $dstFile, set that to something else unique, you can either call uniqid(); once again, or use the current time.
If you do both of those things, then you're not accepting user input at all and your script will be perfectly safe and secure.
Upvotes: 3
Reputation: 449733
using the exec() function can be a security risk and should be avoided if possible.
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.
Upvotes: 3