23 Апреля, 2009

Устранение наиболее часто встречаемых уязвимостей в web

Dmitriy Evteev
Достаточно часто в своей работе наблюдаю ситуацию, в которой разработчики web-приложений не до конца понимают, как правильно устранять наиболее распространенные уязвимости в своих приложениях (такие как SQL-Injection, Cross-Site Scripting и др.). Порой доходит до того, что устранение выявленных мною уязвимостей, при выполнении соответствующих работ, ограничивается частичным закрытием вектора атаки, указанного в отчете по анализу этого приложения. Собственно подобная ситуация и побудила меня описать базовые способы устранения наиболее распространенных уязвимостей в web на примере Web-сервера Apache с используемым движком PHP. Сразу отмечу, что данные рекомендации не являются исчерпывающим руководством по устранению всех возможных уязвимостей в среде web-приложений. Более того, многие подходы к организации достаточного уровня защищенности для web-приложений, описанные здесь, могут быть построены иным образом, который обеспечивает аналогичный уровень информационной безопасности web-приложения. name='more'> 1.1 Устранение уязвимостей на уровне исправления исходного кода (PHP) Множество уязвимостей в web-приложениях появляется, когда приложением не достаточно проверяются (или не проверяются вовсе) поступающие данные со стороны пользователя (GET/POST/COOKIE/USER-AGENT/REFERER и т.д.). Это справедливо для следующих типов уязвимостей: - SQL Injection - File Including (Path Traversal) - Cross-Site Scripting - Cross-Site Request Forgery - и т.д. Более того в ряде случаев, становится возможным воспользоваться уязвимостью даже в тех случаях, когда приложение манипулирует (как ему кажется) доверенными данными. В основном это некие внутренние переменные, которые вследствие различных обстоятельств (использования уязвимостей) могут быть переопределены. Также, уязвимости могут быть проэксплуатированы вследствии, когда приложением не происходит корректная обработка данных, полученных из файлов конфигурации (злоупотребление функциональными возможностями) или СУБД (Cross-Site Scripting и др.). Поэтому основополагающая рекомендация по устранению уязвимостей в web-приложении - это добавление проверок на корректность ожидаемых данных, полученных из любых источников, перед тем, как эти данные будут переданы в качестве аргументов в различные функции ( print(), echo(), include(), mysql_query() и т.д.). 1.1.1 Устранение уязвимостей типа [Межсайтовое выполнение сценариевk Для устранения данного типа уязвимостей можно перед выводом любых данных в браузер пользователя предварительно обрабатывать их с использованием функции htmlspecialchars(). Однако, в тех случаях, когда выводимые данные попадают в открытые HTML теги, в сценарии java-script/vb-script и пр., использование одной лишь функции htmlspecialchars недостаточно. В этих случаях рекомендуется пользоваться функциями привидения типов (например, intval()) и/или проводить разбор выводимых данных с использованием регулярных выражений, например: if (ereg ("([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})", $date, $regs)) { echo "$regs[3].$regs[2].$regs[1]"; } else { здесь обработчик для случая, когда переменная $date не соответствует регулярному выражению Важно: выводить переменную $date в данном блоке опасно! } Вообще, хорошей практикой безопасного программирования web-приложений является повсеместное приведение типов и использование регулярных выражений. Однако стоит заметить, что перед тем как проверять данные с использованием регулярных выражений, необходимо предварительно использовать функцию экранирования спецсимволов (addcslashes()), например, в качестве контрмеры от использования атакующим null-byte. В общем случае, для защиты от уязвимости типа Cross-Site Scripting необходимо производить замену потенциально небезопасных символов, которые могут быть использованы при форматировании HTML страницы на их эквиваленты, не являющиеся символами форматирования. 1.1.2 Устранение уязвимостей типа [Внедрение операторов SQLk Для устранения данного типа уязвимостей можно перед передачей параметров в функцию выполнения запроса к СУБД (например, mysql_query()), предварительно обрабатывать переменные с использованием функции addslashes(). Однако, в тех случаях, когда используются конструкции вроде: mysql_query("SELECT * from my_table where id=$id"); данной обработки недостаточно, т.к. не используются кавычки при выполнении запроса. Поэтому для случая приведенного выше необходимо использовать функцию приведения типа intval(). 1.1.3 Устранение уязвимостей типа [Обход каталогаk Для устранения данного типа уязвимостей можно перед передачей параметров в функции открытия файлов (например, fopen()), предварительно проверять переменные с использованием функций регулярных выражений (например, ereg()), а также обрабатывать переменные с использованием функции addcslashes(). 1.1.4 Устранение уязвимостей типа [File Includingk Для устранения данного типа уязвимостей можно перед передачей параметров в функции include(), require() и пр., предварительно проверять поступающие данные с использованием функций регулярных выражений, а также обрабатывать переменные с использованием функции экранирования спецсимволов. Кроме того, хорошей практикой безопасного программирования является использование конструкций switchcase, везде, где это возможно. Например, следующий код не подвержен уязвимости [File Includingk: switch ($inc) { case 0: include $_SERVER["DOCUMENT_ROOT"]."/inc/my_func.inc.php"; break; case 1: include $_SERVER["DOCUMENT_ROOT"]."/inc/my_user.inc.php"; break; default: include $_SERVER["DOCUMENT_ROOT"]."/inc/my_func.inc.php"; } Примечание: рекомендуется избегать динамического инклудинга файлов, когда это возможно. 1.1.5 Устранение уязвимостей типа [Внедрение произвольного PHP-кодаk и [Выполнение команд ОСk Данные уязвимости в большинстве случаев возникают при использовании функций eval(), system(), passthru(), exec() и пр. Рекомендуется избегать их использование. В тех случаях, когда их использование необходимо, требуется тщательно проверять поступающие данные в эти функции на соответствие ожидаемым данным в контексте логики приложения. Опционально передаваемые переменные в функции eval(), system(), passthru(), exec() и пр. могут быть предварительно обработаны функциями привидения типов и экранирования символов. 1.1.6 Устранение прочих уязвимостей Как уже было отмечено ранее, большинство уязвимостей в web-приложениях связано с передачей различным функциям не обработанных переменных или обработанных не достаточно тщательно. Уязвимостей разного рода критичности удается избежать в случае, когда происходит доскональная проверка всех переменных ожидаемым данным, поступающих в приложение. Для этого достаточно эффективно могут использоваться проверки на соответствие типов, проверки по регулярным выражениям. Не стоит также забывать пользоваться функциями экранирования спецсимволов, HTML-сущностей и т.п. Рекомендуется использовать конструкции switchcase, когда это возможно. 1.2 Устранение уязвимостей на уровне проектирования web-сервера (Apache) Множество уязвимостей, различного уровня критичности, удается избежать путем использования конфигураций web-сервера, с повышенными требованиями к информационной защищенности web-приложения. В совокупности с продуманными и безопасными конфигурациями других сервисов (СУБД, модули web-сервера, файловая система и т.д.) становится возможным избежать различных уязвимостей web-приложения и максимально затруднить действия потенциального злоумышленника по компрометации системы. Для понимания процесса организации защищенной среды web-сервера, рекомендуется обратиться к справочным материалам, ссылки на которые приведены в заключении данной публикации. При настройке защищенной среды web-сервера рекомендуется руководствоваться промышленными стандартами по информационной безопасности от CIS, DISA и SANS. 1.2.1 Устранение уязвимости раскрытия чувствительной информации Многие web-приложения могут раскрывать чувствительную информацию вследствии: - Обращения к файлам напрямую, в обход логики работы приложения. - Использования различных файлов с расширениями, которые web-сервер обработает в режиме plain/text (txt, bak, log, inc и т.д.). - Прочих уязвимостей web-приложения. Первые два случая раскрытия чувствительной информации могут быть предотвращены (но не устранены!) путем использования защищенных конфигураций web-сервера. Для первого случая, возможным путем устранения уязвимости может быть адаптация приложения к работе с модулем mod_rewrite. Если приложение спроектировано таким образом, что все запросы со стороны пользователя обрабатывает только один единственный файл, подгружая в процессе своей работы необходимые функции, тогда это задача становиться достаточно тривиальной. Пример конфигурации .htaccess, который будучи помещенный в корневую директорию web-сервера, способен закрыть вектор атаки для случая, когда все запросы со стороны пользователя обрабатывает файл index.php: <FilesMatch "."> order allow,deny deny from all </FilesMatch> <FilesMatch "(index.php|.(gif|jpe?g|png|css|js|html))$"> order allow,deny allow from all </FilesMatch> RewriteEngine On RewriteRule !.(gif|jpe?g|png|css|js|html)$ index.php Для предотвращения доступа к чувствительной информации во втором случае рекомендуется запретить прямой доступ к файлам, которые ее раскрывают. Для этого также можно использовать файл .htaccess, содержащийся в корневой директории web-сервера, с директивой [FilesMatchk. Указанная директива запрещает доступ к файлам в обход логики работы приложения. Пример: <FilesMatch ".(inc|save|bak)$"> Order allow,deny Deny from all </FilesMatch> 1.2.2 Устранение уязвимости идентификации серверных приложений Плохой практикой при промышленном использовании web-приложения, в защищенной конфигурации, является передача клиенту используемых версий web-сервера и его модулей. Рекомендуется использовать следующие директивы web-сервера Apache для предотвращения раскрытия его версии: ServerSignature Off ServerTokens Prod Данная уязвимость относится и к используемым модулям web-сервера. Поэтому, если в качестве модуля используется интерпретатор PHP, рекомендуется также и в его конфигурационный файл внести следующую директиву: expose_php = Off 1.2.3 Устранение уязвимости листинга директорий Для большинства web-приложений в промышленном использовании листинг директорий не требуется. Поэтому его рекомендуется отключать. Для этого может использоваться следующая директива файла .htaccess, расположенного в корневой директории web-сервера: Options -Indexes Опционально для устранения данной уязвимости может быть отключена загрузка модуля Apache mod_autoindex путем внесения изменений в конфигурационный файл web-сервера. 1.2.4 Устранение прочих уязвимостей Рекомендуется ознакомиться с распространяемыми стандартами от CIS, DISA, SANS и, используя рекомендуемые конфигурации, определить приемлемый уровень защищенности (сформировать профиль защиты) и настроить среду web-приложения в соответствии с ним. За дополнительными материалами по обеспечению достаточного уровня информационной защищенности web-приложений можно обратиться к следующим ресурсам: - OWASP - WASC - Материалы SecurityLab