【问题标题】:How to escape php exec() command with quotes如何用引号转义 php exec() 命令
【发布时间】:2010-11-18 08:38:54
【问题描述】:

我在 Linux 上使用 Exiv2 命令行工具来编辑图像元数据,如下所示:

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

我想使用用户提供的标题从 PHP 执行此操作。如果用户没有输入特殊字符,这将起作用:

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

我需要允许用户使用特殊字符,例如单引号和双引号。我想使用 escapeshellcmd() 来防止恶意数据。如何正确转义命令和参数以使其正常工作?我尝试了很多选择,但我无法正确选择。

【问题讨论】:

    标签: php escaping exec exiv2


    【解决方案1】:

    是的,这是一个难题,因为该命令使用了非标准的 shell 参数(就像它自己的小元语言一样)。 ImageMagick 也有同样的问题。

    如果你只是在双引号字符串中使用 escapeshellarg(),它就会变得毫无用处。 escapeshellcmd() 确实转义了所有特殊字符,并且在双引号字符串中使用是安全的。因此,您需要在其周围硬编码单引号以使其正常工作。

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

    escapeshellarg() 在单引号字符串中不起作用的原因是:

    # 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...
    

    【讨论】:

    • 谢谢,这对理解问题很有帮助。看起来 exiv2 通过允许将 exiv2 命令(设计为写入文件中)也作为快捷方式写入 shell 参数而获得了非标准的 shell 参数。
    • 哦,我试过了,它没有保留用户输入的双引号。不过,单引号的荣誉在我的输入中更为常见!
    【解决方案2】:

    使用heredoc怎么样?

    $str = <<<'EOD'
    /usr/local/bin/exiv2 -M "set Iptc.Application2.Caption String $options" modify IMG.jpg
    EOD;
    exec($str);
    

    修改它以使用 excapeshellcmd():

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

    【讨论】:

      【解决方案3】:

      由于 Exiv2 的非标准 shell 参数,要找到一个简单而强大的解决方案来正确处理用户提供的引号并不容易。还有另一种解决方案可能更加可靠且易于维护,并且性能损失很小。

      将 Exiv2 指令写入文件cmds.txt,然后调用:

      exiv2 -m cmds.txt IMG.jpg
      

      从文件中读取指令。

      更新:我已经实现了这个方法,它不需要转义用户提供的数据。此数据直接写入 Exiv2 读取的文本文件。 Exiv2 命令文件格式非常简单且以换行符结尾,不允许在值内转义,所以我需要做的就是防止换行符通过,无论如何我都不允许这样做。

      【讨论】:

        猜你喜欢
        • 2011-01-25
        • 2021-07-11
        • 1970-01-01
        • 2012-05-03
        • 1970-01-01
        • 2013-07-13
        • 2014-08-21
        • 2021-07-22
        • 1970-01-01
        相关资源
        最近更新 更多