Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Middle: питання на співбесіді з теми «OWASP і процеси безпеки»

Питання з реальних співбесід з відповідями: Laravel і PHP, бази даних, JavaScript і фронтенд, Git, Docker, API, безпека й архітектура. Тими самими темами, що й тести.

5 питань

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

Чотири питання (за OWASP і Адамом Шостаком):

  1. Над чим ми працюємо? - модель системи;
  2. Що може піти не так? - загрози;
  3. Що ми з цим робимо? - заходи;
  4. Чи добре ми впоралися? - перевірка.

Модель системи - діаграма потоків даних (DFD): зовнішні сутності (користувач, платіжна система), процеси (застосунок, черга), сховища (база, S3), потоки даних між ними і межі довіри - місця, де дані переходять з менш довіреної зони в більш довірену (браузер → сервер, сторонній вебхук → застосунок).

STRIDE - категорії загроз для кожного елемента діаграми:

Літера Загроза Порушена властивість Приклад
S Spoofing - підробка автентичність підроблений вебхук від «платіжної системи»
T Tampering - зміна цілісність зміна ціни в запиті оформлення замовлення
R Repudiation - заперечення неспростовність «я не змінював цей платіж» - а журналу немає
I Information disclosure - розкриття конфіденційність чужий рахунок за іншим id
D Denial of service - відмова доступність експорт без ліміту, що вантажить базу
E Elevation of privilege - підвищення прав авторизація користувач робить себе адміністратором

Приклад: нова функція «імпорт товарів з CSV за посиланням»:

  • S: хто може запускати імпорт? → лише роль менеджера;
  • T: чи можна підмінити файл між перевіркою й обробкою? → завантажити один раз і обробляти локальну копію;
  • R: хто і коли імпортував? → журнал з користувачем і файлом;
  • I: чи може URL вказувати на внутрішні ресурси (SSRF)? → перевірка URL і IP;
  • D: файл на 10 ГБ? → ліміт розміру, обробка в черзі;
  • E: CSV-ін'єкція формул при експорті назад в Excel? → екранування.

Як впровадити без бюрократії: 30-60 хвилин обговорення для функцій, що зачіпають автентифікацію, платежі, файли, зовнішні інтеграції, персональні дані; результат - перелік загроз і задач у трекері, а не документ на полиці.

Докладніше в документації: OWASP: моделювання загроз

Три класи автоматизованих перевірок безпеки шукають різне і доповнюють одне одного.

SAST (Static Application Security Testing) - аналіз вихідного коду без запуску:

  • знаходить небезпечні шаблони: конкатенацію в SQL, eval, unserialize даних користувача, виведення без екранування;
  • taint-аналіз відстежує, чи потрапляють дані з запиту ($request->input()) у небезпечні місця (DB::raw, exec) без очищення;
  • інструменти для PHP: Psalm (taint-аналіз --taint-analysis), Semgrep з правилами для PHP і Laravel, SonarQube; PHPStan з пакетами правил для частини перевірок;
  • плюси: працює рано, в PR, вказує на рядок коду;
  • мінуси: хибні спрацьовування, не бачить конфігурації й поведінки під час виконання.

DAST (Dynamic Application Security Testing) - атакує запущений застосунок ззовні, як зловмисник:

  • знаходить те, що видно лише в роботі: відсутні заголовки безпеки, відкриті службові файли, XSS і ін'єкції у відповідях, проблеми TLS, налагоджувальні сторінки;
  • інструменти: OWASP ZAP (зокрема в CI в режимі baseline scan), Burp Suite, Nuclei з шаблонами для відомих вразливостей;
  • плюси: реальна поведінка, мало хибних спрацьовувань на конфігураційних проблемах;
  • мінуси: не бачить коду, погано покриває логіку за авторизацією, повільний.

SCA (Software Composition Analysis) - аналіз залежностей:

  • зіставляє версії пакетів з базами вразливостей, перевіряє ліцензії, покинуті пакети;
  • інструменти: composer audit, npm audit, Dependabot, Renovate, Snyk, OSV-Scanner, Trivy (ще й для Docker-образів).

Чого не знайде жоден автоматичний інструмент: логічні вразливості й контроль доступу - «чи може користувач A побачити замовлення B», «чи можна оплатити замовлення за ціною 0». Для цього - тести авторизації, рев'ю коду й ручне тестування.

Практичний набір для Laravel-проєкту:

  • у кожному PR: composer audit, PHPStan/Larastan, Semgrep чи Psalm з taint-аналізом для критичних частин;
  • за розкладом: DAST (ZAP baseline) проти staging;
  • Dependabot/Renovate для оновлень;
  • тести на авторизацію для кожного ендпойнта з ідентифікатором.

Головне - реакція на результати: інструмент, звіт якого ніхто не читає, лише створює ілюзію захищеності.

Докладніше в документації: OWASP: інструменти аналізу вихідного коду

Більшість вразливостей потрапляє в код через звичайні PR. Рев'ю - найдешевше місце, щоб їх зупинити, якщо знати, куди дивитися.

1. Авторизація - перше питання до кожного нового ендпойнта:

  • чи перевіряється, що користувач має доступ саме до цього об'єкта (політика, authorize, пошук через власника)?
  • чи захищені нові методи Livewire-компонентів і дії Filament?
  • адміністративні функції - за правами, а не лише «прихована кнопка»?

2. Вхідні дані:

  • валідація з межами (довжина рядків, розмір масивів, діапазони чисел);
  • $request->validated() у create/update, а не $request->all();
  • ідентифікатори власника беруться з автентифікації, а не з тіла запиту.

3. Ін'єкції:

  • DB::raw, whereRaw, orderByRaw з даними користувача; назви колонок для сортування - з білого списку;
  • {!! !!} у Blade, v-html, dangerouslySetInnerHTML;
  • виконання команд (Process, exec), шляхи до файлів з введення користувача.

4. Дані на виході:

  • API Resource замість повернення моделі цілком;
  • чутливі поля не в журналах, відповідях і повідомленнях про помилки.

5. Секрети й конфігурація:

  • ключі в коді, тестах, прикладах конфігурації;
  • нові змінні оточення - в .env.example без значень.

6. Зовнішні взаємодії:

  • HTTP-запити за URL з введення (SSRF);
  • вебхуки - перевірка підпису;
  • завантаження файлів - тип, розмір, зберігання поза public.

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

8. Обробка помилок і стану:

  • що відбувається при винятку посеред операції - чи не лишається «напіввідкритого» стану;
  • перевірки, що «пропускають» при помилці (fail-open): catch повертає true;
  • гонитва: перевірка й зміна балансу без транзакції чи блокування.

Як зробити рев'ю ефективним:

  • чекліст у шаблоні PR для змін, що торкаються автентифікації, платежів, файлів, персональних даних;
  • автоматика бере рутину (лінтери, SAST, аудит залежностей) - людина зосереджується на логіці й авторизації;
  • тести на безпеку - частина PR: «чужий користувач отримує 403» перевіряється тестом, а не на око.

Найчастіший пропуск - не ін'єкції, а відсутня перевірка прав у новому методі, що «просто повертає дані».

Докладніше в документації: OWASP Code Review Guide

Застарілі залежності - один з основних джерел вразливостей. Але бот, що щодня відкриває 30 пул-реквестів, швидко вчить команду їх ігнорувати. Мета - регулярні, невеликі, зрозумілі оновлення.

Два види оновлень:

  • security updates - негайні PR для версій з відомими вразливостями (Dependabot alerts);
  • version updates - планові оновлення до нових версій за розкладом.

Базова конфігурація Dependabot (.github/dependabot.yml):

version: 2
updates:
  - package-ecosystem: composer
    directory: /
    schedule:
      interval: weekly
    groups:
      laravel:
        patterns: ['laravel/*']
      minor-and-patch:
        update-types: [minor, patch]
    open-pull-requests-limit: 5

  - package-ecosystem: npm
    directory: /
    schedule:
      interval: weekly

  - package-ecosystem: github-actions
    directory: /
    schedule:
      interval: monthly

Що робить процес керованим:

  • групування - усі патч- і мінорні оновлення одним PR на тиждень замість десятків окремих; пов'язані пакети (laravel/*, @vue/*) - разом;
  • розклад - щотижня в певний день, коли хтось точно подивиться;
  • ліміт відкритих PR;
  • автоматичне злиття патч-оновлень, якщо проходять тести (Renovate вміє це з коробки, для Dependabot - через правила репозиторію й workflow). Без хорошого покриття тестами автозлиття небезпечне;
  • мажорні оновлення - окремо й свідомо, з читанням журналу змін.

Renovate гнучкіший: пресети конфігурації, автозлиття за правилами, «dependency dashboard» з переліком усіх доступних оновлень, затримка для щойно опублікованих версій (minimumReleaseAge).

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

Не забувати:

  • lock-файли (composer.lock, package-lock.json) у репозиторії - щоб продакшен отримав рівно те, що протестовано;
  • оновлення GitHub Actions і Docker-образів - теж залежності;
  • CI має запускати всі тести на PR від бота - інакше оновлення «пройде», зламавши застосунок;
  • відповідальний за розбір - інакше PR накопичуються, і за пів року оновлення стає великим і страшним.

Докладніше в документації: GitHub: оновлення версій Dependabot

Багато зламів тривають тижнями й місяцями, перш ніж їх помітять, - часто ззовні (клієнти, журналісти, дослідники). Причина - журнали або не пишуться, або пишуться, але ніхто на них не реагує. OWASP Top 10:2025 називає категорію саме «журналювання й сповіщення»: записати замало, потрібна реакція.

Які події безпеки записувати:

  • автентифікація: вдалі й невдалі входи, вихід, скидання пароля, зміна email і пароля, увімкнення/вимкнення 2FA;
  • авторизація: відмови в доступі (403), особливо серійні - ознака перебору чужих id;
  • адміністративні дії: зміна ролей і прав, видалення записів, зміна налаштувань, вхід під іншим користувачем (impersonation);
  • операції з чутливими даними: експорт, масове вивантаження, перегляд персональних даних в адмінці;
  • помилки валідації й підозрілі запити у великих кількостях;
  • платіжні операції й зміни балансу;
  • зміни API-ключів і токенів.

Що має бути в записі: час (з поясом), хто (id користувача, а не лише IP), що зроблено і з чим, звідки (IP, User-Agent), результат, ідентифікатор запиту для зв'язку з іншими журналами.

Чого не має бути: паролі, токени, повні номери карток, зайві персональні дані. Журнали - теж джерело витоків.

Захист самих журналів:

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

Сповіщення - на події, що потребують реакції:

  • сплеск невдалих входів (перебір паролів, credential stuffing);
  • вхід адміністратора з нової країни чи пристрою;
  • масовий експорт даних;
  • серія 403/404 на ресурси з ідентифікаторами;
  • зміна прав адміністратора.

У Laravel: окремий канал журналу для подій безпеки, події Login, Failed, PasswordReset з пакета автентифікації, пакет журналу дій (наприклад, spatie/laravel-activitylog) для змін моделей, відправлення в централізовану систему (SIEM, ELK, Sentry, хмарні журнали) з правилами сповіщень.

Докладніше в документації: OWASP A09:2025