Більшість стартапів ламають не через хитрі експлойти нульового дня. Ламають через те, що ніхто жодного разу не подивився в код який пишеться автономно. Ви робили продукт, шукали клієнтів і безпека залишилась на «потім, коли виростемо».

Проблема в тому, що атакуючий не чекає, поки ви виростете. Він сканує все підряд автоматично, і ваш сервіс потрапляє в цей скан у той самий день, коли ви купили домен.

Нижче 15 конкретних способів. Кожен ми бачили на реальних проєктах, і кожен перевіряється за кілька хвилин. Паралельно провіряйте свій AI-B2B-SAAS-six-seven.

Спершу зайти

1. Вхід без обмеження спроб

_CWE-307: Improper Restriction of Excessive Authentication Attempts · OWASP A07:2021 Identification and Authentication Failures_

Форма логіну, яка приймає скільки завгодно спроб. Скрипт бере список найпоширеніших паролів і перебирає їх, поки не зайде. Сервер відповідає за мілісекунди, тож сто тисяч спроб проходять за кілька хвилин.

Помітити це нескладно, але тільки якщо є кому. У логах з'являються десятки тисяч невдалих входів підряд, і якщо ніхто не налаштував сповіщення на таку аномалію, атака проходить непоміченою до самого кінця. Дізнаєтесь ви вже з наслідків.

Що зробити: обмежте кількість спроб на акаунт і на IP (рейт ліміти), додайте зростаючу затримку після третьої невдачі. Капча на формі логіну коштує годину роботи. І поставте сповіщення на сплеск невдалих входів, щоб наступного разу дізнатись під час атаки, а не після.

2. Ваш пароль уже лежить у чужій базі

Ще гірший сценарій, бо перебору взагалі не буде. Користувач зареєструвався у вас із тим самим паролем, що й на форумі, який зламали три роки тому. Атакуючий бере готовий список пар пошта-пароль зі старих витоків і просто пробує їх у вас. Це називається credential stuffing, і воно тихе: у логах звичайні успішні входи.

Особливо больно, коли такий пароль у фаундера, а там вже доступ до всього.

І це не проблема лише маленьких команд. У січні 2024 Microsoft сама розповіла, як угруповання Midnight Blizzard зайшло до неї через password spray: зламали legacy тестовий акаунт без двофакторної автентифікації. Атаку вели з розподіленої мережі домашніх проксі й малою кількістю спроб на акаунт, щоб не спрацювали блокування за кількістю невдач.

Що зробити, за спаданням користі:

  • Двофакторна автентифікація на всіх, у кого є доступ до адмінки, хмари й репозиторію. Це закриває проблему майже повністю: навіть з правильним паролем без другого фактора не зайдуть. Якщо робити тільки один пункт зі списку, робіть цей.
  • Перевірте пошти команди на haveibeenpwned.com. Дві хвилини, показує, у яких витоках ви вже засвітились.
  • Не давайте реєструватись зі скомпрометованим паролем. Цього мало хто робить, хоча це прямо рекомендує стандарт NIST SP 800-63B, а зробити можна за вечір. У Have I Been Pwned є безкоштовне API Pwned Passwords, і воно влаштоване так, що ви не передаєте пароль нікуди: рахуєте SHA-1 від пароля, шлете перші п'ять символів хешу, у відповідь отримуєте список і звіряєте локально. Сервіс не дізнається ні пароля, ні навіть повного хешу. Якщо збіг знайшовся, просто просите користувача придумати інший.

3. Ключі, які лежать у браузері користувача

_CWE-540: Inclusion of Sensitive Information in Source Code_

Ключі доступу висипаються з коробки в серверній

Класика швидкого прототипу: ключ до бази, токен бота і інші секрети опинилися у файлі, який збирається у фронтенд. Усе, що потрапило у фронтенд, лежить у браузері кожного відвідувача. Це не «сховано в мініфікованому коді», це відкритий текст, до якого достатньо натиснути Ctrl+F.

Плутанина тут типова, тому запам'ятайте правило на прикладі Stripe: publishable key (pk_) безпечно класти у фронтенд, а secret key (sk_) не можна ніколи. Якщо у вашого ключа в назві є слово secret, він не має опинитись у браузері.

Що зробити: усі секрети тримайте на сервері. Відкрийте зібраний бандл і пошукайте в ньому secret, token, key, password. Якщо щось знайшли, ключ уже треба вважати скомпрометованим і міняти, а не просто прибирати з коду.

4. Секрет, який ви прибрали, але він лишився в історії git

_CWE-798: Use of Hard-coded Credentials_

Ключ видалили наступним комітом і заспокоїлись. Але git зберігає всю історію, і секрет доступний у попередньому коміті. Публічні репозиторії постійно скануються ботами, які шукають саме такі рядки, і робиться це швидше, ніж ви встигаєте помітити помилку.

Найвідоміший приклад старий, але показовий. За позовом FTC, у травні 2014 сторонній отримав доступ до персональних даних в Amazon S3 компанії Uber, використавши AWS-ключ, який інженер Uber публічно виклав на GitHub. Ключ давав повний адміністративний доступ.

Чому видалити наступним комітом недостатньо, пояснює сам GitHub: секретне сканування читає всю історію репозиторію в усіх гілках. Те саме доступно і боту атакуючого. GitHub прямо пише: якщо витік секрет, спершу відкликайте і замініть його, бо переписування історії саме собою нічого не рятує.

Що зробити: проженіть по історії gitleaks detect --source . або trufflehog git file://. Знайдене міняйте, а не просто вичищайте. Далі поставте перевірку в CI процесі, щоб такого не повторилось.

Потім узяти чуже

5. Одне замовлення вам, чи два чужих наступному?

Схема атаки IDOR: зміна номера в адресі відкриває чуже замовлення

_CWE-639: Authorization Bypass Through User-Controlled Key · OWASP A01:2021 Broken Access Control, API1:2023 Broken Object Level Authorization_

Ви відкриваєте своє замовлення за адресою /api/order/125. Міняєте цифру на 126 і бачите чуже: іншу людину, іншу суму, іноді її телефон і адресу.

Сервер перевірив, що ви залогінені, але не перевірив, що запис належить саме вам. Це найпоширеніша діра в сучасних застосунках, і вона не потребує жодних інструментів.

Настільки поширена, що кіберагентства США, Австралії та Нової Зеландії випустили окрему спільну пораду, присвячену виключно IDOR.

А ось чим це закінчується. У 2021 Комісія з цінних паперів США винесла припис компанії First American Financial. У документі цитується її ж власний звіт пентесту від січня 2019: «заміна ID документа в URL сторінки на інше послідовне число дає доступ до інших, не пов'язаних сесій документів без автентифікації». Знахідку не виправили, і вразливість спливла публічно вже в травні того ж року.

Що зробити: кожен запит на об'єкт має перевіряти власника, а не лише факт входу. Правило просте: умова WHERE id = ? майже завжди має бути WHERE id = ? AND owner_id = ?.

6. Адмінка, захована в інтерфейсі

_CWE-425: Direct Request (Forced Browsing) · OWASP API5:2023 Broken Function Level Authorization_

Кнопка «Адмін» не показується звичайному користувачу, і на цьому перевірку закінчили. Але кнопка це лише картинка у браузері. Атакуючий не натискає кнопку, він шле запит напряму на адресу, до якої вона веде.

Знаходять такі адреси без зусиль: назви ендпоінтів видно у зібраному фронтенді, бо код вашого інтерфейсу вміє їх викликати, просто ховає кнопку.

Що зробити:

  • Винесіть адмінку за периметр: окремий домен, доступ через VPN або allowlist по IP. Якщо у вас справді окрема адмін-панель, це сильний другий шар: до неї просто не достукаються ззовні. Тільки не плутайте його з першим. VPN не захистить адмінські ендпоінти всередині публічного API, не зупинить вашого ж залогіненого користувача і не допоможе, якщо зламали ноутбук співробітника, який уже у вашій мережі.

7. Поле пошуку, яке ходить у базу без фільтра

_CWE-89: SQL Injection · OWASP A03:2021 Injection_

Текст із форми потрапляє в запит до бази як є. Атакуючий вписує в поле імені конструкцію, яка закриває ваш запит і додає свій, і база слухняно віддає таблицю користувачів разом із хешами паролів.

Вразливості з ін'єкцією знаходять автоматичні сканери за хвилини, тому шукати їх будуть навіть у проєкті без жодного відвідувача.

Що зробити: параметризовані запити або ORM. Ніколи не склеюйте рядок запиту конкатенацією з користувацьким вводом.

8. Чужий скрипт на вашій сторінці

_CWE-79: Cross-site Scripting · OWASP A03:2021 Injection_

Ви дозволили користувачам залишати коментарі й виводите їх на сторінку без обробки. Хтось замість тексту лишає скрипт. Тепер цей скрипт виконується у браузері кожного, хто відкрив сторінку, і першим ділом забирає cookie сесії. Із чужою сесією пароль уже не потрібен.

Що зробити: екрануйте будь-який користувацький вивід, поставте заголовок Content-Security-Policy, а cookie сесії видавайте з прапорцями HttpOnly і Secure, щоб їх не можна було прочитати скриптом.

9. CORS, відкритий для всіх

_CWE-942: Permissive Cross-domain Policy with Untrusted Domains · OWASP A05:2021 Security Misconfiguration_

У конфігурації стоїть Access-Control-Allow-Origin: * разом із Allow-Credentials: true, бо так «запрацювало» на етапі налагодження. Тепер будь-який сайт може від імені вашого залогіненого користувача звертатись до вашого API і читати відповіді.

Що зробити: явний перелік дозволених доменів. Зірочка і передача облікових даних разом не поєднуються ніколи.

Забрати гроші

10. Вебхук, який вірить на слово

_CWE-345: Insufficient Verification of Data Authenticity · OWASP A08:2021 Software and Data Integrity Failures_

Платіжна система шле вам повідомлення «замовлення оплачено». Ваш сервер приймає його і відкриває доступ. Проблема в тому, що таке саме повідомлення може надіслати будь-хто, хто знає адресу вашого вебхука. Підпис ви не перевіряєте.

І це справді трапляється в бойовому коді. У березні 2026 в системі моніторингу OneUptime знайшли CVE-2026-33143: обробник вебхуків WhatsApp приймав події, не перевіряючи HMAC-підпис X-Hub-Signature-256, тож будь-хто без автентифікації міг слати підроблені повідомлення.

Що зробити:

  • Перевіряйте підпис кожного вхідного вебхука. Це HMAC: разом із тілом запиту приходить хеш, порахований на спільному секреті, і ви рахуєте такий самий у себе.
  • Порівнюйте підписи функцією сталого часу (crypto.timingSafeEqual у Node), а не звичайним ===. Це не параноя: у бібліотеці svix-webhooks була CVE-2024-21491 саме через неправильне порівняння, коли коротший підпис проходив перевірку.
  • Обережно з порядком middleware. Найчастіша практична помилка, і Stripe винесла її в окрему сторінку: в Express app.use(express.json()) має стояти після маршруту вебхука. Інакше тіло запиту розпарситься до перевірки, і підпис не зійдеться.
  • Звіряйте суму й статус зустрічним запитом до API платіжної системи, а не довіряйте тілу повідомлення.

11. Сто запитів в одну мить

Схема race condition: сто одночасних запитів проходять одну перевірку

_CWE-362: Race Condition, окремий випадок CWE-367 TOCTOU (time-of-check to time-of-use)_

Ваш код перевіряє «промокод ще не використаний», а потім списує його. Між цими двома діями є проміжок у мілісекунди. Якщо надіслати сто запитів одночасно, усі сто пройдуть перевірку до того, як перший встигне записати результат.

Так виносять промокоди, реферальні бонуси, ліміти на виведення і залишки на балансі. Джеймс Кеттл із PortSwigger назвав цей клас limit-overrun атаками і в переліку прикладів прямо є «повторне застосування одного промокоду» і «зняття суми понад залишок на рахунку».

Приклади з реального коду є, і свіжі. У квітні 2024 в системі продажу квитків alf.io виправили CVE-2024-45300 з описом дослівно: «race condition дозволяє користувачу обійти ліміт на кількість промокодів і використати купон на знижку кілька разів». У 2026 те саме знайшли в e-commerce фреймворку Sylius (CVE-2026-31824): перевірка читала лічильник використань з пам'яті, а збільшувався він пізніше, і між цими двома моментами не було блокування в базі.

Що зробити: робіть перевірку й списання однією атомарною операцією в базі, з блокуванням рядка. Перевірка в коді застосунку від цього не рятує.

Зайти через чужі двері

12. Пакет, який радив блогер

_CWE-506: Embedded Malicious Code · OWASP A03:2025 Software Supply Chain Failures_

Ви поставили бібліотеку, про яку прочитали в популярному треді. У неї в postinstall прописаний скрипт, який виконується одразу при встановленні, ще до першого запуску вашого коду. Він забирає змінні середовища з вашої машини і з вашого CI разом з усіма ключами.

Атаки через ланцюг постачання стали одним з головних способів, бо не треба ламати вас, достатньо зламати те, що ви самі собі поставите.

У вересні 2025 екосистему npm накрив хробак Shai-Hulud. За описом самого GitHub, він поширювався сам, заходив через зламані акаунти супровідників і вбудовував шкідливі post-install скрипти в популярні JavaScript-пакети. Видалити довелось понад 500 скомпрометованих пакетів. CISA випустила окреме попередження, а OWASP у редакції 2025 називає це першим успішним самопоширюваним хробаком у npm.

Що зробити: дивіться на пакет перед встановленням: вік, кількість супровідників, чи збігається назва з тією, що ви шукали. Ставте npm ci --ignore-scripts там, де це можливо, і фіксуйте версії через lock-файл.

13. Залежність із відомою дірою, яку полагодили пів року тому

_CWE-1395: Dependency on Vulnerable Third-Party Component · OWASP A06:2021 Vulnerable and Outdated Components_

У package.json лежить бібліотека з вразливістю, для якої давно є виправлення. Ви не оновлювались, бо «працює і не чіпай». Атакуючому не треба нічого вигадувати: він бере опис уже опублікованої вразливості й готовий експлойт.

Масштаб такого сценарію показує Log4Shell (CVE-2021-44228) з максимальною оцінкою 10.0 за CVSS: одна популярна бібліотека логування дала виконання коду на мільйонах серверів. А класичний приклад ціни зволікання це Equifax: за звітом GAO, зловмисники почали сканувати систему через два дні після публікації вразливості, і в результаті постраждали дані щонайменше 145,5 мільйона людей.

Що зробити: npm audit раз на тиждень, а краще Dependabot чи osv-scanner, який підключається до CI і не дає забути.

І те, про що згадують останнім

14. Ваш сервер сходив туди, куди атакуючий не міг

Схема SSRF: сервер звертається до службової адреси хмари і віддає ключі

_CWE-918: Server-Side Request Forgery · OWASP A10:2021 SSRF_

Почнемо з того, звідки взагалі береться проблема.

Коли ваш сервер працює в хмарі (AWS, GCP, Azure), у нього є службовий довідник про самого себе. Лежить він за адресою 169.254.169.254, і машина ходить туди, щоб дізнатись власні налаштування. Разом з ними там лежить найцікавіше: тимчасові ключі доступу до вашого хмарного акаунта. Саме так ваш код працює з хмарою, не зберігаючи паролів.

Ця адреса влаштована так, що відповідає тільки тому, хто питає зсередини самої машини. З інтернету туди не достукатись, і в цьому весь задум.

Тепер атака. У вас є зручна функція «завантажити файл за посиланням»: користувач дає URL, ваш сервер іде за ним і приносить вміст. Атакуючий замість картинки вписує туди http://169.254.169.254/....

Ваш сервер не бачить у цьому нічого дивного. Він іде за вказаною адресою, а оскільки він усередині хмари, довідник йому відповідає й віддає ключі. Сервер слухняно приносить їх атакуючому у відповіді.

Підсумок: атакуючий не зміг би дістати ці ключі сам, тому він скористався вашим сервером як посередником. А далі він працює з вашою хмарою тими самими правами, що й ваш застосунок: читає бази, файли, бекапи.

Саме так стався один із найбільших витоків в історії банків. У 2019 з Capital One забрали дані приблизно 100 мільйонів людей у США і 6 мільйонів у Канаді. У листі до сенатора Вайдена директор з безпеки AWS підтвердив, що після проходу через неправильно налаштований фаєрвол, за їхньою оцінкою, було використано саме SSRF.

Що зробити:

  • Не ходіть за довільним URL від користувача. Тільки білий список дозволених доменів.
  • Заблокуйте приватні діапазони IP (169.254.0.0/16, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 127.0.0.0/8) і перевіряйте адресу після резолву DNS, бо домен атакуючого може резолвитись у внутрішню адресу.
  • Увімкніть IMDSv2 у налаштуваннях хмари. Тоді довідник вимагає попередньо отримати токен окремим запитом, і простий «сходи за посиланням» уже не спрацьовує.

15. Файл, який назвали картинкою

_CWE-434: Unrestricted Upload of File with Dangerous Type · OWASP A04:2021 Insecure Design_

Форма аватара перевіряє розширення в назві. Атакуючий вантажить avatar.php.jpg, і файл лягає в папку, звідки сервер виконує код. Далі це не аватар, а працюючий скрипт на вашому сервері.

Трюк із подвійним розширенням описаний у самому CWE-434: деякі версії Apache обробляють файли за внутрішнім розширенням, тому filename.php.gif потрапляє в інтерпретатор PHP. OWASP у File Upload Cheat Sheet називає це прямо: подвійні розширення легко обходять перевірку регуляркою.

Свіжий масштабний приклад: плагін WordPress File Manager, CVE-2020-25213, оцінка 9.8, дозволяв завантажити й виконати довільний PHP-код. Його внесли до каталогу вразливостей, які активно експлуатують.

Що зробити: перевіряйте реальний тип файлу, а не назву. Зберігайте завантажене поза каталогом застосунку (OWASP радить саме так), роздавайте через окремий домен, перейменовуйте файли самі й дозволяйте лише конкретний перелік розширень.

Бонус. Секрети, які ви самі записали в логи

Зручний налагоджувальний вивід залишився в проді, і тепер у логах лежать паролі, токени, посилання для відновлення доступу і відповіді платіжки з фрагментами карток. Логи бачить більше людей, ніж базу: підрядники, сервіси моніторингу, будь-хто з доступом до сервера.

Що зробити: заборонений список полів, які ніколи не логуються, і перевірка того, що реально пишеться в проді, а не того, що ви збиралися писати.

Що зробити сьогодні, за одну годину

Порядок саме такий, від найдешевшого до найдовшого:

  • Пошукайте secret, token, key у зібраному фронтенд-бандлі
  • Прогоніть gitleaks detect --source . по історії репозиторію
  • Перевірте пошти команди на haveibeenpwned.com
  • Увімкніть двофакторну автентифікацію всім, у кого є доступ до адмінки, хмари й репозиторію
  • Відкрийте свій запис в API, підставте сусідній ID і подивіться, що повернеться
  • Запустіть npm audit і полагодьте критичні
  • Перевірте, чи перевіряється підпис на платіжному вебхуку
  • Спробуйте ввести неправильний пароль двадцять разів поспіль і подивіться, чи вас зупинять

Якщо хоча б один пункт дав неприємний результат, це не привід панікувати. Це привід подивитися далі, бо там, де знайшлося одне, зазвичай знаходиться ще.

Чому це варто зробити зараз

Дірка коштує дешево, поки її не знайшли. Після витоку рахунок іде не тільки за виправлення: це втрачені клієнти, розмова з тими, чиї дані ви не вберегли, і питання від партнерів, чому у вас так вийшло. Українські компанії, що працюють з персональними даними, ще й відповідають за це за законом, а якщо серед клієнтів є європейські, додається GDPR.

Найдешевший момент подивитися на свою безпеку це той, коли вас ще не зламали.

Хочете, щоб на ваш продукт подивилися ззовні? Ми проводимо безкоштовну консультацію на тридцять хвилин: розкажете про проєкт, ми покажемо, де найслабші місця і з чого починати. Без оплати й без зобов'язань.

Якщо потрібна повна перевірка, у нас є пентест зі звітом за методологією OWASP, де кожна знахідка йде з демонстрацією і планом виправлення, а після ваших фіксів ми безкоштовно перевіряємо повторно.