WAF глазами хакеров

59e555ea45527050889028.png
Привет, Хабр! Сегодня мы поговорим об одном из современных механизмов защиты веб-приложений, а именно о WAF, Web Application Firewall. Мы расскажем, на чем основываются и как работают современные WAF, какие существуют способы обхода и bypass-техники, как их применять, а также почему ни в коем случае не стоит всецело полагаться на WAF. Мы представим свой взгляд пентестеров, которые никогда не принимали участие в разработке WAF и которые собирали информацию из открытых источников и на основе своего опыта, поэтому о некоторых тонкостях работы WAF мы можем даже и не подозревать.

59e543ce39bda172045649.png

Содержание


  1. Введение
  2. Что представляет собой современный WAF
  3. Идентифицируем WAF
  4. WAF bypass cheatsheet
  5. Обходим WAF на практике
  6. Заключение


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

Введение


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

59e395af93092095133873.png

Итак, что должен уметь WAF, чтобы его внедрение было обосновано в реальном проекте? Основная его функция — детектирование и блокирование запросов, в которых, согласно анализу WAF, есть некоторые аномалии или прослеживается атакующий вектор. Такой анализ не должен затруднять взаимодействие легитимных пользователей с веб-приложением, в то же время должен точно и своевременно детектировать любые попытки атак. Для того, чтобы реализовать такую функциональность, разработчики WAF обычно применяют регулярные выражения, токенайзеры, поведенчиский анализ, репутационный анализ, а также машинное обучение, и зачастую все эти технологии используются совместно. Кроме этого, WAF может еще предоставлять и другую функциональность: защита от DDoS, блокировка IP-адресов атакующих, отслеживание подозрительных IP-адресов, добавление security-заголовков (X-XSS-Protection, X-Frame-Options, etc…), добавление http-only флага к cookie, внедрение механизма HSTS, добавление функциональности CSRF-токенов. Также некоторые WAF имеют встраеваемый на сайт клиентский модуль, написанный на JavaScript.

Разумеется, WAF создает ряд трудностей для работы хакеров и пентестеров. Обнаружение и эксплуатация уязвимостей становится более трудоемкой задачей, если, конечно, атакующим не известны эффективные 0day-способы обхода конкретного WAF. Использовать автоматизированные сканеры при анализе веб-приложений под защитой WAF почти бесполезно. WAF надежно защищает сайты как минимум от scriptkiddies. Однако, опытный специалист или хакер, не имея должной мотивации, может также решить не тратить много времени на поиск способов обхода. Отдельно отметим, что, чем сложнее и многофункциональнее веб-приложение, тем больше возможная область атаки, и тем проще будет найти способ обхода WAF.

В последнее время довольно часто в наших аудитах встречаются разные WAF, про некоторые случаи мы даже расскажем чуть ниже. Мы уже опробовали некоторые проприетарные WAF в двух основных сценариях:

  • Мы знаем конкретную уязвимость в веб-приложении и пробуем обойти WAF, чтобы эксплуатировать её
  • Конкретная уязвимость неизвестна, задача состоит в том, чтобы обнаружить ее, не взирая на WAF, а затем проэксплуатировать, обходя WAF.


Но для начала остановимся подробнее на основных механизмах работы WAF и посмотрим, какие проблемы с этим существуют.

Что представляет собой современный WAF


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

59e395af93c4f468367566.png

Правила на основе регулярных выражений


Большинство существующих WAF базируется на правилах, основанных на регулярных выражениях. Для их создания некоторое известное множество атак изучается разработчиком WAF, в результате определяются ключевые синтаксические конструкции, по наличию которых можно утверждать о проведении атаки. На основе полученных результатов пишутся регулярные выражения, способные находить такие конструкции. Кажется, что всё просто, однако такой подход имеет ряд недостатков. Зона применимости регулярного выражения ограничивается одним запросом, а чаще даже конкретным параметром запроса, что очевидно снижает эффективность таких правил и создает ряд «слепых зон» для подобного механизма. Во-вторых, синтаксис регулярных выражений, сложная логика текстовых протоколов, допускающая замену на эквивалентные конструкции и использование различных представлений символов, приводят к ошибкам при создании подобных правил. На данную тему есть отличное исследование от Владимира Иванова.

Scorebuilding


Данный механизм должен быть знаком всем, кто интересовался устройством межсетевых экранов и антивирусов. Сам по себе он не детектирует атаки, однако дополняет другие методы, делая их более точными и гибкими. Причина появления инструмента — в том, что присутствие в запросе некоторой «подозрительной» конструкции является недостаточным условием для выявления атаки или же, напротив, может приводить к большому числу false-positive ошибок. Данная проблема решается введением балльной системы. Например, каждое правило, основанное на регулярных выражениях, дополняется информацией о критичности его срабатывания; после выявления всех сработавших правил их критичность суммируется. В случае преодоления некоторого порогового значения атака детектируется, а запрос блокируется. Данный механизм, несмотря на свою простоту, хорошо зарекомендовал себя в задачах подобного класса и применяется повсеместно.

Токенайзеры


Этот подход к детектированию атак был представлен на Black Hat 2012 в виде C/C++ библиотеки libinjection, позволяющей быстро и точно выявлять атаки класса SQL injection. На данный момент, для библиотеки libinjection существуют порты под различные языки программирования, включая PHP, Lua, Python, etc… По сути, механизм сводится к поиску сигнатур, представленных в виде последовательности токенов. Некоторое количество сигнатур вносится во встроенный черный список и считается недопустимым или вредоносным. Иными словами, перед тем, как проанализировать какой-либо запрос, его сначала приводят к набору токенов. Токены подразделяются на различные типы, например, variable, string, regular operator, unknown, number, comment, union-like operator, function, comma, etc… Один из основных недостатков данного метода заключается в том, что существует возможность построить такую конструкцию, которая приведет к некорректному формированию токенов, следовательно, сигнатура запроса будет отлична от ожидаемой. Такие конструкции обычно называются token breaker, о них мы расскажем чуть позже.

Анализ поведения


Детектирование попыток эксплуатации уязвимостей в параметрах запроса — не единственная задача WAF. Важно выявлять и саму процедуру поиска уязвимости, которая может проявляться в попытках сканирования, брутфорса директорий, фаззинга параметров и прочих часто применяемых автоматизированными средствами методик обнаружения уязвимостей и соответственным образом реагировать на них. Более продвинутые WAF даже умеют строить цепочки запросов, «типичные» для нормального поведения пользователя и блокировать попытки отправки запросов в отличном от стандартного поведения порядке. Данный механизм не столько противодействует атакам, сколько затрудняет процесс нахождения уязвимости. Ограничение на количество запросов в минуту никак не скажется на типичном пользователе, но будет существенной помехой для сканера, работающего в несколько потоков.

Репутационный анализ


Еще один механизм, напрямую унаследованный от межсетевых экранов и антивирусов. Сегодня почти любой WAF включает в себя списки адресов VPN-сервисов, анонимайзеров, узлов Tor-сети, участников ботнетов, которые могут применяться для блокировки запросов, исходящих от подозрительных адресов. Более продвинутые WAF умеют автоматически обновлять свои базы и вносить в них дополнительные записи на основе анализируемого трафика.

Машинное обучение


Один из самых спорных моментов в WAF. Данный механизм сложнее всего описать, и тому есть множество причин. Для начала, стоит отметить, что само понятие «машинное обучение» крайне обширно и фактически включает в себя множество технологий и методик. Кроме того, «машинное обучение» считается лишь одним из классов методов ИИ. «Внедрение» машинного обучения или «использование ИИ» — очень популярный маркетинговый ход. Зачастую непонятно, какие методы и алгоритмы используются на практике, а иногда со стороны атакующего кажется, что машинное обучение в WAF — это лишь красивые слова. Среди тех игроков рынка, кто действительно смог подчинить себе всю мощь машинного обучения, мало кто готов делиться своим опытом. Всё это складывается в довольно печальную картину для «человека извне», желающего разобраться в вопросе. И всё же попробуем выделить хотя бы парочку здравых идей на основе доступной информации.
Во-первых, машинное обучение полностью зависит от тех данных, на основе которых оно осуществлялось, и это зачастую является большой проблемой. Требуется наличие у компании-разработчика актуальной и полной коллекции существующих атак и их методов применения, что довольно непросто. По этой причине многие поставщики тщательно логируют результаты работы своих WAF и сотрудничают с другими компаниями, предлагающими IDS, SIEM системы для доступа к реальным примерам атак. Во-вторых, модель, обученная на «сферическом веб-приложении в вакууме» может оказаться попросту неэффективной при установке на реальное веб-приложение клиента. Для наилучшего эффекта считается правильным проводить дополнительное обучение модели на стадии внедрения WAF у клиента, что требует дополнительных расходов, времени, организационных трудностей, а также не гарантирует лучшего результата.

Идентифицируем WAF


Разработчики WAF по-разному подходят к оповещению пользователя о том, что WAF заблокировал запрос. Поэтому, анализируя ответ на наш атакующий запрос, мы можем понять, каким именно WAF защищено веб-приложение. Для этого часто используется термин WAF Fingerprint. Это может помочь в случае, если WAF по какой-либо причине не обновляется (обычно это относится к WAF с открытым исходным кодом). Разработчики проприетарных WAF заботятся о клиентах и реализуют механизм автообновления. Также, если мы смогли идентифицировать WAF и он оказался обновленным до последней версии, все равно сведения о конкретном WAF помогут нам немного узнать о специфике его работы.

Перечислим основные места, по которым можно идентифицировать WAF:

  • Дополнительные куки
  • Дополнительные заголовки, добавляемые к любому ответу или запросу
  • Содержание ответа (в случае блокировки запроса)
  • Код ответа (в случае блокировки запроса)
  • IP-адрес (относится к Cloud WAF)
  • JS-модуль (Client-side WAF)


Для наглядности приведем несколько примеров.

PT AF
Код ответа при блокировке: 403
Может встраивать в страницу ответа клиентский модуль waf.js.
Тело ответа при блокировке:

Forbidden

Request ID: 2017-07-31-13-59-56-72BCA33A11EC3784


Дополнительный заголовок, который добавляет waf.js:

X-RequestId: cbb8ff9a-4e91-48b4-8ce6-1beddc197a30

Nemesida WAF
Код ответа при блокировке: 403
Тело ответа при блокировке:

Suspicious activity detected. Access to the site is blocked. If you think that is's an erroneous blocking, please email us at nwaf@pentestit.ru and specify your IP-address.

Wallarm
Код ответа при блокировке: 403
Дополнительный заголовок: nginx-wallarm

Citrix NetScaler AppFirewall
Дополнительные куки:

ns_af=31+LrS3EeEOBbxBV7AWDFIEhrn8A000;
ns_af_.target.br_%2F_wat=QVNQU0VTU0lP
TklEQVFRU0RDU0Nf?6IgJizHRbTRNuNoOpbBOiKRET2gA

Mod_Security ver. 2.9
Код ответа при блокировке: 403
Тело ответа при блокировке:


403 Forbidden

Forbidden

You don't have permission to access /form.php on this server.

Mod_Security ver. <2.9
Код ответа при блокировке: 406 или 501
Тело ответа при блокировке:
В теле ответа можно найти mod_security, Mod_Security или NOYB

Varnish FireWall
Добавляет в ответ заголовки вида:

X-Varnish: 127936309 131303037.
X-Varnish: 435491096
Via: 1.1 varnish-v4

Разработчики WAF сами решают, какой код ответа возвращать в случае блокировки запроса, бывают и специфические коды. К примеру, код 999 вернет Web_Knight WAF в случае блокировки запроса, а dotDefender вернет код 200 с пустым телом ответа или содержащим сообщение об ошибке.
Также не стоит забывать, что WAF, как и любое приложение, развивается и видоизменяется. Поэтому всегда важно проверять актуальность известных вам «отпечатков». Кроме того, разработчики могут сделать кастомную страницу ответа при блокировке с каким-либо другим содержанием.

WAF bypass cheatsheet


Общая идея нахождения способов обхода WAF — привести нужный нам запрос к виду, в котором он всё ещё понятен атакуемому веб-приложению, но при этом не понятен или кажется безобидным для WAF. Важно отметить, что один тип WAF должен уметь обслуживать большое количество различных типов серверов, включая экзотические, такие как Unicorn, Tornado, Weblogic, Lighthttpd etc… Каждый сервер может по-разному воспринимать те или иные исключительные случаи парсинга HTTP-запроса, что должно быть учтено в WAF. Таким образом, атакующий может воспользоваться спецификой парсинга HTTP-запроса атакуемого сервера для того, чтобы найти способ обхода WAF.

59e395afb9650235665851.png

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

Добавление спецсимволов


Различные спецсимволы могут нарушать логику работы WAF и при этом быть понятными самому серверу. Вариации спецсимволов тоже могут быть любыми: их можно преобразовать в urlencode (но большинство WAF уже давно с этим справляются) или в иные кодировки. Можно также вставлять спецсимволы в запрос без какой-либо кодировки, в raw-формате, что может оказаться довольно неожиданно для WAF. Например, \r\n\r\n в таком виде может восприниматься как конец HTTP-request body, а null byte может вообще нарушать логику работы регулярных выражений и парсеров различных форматов данных. Также могут быть полезны и другие спецсимволы из первых двух десятков символов ASCII-таблицы.
Примеры полезных спецсимволов:

  • 0×00 — Null byte;
  • 0×0D — Carriage return;
  • 0×0A — Line feed;
  • 0×0B — Vertical Tab;
  • 0×09 — Horizontal tab;
  • 0×0C — New page


При поиске bypass будет полезно вставлять спецсимволы в различные места в теле запроса, не ограничиваясь включением в значение параметра. Например, если запрос представлен в формате JSON, то можно вставлять null byte как в один из параметров, так и между параметрами, и в начале JSON, и в конце. То же самое относится и к остальным форматам тела POST-запроса. В общем, рекомендуем исследовать и развлекаться, искать места, которые может проверять или парсить WAF, и пробовать там разные спецсимволы.
Например:

{"id":1337,"string0x00":"test' or sleep(9)#"}
{"id":1337,"string":"test'/*0x00*/ or sleep(9)#"}
{"id":1337,"string"0x0A0x0D:"test' or sleep(9)#"}


clickme
clickme


Для наглядности мы заменили спецсимволы на их hex представление.

Замена пробельных символов


В отдельную категорию стоит выделить замену пробелов на эквивалентные символы. Например, большинство синтаксисов предполагает разделение ключевых слов и операторов пробельными символами, однако строго не указывает, какой именно символ должен быть использован. Таким образом, вместо привычных 0×20 (Space) могут быть использованы 0×0B (Vertical Tab), 0×09 (Horizontal tab). Также в эту категорию стоит отнести замену пробельных символов на разделяющие конструкции, не несущие смысловой нагрузки. В SQL, например, это /**/ (многострочный SQL комментарий), #\r\n (однострочный SQL комментарий, завершающийся переносом строки), --\r\n (альтернативный однострочный SQL комментарий, завершающийся переносом строки). Вот несколько примеров:

http://test.com/test?id=1%09union/**/select/**/1,2,3
http://test.com/test?id=1%09union%23%0A%0Dselect%2D%2D%0A%0D1,2,3


Также можно изменить выражение таким образом, чтобы, используя синтаксис языка, избавиться от пробелов. К примеру, в SQL можно воспользоваться скобками:

UNION(SELECT(1),2,3,4,5,(6)FROM(Users)WHERE(login='admin'))


А в JS использовать символ /: