Эксклюзивно для codeby.net продолжаю публиковать перевод ресерчей по книге 2021 года от Brandon Wieser The Hackers Codex: Modern Web Application Attacks Demystified.
В этот раз разберем CSRF уязвимости и как их находить.
CRSF
Прежде чем мы обсудим следующий тип cross-origin атак, нам нужно определить новую концепцию - идею запроса, изменяющего состояние данных (state-changing request). В контексте безопасности веб-приложений, запрос на изменение состояния может быть определен как веб-запрос, который изменяет хранящуюся информацию с одного значения на другое. Например, запросы, которые изменяют информацию профиля пользователя (адрес, номер телефона, имя и т. д.), учетные данные пользователя, электронную почту для сброса пароля, независимо от того, включена ли для пользователя двухфакторная аутентификация, перевод средств с одного банковского счета на другой или автоматическая покупка товара в интернет-магазине (Amazon's One-Click Buy, например).
Несмотря на то, что существует множество книг и ресурсов, посвященных CSRF атакам, давайте кратко рассмотрим вектор атаки. Для тех, кто не знает – согласно OWASP, подделка межсайтовых запросов (CSRF) - это «атака, которая заставляет конечного пользователя выполнять нежелательные действия в веб-приложении, в котором в настоящее время они аутентифицированы. С небольшой помощью социальной инженерии (например, отправки ссылки по электронной почте или в чате), злоумышленник может обмануть пользователя приложения для выполнения действий по выбору злоумышленника. Если жертвой стал обычный пользователь, то успешная CSRF-атака может заставить его выполнить запрос на изменение данных (state-changing request), например перевод средств, изменение адреса электронной почты и так далее. Если жертвой стал пользователь с правами админа, CSRF может скомпрометировать все веб-приложение".
Есть несколько книг и ресурсов, которые посвящены тестированию CSRF уязвимостей; однако большинство современных фреймворков программирования автоматически защищаются от большинства этих атак.
Например,
Хотя большинство фреймворков предоставляют защиту по умолчанию, которую легко настроить, в некоторых случаях CSRF все еще может возникнуть.
Например,
Аналогичным образом,
По сути, в этих документах упоминается тот факт, что по умолчанию защита от CSRF может быть реализована только с помощью HTTP-методов PATCH, POST, PUT и / или DELETE. Если разработчик реализовал запрос на изменение данных с помощью запроса GET, эти средства защиты по умолчанию не могут спасти пользователя.
Резюмируя и уточняя, если вы видите действие, изменяющее состояние (например, изменение учетных данных, обновление адреса электронной почты для сброса пароля, перевод средств на счет в банке), осуществляющееся любым HTTP-методом, кроме PATCH, POST, PUT, и / или DELETE, стоит здесь внимательнее осмотреться, вероятно, запрос уязвим для CSRF.
Кроме того, есть и другая интересная информация в документации Spring. Например, в разделе JSON говорится: «Распространенный вопрос: нужно ли мне защищать запросы JSON, отправленные через JavaScript? Короткий ответ: это зависит от обстоятельств. Однако вы должны быть очень осторожны, поскольку существуют CSRF, которые могут повлиять на запросы JSON.
Например, злоумышленник может
CSRF-эксплойт для JSON
Что сгенерирует следующую JSON Структуру:
JSON-структура, которая будет отправлена в запросе
Если бы приложение не проверяло Content-Type, то оно было бы подвержено этому эксплойту. В зависимости от настройки, приложение Spring MVC (которое проверяет Content-Type) может быть проэксплуатировано, путем добавления в URL суффикса, чтобы заканчиваться на ".json", как показано ниже:
Использование .json в форме приводит к попытке отправить данные в JSON формате
Кроме того,
И хотя эта информация подходит для Spring, вероятно, что большинство других фреймворков будут содержать те же слабые места. С точки зрения злоумышленника это великолепная находка. По сути, документация говорит нам внимательно присмотреться к JSON-запросам, изменяющим состояния (state-changing JSON requests), сделанным в JavaScript, потому что их можно будет использовать для CSRF-атак.
Обход защиты от CSRF. Получение CSRF токена через CORS уязвимость
В случае когда злоумышленник может обойти Same Origin Policy (см. предыдущие статьи), например через XSS-уязвимость или используя неверную конфигурацию CORS, он сможет затем обойти и защиту от CSRF, используемую в приложении (т.н. проверка CSRF-токенов). Давайте для примера, возьмем прошлые данные
и проэсплуатируем с помощью JavaScript ошибку отражения Origin (Origin Reflection).
Как вы можете помнить, скрипт заставляет конечного пользователя, который посещает вредоносную страницу, отправить запрос на сервер, в ответе которого есть конфиденциальные данные, а затем он сохраняет ответ в переменной, которая отправляется на сервер злоумышленника. Если злоумышленник может читать ответы на посылаемые запросы, тогда ничто не мешает ему прочесть CSRF токен и включить этот токен в дальнейший запрос. Например, представьте, что следующий код JavaScript (взятый из
и размещен на веб-сервере злоумышленника.
По сути, атака работает так:
1. Жертва с активным файлом cookie сеанса уязвимого приложения переходит на сайт злоумышленника.
2. На сайте злоумышленников размещен вредоносный код JavaScript, который выполняет следующие действия через браузер жертвы:
Некоторые приложения пытаются защититься от CSRF, используя шаблон, называемый «шаблоном двойной отправки cookie». Например,
Затем в документации приводится «простой экспресс-пример», демонстрирующий использование «шаблона двойной отправки cookie». Ниже приводится пример некоторого серверного кода, который генерирует форму, требующую CSRF токен для отправки.
документация ExpressJS о том как работает защищающий от CSRF шаблон двойной отправки cookie
Внутри установим значение csrfToken как значение скрытого поля ввода (hidden input name) с именем _csrf:
HTML-код для использования шаблона двойной отправки cookie
Как видно из строки «csrf ({cookie: true})», «шаблон двойной отправки cookie» активизирован. Давай копнем глубже. При нажатии в документации на ссылку «шаблон двойной отправки cookie» нам показывается
«Если содержание состояние для токена CSRF на стороне сервера проблематично, альтернативной защитой является использование метода двойной отправки cookie. Этот метод прост в реализации и самодостаточен. В этой технике мы отправляем случайное значение как в файле cookie, так и в качестве параметра запроса, а сервер проверяет совпадение значения cookie и значения запроса. Когда пользователь посещает (даже до аутентификации, чтобы предотвратить вход через CSRF), сайт должен сгенерировать (криптографически стойкое) псевдослучайное значение и установить его как cookie на машине пользователя отдельно от идентификатора сеанса. Затем сайт требует, чтобы в каждом транзакционном запросе содержалось это псевдослучайное значение как hidden value или как другой параметр/заголовок запроса. Если на стороне сервера проверка подтвердила, что cookie и параметр запроса совпадают, сервер обрабатывает запрос как легитимный, иначе он отклоняет запрос.
Поскольку субдомены могут записывать файлы cookie в родительские домены и файлы cookie могут быть установлены для домена через незащищенное HTTP-соединение, эта техника работает, пока вы уверены, что ваши поддомены полностью защищены и принимают только HTTPS-соединения…»
Подводя итог, «шаблон двойной отправки cookie» записывает в cookie случайное значение, и такое же значение отправляется в параметре запроса. При поступлении запросов на изменение данных приложение проверяет соответствие этих двух значений (значение cookie и значение параметра запроса). Как изображено на картинке:
Согласно документации, если существует уязвимость поддомена, неправильная конфигурация CORS, ошибка XSS в любом поддомене или какой-либо из поддоменов не использует HTTPS, тогда можно обойти механизм защиты от CSRF.
Кроме того, возможен другой вектор атаки, о котором не говорится в документации. Если злоумышленник может создать и установить значение или перезаписать произвольные cookie (или даже CSRF cookie), то также можно обойти защиту. Это не такая уж и редкость, чтобы обнаружить уязвимость, которая позволяет злоумышленнику устанавливает значения cookie (в моем случае это случается не реже нескольких раз в год во время тестирования веб-приложений на проникновение, прим. автора). Более серьезные векторы подобных атак могут быть через уязвимость внедрения заголовка (header injection) или когда значение параметра запроса напрямую используется для установки значения cookie.
Обычно в баг-баунти эти уязвимости игнорируются или получают «информационные» или «низкие» рейтинг серьезности (если это не header injection); однако в случае "шаблона двойной отправки cookie" во многих случаях его можно использовать для обхода механизма защиты CSRF. Более подробную информацию можно найти в
Подводя итог, для поиска уязвимостей CSRF выполните следующие действия:
1. Определите все возможные содержащиеся в приложении функции, изменяющие информацию (state-changing actions), особо отмечая любое использование «шаблона двойной отправки cookie».
3. Для каждого запроса сначала попытайтесь удалить токен CSRF и ретранслировать запрос.
4. Если в запросе на изменение информации НЕ используется какой-либо из методов PATCH, POST, PUT и / или DELETE - попытайтесь выполнить CSRF-атаку.
5. Измените любой из запросов PATCH, POST, PUT и / или DELETE на GET и воспроизвести запрос. Если приложение принимает запрос, удалите все токены CSRF, отправляемые в URL-адресе, и повторите попытку.
6. Для любых JSON или AJAX запросов попытайтесь изменить «Content-Type» на «text/plain». Если приложение принимает запрос, создайте proof of concept, подобно показанному на рисунке
В этот раз разберем CSRF уязвимости и как их находить.
- Html Injection
- Host Header Injection
- Username Enumeration – SSN
- Same Origin Policy и Exploiting CORS Misconfigurations
- Origin Reflection Attacks
- CSRF
- CSRF Bypass – Clickjacking Drag and Drop
- Redirection Bugs
- XSS – Cross-Site Scripting
- Identifying XSS Vulnerabilities
- JSONP
- Language-Specific XSS
- SOME Attacks
- CSV Injection
- HTTP Desync
- Web Cache Poisoning
CRSF
Прежде чем мы обсудим следующий тип cross-origin атак, нам нужно определить новую концепцию - идею запроса, изменяющего состояние данных (state-changing request). В контексте безопасности веб-приложений, запрос на изменение состояния может быть определен как веб-запрос, который изменяет хранящуюся информацию с одного значения на другое. Например, запросы, которые изменяют информацию профиля пользователя (адрес, номер телефона, имя и т. д.), учетные данные пользователя, электронную почту для сброса пароля, независимо от того, включена ли для пользователя двухфакторная аутентификация, перевод средств с одного банковского счета на другой или автоматическая покупка товара в интернет-магазине (Amazon's One-Click Buy, например).
Несмотря на то, что существует множество книг и ресурсов, посвященных CSRF атакам, давайте кратко рассмотрим вектор атаки. Для тех, кто не знает – согласно OWASP, подделка межсайтовых запросов (CSRF) - это «атака, которая заставляет конечного пользователя выполнять нежелательные действия в веб-приложении, в котором в настоящее время они аутентифицированы. С небольшой помощью социальной инженерии (например, отправки ссылки по электронной почте или в чате), злоумышленник может обмануть пользователя приложения для выполнения действий по выбору злоумышленника. Если жертвой стал обычный пользователь, то успешная CSRF-атака может заставить его выполнить запрос на изменение данных (state-changing request), например перевод средств, изменение адреса электронной почты и так далее. Если жертвой стал пользователь с правами админа, CSRF может скомпрометировать все веб-приложение".
Есть несколько книг и ресурсов, которые посвящены тестированию CSRF уязвимостей; однако большинство современных фреймворков программирования автоматически защищаются от большинства этих атак.
Например,
Ссылка скрыта от гостей
заявляет: «CSRF защита включена по умолчанию с конфигурацией Java. Если вы хотите отключить CSRF, см. соответствующую конфигурацию Java. Посмотрите функцию csrf() в Java-документации для дополнительных настроек защиты CSRF».Хотя большинство фреймворков предоставляют защиту по умолчанию, которую легко настроить, в некоторых случаях CSRF все еще может возникнуть.
Например,
Ссылка скрыта от гостей
(гласит: «Самая главная защита от CSRF-атак заключается в том, чтобы гарантировать, что запросы GET (и другие "безопасные" методы, как определено RFC 7231 # section-4.2.1) не имеют побочных эффектов. Запросы через "небезопасные" методы, такие как POST, PUT и DELETE, могут быть защищены, через выполнение следующих действий…».Аналогичным образом,
Ссылка скрыта от гостей
говорится: «Первый шаг к защите от CSRF-атак - убедиться, что ваш веб-сайт использует правильные HTTP-методы. В частности, перед использованием CSRF Spring Security вы должны быть уверены, что ваше приложение использует PATCH, POST, PUT и / или DELETE для всего, что изменяет состояние».По сути, в этих документах упоминается тот факт, что по умолчанию защита от CSRF может быть реализована только с помощью HTTP-методов PATCH, POST, PUT и / или DELETE. Если разработчик реализовал запрос на изменение данных с помощью запроса GET, эти средства защиты по умолчанию не могут спасти пользователя.
Резюмируя и уточняя, если вы видите действие, изменяющее состояние (например, изменение учетных данных, обновление адреса электронной почты для сброса пароля, перевод средств на счет в банке), осуществляющееся любым HTTP-методом, кроме PATCH, POST, PUT, и / или DELETE, стоит здесь внимательнее осмотреться, вероятно, запрос уязвим для CSRF.
Кроме того, есть и другая интересная информация в документации Spring. Например, в разделе JSON говорится: «Распространенный вопрос: нужно ли мне защищать запросы JSON, отправленные через JavaScript? Короткий ответ: это зависит от обстоятельств. Однако вы должны быть очень осторожны, поскольку существуют CSRF, которые могут повлиять на запросы JSON.
Например, злоумышленник может
Ссылка скрыта от гостей
:CSRF-эксплойт для JSON
Что сгенерирует следующую JSON Структуру:
JSON-структура, которая будет отправлена в запросе
Если бы приложение не проверяло Content-Type, то оно было бы подвержено этому эксплойту. В зависимости от настройки, приложение Spring MVC (которое проверяет Content-Type) может быть проэксплуатировано, путем добавления в URL суффикса, чтобы заканчиваться на ".json", как показано ниже:
Использование .json в форме приводит к попытке отправить данные в JSON формате
Кроме того,
Ссылка скрыта от гостей
, которое приводит к байпасу (обходу) защиты. Если приложение принимает Content-Type «application /x-www-form-urlencoded», тогда появляется возможность создать следующую форму запроса:
Код:
<form action=”https://redact.com/api/rest/model/atg/userprofiling/ProfileActor/updateMyData" method=”post”>
<input hidden=”true” type=”text” name=”firstName” value=”Foo”>
<input hidden=”true” type=”text” name=”lastName” value=”Bar”>
<input hidden=”true” type=”text” name=”email” value=”hacked@gmail.com”>
<input type=”text” hidden=”true” name=”gender” value=”Mujer”>
<input type=”text” name=”mobileNumber” hidden=”true” value=”+521452453698">
<input type=”text” name=”countryCode” hidden=”true” value=”+52">
<input type=”submit” value=”send”>
Обход защиты от CSRF. Получение CSRF токена через CORS уязвимость
В случае когда злоумышленник может обойти Same Origin Policy (см. предыдущие статьи), например через XSS-уязвимость или используя неверную конфигурацию CORS, он сможет затем обойти и защиту от CSRF, используемую в приложении (т.н. проверка CSRF-токенов). Давайте для примера, возьмем прошлые данные
и проэсплуатируем с помощью JavaScript ошибку отражения Origin (Origin Reflection).
Как вы можете помнить, скрипт заставляет конечного пользователя, который посещает вредоносную страницу, отправить запрос на сервер, в ответе которого есть конфиденциальные данные, а затем он сохраняет ответ в переменной, которая отправляется на сервер злоумышленника. Если злоумышленник может читать ответы на посылаемые запросы, тогда ничто не мешает ему прочесть CSRF токен и включить этот токен в дальнейший запрос. Например, представьте, что следующий код JavaScript (взятый из
Ссылка скрыта от гостей
) был добавлен к кодуи размещен на веб-сервере злоумышленника.
Код:
// Получение содержания страницы
var xhr = new XMLHttpRequest();
xhr.open("GET", "https://www.example.com/shop/viewAccount", false);
xhr.withCredentials=true;
xhr.send(null);
// извлечение со страницы CSRF токена
var token = xhr.responseText;
var pos = token.indexOf("csrftoken");
token = token.substring(pos,token.length).substr(12,50);
// теперь выполним CSRF атаку используя XHR с извлеченным токеном
xhr.open("POST", "https://www.example.com/shop/voteForProduct", false);
xhr.withCredentials=true;
var params = "productId=4711&vote=AAA&csrftoken="+token;
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.setRequestHeader("Content-length", params.length);
xhr.send(params);
По сути, атака работает так:
1. Жертва с активным файлом cookie сеанса уязвимого приложения переходит на сайт злоумышленника.
2. На сайте злоумышленников размещен вредоносный код JavaScript, который выполняет следующие действия через браузер жертвы:
а. Отправляет GET-запрос через браузер жертвы с учетными данными до конечной точки, которая содержит форму изменения данных.
б. Читает ответ на запрос из-за мисконфигурации CORS и ищет CSRF токен.
в. Создает новый POST-запрос с учетными данными и параметром значения, которые злоумышленник хочет изменить, и включает CSRF токен как одно из этих значений.
г. Отправляет этот POST-запрос, тем самым изменяя значение или выполнение действия, которое желает злоумышленник.
Обход защиты от CSRF. Внедрение CookieНекоторые приложения пытаются защититься от CSRF, используя шаблон, называемый «шаблоном двойной отправки cookie». Например,
Ссылка скрыта от гостей
описывает опцию, позволяющую включить этот шаблон; однако по умолчанию она отключена. Документация заявляет: «Определитесь, должен ли секретный токен для пользователя храниться в cookie или в req.session. Хранение секретного токена в файле cookie активизирует шаблон двойной отправки cookie. По умолчанию - false».Затем в документации приводится «простой экспресс-пример», демонстрирующий использование «шаблона двойной отправки cookie». Ниже приводится пример некоторого серверного кода, который генерирует форму, требующую CSRF токен для отправки.
документация ExpressJS о том как работает защищающий от CSRF шаблон двойной отправки cookie
Внутри установим значение csrfToken как значение скрытого поля ввода (hidden input name) с именем _csrf:
HTML-код для использования шаблона двойной отправки cookie
Как видно из строки «csrf ({cookie: true})», «шаблон двойной отправки cookie» активизирован. Давай копнем глубже. При нажатии в документации на ссылку «шаблон двойной отправки cookie» нам показывается
Ссылка скрыта от гостей
:«Если содержание состояние для токена CSRF на стороне сервера проблематично, альтернативной защитой является использование метода двойной отправки cookie. Этот метод прост в реализации и самодостаточен. В этой технике мы отправляем случайное значение как в файле cookie, так и в качестве параметра запроса, а сервер проверяет совпадение значения cookie и значения запроса. Когда пользователь посещает (даже до аутентификации, чтобы предотвратить вход через CSRF), сайт должен сгенерировать (криптографически стойкое) псевдослучайное значение и установить его как cookie на машине пользователя отдельно от идентификатора сеанса. Затем сайт требует, чтобы в каждом транзакционном запросе содержалось это псевдослучайное значение как hidden value или как другой параметр/заголовок запроса. Если на стороне сервера проверка подтвердила, что cookie и параметр запроса совпадают, сервер обрабатывает запрос как легитимный, иначе он отклоняет запрос.
Поскольку субдомены могут записывать файлы cookie в родительские домены и файлы cookie могут быть установлены для домена через незащищенное HTTP-соединение, эта техника работает, пока вы уверены, что ваши поддомены полностью защищены и принимают только HTTPS-соединения…»
Подводя итог, «шаблон двойной отправки cookie» записывает в cookie случайное значение, и такое же значение отправляется в параметре запроса. При поступлении запросов на изменение данных приложение проверяет соответствие этих двух значений (значение cookie и значение параметра запроса). Как изображено на картинке:
Согласно документации, если существует уязвимость поддомена, неправильная конфигурация CORS, ошибка XSS в любом поддомене или какой-либо из поддоменов не использует HTTPS, тогда можно обойти механизм защиты от CSRF.
Кроме того, возможен другой вектор атаки, о котором не говорится в документации. Если злоумышленник может создать и установить значение или перезаписать произвольные cookie (или даже CSRF cookie), то также можно обойти защиту. Это не такая уж и редкость, чтобы обнаружить уязвимость, которая позволяет злоумышленнику устанавливает значения cookie (в моем случае это случается не реже нескольких раз в год во время тестирования веб-приложений на проникновение, прим. автора). Более серьезные векторы подобных атак могут быть через уязвимость внедрения заголовка (header injection) или когда значение параметра запроса напрямую используется для установки значения cookie.
Обычно в баг-баунти эти уязвимости игнорируются или получают «информационные» или «низкие» рейтинг серьезности (если это не header injection); однако в случае "шаблона двойной отправки cookie" во многих случаях его можно использовать для обхода механизма защиты CSRF. Более подробную информацию можно найти в
Ссылка скрыта от гостей
.Подводя итог, для поиска уязвимостей CSRF выполните следующие действия:
1. Определите все возможные содержащиеся в приложении функции, изменяющие информацию (state-changing actions), особо отмечая любое использование «шаблона двойной отправки cookie».
а. Если в этих функциях, используется шаблон двойной отправки cookie, проверьте домен на наличие ошибок по внедрению файлов cookie.
2. Настройте перехватывающий прокси, например BurpSuite, и один за другим выполните каждый запрос на изменение состояния, захватывая запрос в прокси.3. Для каждого запроса сначала попытайтесь удалить токен CSRF и ретранслировать запрос.
4. Если в запросе на изменение информации НЕ используется какой-либо из методов PATCH, POST, PUT и / или DELETE - попытайтесь выполнить CSRF-атаку.
5. Измените любой из запросов PATCH, POST, PUT и / или DELETE на GET и воспроизвести запрос. Если приложение принимает запрос, удалите все токены CSRF, отправляемые в URL-адресе, и повторите попытку.
6. Для любых JSON или AJAX запросов попытайтесь изменить «Content-Type» на «text/plain». Если приложение принимает запрос, создайте proof of concept, подобно показанному на рисунке
а. Если приложение проверяет «Content-Type», попробуйте создайте вторую форму, добавив «.json» к ссылке.
б. Кроме того, попробуйте изменить «Content-Type» на «Application/x-www-form-urlencoded».
7. Проверьте остальные функции, изменяющие информацию в обычном режиме.
Последнее редактирование: