Как выйти из команды php exec () с кавычками - PullRequest
3 голосов
/ 10 августа 2009

Я использую инструмент командной строки Exiv2 в Linux для редактирования метаданных изображения следующим образом:

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 () для предотвращения вредоносных данных. Как я могу правильно избежать команды и аргумента, чтобы он работал? Я перепробовал много вариантов, но не могу понять это правильно.

Ответы [ 3 ]

5 голосов
/ 10 августа 2009

Да, это сложная проблема, потому что команда использует нестандартные аргументы оболочки (например, собственный мета-язык). 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...
0 голосов
/ 11 августа 2009

Из-за нестандартных аргументов оболочки Exiv2 нелегко найти простое и надежное решение для правильной обработки предоставленных пользователем кавычек. Существует другое решение, которое, вероятно, будет гораздо более надежным и простым в обслуживании с небольшим снижением производительности.

Запишите инструкции Exiv2 в файл cmds.txt, затем вызовите:

exiv2 -m cmds.txt IMG.jpg

чтобы прочитать инструкцию из файла.

Обновление: я реализовал этот метод, и он не требует экранирования предоставленных пользователем данных. Эти данные записываются непосредственно в текстовый файл, который читается в Exiv2. Формат командного файла Exiv2 очень прост и завершен символом новой строки, не допускает экранирования внутри значений, поэтому все, что мне нужно сделать, - это предотвратить прохождение новых строк, чего я все равно не разрешал.

0 голосов
/ 10 августа 2009

Как насчет использования 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);
...