Безопасность в вебе, или TrustedTypes как новый способ защиты от XSS

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

Безопасность в вебе

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

Однако после крупных взломов таких компаний, как MySpace (XSS), eBay (XSRF) и многих других, до компаний начало доходить, что нужно что-то делать.

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

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

В своей статье я хочу сфокусироваться на XSS-атаке, а также рассмотреть новый способ защиты от нее — DOM TrustedTypes.

Почему XSS все еще опасен

XSS (англ. Cross-Site Scripting — «межсайтовый скриптинг») — атака не новая, и большая часть программистов с ней знакомы. Хакер использует уязвимость (как правило, это неотфильтрованный пользовательский ввод данных), чтобы разместить вредоносный код.

С каждым годом фронтенд-приложений становится все больше, и сами приложения становятся все объемнее и сложнее. Поэтому логично, что появляется все больше атак XSS непосредственно в DOM.

Давайте рассмотрим пример. Программисты веб-приложения написали вот такой код:

Чем это может быть опасно? Тем, что мы выводим неотфильтрованные данные прямиком в DOM. Хакер может подкинуть для нашего пользователя-жертвы вот такую ссылку:

При этом в DOM мы получим вредоносный код:

Вывод alert сообщения сам по себе не опасен, но обычно с его помощью хакер тестирует сайт на уязвимости.

Многие считают, что основная цель XSS — стянуть пароль из кукисов, ну а если пароль/токен в кукисах не хранится (а например, в localStorage), то XSS сайту не страшен. Это заблуждение. Кроме стягивания кукисов, c XSS можно совершать много различных манипуляций, например:

Как вы, наверное, догадались — этот код предназначен, чтобы красть номера кредитной карточки.

А вот этот будет заниматься майнингом криптовалюты за счет браузера нашего пользователя:

Но это далеко не все. Если вы дадите хакеру доступ к выполнению произвольных скриптов путем внедрения XSS, он сможет сделать практически все с компьютером жертвы, даже такой интересный вариант, как, например, организовать запись с веб-камеры.

Если вы до этого не сталкивались с такой утилитой, как BeEF — очень рекомендую обратить внимание. Она помогает раскрыть потенциал уязвимости и обеспечивает удобный графический интерфейс.

Еще одно заблуждение, что XSS — проблема прошлого, а сейчас нас защищают современные фреймворки и фаерволы на серверах, что у всех серьезных компаний инфраструктура настроена так, что как бы «криворукие» программисты ни старались, они не смогут создать XSS.

Чтобы развенчать этот миф, достаточно привести пример Google: основная функция — поиск — подверглась XSS в конце прошлого года. А привела к этому уязвимость в библиотеке Closure.

Как защититься от XSS

Если я вас уже убедил, что XSS до сих пор является достаточно серьезной угрозой вашим веб-проектам — можем переходить к рассмотрению способов защиты.

Фильтрация/санитизация данных

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

  • Не доверять никому (с вашего API тоже могут прийти опасные с точки зрения HTML данные, на стороне сервера работают такие же программисты, которые могли забыть что-то отфильтровать).
  • Не пытайтесь написать санитизатор самостоятельно, вы не умнее десятков тысяч хакеров, которые пытаются обойти все варианты фильтрации. Уже существует множество зрелых решений для любой технологии.
  • Общая санитизация не подходит, если мы не знаем тип контента, который собираемся отфильтровать (ведь для URL и для HTML опасными будут разные кодовые комбинации).

Использование CSP-заголовков

Content Security Policies (или просто CPS) — очень хороший способ защиты от XSS, когда у вас огромный проект, и вы не уверены, что знаете все его места. CSP позволяет будто зонтиком «накрыть» сразу весь проект, и даже плохой код с уязвимостями и неотфильтрованными данными.

Как работает CSP

CSP — это специальная дополнительная информация, которая передается браузеру либо в HTTP-заголовках, либо в мета-тегах сайта. В ней задаются правила, как браузер должен себя вести с разными типами ресурсов: разрешать или блокировать.

То есть в теории если мы знаем, что у нас нет инлайн скриптов, мы можем их просто запретить, и если хакер сможет внедрить опасный код из примера выше:

Он просто не выполнится в браузере.

Включение CPS в режиме отчета

Самое прекрасное, что вы можете включить CSP в режиме отчета: то есть ничего у вас не поломается, не заблокируется — просто система будет оповещать, что что-то работает некорректно согласно политикам безопасности, и до того как их включать, необходимо это исправить, иначе на сайте может перестать работать какая-то функция.

CSP в реальной жизни

Мы на своем проекте принципиально отказались от inline-скриптов, и даже код-сниппеты, такие как Google Analytics, перенесли в отдельные файлы. Это, я думаю, первое, что вам необходимо сделать, чтобы предотвратить возможную XSS-атаку.

Далее прошлись по всем сторонним ресурсам, которые используются приложением, и добавили их в исключения. Не со всеми сервисами 3rd Party это получается просто: они подгружают дополнительные файлы динамически, то есть при обновлении библиотеки это уже может быть другой файл.

Проблемным также оказался вопрос с фреймами: некоторые клиенты используют наш портал внутри тега iframe.

Курьезный момент: благодаря CSP мы обнаружили, что одна из наших библиотек использует внутри себя метод eval. Пришлось отписать им, чтобы обновили. Так CSP помогает вам не только в целом защититься от возможных атак, но также выявить и устранить проблемные места в ваших проектах.

Более подробно о CSP можно почитать в MDN-документации.

Использование Trusted Types в DOM

Если мы копнем глубже — из-за чего происходят все проблемы — то окажется, что мы просто доверяем браузеру делать слишком много магии, при этом не задавая контент для выполнения. Самый распространенный случай — innerHTML= ‘.......’ То есть мы передаем строку, в которой может быть все что угодно, в том числе вредоносный скрипт.

При этом вы можете работать с innerHTML не напрямую — это может делать одна из ваших вспомогательных библиотек (так, например, делала jQuery в методе append).

Так, может, нам просто заблокировать innerHTML на глобальном уровне? Нет, увы: innerHTML — не единственное проблемное место в DOM, есть много свойств-методов, которые делают примерно такую же магию с передаваемой строкой:

Но что, если бы существовала возможность передавать значение не как строка, а как объект? Ведь DOM уже давно поддерживает такую возможность:

При этом этот объект знал бы свой скоуп, то есть либо это URL, либо это HTML, либо еще что-то. В зависимости от этого браузер или сам объект мог бы валидировать/фильтровать данные, ничего не ломая.

Веб-платформа либо полифилы предоставляет набор готовых типов:

  • TrustedHTML
  • TrustedScript
  • TrustedURL
  • TrustedScriptURL

Но при этом мы можем добавлять свои в случае необходимости.

Как подключить Trusted Types

Для подключения Trusted Types необходимо лишь добавить в CSP дополнительную инструкцию:

Content-Security-Policy: trusted-types *

И теперь, если мы попытаемся сделать что-то такое в коде:

Браузер просто выдаст ошибку:

Uncaught TypeError: Failed to set the ’innerHTML’ property on ’Element’: This document requires `TrustedHTML` assignment.

Но если мы сделаем присвоение через специальный объект:

Все отработает правильно!

Плюс ко всему, мы еще можем лимитировать возможные варианты политик: добавим вместо звездочки имя политики (класса), которую используем:

Content-Security-Policy: trusted-types myPolicy

Несмотря на то что этот проект все еще остается в формате Draft, вы уже можете поиграться в Chrome 73+, используя специальный флаг:

chrome --enable-blink-features=TrustedDOMTypes

TrustedTypes в реальной жизни

Даже при том, что DOM TrustedTypes по-прежнему является экспериментальной функцией, если вы хотите в последующем (с принятием стандарта) активировать его на проекте — изменения нужно начинать готовить уже сейчас.

Мы на своем проекте используем Angular, который уже частично включает концепцию TrustedTypes: если правильно использовать фреймворк, то он будет контролировать всю передачу и отображение данных в шаблоне, при этом Angular четко знает тип передаваемых данных и экранирует их в зависимости от типа. Более того, уже даже есть Pull Request добавить TrustedTypes нативно во фреймворк.

P. S. Я надеюсь, эта статья позволит вам быстрее разобраться с TrustedTypes и поможет сделать вашу систему безопаснее уже сегодня благодаря использованию лишь нескольких дополнительных настроек.

Похожие статьи:
Незалежно від статусу резиденства українці зобовʼязані сплачувати податки на доходи, зароблені у Польщі. Про це повідомляє заступник...
Норвежская компания Opera Software объявила о выпуске новой версии мобильного браузера Opera Mini для платформы Android, благодаря которой, как...
Станом на перший квартал 2017 року Android був найпопулярнішою мобільною платформою. Кількість пристроїв на цій операційній системі...
Вопрос знатокам: какая одна из высоких позиций в IT-компаниях все еще непосредственно связана с решением технических задач?...
У першому півріччі 2024 року прийнято на озброєння, кодифіковано й допущено до експлуатації в Силах оборони майже 480...
Яндекс.Метрика