При проведении тестирования безопасности веб-приложений (например, тестирования на проникновение) в большинстве случаев используется так называемый веб-прокси или прокси перехвата (иногда в сочетании со сканером веб-приложений, что позволяет проводить автоматизированное тестирование). Веб-прокси, как следует из названия, располагается между браузером и веб-сервером и перехватывает трафик. Этот тип инструмента используется для прямого взаимодействия с приложением посредством отправки запросов на веб-сервер и откликов после завершения работы JavaScript в интерфейсе пользователя (в компьютере либо браузере пользователя). Если вы впишете код проверки в JavaScript, чтобы убедиться в безопасности пользовательского ввода, любой пользователь с помощью веб-прокси может ввести достоверные данные, приостановить их передачу (перехватить запрос) после того, как JavaScript закончит проверку данных, и заменить на вредоносные данные (отредактировать запрос и отправить его дальше). Будет правильным, если приложение повторно проверит данные на сервере: можно выполнить очень простую проверку данных в JavaScript, которая сэкономит время. Если же данные на сервере не будут проверены, злоумышленники легко могут отправить приложению вредоносные запросы с помощью веб-прокси. На рис. 3.5 изображен поток HTTP-запросов при использовании веб-прокси.
Рис. 3.5. Использование веб-прокси для обхода проверки JavaScript
К великому сожалению проектировщиков веб-приложений, пользователи обладают большими возможностями. Они могут использовать небезопасный или устаревший браузер, заходить на сайты с компьютера, зараженного вредоносным ПО, изменять настройки браузера, редактировать параметры в URL-адресе и даже перехватывать запросы и отклики в наших приложениях. Люди также могут скрыть свое местоположение, IP-адрес, тип используемых ими операционной системы и браузера и даже веб-страницу, с которой они пришли. Плохо это или хорошо, но интернет был создан для того, чтобы дать пользователям большую власть.
Отправка результатов каждой проверки обратно на сторону сервера может показаться дорогостоящей, однако в действительности она обойдется дешевле, чем успешная эксплуатация веб-приложения злоумышленником.
В молодости Боб недолго проработал программистом, но понял, что кодирование не для него. Сначала он подумал, что может написать собственные функции, вместо того чтобы использовать элементы платформы. Таким образом он хотел улучшить качество работы и продемонстрировать руководству свою ценность. Начальник же объяснил Бобу, что писать собственные средства защиты опасно: «Боб, над этой платформой работали несколько профессионалов, люди, которые подробно изучили проблему и имеют многолетний опыт. Ты действительно думаешь, что у нас есть деньги, чтобы заплатить тебе за изобретение колеса, а в проекте выделено время на тестирование написанного тобой кода? Неужели ты считаешь, что один человек, не имеющий специальных знаний в данной области, может сделать работу лучше, чем целая команда экспертов?» Боб был подавлен, но, поразмыслив, признал правоту начальника: следует использовать функции безопасности платформы, а не писать собственные.
Это относится ко всем нам. Ни в коем случае нельзя писать собственные функции безопасности взамен существующих в используемой платформе. Если платформа таких функций не имеет, то, прежде чем приступить к их созданию, необходимо тщательно оценить ситуацию или приобрести доступный и надежный вариант.
Например, существует множество различных тайников, которые можно получить бесплатно или по цене, доступной для большинства организаций. Придумать, как хранить секреты вне кода, – очень сложная задача, поэтому почти всегда имеет смысл использовать готовое решение. Тем не менее в очень редких случаях иногда нет другого выхода, кроме как написать собственный код. Но прежде, чем принять такое решение, следует провести анализ вариантов.
СОВЕТ. Тайник – это место, где хранятся секреты приложения. В отличие от менеджеров паролей, предназначенных для людей, тайниками пользуются машины. В них можно и нужно хранить строки подключения, учетные данные, ключи, хеши и другие секреты.
Функции, касающиеся безопасности (это относится и к проектированию оборудования), по возможности следует изолировать от остальной функциональной части приложения. Благодаря этому нарушение функций, не связанных с обеспечением безопасности, не заденет защиту приложения и не станет причиной возникновения уязвимости. Данный совет упоминается в очень надежных руководствах по безопасности: ITSG-33 канадского правительства и Специальной публикации NIST 800-53 S-3.
Как его реализовываем мы? Для каждого элемента управления безопасностью мы обособляем код или функцию. Мы выделяем их в отдельный объект либо класс, размещаем на другой странице либо панели внутри приложения или системы и/или вообще в отдельном приложении. Вероятнее всего, мы также заставим пользователя или приложение пройти повторную аутентификацию прежде, чем разрешить доступ к функциям безопасности. Вот примеры наших действий.
• Вынесение проверки ввода в отдельный объект или класс.
• Вынесение аутентификации и авторизации в отдельное приложение.
• Управление идентификацией, осуществляемое облачным провайдером или другой внешней системой.
Уровень разделения функций зависит от чувствительности данных, с которыми будет работать разрабатываемое приложение, и мощности функционала, отвечающего за обеспечение безопасности.
Код функции безопасности может храниться на отдельном веб-сервере, PaaS, контейнере или файловой системе. Между двумя приложениями может быть брандмауэр или в крайнем случае совершенно отдельные сети.
Системы идентификации и аутентификации всегда должны находиться на отдельном сервере и следовать принципам по усилению защиты.
В число функций безопасности, которые всегда должны быть изолированы, входят: связанные с безопасностью протоколирование и мониторинг, предотвращение и обнаружение попыток несанкционированного доступа, файрвол веб-приложений (англ. Web application firewall, WAF), программное обеспечение для контроля приложений, мониторинг целостности файлов, оповещение или блокирование.