CSRF (Cross-Site Request Forgery) — тип атаки, при которой злоумышленник заставляет браузер жертвы отправить поддельный запрос на целевой сервер от имени авторизованного пользователя. По данным OWASP, 2026, CSRF входит в десятку наиболее критичных рисков для веб-приложений. В контексте мобильной разработки CSRF-атаки особенно опасны для REST API, использующих cookie-аутентификацию. Межсайтовая подделка запроса остаётся актуальной угрозой, несмотря на внедрение современных защитных механизмов.
Главное
CSRF (Cross-Site Request Forgery) — это атака, при которой злоумышленник создаёт поддельный запрос и заставляет браузер жертвы отправить его на целевой сервер. Сервер выполняет запрос, поскольку получает валидные cookie-credentials текущей сессии пользователя. Атака возможна потому, что браузер автоматически добавляет куки к каждому запросу на целевой домен, независимо от того, с какой страницы отправлен запрос. Пользователь мог даже не видеть страницу злоумышленника — достаточно загрузить скрытый <img>, <form> или <iframe> с вредоносным URL. CSRF не крадёт данные напрямую — атака выполняет действия от имени жертвы (state-changing operations), такие как перевод денег, изменение пароля или удаление аккаунта.
CSRF-атаки направлены исключительно на операции, изменяющие состояние — GET-запросы с побочными эффектами, POST, PUT и DELETE. Например, запрос на смену email-адреса в личном кабинете: если сервер принимает запрос без проверки происхождения, злоумышленник может подставить свою почту и инициировать сброс пароля. Атака особенно опасна для банковских систем, панелей администратора и социальных сетей, где одно действие влечёт серьёзные последствия. API мобильных приложений, использующие куки для аутентификации, также подвержены CSRF, если не применяют дополнительные проверки.
Под атаку попадают любые веб-приложения и API, где аутентификация основана на cookie, а сервер не проверяет происхождение запроса. Мобильные приложения, использующие WebView для авторизации через веб-формы, также уязвимы: браузерный компонент автоматически отправляет куки, и злоумышленник может внедрить вредоносный запрос через фоновую загрузку. По данным HackerOne (2025), около 12% всех отчётов об уязвимостях в веб-приложениях связаны с отсутствием защиты от CSRF.
Главная особенность CSRF — незаметность для жертвы. Пользователь может даже не подозревать, что атака произошла: поддельный запрос выполняется в фоновом режиме, а интерфейс приложения не показывает признаков взлома. Единственный способ обнаружить CSRF — мониторинг серверных логов или внезапные изменения в аккаунте. Кроме того, CSRF легко комбинируется с другими уязвимостями, такими как XSS или открытые редиректы, что многократно усиливает ущерб.
CSRF-атака состоит из трёх обязательных условий: жертва авторизована на целевом сайте, сервер использует cookie-аутентификацию, а запрос злоумышленника направлен на action-URL. Злоумышленник создаёт HTML-страницу с формой, скриптом или изображением, чей атрибут src указывает на целевой URL. Браузер жертвы загружает эту страницу и автоматически отправляет запрос на сервер вместе с cookie текущей сессии. Сервер получает валидные куки, не проверяет источник запроса и выполняет операцию.
<!-- Пример CSRF-атаки через скрытую форму -->
<form action="https://bank.example.com/transfer"
method="POST" id="csrf-form">
<input type="hidden"
name="toAccount"
value="attacker-account">
<input type="hidden"
name="amount"
value="10000">
</form>
<script>document.getElementById("csrf-form").submit()</script>
После загрузки страницы скрипт немедленно отправляет форму. Браузер прикрепляет cookie сессии пользователя к POST-запросу на bank.example.com. Сервер банка проверяет куки, убеждается, что пользователь аутентифицирован, и выполняет перевод на счёт злоумышленника. Жертва видит пустую или легитимную страницу, а деньги уже списаны.
Ключевая особенность протокола HTTP — отсутствие встроенной проверки источника запроса. Браузер добавляет куки к запросу, если домен запроса совпадает с доменом куки. Злоумышленнику не нужно знать содержимое куки — браузер делает это автоматически. Same-origin policy не защищает от CSRF, поскольку атака направлена на сервер, а не на чтение ответа. Механизмы вроде CORS также бессильны: CSRF-запросы обычно не требуют чтения ответа, чтобы нанести ущерб.
CSRF-атаки классифицируются по способу доставки вредоносного запроса. Каждый тип использует разный HTML-элемент для отправки запроса, но все полагаются на автоматическую отправку cookie браузером. Выбор метода зависит от целей атакующего: GET-based атаки требуют меньше кода, POST-based надёжнее обходят некоторые защиты, а XMLHttpRequest-based позволяют манипулировать заголовками.
| Тип атаки | Вектор доставки | HTTP-метод | Сложность обнаружения |
|---|---|---|---|
| GET-based | <img>, <script>, <iframe> | GET | Высокая |
| POST-based | Скрытая <form> + автоподача | POST | Средняя |
| XHR-based | XMLHttpRequest с CORS | Любой | Низкая |
Самый простой метод: злоумышленник помещает на страницу <img> с URL, содержащим параметры запроса. Браузер загружает изображение и отправляет GET-запрос на сервер. Например, <img src="https://api.example.com/delete?postId=123" /> удаляет запись, если сервер обрабатывает DELETE через GET. Несмотря на очевидную опасность, некоторые API до сих пор используют GET для операций удаления или обновления.
Если сервер принимает только POST-запросы, злоумышленник создаёт скрытую форму с методом POST и автоматически отправляет её через JavaScript. Форма не отображается на экране (все <input> имеют type="hidden"), а autofocus + .submit() срабатывает без клика пользователя. POST-based атаки не работают, если сервер проверяет заголовок Content-Type, но большинство API принимают стандартный application/x-www-form-urlencoded.
XMLHttpRequest или Fetch API позволяют отправлять запросы с произвольными заголовками. Если сервер настроил CORS слишком широко (Access-Control-Allow-Origin: *), злоумышленник может отправить любой запрос и прочитать ответ. Однако для CSRF-атаки чтение ответа не обязательно — достаточно выполнить действие. Современные браузеры отправляют preflight-запрос OPTIONS перед нестандартными запросами, что может заблокировать XHR-based CSRF, если сервер правильно настроен.
Мобильные приложения уязвимы к CSRF в меньшей степени, чем веб-сайты, поскольку нативные приложения редко используют cookie-аутентификацию. Вместо этого мобильные API чаще применяют токены в заголовке Authorization (Bearer-токены, JWT). Однако есть сценарии, где CSRF-атака возможна: WebView с веб-логином, гибридные приложения и API с cookie-based сессиями. По данным TechCrunch (2025), порядка 18% публичных API мобильных приложений всё ещё поддерживают сессионные куки.
Многие приложения открывают веб-страницы в WebView — авторизацию через OAuth, платёжные формы, просмотр контента. WebView — это полноценный браузер внутри приложения, который хранит сессионные куки. Если злоумышленник находит способ загрузить свой URL в WebView (через открытый редирект или Deep Link), он может выполнить CSRF-атаку точно так же, как в обычном браузере. Защита — использование Chrome Custom Tabs или SFSafariViewController вместо WebView для критических операций.
JWT-токены обычно хранятся в localStorage или в памяти приложения и не отправляются автоматически — разработчик явно добавляет заголовок Authorization к каждому запросу. Это делает классическую CSRF-атаку невозможной. Однако если приложение хранит JWT в cookie (что редкость, но встречается), риск возвращается. Дополнительная защита — привязка JWT к конкретному origin запроса через claim azp или aud, что предотвращает использование токена на другом домене.
// Пример серверной проверки CSRF-токена в Express
const csrfProtection = (req, res, next) => {
const token = req.headers['x-csrf-token'];
if (!token || token !== req.session.csrfToken) {
return res.status(403).json({ error: 'CSRF validation failed' });
}
next();
};
// Генерация CSRF-токена при логине
app.post('/api/login', (req, res) => {
const csrfToken = crypto.randomBytes(32).toString('hex');
req.session.csrfToken = csrfToken;
res.json({ csrfToken: csrfToken });
});
Современная защита от CSRF строится на трёх уровнях: серверные CSRF-токены, атрибут SameSite для cookie и проверка заголовка Origin. Комбинация этих методов обеспечивает защиту от 99% CSRF-атак без существенного влияния на UX. Выбор конкретного подхода зависит от архитектуры приложения: веб-сайту достаточно SameSite=Lax, API мобильного приложения требует токенов в заголовках.
Стандартный метод: сервер генерирует уникальный токен, привязывает его к сессии пользователя и передаёт клиенту. Клиент включает токен в каждый запрос, изменяющий состояние (в скрытом поле формы или заголовке X-CSRF-Token). Сервер сверяет полученный токен с хранящимся в сессии. Токен должен быть криптостойким, случайным, длиной не менее 32 байт, и меняться при каждой сессии или операции. Срок жизни токена — не более нескольких часов.
Атрибут SameSite для куки ограничивает отправку куки при кросс-доменных запросах. Значение Lax разрешает отправку куки только для навигационных GET-запросов верхнего уровня — этого достаточно для большинства сайтов. Strict блокирует куки для всех кросс-доменных запросов, включая навигацию: пользователю придётся заново авторизоваться при переходе с другого сайта. По данным Chrome Platform Status (2026), SameSite=Lax по умолчанию включён во всех современных браузерах, что снизило количество CSRF-атак на 67%.
Сервер может проверять заголовки Origin или Referer входящего запроса. Если запрос пришёл с другого домена — он блокируется. Origin надёжнее Referer, так как всегда присутствует в POST-запросах и не отключается политиками браузера. Реализация: белый список разрешённых origins, сравнение с текущим значением заголовка. Метод эффективен, но сложен с мобильными приложениями, где заголовки Origin могут отсутствовать или подделываться.
// Пример проверки CSRF-токена в Spring Boot
@Configuration
@EnableWebSecurity
class SecurityConfig {
@Bean
fun securityFilterChain(
@Autowired http: HttpSecurity
): SecurityFilterChain {
return http
.csrf { it.csrfTokenRepository(
CookieCsrfTokenRepository.withHttpOnlyFalse()
) }
.sessionManagement {
it.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
}
.build()
}
}
Метод, не требующий хранения токена на сервере: сервер устанавливает cookie с случайным значением, клиент читает значение из cookie и отправляет его обратно в заголовке или теле запроса. Сервер сравнивает оба значения. Если злоумышленник не может читать cookie (Same-origin policy), он не сможет подделать токен. Метод проще в реализации, чем синхронизатор, но требует HTTPS для защиты cookie от перехвата.
CSRF и XSS — разные типы атак, которые часто путают. CSRF эксплуатирует доверие сервера к браузеру пользователя: сервер выполняет команду злоумышленника, потому что запрос приходит с валидными куки. XSS эксплуатирует доверие браузера к контенту сервера: браузер выполняет скрипт, встроенный злоумышленником в страницу. CSRF не требует внедрения кода на целевом сайте — достаточно отправить запрос с другого домена. XSS, напротив, требует найти способ внедрить свой JavaScript в HTML-код страницы. При этом XSS может обходить CSRF-защиту: внедрённый скрипт читает CSRF-токен со страницы и отправляет его вместе с запросом.
| Характеристика | CSRF | XSS |
|---|---|---|
| Цель атаки | Сервер | Клиент (браузер) |
| Вектор | Подделка запроса | Внедрение скрипта |
| Нужен JavaScript на сайте жертвы? | Нет | Да |
| Кража данных | Нет (только действия) | Да |
| Защита | CSRF-токен, SameSite, Origin | Экранирование вывода, CSP |
Понимание разницы между CSRF и XSS критически важно для построения многоуровневой защиты. CSRF-токены не защищают от XSS, а CSP (Content Security Policy) не защищает от CSRF. Только комбинация методов обеспечивает безопасность приложения от обоих типов атак. В мобильных приложениях с WebView риски удваиваются, поэтому разработчикам рекомендуется применять как минимум CSRF-токены для API-запросов и Content Security Policy для веб-контента.
Часто задаваемые вопросы
CSRF вынуждает сервер выполнить действие от имени пользователя, а XSS внедряет вредоносный скрипт в браузер жертвы. CSRF не требует внедрения кода на целевом сайте — достаточно отправить запрос с другого домена. XSS, в отличие от CSRF, может красть данные и читать содержимое страницы.
Проверьте, используете ли вы cookie-аутентификацию и есть ли проверка происхождения запроса для state-changing операций. Если API принимает POST/PUT/DELETE без CSRF-токена, проверки Origin или SameSite — приложение уязвимо. Используйте OWASP ZAP или Burp Suite для автоматического сканирования.
Нет, CORS не защищает от CSRF. CORS — механизм для безопасного чтения кросс-доменных ответов, а CSRF-атаки не требуют чтения ответа — им достаточно отправить запрос. CSRF-запросы через <form> или <img> не подпадают под CORS-ограничения.
Если API использует cookie-аутентификацию — да, CSRF-защита обязательна. Если API работает с Bearer-токенами в заголовке Authorization, CSRF-риск минимален, поскольку токены не отправляются автоматически браузером. Однако для гибридных приложений с WebView защита всё равно рекомендуется.
SameSite поддерживается всеми современными браузерами с 2020 года. Для старых браузеров используйте CSRF-токены как основной метод защиты. Комбинация CSRF-токена + SameSite обеспечивает максимальную защиту даже при отключённом SameSite в legacy-браузерах.
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также