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

Junior: питання на співбесіді з теми «Інфраструктура й секрети»

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

5 питань

Секрети - паролі до бази, APP_KEY, ключі API, токени платіжних систем - не повинні жити в коді. У Laravel їх зберігають у файлі .env, який:

  • ніколи не комітиться - він уже є в .gitignore стандартного проєкту;
  • має шаблон .env.example у репозиторії - з назвами змінних, але без справжніх значень;
  • на сервері доступний лише користувачу, від якого працює застосунок (chmod 600), і лежить поза публічним каталогом (public/).

У коді секрети читаються лише через конфігурацію: config('services.stripe.secret'), а env() - тільки у файлах config/*.php. Після php artisan config:cache виклики env() поза конфігурацією повертають null.

Якщо .env потрапив у Git (навіть на хвилину, навіть у приватний репозиторій):

  1. вважати всі секрети з файлу скомпрометованими і змінити їх - згенерувати нові ключі API, паролі до бази, новий токен бота. Це головний крок;
  2. видалити файл з репозиторію й додати в .gitignore;
  3. за потреби переписати історію (git filter-repo) - але це вже другорядне: копія могла лишитися у форках, клонах, кешах CI, на GitHub у вигляді доступних за хешем комітів.

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

Профілактика:

  • сканування секретів перед пушем: GitHub secret scanning з push protection, gitleaks чи trufflehog у pre-commit або CI;
  • окремі ключі для кожного оточення (локальне, staging, продакшен) - витік локальних ключів не зачіпає продакшен;
  • ключі з найменшими правами - токен, якому потрібно лише читати, не повинен уміти писати;
  • для командної роботи - зашифрований .env (php artisan env:encrypt) чи менеджер секретів, а не пересилання файлу в месенджері.

Докладніше в документації: Laravel: конфігурація оточення

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

Що перевірити перед запуском:

Що Чим небезпечне відкрите Як закрити
Laravel Telescope (/telescope) запити з тілами, SQL, винятки, вміст сесій і кешу лише --dev залежність або gate viewTelescope з переліком адмінів
Laravel Horizon (/horizon) дані завдань у черзі (часто з email чи id), можливість повторити чи видалити завдання Gate::define('viewHorizon', ...) - за замовчуванням на не-локальному середовищі доступу немає ні в кого, але ворота часто «відкривають» для зручності
Debugbar SQL з параметрами, сесія, конфігурація на кожній сторінці лише в require-dev, APP_DEBUG=false
Сторінка винятку (APP_DEBUG=true) стек викликів, шляхи, фрагменти коду, змінні оточення APP_DEBUG=false на продакшені
phpinfo(), info.php версії, модулі, змінні середовища, іноді ключі не тримати такі файли в public/
Pulse, Log Viewer та інші панелі метрики, логи з персональними даними авторизація через Gate
.env, .git, storage/, composer.json секрети й вихідний код корінь вебсервера - лише public/
адмінка й Filament повний доступ до даних canAccessPanel(), двофакторна автентифікація, бажано обмеження за IP чи VPN

Принципи:

  • dev-пакети - у require-dev, а на продакшені composer install --no-dev: якщо пакета немає, його неможливо випадково відкрити;
  • ворота (Gate) замість «таємної адреси» - змінений шлях /telescope-x7k2 не захист, його знаходять перебором і з логів;
  • перевірка ззовні: після деплою відкрити ці адреси без входу (чи прогнати сканер) - очікується 404 чи 403, а не сторінка інструменту;
  • автоматичний тест: Pest-тест, що гість отримує 403 на /horizon і /telescope, ловить випадкову зміну воріт ще до продакшену.

Додатковий шар - WAF чи правило на рівні проксі, що блокує типові службові шляхи (/phpinfo, /.env, /_ignition, /telescope) для всіх, крім адміністраторів. Але це доповнення до закритих інструментів, а не заміна.

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

Застосунок часто підключається до бази під обліковим записом з усіма правами - root у MySQL чи postgres у PostgreSQL. Поки все працює, різниці не видно. Різниця з'являється, коли щось іде не так.

Що дає зловмиснику всемогутній користувач:

  • через SQL-ін'єкцію - не лише читання даних, а DROP DATABASE, читання й запис файлів сервера (LOAD DATA, COPY ... TO PROGRAM у PostgreSQL для суперкористувача), створення нових користувачів;
  • через вкрадений .env - повний контроль над усіма базами на сервері, а не лише над даними застосунку.

Принцип найменших прав - кожен обліковий запис має лише те, що йому справді потрібно:

Користувач Права
застосунок SELECT, INSERT, UPDATE, DELETE на свою базу
міграції (деплой) + CREATE, ALTER, DROP, INDEX на свою базу
аналітика, звіти лише SELECT, бажано на репліці
бекап читання й блокування, без зміни даних
-- PostgreSQL
CREATE ROLE app LOGIN PASSWORD '...';
GRANT CONNECT ON DATABASE shop TO app;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO app;
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO app;

Інші правила:

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

Практичний компроміс у Laravel: міграції часто запускають тим самим користувачем, що й застосунок. Окреме підключення для міграцій (--database=migrations) з ширшими правами - кращий варіант для продакшену.

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

У Laravel-проєкті кореневий каталог сайту (document root) - лише public/. Там лежать index.php і зібрані ассети. Усе інше - код, .env, storage/, vendor/, .git/ - має бути поза доступом вебсервера.

Типова помилка - document root вказує на корінь проєкту:

root /var/www/shop;          # неправильно
root /var/www/shop/public;   # правильно

Тоді за прямими посиланнями доступні:

  • /.env - паролі до бази, APP_KEY, ключі API. Сканери перевіряють цей шлях на мільйонах сайтів щодня;
  • /.git/ - з каталогу .git інструменти на кшталт git-dumper відновлюють увесь вихідний код і історію комітів, включно з колись видаленими секретами;
  • /storage/logs/laravel.log - стеки помилок, інколи персональні дані;
  • /composer.json, composer.lock - точні версії залежностей для пошуку відомих вразливостей;
  • резервні копії й дампи (backup.sql, .env.bak, index.php~), залишені в публічних каталогах.

Як захиститися:

  • document root = public/ - головне правило;
  • у Nginx - заборона прихованих файлів, крім .well-known (потрібен для сертифікатів Let's Encrypt і security.txt):
location ~ /\.(?!well-known).* {
    deny all;
}
  • не класти в public/ нічого, крім того, що має бути публічним. Файли користувачів - через storage:link лише для публічного диска, приватні - через контролер з перевіркою прав;
  • не деплоїти .git на сервер, якщо він не потрібен (збірка артефакту в CI);
  • регулярна перевірка ззовні: curl -I https://example.com/.env має повертати 404 чи 403. Такі перевірки варто додати в моніторинг.

WAF-правила (наприклад, у Cloudflare), що блокують запити до .env, .git, wp-admin, phpmyadmin, - корисний додатковий рубіж, але не заміна правильному document root.

Докладніше в документації: Laravel: налаштування Nginx

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

Правило 3-2-1:

  • 3 копії даних (основна + дві резервні);
  • на 2 різних носіях чи типах сховищ;
  • 1 копія поза основною інфраструктурою - інший провайдер, регіон, обліковий запис.

Захист від вимагачів і зловмисників:

  • зловмисник, що отримав доступ до сервера, видалить і бекапи, якщо сервер має права на їх видалення. Тому:
    • сервер має лише право дописувати нові копії, але не видаляти чи перезаписувати старі;
    • незмінні копії - Object Lock в S3-сумісних сховищах (режим compliance), версіонування бакетів;
    • окремий обліковий запис для бекапів, до якого немає доступу з продакшену;
  • офлайн- чи ізольовані копії - CISA рекомендує тримати хоча б одну копію поза мережею.

Шифрування: бекапи містять усі персональні дані й секрети. Вони мають бути зашифровані, а ключ - зберігатися окремо від бекапів (і не лише на тому самому сервері).

Що бекапити:

  • базу даних (дамп чи фізична копія + журнали для відновлення на момент у часі);
  • файли користувачів (storage/app, бакет S3);
  • конфігурацію й секрети (зашифрованими) - без них відновлений застосунок не запуститься.

Найважливіше - перевірка відновлення. Бекап, який жодного разу не відновлювали, - лише надія. Регулярне (автоматизоване) відновлення в окреме оточення з перевіркою:

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

Так заодно вимірюється реальний час відновлення - і він часто неприємно дивує.

Моніторинг: сповіщення, якщо бекап не створився чи його розмір різко змінився (і раптове зменшення - ознака проблеми).

Докладніше в документації: CISA: посібник з протидії програмам-вимагачам