PHP's escapeshellarg() isn't secure?

According to OWASP’s PHP Security Cheat Sheet, you shouldn’t use shell calls from PHP with any input provided by the user, without first validating that input against a whitelist of allowed values. I always thought that using escapeshellarg() on any user provided input would ensure that any command passed to the shell was secure. However, the OWASP document says:

Escaping and any other countermeasures are ineffective, there are plenty of vectors for bypassing each and every one of them; don’t believe what novice developers tell you.

I couldn’t find any evidence of vulnerabilities in escapeshellarg() other than a mention of something that was fixed back in PHP4.3.7 and supplying options to the command (which looks like it should be simple to mitigate - don’t pass the arg if the first character is a dash). I think that the OWASP advice is probably being overly cautious, imagining that some new vulnerability in escapeshellarg() will likely be found or introduced in the future.

If “there are plenty of vectors for bypassing” escapeshellarg(), can anyone provide some examples of these?

I dont know about any current issues with it, though I agree with the statement that you should never use shell calls with user provided input.

That is a major risk, mainly as it depend on the OS running, the OS version, PHP version etc. Something that is safe today, might be a vulnerability in the future.

If you have a specific thing the user should be able to do, I would create a specific function for that instead of giving them access to type their commands. Though keep in mind I have no idea what your trying to make, and I assume it is not a PHP Bash System :slight_smile:

There seems to be some truth to their statement:

There are several reports of recent PHP versions having vulnerabilities affecting escapeshellarg

Also keep in mind escaping is helpful for one attack vector but not others – what if you leave a hole where someone can actually just execute harmful commands without needing to compromise the string’s escapes?

We aren’t doing PHP at all these days but our model for things that need to execute commands on servers is to have a separate app that takes messages from a queue rather than even thinking about putting this in the web tier. This came up more because we have the backend processing stuff on separate boxes than out of a security audit but it really has made tons of sense from that angle as well.