Не смотря на то, что в последнем публиковавшемся перечне уязвимостей OWASP Top 10 2017 CSRF атаки отнесены к разряду “Удалены, но не забыты”, мы решили, что не будет лишим еще раз напомнить о том, как защититься от CSRF атак, опираясь на те же правила, предоставляемые OWASP.
Использование CSRF токена
Использование токена (как stateless, так и statefull методов) является первичным и самым популярным способом защиты. Токен должен быть уникален для каждой пользовательской сессии, сгенерирован криптографически стойким генератором псевдослучайных чисел. OWASP при этом рекомендует для шифрования использовать алгоритм AES256-GCM и SHA256/512 при использовании HMAC.
Существует несколько подходов к работе с токенами: Synchronizer Token, Encryption based Token Pattern, HMAC Based Token
Synchronizer Token
При использовании подхода Synchronizer Token (statefull метод) подразумевается отправка токена при каждом запросе, подразумевающем какие-то изменения на стороне сервера. Если токен не является валидным, то сервер отклоняет запрос.
При отправке запроса на сервер рекомендуется добавлять токен в параметры запроса, нежели в заголовок. Если все же вставляете токен в заголовок запроса, то убедитесь, что он не логируется на сервере. Полученный токен можно сохранять на стороне клиента в скрытом поле:
<form action="/post.php" method="post"> <input type="hidden" name="CSRFToken" value="l5824xNMAYFesBxing975yR8HPJlHZ"> ... </form>
в заголовках:
POST /page HTTP/1.1 Accept: application/json, application/xml, text/json, text/x-json, text/javascript, text/xml User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36 Content-Type: application/json Host: example.com X-CSRF-TOKEN: l5824xNMAYFesBxing975yR8HPJlHZ
или в куках
POST /page HTTP/1.1 Host: example.com Set-Cookie: CSRFToken=l5824xNMAYFesBxing975yR8HPJlHZ; Content-Type: application/x-www-form-urlencoded
OWASP рекомендует хранить токен в заголовках, объясняя это тем, что даже если токен раскрыт или у него истек срок действия, то атакующий все равно не сможет подделать запрос, благодаря особенностям работы браузеров.
Также для повышения уровня безопасности предложенного метода, предлагается генерировать случайное имя параметра токена и/или сам токен для каждого запроса. При таком подходе время, в течение которого злоумышленник может воспользоваться украденным токеном, минимально. Однако это может привести к проблемам с юзабили. Например, нажатие на кнопку “Назад” может привести к отправке на сервер невалидного токена, который содержался на предыдущей странице.
Отправка токена, используя GET запрос, не рекомендуется, так как при таком подходе токен может быть раскрыт: в истории браузера, лог файлах, referrer заголовках.
Encryption based Token
Данный подход является stateless, так как использует шифрование/дешифроврование для валидации токена, а значит не требует хранения токена на стороне сервера.
Сервер генерирует токен, состоящий из идентификатора сессии и timestamp (для предотвращения атаки повторного воспроизведения). Для шифрования рекомендуется использовать алгоритм шифрования AES256 в режиме блочного шифрования GSM/GSM-SIV. Использование режима ECB строго не рекомендуется. Зашифрованный сервером токен возвращается клиенту так же как и в случае с «Synchronizer Token» в скрытом поле формы или же в заголовке/параметре ответа. При получении токена сервер должен расшифровать его, после чего сверить идентификатор сессии, а также сверить timestamp с текущим временем и убедиться, что оно не превышает установленного времени жизни токена.
Если сверка идентификатора сессии проходит успешно, а timesmap – нет, то запрос может считаться валидным. Во всех остальных случаях рекомендуется отклонять запрос и регистрировать его, чтобы в дальнейшем понять как реагировать на попдобные запросы.
HMAC Based Token
Также не требует хранения токена, принцип работы похож на Encryption based Token, за исключением того, что вместо шифрования токена используется HMAC (hash-based message authentication code) функция для генерации токена (рекомендуется использовать SHA256 или более сильный алгоритм). При этом токен представляет из себя результат HMAC функции от идентификатора сессии пользователя+ timestamp.
Автоматизация работы с токенами
Главная проблема в противодействии CSRF атакам заключается в том, что разработчики часто просто забывают добавлять функционал обеспечивающий работу с токенами. Чтобы избежать подобных проблем стоит автоматизировать данный прцоесс:
• Напишите обертку, автоматически добавляющую токен к запросам через тег form или при использовании ajax. Например, Spring Security использует подобный подход каждый раз, когда используется тег <form:form>
• Напишите хук, который перехватывает трафик и добавляет токены ко всем уязвимым ресурсам. Так как довольно трудно проанализирвоать какой запрос выполняет изменение состояния, нуждаясь в токене, рекомендуется включать токены во все POST ответы, но стоит при этом учитывать затраты на производительность.
• Автоматически добавлять токен при рендере страницы. Даный подход используется CSRF Guard: токены добавляются ко всем href и src аттрибутам, скрытым полям и во все формы.
Прежде чем пытаться написать собственную систему автоматической генерации токена, рекомендуется уточнить имеет ли используемый вами фреймворк возможность по умолчанию обеспечить защиту от CSRF атак. Например, тот же фреймворк Django реализует защиту от CSRF.
Login CSRF
Воспользовавшись CSRF в форме входа, злоумышленник может войти в систему,
под видом жертвы. С такой уязвимостью сталкивались такие гиганты как PayPal и Google.
Бороться с CSRF в форме входа можно путем создания пре-сессий, которые создаются до того, как пользователь прошел аутентификацию, и включением токенов в форму входа.
Samesite Cookie
SameSite Cookie – атрибут, описанный в RFC6265bis, цель которого – противодействие CSRF атакам. Работает это следующим образом. Один из способов защиты – проверка заголовков origin и referer, по которым можно понять откуда пришел запрос, но такой подход требует внедрения механизма проверки. Используя атрибут SameSite, мы ограничиваем отправку куки с запросом с посторонних ресурсов. У данного атрибута есть несколько возможных значений: Strict, Lax и None.
Использование значения strict подразумевает, что браузер не будет отправлять куки с любых источников, не совпадающих с доменным именем текущего ресурса.
Значение lax дает возможность не блокировать куки с внешних ресурсов, переход с которых был осуществлен безопасным способом – по протоколу HTTPS. Lax обеспечивает баланс между удобством использования ресурса для пользователей и безопасностью.
Выставить атрибут довольно просто:
Set-Cookie: JSESSIONID=xxxxx; SameSite=Strict Set-Cookie: JSESSIONID=xxxxx; SameSite=Lax
На момент написания статьи поддержка атрибута браузерами выглядит вот так:
Важно помнить, что данный атрибут стоит использовать как дополнительную меру защиты, а не как способ обойтись без использования CSRF токена.
Проверка заголовков
Как уже упоминалось выше, один методов защиты – проверка значений referrer и origin заголовка запроса.
Суть данной проверки сводится к проверке значений заголовков на стороне сервера. Если они совпадают с ресурсом, то запрос считается корректным, в противном случае отклоняется. Если заголовок Origin отсутствует, то нужно убедиться, что значение Referrer соответствует текущему ресурсу. OWASP рекомендует отклонять запросы, которые не содержат Origin или Referrer заголовки. Также можно логгировать все подобные запросы, чтобы после проанализировать их и принять решение о том как с ними поступать.
Однако все усложняется, если ваше приложение находится за прокси-сервером, поскольку URL в заголовке при этом будет отличаться. В таком случае есть несколько вариантов:
• Сконфигурируйте ваше приложение таким образом, чтобы всегда знать происхождение запроса. Проблема подобного подхода заключается в установке правильного значения, если ваше приложение развернуто на нескольких окружениях (например, dev, QA, production), что приводит проблеме поддержки.
• Используйте заголовок Host. Данный заголовок даст возможность определять источник запрос не зависимо от окружения.
• Используйте заголовок X-Forwarded-Host, цель которого — хранение исходных заголовоков, полученного прокси-сервером.
Все описанные методы работают только когда присутствуют заголовки origin и referer. Но встречаются случаи, когда данные заголовки отсутствуют. Вот ряд случаев, когда эти заголовки не включаются в запрос:
• IE 11 не включается заголовок Origin для доверенных сайтов. Остается полагаться только на заголовок Referer
• В случае перенаправления Origin не включен в запрос, так как считается, что он может содержать конфиденциальную информацию, которую не следует отправлять другому источнику.
• Заголовок Origin включен для всех межсайтовых запросов, но большинство браузеров добавляют его только для POST/DELETE/PUT запросов
Как правило незначительное количество трафика попадает под описанные категории, но часто не хочется терять даже эту малую часть пользователей, поэтому принято считать валидным запрос, со значением null для origin/referrer или со значением, соответствующим списку доверительных доменов.
Double Submit Cookie
Данный подход довольно прост в реализации и не требует хранения токена на стороне сервера (stateless). Суть метода заключается в отправке пользователем токена в параметре запроса и в куках. На каждый запрос, требующий изменения состояния, сверяем значение токена в куках и в запросе. Если сверка идентификатора сессии проходит успешно, а timesmap – нет, то запрос может считаться валидным
ссылка на оригинал статьи https://habr.com/ru/company/acribia/blog/476880/
Добавить комментарий