How to escape php exec() command with quotes

13,199

Yes, this is a hard problem, because the command is using non-standard shell arguments (like it's own little meta-language). ImageMagick has the same issues.

If you simply use escapeshellarg() within a double-quoted string, it is rendered useless. escapeshellcmd() does escape all special characters, and is safe for use in a double-quoted string. So you need to hard code single quotes around it to make it work right.

exec('/usr/local/bin/exiv2 -M"set Iptc.Application2.Caption String \'' . escapeshellcmd($caption) . '\'" modify IMG.jpg');

The reason escapeshellarg() will not work in a single quoted string is:

# for this input:
The smith's "; rm -rf *; echo "went to town

# after escapeshellarg()
'The smith\'s "; rm -rf *; echo "went to town'

# Works fine if left as a top-level argument
/usr/bin/command 'The smith\'s "; rm -rf *; echo "went to town'

# BUT if put in a double-quoted string:
/usr/bin/command "subcommand1 'The smith\'s "; rm -rf *; echo "went to town'"

# it is broken into 3 shell commands:
/usr/bin/command "something and 'The smith\'s ";
rm -rf *;
echo "went to town'"

# bad day...
Share:
13,199
Liam
Author by

Liam

With over 15 years experience as a Web Developer, I have gained in-depth knowledge of a wide range of web technologies. I have been responsible for the architecture of several key pieces of software for a diverse portfolio of clients, in the Photography, Education, Tourism, and Retail industries. I mostly work with PHP and JavaScript.

Updated on June 05, 2022

Comments

  • Liam
    Liam almost 2 years

    I use the Exiv2 command line tool on Linux to edit image metadata like so:

    exiv2 -M"set Iptc.Application2.Caption String This is my caption....." modify IMG.jpg
    

    I want to execute this from PHP, using a caption provide by a user. This will work if the user enters no special characters:

    exec('/usr/local/bin/exiv2 -M"set Iptc.Application2.Caption String '.$caption.'" modify IMG.jpg');
    

    I need to allow the user special characters such as single and double quotes. I would like to use escapeshellcmd() to prevent malicious data. How can I correctly escape the command and the argument so that it works? I have tried many options but I can't get it right.