CSRF-защита

Cross-Site Request Forgery (CSRF) представляет собой угрозу безопасности, при которой злоумышленник заставляет пользователя выполнить нежелательное действие на веб-сайте, на котором он авторизован. Эта атака возможна, если сервер не проверяет, что запрос был отправлен с допустимого источника. В приложениях, построенных с использованием фреймворка Marko, CSRF-защита имеет особое значение, так как веб-приложения часто требуют аутентификацию пользователей и обрабатывают различные формы.

Проблема CSRF

CSRF-атака использует доверие пользователя к веб-приложению. Примером может быть ситуация, когда пользователь авторизован на веб-сайте, а затем посещает другую страницу, на которой находится скрипт, отправляющий запросы на исходный сайт. Если на сервере нет механизмов защиты от таких действий, запрос может быть выполнен от имени пользователя, что может привести к нежелательным последствиям: удалению данных, переводу средств или изменению личной информации.

Основные принципы защиты от CSRF

Для предотвращения CSRF-атак важно удостовериться, что все запросы, которые могут повлиять на данные (например, POST, PUT, DELETE), защищены от подделки. Рассмотрим несколько методов защиты:

  1. Использование токенов CSRF

    Один из наиболее распространенных методов защиты от CSRF-атак заключается в применении токенов. Токен CSRF — это случайная строка, которая генерируется сервером и передается клиенту. При отправке запроса клиент должен включить этот токен, и сервер проверяет его соответствие. Если токен отсутствует или неверен, запрос отклоняется.

  2. Проверка источника запросов

    Еще одним способом защиты является проверка заголовка Origin или Referer. Этот заголовок указывает, с какого домена был отправлен запрос. Если запрос пришел с другого домена, его можно отклонить, если только не разрешено выполнение запросов из внешних источников.

  3. Использование куки с флагом HttpOnly и SameSite

    Для обеспечения безопасности куки, которые используются для хранения информации о сессии, важно установить флаг SameSite. Это ограничивает отправку куки с кросс-доменными запросами, предотвращая возможность их использования в CSRF-атаках. Дополнительно стоит установить флаг HttpOnly, чтобы куки не могли быть доступны через JavaScript.

Реализация CSRF-защиты в приложении на Marko

  1. Генерация и валидация токенов CSRF

    Для реализации CSRF-защиты на серверной стороне можно использовать пакет csurf, который интегрируется с Express и другими фреймворками, поддерживающими middleware.

    Установка:

    npm install csurf

    Подключение и настройка middleware в Express:

    const express = require('express');
    const csurf = require('csurf');
    const bodyParser = require('body-parser');
    const app = express();
    
    // Настройка body-parser
    app.use(bodyParser.urlencoded({ extended: false }));
    
    // Настройка csurf
    const csrfProtection = csurf();
    app.use(csrfProtection);
    
    app.get('/form', (req, res) => {
      res.marko({
        csrfToken: req.csrfToken()  // Передаем токен в шаблон Marko
      });
    });

    В шаблоне Marko необходимо вставить токен CSRF в скрытое поле формы:

    <form method="POST" action="/submit">
      <input type="hidden" name="_csrf" value="${csrfToken}">
      <!-- Остальные поля формы -->
      <button type="submit">Отправить</button>
    </form>

    При отправке формы сервер проверит токен, и если он не совпадает с тем, что был сгенерирован на сервере, запрос будет отклонен.

  2. Проверка заголовков Origin и Referer

    Важным элементом защиты является проверка, откуда был отправлен запрос. Это можно сделать с помощью middleware, который будет проверять заголовки Origin или Referer.

    Пример middleware для проверки Origin:

    app.use((req, res, next) => {
      const allowedOrigin = 'https://yourtrustedsite.com';
      const origin = req.get('Origin') || req.get('Referer');
    
      if (origin && !origin.startsWith(allowedOrigin)) {
        return res.status(403).send('Forbidden');
      }
    
      next();
    });

    Такой подход предотвратит обработку запросов, которые не пришли с ожидаемого домена.

  3. Настройка SameSite для cookies

    Чтобы предотвратить отправку куки с кросс-доменными запросами, необходимо установить для сессионных куки флаг SameSite. В Express можно использовать модуль cookie-session для настройки этого флага:

    const cookieSession = require('cookie-session');
    
    app.use(cookieSession({
      name: 'session',
      keys: ['your-secret-key'],
      cookie: {
        httpOnly: true,
        secure: process.env.NODE_ENV === 'production',
        sameSite: 'Strict'  // Включение защиты от CSRF через SameSite
      }
    }));

    Этот флаг гарантирует, что куки не будут отправляться в запросах, сделанных с других сайтов.

Важные замечания

  • Токен CSRF: Важно, чтобы токен был уникальным для каждой сессии пользователя. Это предотвращает возможность повторного использования токенов.
  • Безопасность сессий: Важно использовать HTTPS для всех обменов данными, чтобы исключить возможность перехвата токенов CSRF или куки.
  • CORS: При использовании CORS для разрешения кросс-доменных запросов важно правильно настроить заголовки, чтобы избежать уязвимостей.

Заключение

CSRF-защита является важной частью безопасности веб-приложений, и фреймворк Marko предоставляет все необходимые возможности для её реализации. Использование токенов CSRF, проверка источников запросов и правильная настройка куки — эти меры помогают защитить веб-приложения от одной из самых распространенных угроз безопасности.