Внедрение PHP из данных HTTP GET, используемых в качестве значения ключа массива PHP

я хотел бы знать, есть ли возможная инъекция кода (или любая другая угроза безопасности, такая как чтение блоков памяти, которые вы не должны были делать и т. д.) в следующем сценарии, где несанированные данные из HTTP GET используется в коде PHP как КЛЮЧ массива.

Это должно было преобразовать буквы в их порядок в алфавите. a до 1, b до 2, c до 3.... Переменная HTTP GET "letter" должна иметь значения букв, но, как вы понимаете, на сервер можно отправить что угодно:

HTML:

http://www.example.com/index.php?letter=[anything in here, as dirty it can gets]

PHP:

$dirty_data = $_GET['letter'];

echo "Your letter's order in alphabet is:".Letter2Number($dirty_data);

function Letter2Number($my_array_key)
{
    $alphabet = array("a" => "1", "b" => "2", "c" => "3");

    // And now we will eventually use HTTP GET unsanitized data
    // as a KEY for a PHP array... Yikes!

    return $alphabet[$my_array_key]; 

}

Вопросы:

  1. Видите ли вы какие-либо угрозы безопасности?
  2. Как я могу дезинфицировать данные HTTP, чтобы иметь возможность использовать их в коде как KEY массива?
  3. Насколько плоха эта практика?

person easy_weezy    schedule 07.09.2011    source источник


Ответы (3)


Я не вижу никаких проблем с этой практикой. Все, что вы... эээ... получаете от $_GET, является строкой. Он не будет представлять никакой угрозы безопасности, если вы не вызовете для него eval(). Любая строка может использоваться в качестве ключа массива PHP, и это не будет иметь никаких побочных эффектов (хотя, если вы используете очень длинную строку, очевидно, это повлияет на использование памяти).

Это не похоже на SQL, где вы создаете код, который будет редактироваться позднее — ваш PHP-код уже создан и выполняетсявыполняется, и единственный способ, которым вы можете изменить способ, которым он выполняется во время выполнения, - это вызов eval() или include()/require().

ИЗМЕНИТЬ

Если подумать, помимо eval() и include() существует еще несколько способов, которыми этот ввод может повлиять на работу скрипта, а именно использовать предоставленную строку для динамического вызова функции/метода. , создать экземпляр объекта или в переменных переменных/свойствах. Так, например:

$userdata = $_GET['userdata'];

$userdata();
// ...or...
$obj->$userdata();
// ...or...
$obj = new $userdata();
// ...or...
$someval = ${'a_var_called_'.$userdata};
// ...or...
$someval = $obj->$userdata;

... было бы очень плохой идеей, если бы вы сначала сделали это с санитарной обработкой $userdata.

Тем не менее, для того, что вы делаете, вам не нужно беспокоиться об этом.

person DaveRandom    schedule 07.09.2011
comment
К сожалению, PHP не гарантирует, что что-либо из $_GET является строкой, это также может быть массив. См. owasp.org/index.php/PHP_Security_Cheat_Sheet#Input_handling. Это усложняет любой ответ, связанный с пользовательским вводом, особенно потому, что PHP часто молча пропускает ошибки типов, часто с неожиданными результатами. - person spookylukey; 29.03.2016

Любой внешний файл, полученный от GET, POST, FILE и т. д., следует рассматривать как грязный и соответствующим образом очищать. Как и когда вы очищаете, зависит от того, когда данные будут использоваться. Если вы собираетесь хранить его в БД, его необходимо экранировать (чтобы избежать SQL-инъекций. см., например, PDO). Экранирование также необходимо при выполнении команды ОС на основе пользовательских данных, таких как eval, или при попытке чтения файла (например, при чтении ../../../etc/passwd). Если он будет отображаться обратно пользователю, его необходимо закодировать (чтобы избежать внедрения html. см., например, htmlspecialchars).

Вам не нужно дезинфицировать данные так, как вы их используете выше. На самом деле, вы должны только экранировать для хранения и кодировать для отображения, но в остальном оставлять данные необработанными. Конечно, вы можете захотеть выполнить собственную проверку данных. Например, вы можете захотеть, чтобы dirty_data было в списке [a, b, c], а если нет, выводить его обратно пользователю. Тогда вам придется кодировать его.

Любая известная ОС не столкнется с проблемой, даже если пользователю удастся прочитать неверный адрес памяти.

person Explosion Pills    schedule 07.09.2011

  1. Предположительно, содержимое этого массива должно быть общедоступным таким образом, так что нет.
  2. Прогоните через array_key_exists()
  3. Наверное, по крайней мере, немного плохо. Может быть, есть что-то, что можно сделать с неправильно сформированной многобайтовой строкой, или что-то, что может вызвать какое-то переполнение на плохо сконфигурированном сервере... но это чистое (невежественное) предположение с моей стороны.
person josh.fremer    schedule 07.09.2011