Инъекции и разграничение доступа — Примеры

Пример 1 — Кавычка, которая меняет оператор

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

// orders.ts — как на ревью
app.get("/orders/:id", (req, res) => {
  const rows = db.query(
    `SELECT * FROM orders WHERE id = '${req.params.id}'`
  );
  res.json(rows);
});

Решение

// orders.ts — после исправления
app.get("/orders/:id", (req, res) => {
  const rows = db.query(
    "SELECT * FROM orders WHERE id = $1",
    [req.params.id]
  );
  res.json(rows);
});

Теперь значение идёт отдельным параметром и не может изменить структуру оператора. Для инъекции нужна одиночная кавычка, чтобы закрыть строковый литерал и начать писать SQL; как связанный параметр этот символ — просто данные. Обычное половинчатое исправление — параметризовать идентификатор и оставить ту же конкатенацию ниже для столбца сортировки, где плейсхолдер привязки стоять не может.

Пример 2 — Чужой счёт

Эндпоинт детали ниже добавлен после страницы списка, которая фильтрует по вошедшему аккаунту. Он загружает любой пришедший идентификатор. Имея действительную сессию и id, принадлежащий другому аккаунту, напишите проверку, закрывающую дыру, и выберите ответ осознанно.

GET /invoices/1042
  session.accountId = 7
  invoice 1042.accountId = 9
  -> 200 OK, тело: счёт другого аккаунта

Решение

GET /invoices/1042
  invoice = invoices.find(req.params.id)
  if (!invoice || invoice.accountId !== session.accountId)
    -> 404 Not Found

Авторизовать маршрут — не то же самое, что авторизовать объект, поэтому проверка выполняется при каждой загрузке относительно аккаунта из сессии, а не присланного клиентом id. Возвращается «не найдено», а не «запрещено», потому что признание существования счёта 1042 — само по себе раскрытие. Обычная ошибка — довериться фильтру на странице списка и решить, что страница детали его наследует; это не так.