Как я могу безопасно использовать eval в php? - PullRequest
3 голосов
/ 09 декабря 2010

Я знаю, что некоторые люди могут просто отвечать "никогда", если есть пользовательский ввод.Но предположим, что у меня есть что-то вроде этого:

$version = $_REQUEST['version'];
$test = 'return $version > 3;';
$success = eval($test);

Это, очевидно, упрощенный случай, но есть ли что-нибудь, что пользователь может ввести как version, чтобы заставить это сделать что-то вредоносное?Если я ограничу тип строк, которые $test может использовать для сравнения значений определенных переменных с другими переменными, есть ли способ, которым кто-нибудь может воспользоваться, чтобы использовать это?

Редактировать

Я попытался запустить следующий скрипт на сервере, и ничего не происходит:

<?php
  $version = "exec('mkdir test') + 4";
  $teststr = '$version > 3;';
  $result = eval('return ' . $teststr);
  var_dump($result);
?>

все, что я получаю, это bool(false).Новый каталог не создан.Если у меня есть строка, которая на самом деле вызывает exec('mkdir test') до этого, она действительно создает каталог.Кажется, что он работает правильно, поскольку он просто сравнивает строку, преобразованную в число, с другим числом и обнаруживает, что результат ложен.

Ответы [ 6 ]

3 голосов
/ 09 декабря 2010

Если вы это сделаете.Принимайте только целые числа.

Если вы должны принимать строки, не делайте этого.

Если вы все еще считаете, что должны это сделать.Не надо!

И наконец, если вы все еще после этого думаете, что вам нужны строки.НЕ ПРОСТО!

3 голосов
/ 09 декабря 2010

Оооо, мальчик!

$version = "exec('rm-rf/...') + 4"; // Return 4 so the return value is "true" 
                                    // after all, we're gentlemen!
$test = "return $version > 3"; 
eval($test);

:)

В этом случае вам нужно будет ввести хотя бы filter_var() или is_numeric() для входного значения.

Кстати, способ использования eval (присвоение результата $success) не работает в PHP. Вы должны будете поместить это назначение в строку eval () ed.

1 голос
/ 09 декабря 2010

да что угодно. Я бы использовал $version = (int)$_REQUEST['version']; для проверки данных.

0 голосов
/ 11 июня 2012

Используйте этот код для удаления всего, кроме чисел (0-9): preg_replace ('/ [^ 0-9] + /', '', $ version);

0 голосов
/ 09 декабря 2010

Вы должны быть более точными с вашими определениями «злонамеренный» или «безопасный».Рассмотрим, например,

exec("rm -rf /");

echo "enlarge your rolex!";

while(true) echo "*";

. Все три фрагмента являются «вредоносными» с точки зрения здравого смысла, однако технически они совершенно разные.Методы защиты, которые могут применяться к # 1, не будут работать с двумя другими и наоборот.

0 голосов
/ 09 декабря 2010

Способ сделать это безопасным состоял бы в том, чтобы убедиться, что $version - это число ДО того, как вы попытаетесь eval.

...