Безпека застосунків: найпоширеніші проблеми в реальних проєктах
Проблеми безпеки, що справді трапляються в комерційних вебпроєктах — від OWASP Top 10 до специфічних фронтенд-помилок — і практичні виправлення, що запобігають більшості з них.
Більшість інцидентів безпеки в комерційних вебпроєктах походить не з новаторської атаки — а з жменьки добре відомих помилок, що повторюються, бо їх легко допустити й легко пропустити на рев’ю. Ось список, який ми реально знаходимо під час аудитів, приблизно за частотою.
Звідки береться більшість реальних проблем
| Проблема | Типова причина | Наслідок |
|---|---|---|
| Зламаний контроль доступу | Відсутні серверні перевірки авторизації | Витік/зміна даних неавторизованими користувачами |
| Ін’єкції (SQL, NoSQL, командні) | Несанітизований ввід потрапляє в запит/команду | Витік даних, повна компрометація |
| Cross-site scripting (XSS) | Неекранований користувацький контент рендериться як HTML | Викрадення сесії, захоплення акаунта |
| Секрети в клієнтському коді чи репо | API-ключі/токени закомічені чи забандлені на клієнті | Неавторизований доступ до API, зловживання витратами |
| Застарілі залежності | Немає рутинного процесу оновлення/аудиту | Відомі публічні експлойти стають робочими |
| Небезпечні прямі посилання на обʼєкти | Довіра до клієнтського ID без перевірки власності | Доступ до даних інших користувачів |
1. Зламаний контроль доступу
Найчастіша знахідка в реальних аудитах: API-ендпоінт перевіряє, що користувач залогінений, але не те, що він володіє запитуваним ресурсом. Кожна перевірка авторизації має відбуватися на сервері, на кожному запиті — прихована кнопка чи задизейблений елемент UI — не контроль безпеки, а лише UX.
2. Ін’єкції
Досі в OWASP Top 10 через два десятиліття, бо запити зі склеєними рядками продовжують писати під тиском часу. Параметризовані запити й ORM, що екранує за замовчуванням, майже повністю усувають цю категорію — виправлення не в пильності, а в тулінгу, що робить небезпечний патерн важче написати, ніж безпечний.
3. Cross-site scripting (XSS)
Сучасні фреймворки (React, Vue) екранують вивід за замовчуванням, що тихо усунуло більшість класичного XSS — доки розробник не сягне до `dangerouslySetInnerHTML` чи `v-html` для поля з rich-text і не відновить саме ту діру, яку фреймворк запобігав. Будь-який рендеринг сирого HTML потребує бібліотеки санітизації, а не довіри до джерела.
4. Секрети в клієнтському коді чи системі контролю версій
API-ключі й токени, закомічені в репо або забандлені в клієнтський JavaScript, де їх може прочитати будь-хто з devtools, — повторювана знахідка навіть у якісно організованих проєктах. Секрети мають бути в змінних оточення на сервері, ніколи в тому, що йде в браузер чи в git — а витекший секрет потребує негайної ротації, а не просто видалення з останнього коміту.
5. Застарілі залежності з відомими вразливостями
Вразлива транзитивна залежність на три рівні вглиб непомітна без тулінгу й регулярного перегляду. Автоматизоване сканування залежностей (Dependabot, npm audit чи аналог) у CI з реальним процесом тріажу та патчингу знайденого закриває більшість цього розриву — саме відсутність моніторингу є реальним провалом, а не якийсь окремий вразливий пакет.
6. Небезпечні прямі посилання на обʼєкти (IDOR)
Довіра до клієнтського ID (`/api/invoices/1234`) без перевірки, що запитуючий користувач справді володіє цим ресурсом, дозволяє атакеру просто інкрементувати число. Кожен ендпоінт, що віддає ресурс, потребує перевірки власності чи прав, а не лише перевірки автентифікації.
Що насправді цьому запобігає
- Перевірки авторизації на кожному серверному запиті — ніколи не виведені з UI.
- Параметризовані запити й ORM за замовчуванням; сирі рядки запитів — перевірений виняток, не норма.
- Бібліотека санітизації для будь-якого рендерингу сирого HTML, з авто-екрануванням фреймворку увімкненим скрізь інде.
- Секрети лише в серверних змінних оточення, ніколи в клієнтських бандлах чи історії git.
- Автоматизоване сканування залежностей, вбудоване в CI, з реальним процесом тріажу знайденого.
- Перегляд безпеки як звичайна частина код-рев’ю всього, що торкається авторизації, доступу до даних чи користувацького вводу — а не окремий разовий аудит.
Підсумок
Безпека застосунків — здебільшого дисципліна навколо відомого, короткого списку повторюваних помилок, а не постійна гонка озброєнь проти новаторських загроз. Виправлення здебільшого процесні й інструментальні (параметризовані запити, сканування залежностей, серверна авторизація), а не героїчні — саме тому вони мають бути частиною стандартного інженерного процесу в кожній співпраці, а не прикручені перед аудитом на відповідність.
Поширені запитання
Яка найпоширеніша помилка безпеки у вебзастосунках?
Зламаний контроль доступу — перевірка, що користувач автентифікований, але не те, що він авторизований для доступу до конкретного запитуваного ресурсу. Це послідовно найчастіша знахідка в реальних аудитах, попереду ін’єкцій і XSS, бо легко пропустити, коли ендпоінт «очевидно» має сенс лише для залогіненого користувача.
Аудит безпеки — це разова річ чи постійний процес?
Має бути постійним. Разовий аудит ловить проблеми, наявні на той момент, але новий код, нові залежності й нові фічі постійно вносять новий ризик. Автоматизоване сканування в CI плюс код-рев’ю з увагою до безпеки на кожну зміну ловить набагато більше з часом, ніж лише періодичний аудит.
Що робити, якщо витік API-ключ чи секрет?
Негайно ротуйте його — згенеруйте новий ключ і відкличте старий — а не просто видаляйте з останнього коміту, бо він лишається читабельним в історії git і може вже бути скомпрометованим. Далі знайдіть, як він витік (клієнтський бандл, публічне репо, вивід логів), і виправте корінну причину, щоб не повторилося.