39. Безопасность web-приложений.
Обеспечение безопасности web-приложений – комплексная многоуровневая задача, имеющая множество аспектов, как общих для любых сетевых служб, так и характерных только для web-приложений. Первые включают безопасность сетевой инфраструктуры (маршрутизаторов, брандмауэров, DNS серверов и так далее), безопасность физических серверов, на которых расположены web-сервер и база данных, включая безопасность реализации стека протоколов TCP/IP и других работающих сервисов и так далее. Аспектами, специфическими для web-приложения, являются безопасность web-сервера и его конфигурации как сервиса и собственно безопасность скриптов, реализующих основную функциональность.
Потенциальные угрозы:
- Нарушение функционирования приложения, или DoS (Denial of Service) атака
- Неавторизованное чтение данных из нашей базы
- Неавторизованная модификация данных в нашей базе
- Чтение файлов на сервере (Опасность п. 4 и 5 зависит от прав доступа пользователя)
- Модификация файлов на сервере или запуск посторонних процессов.
Подавляющее большинство атак на web-приложения осуществляется специальным выбором передаваемых скрипту параметров. Основной способ защиты от этой угрозы заключается в тщательной проверке всех без исключения данных, получаемых от пользователя перед их использованием в программе. Одним из самых распространенных способов реализации угроз 1 и 2 является «SQL injection», то есть посылка скрипту данных, сформированных с целью выполнения скриптом SQL запроса, отличающегося от предусмотренного автором скрипта.
Необходимые проверки пришедшей от пользователя информации в других случаях зависят от специфики использования этой информации. Часто встречающимся на практике случаем является работа с файловой системой в условиях, когда имена файлов задает пользователь. В этом случае для обеспечения приемлемого уровня безопасности требуется очень строгая проверка данных с помощью регулярных выражений. Самый простой и надежный способ состоит в том, чтобы заменить пользовательские имена файлов на сконструированные заведомо безопасные имена и хранить в базе данных таблицу соответствия этих имен. Другой способ состоит в жестком ограничении набора допустимых символов в задаваемых именах файлов (концепция «белых списков», то есть разрешено только то, что явно указано). Обычно же неопытные программисты используют концепцию «черных списков», то есть пытаются обнаружить известные потенциально опасные конструкции. Такой подход гораздо более громоздок и допускает большую вероятность появления уязвимостей ввиду того, что при работе с файловой системой с помощью системной функции open, Perl обеспечивает ее очень большую гибкость за счет разнообразия допустимых синтаксисов вызова. Так, эта функция может запускать другие программы и соединять их конвейерным механизмом передачи данных, дублировать файловые дескрипторы и совершать множество других потенциально опасных (в случае их непредусмотренного заранее вызова) действий. Аккуратное и исчерпывающее предотвращение всех видов нецелевого использования таких функций работы с файлами минимизируя при этом накладываемые на имена файлов ограничения является весьма сложной задачей.
Еще одной часто встречающейся ситуацией является необходимость показывать пользователям информацию, введенную другими пользователями (например, форумы, гостевые книги и т. п.). Проблема состоит в том, что злонамеренный пользователь может ввести такую информацию (например, программу на языке JavaScript), которая негативно отразится на других пользователях нашего сайта. В качестве сравнительно безопасного примера приведем возможность немедленного закрытия только что открытой страницы. Для решения этой проблемы также пользуются концепциями подмены реальных тэгов их искусственными заменителями, белых списков и черных списков. Как и в предыдущем случае, черные списки являются самым трудоемким и самым ненадежным вариантом действий.
Отдельно стоит упомянуть использование функций, напрямую вызывающих другие программы. К ним относятся system(), exec(), те же конвейеры и конструкцию ` `. Вызов таких функций с аргументами, задаваемыми пользователем крайне опасен даже после фильтрации, так как в дополнение к возможности вызова посторонних программ (см. предыдущий абзац) в рассмотрение должна приниматься специфика работы каждого вызываемого приложения, которая нам почти никогда не известна до конца. Например, само вызываемое приложение может содержать еще неизвестные потенциально опасные ошибки. Функция eval() в форме оценки скаляра, задаваемого пользователем, тоже крайне опасна даже после тщательной фильтрации этого скалаяра ввиду чрезвычайной гибкости синтаксиса языка Perl. Использовать такую конструкцию следует только с концепцией тщательно составленных белых списков.
Еще одной особенностью, которую следует иметь в виду, является разные признаки конца строки в языке Perl и в языке C, на котором написана операционная система. В Perl строка может содержать любые символы, в то время как в C используются ASCIIZ строки, то есть символ с кодом 0 является завершающим. Это различие приводит к следующему эффекту: код
open( FD, “$a.html”)
не гарантирует, что имя открываемого файла всегда будет заканчиваться расширением html.
Другие потенциальные уязвимости включают вызовы вспомогательных скриптов, не предназначенных для непосредственной работы с пользователями, попытки чтения файлов, содержащих секретные данные нашего сервера и так далее. Защитой от таких действий является правильное распределение информации между скриптами и расположение скриптов на сервере. Следует создать директорию, недоступную из web (не являющуюся поддиректорией корня web-сервера или любой другой доступной снаружи деректории) и хранить все вспомогательные скрипты, модули, шаблоны параметры локальной конфигурации только в таких директориях. Отдельно остановимся на конфигурации и секретной информации. Почти всем скриптам наряду с множеством других конфигурационных параметров необходимо знать логин и пароль для соединения с базой данных. Такую информацию опасно хранить в теле самого скрипта, так как в результате ошибки в конфигурировании сервера или в результате атаки вместо вызова скрипта может последовать возврат пользователю содержимого скрипта. Кроме того, конфигурацию полезно вынести в отдельный файл и из соображений удобства переноса сайта на другой сервер.
Еще одним важным принципом обеспечения безопасности является минимизация доступной для пользователей информации о внутренней архитектуре системы. Например, в сообщениях об ошибках при работе скрипта не следует сообщать пользователю текст SQL запроса, вызвавшего ошибку, так информация о структуре расположения данных в СУБД может облегчить злоумышленнику дальнейшее планирование атаки.