В сети можно найти множество различных публикаций, посвященных безопасной разработке backend приложений. Основной причиной этого является то, что в бэкенде ведется основная обработка данных и соответственно, там выше риски в случая уязвимости кода. Но не стоит забывать и об уязвимостях на frontend, ведь это та сторона веб-ресурса, которая видна пользователям, и которая первой подвергается различным попыткам эксплуатации уязвимостей. В этой статье мы поговорим о безопасной разработке в таких инструментах фронтенд разработки, как язык разметки HTML.
Эволюция HTML
Прежде, чем начать разговор об уязвимостях HTML не лишним будет совершить краткий экскурс в историю этого языка разметки для того, чтобы посмотреть, как он эволюционировал с момента своего создания до наших дней.
Итак, HTML (Hyper Text Markup Language.стандартизированный язык гипертекстовой разметки документов) предназначен для просмотра веб страниц в браузере. Веб браузер получает документ по HTTP/HTTPS и преобразовывает его содержимое в графический вид. Версия HTML 2.0 появилась в 1995 году и во многом стала результатом противостояний Майкрософт и Netscape и их браузеров Internet Explorer и Netscape Navigator (помните, был когда-то такой браузер) соответственно. Версии HTML 1.0 как таковой не было, так как многие разработчики толковали разметку гипертекста по своему в результате чего было много разночтений. Вторая версия стала определенным стандартом в разметке гипертекста. Далее заслуживает внимания версия 4.0 вышедшая в 1997 году и версий 5.0, вышедшая в 2014. Именно про эту версию HTML мы и будем говорить далее.
Кодируй это
Элементами языка разметки HTML являются теги и текстовые строки, которые мы и видим в окне браузера. Тэги обрамляют текст, указывая, как он должен отображаться.
<HTML>
<BODY>
<H1>Hello World!</H1>
</BODY>
</HTML>
При этом в стандарте HTML есть ряд специальных символов, которые нельзя использовать в качестве текстовых значений. Например, это символы <, >, &, “, ‘, / которые используются для обозначения тэгов в HTML тэгах, Для того, чтобы все-таки использовать в своих HTML страницах эти символы, необходимо указать их коды (<, >, &, ″, ‘, ⁄). Также есть целый список кодов для различных символов.
Таким образом, мы можем использовать коды внутри тегов, например
<img src=”http://www.example.com”>
можно записать как
< img src="http://www.example.com">
Но нельзя использовать коды для замены символов в тэгах
<img srcd;"http://www.example.com">
<img sHc="http://www.example.com">
Вот на этих особенностях работы языка разметки HTML и основаны многие атаки, о которых мы будем говорить далее.
Еще один вид кодирования, который нам потребуется далее это URL-кодирование. По аналогии с HTML кодированием здесь мы также сопоставляем символам различные коды. Обычно это используют для передачи кириллических символов в строке браузера.
Например, вот так выглядит поисковый запрос для фразы: url кодирование онлайн:
https://yandex.ru/search/?text=url+%D0%BA%D0%BE%D0%B4%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5+%D0%BE%D0%BD%D0%BB%D0%B0%D0%B9%D0%BD
Начнем с HTML инъекций.
HTML инъекции
Внедрение собственного кода HTML может дать злоумышленнику интересные возможности по обману пользователей. Несмотря на то, что мы никоим образом не влияем на содержимое веб страниц исходного сайта, то есть не делаем дефейс или другую замену контента, мы можем открыть пользователю по сути чужую страницу с помощью HTML инъекций. HTML инъекции часто называют виртуальным дефейсом.
Например, с помощью таких инъекций можно полностью подменить страницу с вводом данных в результате чего все данные, вводимые на этой странице пользователями будут передаваться злоумышленнику. Так несколько лет назад на одном криптовалютном сайте существовала подобная уязвимость. Сайт обрабатывал передаваемые в адресной строке данные без проверки. В результате злоумышленники подготовили HTML код, подобный представленному ниже, в котором у пользователя запрашиваются логин и пароль и затем эти данные передаются скрипту handler.php:
<form action="/example/handler.php">
<p><input name="login"> <input type="password" name="pass"></p>
<p><input type="submit"></p>
</form>
Данный код был закодирован с помощью онлайн кодировщика. В результате мы получили следующее:
И ссылка на официальный сайт, вместе с таким “хвостом” была размещена на общих ресурсах, спам рассылках и т.д. в результате чего пользователи переходили по ней и злоумышленники перехватывали их учетные данные. Для сокрытия таких подозрительных длинных ссылок часто используют сервисы коротких ссылок, которые позволяют скрыть содержимое ссылки.
Межсайтовый скриптинг
Cross-Site Scripting пожалуй одна из самых известных атак в мире веб. Эта атака заключается во внедрении в выдаваемую веб сервером страницу вредоносного кода, который выполняется на стороне клиента. В общем случае XSS не несет в себе прямой угрозы бэкенду, так как работает на стороне пользователя.
Существует три типа XSS атак:
Отраженные
Хранимые
DOM модели
Начнем с рассмотрения отраженных уязвимостей.
Отраженные (reflected) вредоносная строка порождается из запроса жертвы. То есть пользователь может передать на сервер какой-то скрипт, который затем будет выполнен на стороне клиента.
Простейший тест. Зайдите на http://testphp.vulnweb.com/ (это специальный сайт, разработанный Acunettix для тестирования средств защиты) и в поле Search art введите следующее:
<script>alert('XSS vulnerable!')</script>
После нажатия Go у вас появится сообщение
Также многие сайты позволяют использовать такие скрипты в GET запросах
vulnsite.com/search/?q=test<script>alert(%27XSS%27);</script>
Здесь по аналогии с HTML инъекциями можно закодировать код скрипта и дальше подсовывать эту строку пользователям различными методами. На практике, при выполнении этого скрипта на стороне жертвы злоумышленнику, например могут пересылаться его куки, осуществляться автоматические переходы на другие страницы и т.д.
XSS уязвимости позволяют обойти SOP. Политика одинакового источника (same-origin policy, SOP) определяет как документ или скрипт, загруженный из одного источника (origin), может взаимодействовать с ресурсом из другого источника. Это помогает изолировать потенциально вредоносные документы, снижая количество возможных векторов атак. Однако с помощью XSS атак злоумышленник может обойти данные политики.
Хранимые XSS
Хранимые (stored) XSS хранятся где-то в базе на сайте и подгружаются при запросе пользователя. Например, записи хранимые в Guestbook на сайте будут отображаться всем зашедшим пользователям и соответственно, сохраненные в этих записях скрипты будут выполнять у на клиентских машинах.
Схематически эту атаку можно представить следующим образом:
Первый клиент это злоумышленник, который сохраняет скрипт, ну а второй это собственно жертва.
Слепой XSS
При этой атаке злоумышленник не может сразу увидеть результат. То есть переданные данные могут отображаться на другой странице или в форме обратной связи, которую просматривает модератор. На практике, при такой атаке злоумышленник может например с помощью своего скрипта попытаться украсть куки модератора или администратора сайта, так как скрипт выполнится сразу при просмотре сообщения и модератор просто ничего не успеет сделать.
DOM-модели
Document Object Model это независящий от платформы и языка программный интерфейс, позволяющий программам и скриптам получить доступ к содержимому HTML-, XHTML- и XML-документов, а также изменять содержимое, структуру и оформление таких документов. По сути DOM представляет HTML документ в виде дерева, разделяя все теги на узлы,
как представлено на рисунке:
Получая HTML документ DOM парсит его, попутно выполняя. Этим и может воспользоваться злоумышленник. Он может вставить в документ, например скрипт следующего содержания:
В результате в HTML документ будет добавлена строка со значением поля name. Для эксплуатации DOM XSS нам надо передать строку
http://www.vuln.com/index.html?name=<script>alert(document.cookie)</script>
Поговорим о защите
После подробного описания возможных уязвимостей для HTML самое время поговорить о том, как от них защититься. Прежде всего следует помнить, что никогда нельзя доверять тем данным, которые наше приложение получает от пользователя, будь то данные передаваемые в адресных строках с помощью GET или данные формы, переданные через POST. Необходимо проверять передаваемые данные не позволяя напрямую обрабатывать то что передал пользователь. Служебные символы необходимо правильно отображать не позволяя выполнять переданные тэги или команды JavaScript. Вообще, что касается скриптовых языков – в идеальном мире лучше было бы вообще отказаться от JavaScript, но в реальности это вряд ли возможно, так как без скриптов на стороне клиента страницы будут не такими красивыми. Поэтому, можно рекомендовать отказаться от опасных функций, особенно при использовании DOM.
Также отдельно стоит отметить необходимость использования таких технологий, как SOP и CORS (Cross-Origin Resource Sharing, Технология совместного использования ресурсов между разными источниками) для организации взаимодействия между ресурсами в различных источниках. Но подробнее об этом мы поговорим уже в следующих статьях, посвященных безопасности веб.
В качестве заключение хочу пригласить всех читателей на бесплатный урок, в рамках которого разберем уязвимости в REST API. Выявим основные типы уязвимостей и поймем как их избегать. Поговорим про такие типы уязвимостей как Injection, Security Misconfiguration, Mass Assignment и другие. Научимся избегать или предвидеть уязвимости в своем продукте.