Как защититься от SQL-инъекций в Node.js приложении?

«Как защититься от SQL-инъекций в Node.js приложении?» — вопрос из категории Безопасность, который задают на 26% собеседований Node.js Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Основной и самый надежный метод защиты — использование параметризованных запросов (Prepared Statements). При таком подходе данные пользователя передаются отдельно от кода запроса, и СУБД сама корректно их экранирует.

1. Использование драйверов и ORM с поддержкой параметризации:

  • Нативный драйвер mysql2 / pg (PostgreSQL):

    // УЯЗВИМЫЙ КОД (конкатенация строк)
    const query = `SELECT * FROM users WHERE email = '${email}'`;
    connection.query(query); // Если email = "' OR '1'='1", получим инъекцию
    
    // ЗАЩИЩЕННЫЙ КОД (параметризованный запрос)
    const safeQuery = 'SELECT * FROM users WHERE email = ?';
    connection.execute(safeQuery, [email]); // Драйвер корректно подставит значение
  • ORM Sequelize:

    // Sequelize автоматически использует параметризованные запросы
    const users = await User.findAll({
      where: {
        email: req.body.email // Безопасно!
      }
    });
  • Query Builder Knex.js:

    knex('users').where('email', '=', email).select('*'); // Безопасно

2. Дополнительные меры защиты:

  • Принцип наименьших привилегий: У учетной записи приложения в БД должны быть только необходимые права (обычно SELECT, INSERT, UPDATE, DELETE на конкретные таблицы, но не DROP, CREATE и т.д.).
  • Валидация и санация входных данных: Хотя это не заменяет параметризацию, строгая валидация (например, с помощью Joi или Zod) на уровне API отсекает заведомо некорректные данные.
  • Хранимые процедуры: Могут быть безопасны, если вызываются с параметрами, но в экосистеме Node.js используются реже.
  • Регулярное обновление зависимостей: Уязвимости могут быть в самих ORM или драйверах.

Главное правило: Никогда не доверяйте пользовательскому вводу и никогда не склеивайте SQL-запросы строковой конкатенацией или шаблонными литералами. Всегда используйте механизмы параметризации, предоставляемые вашим драйвером или ORM.