Cross-Site Request Forgery (CSRF) — это тип атаки, при котором злоумышленник заставляет пользователя выполнить нежелательное действие на веб-сайте, где он уже авторизован. Атака обычно включает отправку подложных запросов от имени пользователя, что может привести к несанкционированным изменениям данных, например, переводам средств, изменениям паролей или публикациям сообщений. Эти запросы часто отправляются без ведома пользователя и используют его текущую сессию.
Для выполнения CSRF-атаки злоумышленник может воспользоваться уязвимостью в веб-приложении, не требующем дополнительной авторизации для выполнения запросов, например, запросов POST. Поскольку большинство современных приложений используют механизмы аутентификации с помощью cookies, атакующие могут отправить запрос с подделанными данными, которые будут выглядеть как запрос от законного пользователя. Проблема заключается в том, что браузеры автоматически прикрепляют cookies, ассоциированные с доменом, к каждому запросу, что делает такие атаки возможными.
Для защиты от CSRF-атак применяются различные методы, направленные на проверку подлинности запросов. Рассмотрим основные из них.
Самым популярным методом защиты является использование уникальных токенов, которые отправляются вместе с запросами. Эти токены генерируются сервером для каждого сеанса пользователя и привязываются к его сессии. Когда клиент отправляет запрос (например, через форму или AJAX), токен CSRF должен быть передан вместе с запросом в теле или заголовках.
Сервер проверяет токен на подлинность, сверяя его с тем, который был сгенерирован для текущей сессии. Если токен не совпадает или отсутствует, запрос отклоняется. Этот метод гарантирует, что запрос пришел от доверенного источника, а не от злоумышленника.
Пример реализации с использованием Jav * aScript:
// Генерация токена на стороне сервера (например, через middleware в Express)
app.use((req, res, next) => {
res.locals.csrfToken = generateCsrfToken(); // генерируется уникальный токен
next();
});
// Вставка токена в форму на клиентской стороне
document.querySelector('form').innerHTML += `<input type="hidden" name="csrf_token" value="${res.locals.csrfToken}">`;
// Отправка запроса с токеном через AJAX
const csrfToken = document.querySelector('input[name="csrf_token"]').value;
fetch('/submit', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': csrfToken // передача токена в заголовке
},
body: JSON.stringify({ data: 'value' })
});
Другим методом защиты является проверка заголовков
Referer и Origin. Эти заголовки указывают на
источник запроса, и если запрос приходит с подозрительного источника
(например, с другого домена), сервер может отклонить его. Однако этот
метод не является полностью надежным, так как заголовки могут быть
подделаны.
Пример:
const origin = req.get('Origin');
const referer = req.get('Referer');
if (origin !== 'https://trusteddomain.com' || referer !== 'https://trusteddomain.com') {
res.status(403).send('Forbidden');
return;
}
Этот метод эффективен при правильной настройке, но не всегда может обеспечить 100% защиту, так как некоторые браузеры могут не отправлять эти заголовки.
Особенность CSRF-атак заключается в том, что они часто используют
cookies для аутентификации, так как браузеры автоматически отправляют
cookies с каждым запросом. Чтобы уменьшить уязвимость, можно
использовать атрибут SameSite для cookies. Этот атрибут
ограничивает передачу cookies только для запросов с того же домена, что
и сайт, тем самым блокируя возможность использования cookies для атак с
другого домена.
Существует три значения для атрибута SameSite:
Strict: Cookies отправляются только при прямом переходе
с того же сайта. Запросы с других сайтов не будут включать cookies.Lax: Cookies отправляются с безопасных запросов, таких
как переходы по ссылке, но не с других типов запросов, например,
AJAX.None: Cookies отправляются с любыми запросами, но
требуют наличия флага Secure (т.е. cookies будут
передаваться только через HTTPS).Пример:
document.cookie = "session_id=12345; SameSite=Strict; Secure";
Этот подход значительно уменьшает вероятность атаки CSRF, особенно если приложение использует сессионные cookies для аутентификации.
Еще один способ защиты от CSRF-атак — это проверка заголовка
X-Requested-With. Этот заголовок обычно добавляется
библиотеками AJAX (например, jQuery) при отправке асинхронных запросов.
Сервер может проверять наличие этого заголовка в запросах, чтобы
убедиться, что они были инициированы клиентом (например, веб-страницей),
а не внешним злоумышленником.
Пример:
if (req.get('X-Requested-With') !== 'XMLHttpRequest') {
res.status(400).send('Invalid request');
return;
}
Этот метод является простым, но он также имеет свои ограничения: злоумышленник может подделать заголовок, отправив запрос с тем же заголовком.
Для интеграции защиты от CSRF в проект, использующий библиотеку Petite-Vue, необходимо учесть, что сама библиотека предоставляет только инструменты для работы с данными и реактивностью, но не включает в себя механизм защиты от CSRF. Поэтому для защиты потребуется реализовать соответствующие меры на сервере и в приложении.
Добавление токена в формы: В шаблонах, где используется Petite-Vue, можно добавить скрытые поля для передачи CSRF-токенов. После этого, при отправке данных через реактивную форму, нужно включать этот токен.
Передача токенов через AJAX: В случае, если данные отправляются через AJAX-запросы, необходимо убедиться, что токен CSRF отправляется в заголовках или теле запроса.
Пример компонента Petite-Vue с добавлением CSRF-токена:
<div x-data="{ formData: { name: '', email: '' }, csrfToken: '{{ csrf_token() }}' }">
<form @submit.prevent="submitForm">
<input type="hidden" name="csrf_token" :value="csrfToken">
<input type="text" x-model="formData.name" placeholder="Your Name">
<input type="email" x-model="formData.email" placeholder="Your Email">
<button type="submit">Submit</button>
</form>
<script>
function submitForm() {
fetch('/submit', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': this.csrfToken
},
body: JSON.stringify(this.formData)
}).then(response => response.json())
.then(data => console.log(data));
}
</script>
</div>
Защита от CSRF-атак играет ключевую роль в обеспечении безопасности веб-приложений. Использование уникальных токенов, проверка заголовков и правильная настройка cookies — это основные методы, которые помогают избежать этих атак. Важно помнить, что эффективная защита требует комплексного подхода, и каждый метод должен использоваться в зависимости от контекста приложения и его инфраструктуры.