Суть Читай реальные сниппеты кода, конфига и лога — проверку access control, SSRF-фетч, конфиг CORS — называй категорию OWASP и выбирай фикс, который сеньор делает первым.
Высота — путь к senior
НольJuniorMiddleSenior
Ты на senior-высоте — в орбите
◷ 14 min
Уязвимости живут в коде и конфиге, а не в абстракции. Читай каждый сниппет так, как читал бы в pull request, называй категорию OWASP и выбирай фикс, к которому сеньор тянется первым — корневую причину, а не костыль.
Цель
Потренируй цикл ревью: прочитай хендлер или конфиг, определи, к какой категории Top 10 он относится, предскажи эксплойт и потянись за структурным фиксом до любого периметрового патча.
requireLogin выполняется, значит вызывающий аутентифицирован. В чём уязвимость и какой минимальный корректный фикс?
Heads-up requireLogin доказывает, кто вызывающий, а не к чему он вправе обращаться. Любой залогиненный пользователь читает любой инвойс, меняя id; это хрестоматийный IDOR.
Heads-up id приводится к числу и идёт через ORM как параметр, поэтому injection нет. Недостаёт проверки владения на строку.
Heads-up Транспорт уже шифруется TLS; шифрование тела ничего не меняет, когда авторизованная сессия читает не свою строку. Фикс — авторизация.
Сниппет 2 — фетчер URL
// POST /api/preview { "url": "..." }app.post("/api/preview", async (req, res) => { const r = await fetch(req.body.url); // fetch whatever the client sent const html = await r.text(); res.send(extractOpenGraph(html)); // server returns the fetched content});
Викторина
Completed
Какой это класс бага, какой эксплойт с наибольшим импактом и какая правильная защита?
Heads-up Санитизация строки не останавливает идеально валидный URL, указывающий на внутренний адрес. SSRF — про то, куда серверу разрешено подключаться, защищается allowlist'ингом и проверками IP-диапазонов, а не экранированием.
Heads-up fetch охотно запросит внутренние хосты, link-local metadata-эндпоинты и другие схемы. Именно эту достижимость эксплуатирует SSRF.
Heads-up Логин ограничивает, кто это триггерит, но аутентифицированный сервер всё равно делает опасный внутренний запрос. Корневая причина — неограниченное назначение серверного фетча, то есть SSRF.
Сниппет 3 — конфиг CORS
app.use(cors({ origin: req.headers.origin, // reflect whatever Origin the request sent credentials: true, // allow cookies to be sent cross-origin}));
Викторина
Completed
Отражение Origin запроса при разрешённых credentials — что это на самом деле допускает и как это чинить?
Heads-up Отражение Origin вызывающего с credentials — каноническая misconfiguration CORS; это эквивалент wildcard, который вдобавок утекает куки. CORS ожидает явный allowlist доверенных origin.
Heads-up Secure управляет передачей только по HTTPS, а не тем, какие origin вправе читать cross-origin ответы. Дефект — политика CORS с отражённым origin и credentials.
Heads-up Серверная авторизация всё ещё работает, но браузер отдаст ответ вредоносному origin, потому что CORS сказал, что origin доверенный. Фикс — корректный allowlist CORS.
В этой одной строке лога видны две находки. Какая пара верна?
Heads-up Логирование пароля в открытом виде — реальная утечка чувствительных данных в хранилища логов и SIEM, а быстрые повторные неудачи — несмягчённый сигнал credential-stuffing. Оба — security-находки, а не стиль.
Heads-up Поле ip в auth-логе — обычные метаданные запроса, а не серверный фетч. SSRF здесь ни при чём.
Heads-up UA логируется, а не исполняется против интерпретатора. Реальные проблемы — залогированный пароль в открытом виде и неограниченные повторные auth-неудачи.
Итог
Каждая находка читается обратно к категории и фиксу корневой причины: аутентифицированный хендлер без проверки владения — это IDOR/Broken Access Control (ограничь по owner_id); сервер, фетчащий присланный клиентом URL, — это SSRF (allowlist плюс отклонение приватных диапазонов плюс блокировка IMDS); отражение Origin запроса с credentials — это Security Misconfiguration CORS (allowlist доверенных origin); а строка лога с паролем в открытом виде и быстрыми повторными неудачами — утечка чувствительных данных плюс пробел в auth/logging. Читай код и конфиг как ревьюер — назови причину, потом чини причину.