«Знание — могущество».

11 мая 2009

Null Byte уязвимость в PHP и защита от неё

написал Figaroo в рубрике Web-разработка @ 15:49

Здравствуйте, дорогие читатели. :-)
Расскажу об одной уязвимости в PHP, которая называется «Null Byte» («нулл-байт» — нулевой байт).

Суть уязвимости заключается в следующем. Большинство PHP-функций обрабатывают строки символов как набор двоичных данных (в PHP, в отличие от C, строки знают всё о своей длине. Но пока не знают ничего о кодировке — но это другая история.). Но есть несколько функций, как и в самом PHP, так и вне его, которые обрабатывают строки в C-стиле, то есть, считают байт 0x00 (Null-байт) концом строки.

Пример 1. Допустим, у нас есть в системе 3 файла: index.php (контроллер), page.tpl (шаблон) и config.php (конфигурационный файл).
index.php:

<?php

// получаем файл страницы
$mode = (string)@$_GET['mode'];

// убираем слэши, чтобы было невозможно выйти из текущей директории
$mode = str_replace('/', '', $mode);

// приписываем расширение, чтобы другие файлы не подключались
$mode .= '.tpl';

// если файл страницы существует
if (file_exists($mode)) {
	// выводим его пользователю
	echo htmlspecialchars(file_get_contents($mode));
}
// если нет
else {
	// сообщаем об ошибке
	echo "Error!";
}

?>

Если мы наберём в браузере путь_к_сайту/index.php?mode=page, то в браузер будет выведено содержимое файла page.tpl — что и требуется. Допустим, хакер захочет прочитать файл config.php, в котором хранятся важные настройки системы. Казалось бы, из-за того, что к странице приписывается расширение ".tpl", это сделать невозможно. А на самом деле — возможно, для этого нужно набрать в браузере путь_к_сайту/index.php?mode=config.php%00. Таким образом, в строке окажется нулевой байт 0x00, который сработает для файловой системы как конец строки!

Поэтому, нужно всегда фильтровать нулевой байт, если строка будет обрабатываться в C-стиле. Например, так:

// фильтруем нулевой байт
$mode = preg_replace('/\0/s', '', $mode);

Если строка передаётся в функцию для работы с файловой системой и пр. (вне PHP) — всегда фильтруйте нулевой байт!

Также следует помнить, что некоторые функции в самом PHP работают в C-стиле. Например, «ereg»-функции (ereg, eregi, ereg_ replace, eregi_ replace, split, spliti, sql_regcase, mb_ereg* и другие).

Пример 2.
index.php:

<?php

// получаем кусок текста
$text = (string)@$_GET['text'];

// если в нём нет запрещённых символов - выводим на экран
if (!ereg('<|>|&', $text)) {
	echo $text;
}

?>

Для того, чтобы обойти фильтр, надо в браузере набрать путь_к_сайту/index.php?text=%00<script>alert(/XSS/)</script>.

Спасибо за внимание.

Комментарии (2) »

  1. Полезная статья, еще хотелось бы освещения того, что роисходит после выполнения строки с нулл-байтом =) заранее спасибо!

    Комментарий by aux — 30 марта 2010 @ 18:37


  2. Что вы имеете в виду?

    Комментарий by Figaroo — 2 апреля 2010 @ 11:56


RSS-лента комментариев к этой записи

Оставить комментарий

Пожалуйста, заполните все поля.

© Валерий 'Figaroo' Киркиж, 2008-2012 гг.