Сообщения об ошибках
С точки зрения PHP-безопасности вывод ошибок несёт как вред, так и пользу.
Стандартная тактика атаки состоит в профилировании системы: ввод неправильных данных
и анализ содержания и характера сообщений об ошибках. Взломщик получает
информацию о сервере и определяет слабые места. Пример атаки: взломщик получает
информацию о странице после отправки формы, а затем переопределяет или изменяет
передаваемые значения:
Пример #1 Атака на переменные в HTML-странице
<form method="post" action="attacktarget?username=badfoo&password=badfoo">
<input type="hidden" name="username" value="badfoo" />
<input type="hidden" name="password" value="badfoo" />
</form>
При отладке сообщения об ошибках в PHP-коде возвращают полезную для разработчика
информацию: показывают функцию, номер строки в файле или PHP-файл, в которых произошёл сбой.
Эта информация помогает злоумышленнику во взломе. PHP-разработчик часто пользуется
функциями show_source(), highlight_string()
и highlight_file() как методами отладки, но на живых сайтах
это раскрывает скрытые переменные, непроверенный синтаксис
и другую опасную информацию. Повышенную опасность несёт запуск
в публичных частях сайта открытого исходного кода со встроенными механизмами и методами отладки.
Злоумышленник попытается взломать страницу методом перебора, или «грубой силы» (англ. brute force),
путём отправки общих строк отладки, если узнает,
какой техникой отладки пользуется разработчик:
Пример #2 Пример стандартных отладочных переменных
<form method="post" action="attacktarget?errors=Y&showerrors=1&debug=1">
<input type="hidden" name="errors" value="Y" />
<input type="hidden" name="showerrors" value="1" />
<input type="hidden" name="debug" value="1" />
</form>
Открытость системы к проверке ошибок
снабжает злоумышленника дополнительной информацией
независимо от метода обработки ошибок.
Сам стиль стандартной информации о PHP-ошибке указывает,
что система работает на PHP. При просмотре
.html
-страницы и исследовании бэкенда в поиске слабых мест в системе,
взломщик вводит неверные данные и узнаёт, что систему построили на PHP.
Вывод информации об ошибке, которая возникла в функции, сообщает, работает ли в системе
конкретный движок базы данных, или даёт подсказки, как запрограммировали
или спроектировали веб-страницу. Это помогает злоумышленнику глубже исследовать
открытые порты базы данных или искать конкретные ошибки
и слабые места на веб-странице. Злоумышленник передаёт неверные данные
и по номерам строк с ошибками определяет порядок аутентификации в скрипте, или проверяет,
содержит ли код другие бреши, которые получится использовать в отдельных частях скрипта.
Вывод информации об ошибках в файловой системе или стандартных PHP-ошибок сообщает, с какими
привилегиями запустили веб-сервер, и как организовали каталоги сервера.
Коды ошибок в отладочной информации, которые записал разработчик, усугубляют проблему
и упрощают доступ к информации, которая раньше была «скрыта».
Проблему решают тремя базовыми способами. Первый способ —
тщательно изучить каждую функцию и компенсировать бо́льшую часть ошибок.
Второй — отключить вывод сообщений об ошибках в запущенном коде.
И третий способ — использовать функции, которые устанавливают пользовательский
обработчик PHP-ошибок. Иногда защищаются всеми тремя способами,
в зависимости от политики безопасности, которую принял для себя разработчик.
Способ заранее обнаружить проблему вывода конфиденциальной информации —
изменить уровень сообщений об ошибках в PHP-коде функцией error_reporting(),
которая помогает защитить код и выявить опасные переменные.
На время тестирования кода, перед развёртыванием в рабочей среде,
вывод сообщений об ошибках устанавливают на уровень E_ALL
,
с которым быстро находят области, в которых переменные открываются
для «заражения» — подмены или модификации.
С момента готовности кода к развёртыванию требуется вызывать функцию error_reporting()
со значением 0, чтобы отключить вывод сообщений об ошибках,
либо отключить вывод ошибок в файле php.ini — через директиву display_errors
,
чтобы изолировать код от проверки. Разработчику потребуется также
определить путь к файлу лога через директиву error_log
и включить директиву log_errors
.
Пример #3 Поиск опасных переменных с выводом ошибок уровня E_ALL
<?php
if ($username) { // Переменную $username не инициализировали — не установили начальное значение — и не проверили
$good_login = 1;
}
if ($good_login == 1) { // Переменная $good_login не проинициализируется, а проверка не пройдёт,
// если предыдущая проверка провалится
readfile ("/highly/sensitive/data/index.html");
}
?>