Сообщения об ошибках

С точки зрения безопасности вывод сообщений об ошибках несет в себе как плюсы, так и минусы.

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

Пример #1 Атака на переменные в HTML-странице

<form method="post" action="attacktarget?username=badfoo&amp;password=badfoo">
<input type="hidden" name="username" value="badfoo" />
<input type="hidden" name="password" value="badfoo" />
</form>

Возникаемые во время работы скриптов ошибки являются достаточно ценной информацией для разработчика, содержащей такие данные, как функция или файл, а также номер строки, в которой возникла ошибка. Вся эта информация может быть использована для взлома. Для PHP-разработчика достаточно привычно пользоваться такими функциями, как show_source(), highlight_string() или highlight_file() в целях отладки, но на работающих сайтах это может открыть информацию о скрытых переменных, непроверенном синтаксисе и других потенциально опасных моментах. Особенно опасно наличие кода со встроенным механизмом отладки в публичных частях сайта. Взломщик может попытаться запустить отладочный механизм, подбирая основные признаки отладки:

Пример #2 Использование стандартных отладочных переменных

<form method="post" action="attacktarget?errors=Y&amp;showerrors=1&amp;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 скрипты. Если взломщик анализирует обычную страницу сайта с расширением .html и пытается узнать систему, с помощью которой работает сайт (для дальнейшего поиска уязвимых мест), то подавая на ввод неверные данные он может обнаружить, что система использует PHP.

Также уведомление об ошибке может дать информацию об используемой базе данных, или, к примеру, как построена логика работы скриптов. Это, в свою очередь, может позволить взломщику подключиться к открытому порту базы данных, либо найти определенные ошибки в коде. Пробуя поочередно различные неверные блоки данных, злоумышленник может определить порядок аутентификации в скрипте (например, по номерам строк с ошибками) или проверять на наличие дыр различные участки кода.

Вывод стандартных ошибок или ошибок, связанных с файловой системой, может указать, с какими привилегиями запущен веб-сервер, и как организованы каталоги сайта. Обработка подобных ошибок, написанная разработчиками приложения, может только усугубить проблему, если взломщиком будет найден способ обнаружить "скрытую" отладочную информацию.

Существует три основных способа решения этой проблемы. Первый заключается в том, чтобы структурировать все функции и попытаться компенсировать объем выдаваемых ошибок. Второй способ - полностью отключить в работающем коде вывод сообщений об ошибках. И, наконец, третий способ - использовать специальные средства PHP для создания собственного обработчика ошибок. В зависимости от используемой вами политики безопасности вы можете применить в вашей конкретной ситуации все три способа.

Один из возможных способов обезопасить ваш код перед его публикацией в общий доступ - это использование функции PHP error_reporting(), которая может помочь выявить потенциально опасные переменные. Тестируя код перед выпуском релиза при помощи значения E_ALL, вы достаточно легко можете обнаружить участки кода, в которых переменные могут быть подменены либо модифицированы. После окончания тестирования, вы можете либо полностью отключить все сообщения об ошибках установив error_reporting() в 0, либо отключить их вывод с помощью директивы php.ini display_errors, изолировав таким образом ваш код от прощупывания. Если вы решили использовать последний способ, то необходимо также указать путь к лог-файлу с помощью директивы error_log и включить директиву log_errors.

Пример #3 Поиск потенциально опасных переменных при помощи E_ALL

<?php
if ($username) {  // Переменная не инициализируется или не проверяется перед использованием
    
$good_login 1;
}
if (
$good_login == 1) { // Если предыдущая проверка потерпела неудачу, переменная оказывается неинициализированной
    
readfile ("/highly/sensitive/data/index.html");
}
?>