SQL‑ін’єкція в Prisma – практичний посібник з hardeningu баз даних

Крок за кроком покажемо, як захистити Prisma і TypeScript від SQL‑ін’єкції та виконати вимоги OWASP Top 10.

SQL injection w Prisma – praktyczny przewodnik hardeningu baz danych

SQL‑ін’єкція в Prisma є однією з найпоширеніших вразливостей, які можуть загрожувати цілісності даних та конфіденційності застосунку. У статті ми представляємо коротку модель загрози, механізми роботи Prisma, порівняння уразливого та виправленого коду, чек‑лист мітигації та посилання на визнані стандарти, такі як OWASP Top 10, CWE та принцип least‑privilege.

Модель загрози – як виникає SQL‑ін’єкція

Зловмисник ін’єкціонує власний SQL‑код у місце вхідних даних, які застосунок передає до бази без належної валідації або параметризації. У контексті Prisma це найчастіше відбувається за допомогою методів queryRaw або executeRaw, які дозволяють вручну вставляти фрагменти запитів. Якщо передавати їм неперевірені рядки, відкриваємо двері до маніпуляції запитом.

Базовий сценарій:

  • Користувач вводить значення у форму (наприклад, назва продукту).
  • Застосунок формує SQL‑запит, вставляючи це значення без параметризації.
  • Зловмисник додає інструкцію OR 1=1 або DROP TABLE, що призводить до неавторизованого доступу або знищення даних.

Механізм захисту в Prisma – параметризація та типізація

Prisma ORM за замовчуванням генерує запити за допомогою підготовлених інструкцій (prepared statements). Завдяки цьому значення передаються як параметри, а не вставляються безпосередньо в текст SQL. У TypeScript додатково використовуються типи, які обмежують можливість ін’єкції небажаного коду.

Ключові механізми:

  • Query Builder – методи такі як findMany, create чи update будують запити безпечно.
  • Параметризований RAW – prisma.$queryRaw`SELECT * FROM User WHERE email = ${email}` використовує теговану інтерполяцію, що автоматично санітує змінну.
  • Типи Prisma – визначають структуру даних і примушують до правильного формату вводу.

Приклад: уразливий код vs виправлений код

Нижче порівнюємо два фрагменти – спочатку небезпечний, потім безпечний.

// --- Уразливий код ---
const userInput = req.body.username; // дані з форми
const raw = `SELECT * FROM "User" WHERE username = '${userInput}'`;
const result = await prisma.$queryRaw(raw);

У наведеному прикладі userInput вставляється безпосередньо в рядок, що дозволяє ін’єкцію будь‑якого SQL.

// --- Виправлений код ---
const userInput = req.body.username;
// використання тегованої інтерполяції забезпечує параметризацію
const result = await prisma.$queryRaw`SELECT * FROM "User" WHERE username = ${userInput}`;

Тегована інтерполяція (prisma.$queryRaw`...`) перетворює ${userInput} у прив’язаний параметр, усуваючи ризик ін’єкції.

Чек‑лист мітигації – що впровадити в проєкті

  • Використовуйте лише методи Prisma API (findUnique, create тощо) замість ручних RAW‑запитів.
  • Якщо RAW необхідний, застосовуйте теговану інтерполяцію або передавайте параметри другим аргументом (prisma.$queryRaw(sql, params)).
  • Увімкніть валідацію схеми вводу (наприклад, zod або class-validator) перед передачею даних у шар доступу до бази.
  • Обмежте привілеї облікового запису БД, що використовується застосунком – принцип least‑privilege.
  • Моніторьте SQL‑логи та виявляйте неочікувані патерни (наприклад, раптове використання DROP).

Посилання на стандарти – OWASP, CWE та least‑privilege

OWASP Top 10 зазначає A03:2021 – Injection як одну з найсерйозніших категорій. У каталозі CWE проблемі відповідає CWE‑89: SQL Injection. Реалізуючи наведені практики, ми відповідаємо вимогам обох стандартів.

Принцип least‑privilege вимагає, щоб обліковий запис БД, який використовується Prisma, мав лише необхідні права (SELECT, INSERT, UPDATE, DELETE на потрібних таблицях). Уникайте надання ролі SUPERUSER або DBA продукційному застосунку.

«Безпечні запити – це не додаток, це основа: код, який не може бути ін’єкований, не потребує подальших виправлень.»

Типові помилки та компроміси на практиці

Найчастіші пастки:

  • Використання prisma.$executeRaw без параметризації – легко пропустити, особливо під час міграцій.
  • Динамічне формування імен таблиць або колонок – Prisma не дозволяє параметризувати ідентифікатори, тому їх треба валідовувати у білому списку.
  • Відмова від валідації вводу на користь «довіри» до фронтенду – призводить до непередбачуваних векторів атаки.

Компроміси:

  • У деяких випадках необхідно використати RAW для складних звітів. Тоді варто виділити цей шар у окремий сервіс і оточити його додатковим шаром санітизації.
  • Якщо застосунок має обробляти ad‑hoc запити, розгляньте використання білого списку дозволених полів і операторів замість вільного вставлення тексту.

Практичний приклад – чек‑лист впровадження

// checklista.ts – приклад реалізації на TypeScript
import { PrismaClient } from '@prisma/client';
import { z } from 'zod';

const prisma = new PrismaClient();

// 1. Схема валідації вхідних даних
const userSchema = z.object({
  username: z.string().min(3).max(30),
  email: z.string().email(),
});

export async function createUser(payload: unknown) {
  // 2. Валідація
  const data = userSchema.parse(payload);

  // 3. Безпечне використання Prisma API – не RAW
  return await prisma.user.create({
    data: {
      username: data.username,
      email: data.email,
    },
  });
}

// 4. Приклад RAW з параметризацією
export async function findUsersByDomain(domain: string) {
  const safeDomain = domain.replace(/[^a-zA-Z0-9.-]/g, ''); // додаткова санітизація
  return await prisma.$queryRaw`
    SELECT * FROM "User" WHERE email LIKE ${'%@' + safeDomain}`;
}

Наведений код демонструє, як поєднати валідацію схеми, використання безпечного API та параметризований RAW у випадках, коли це необхідно.

Підсумок і запрошення до співпраці

Застосовуючи описані практики – параметризацію, типізацію, валідацію та обмеження прав – ви усуваєте ризик SQL‑injection у проектах на базі Prisma і TypeScript, одночасно відповідаючи вимогам OWASP Top 10 та CWE‑89. Якщо потрібен аудит безпеки, підтримка у харднінгу бази даних або допомога у впровадженні найкращих практик, зв’яжіться з Coderia.it – наша команда спеціалістів допоможе вам створити надійну та безпечну бек‑енд архітектуру.

Почнімо

Маєте проєкт на думці?

Опишіть його кількома реченнями. Відповім протягом 24 годин із безкоштовною оцінкою та пропозицією стеку.