---
title: "Laravel Scalpel: Сканер для виявлення слідів вторгнень у файлову систему"
url: https://laravelukraine.com/blog/laravel-scalpel-skaner-dlia-viiavlennia-slidiv-vtorgnen-u-failovu-sistemu
date: 2026-09-18
source: https://laravel-news.com/laravel-scalpel?utm_medium=feed&utm_source=feedpress.me&utm_campaign=Feed%3A+laravelnews
---

# Laravel Scalpel: Сканер для виявлення слідів вторгнень у файлову систему

Laravel Scalpel - це сканер слідів вторгнень від [Harry Agustiana](https://github.com/hryagstn), який працює всередині Laravel-додатка та перевіряє файлову систему на ознаки компрометації: підозрілі PHP-файли, обфускований код, змінені серверні директиви та зміни порівняно з еталонним знімком.

Інструменти на кшталт [Ward](https://laravel-news.com/ward-a-security-scanner-for-laravel) та [Checkpoint](https://laravel-news.com/audit-laravel-apps-for-security-issues-with-checkpoint) інспектують вихідний код, конфігурацію та залежності на предмет проблем безпеки. Scalpel виконує іншу задачу: він шукає докази того, що файли в розгорнутому додатку вже було додано, змінено або видалено.

## Сканери файлової системи

Команда `scalpel:scan` за замовчуванням запускає шість сканерів. П'ять з них перевіряють поточні файли, а Baseline Diff scanner порівнює їх зі збереженим знімком.

**Структурний сканер** шукає виконувані PHP-файли в директоріях, де PHP не повинно бути. За замовчуванням це `public/` та `storage/`. Він виявляє `.php` файли та менш поширені розширення, такі як `.phtml`, `.pht` і `.phar`, а також подвійні розширення на кшталт `shell.php.jpg`. Сканер дозволяє `public/index.php`, `public/vendor/` та скомпільовані views і cache Laravel за замовчуванням. Ви можете змінити скановані директорії та додати власні файли й папки до списків дозволених.

**Сканер обфускованого коду** перевіряє PHP-файли на типові паттерни бекдорів. Серед них: `eval(base64_decode(...))`, виконання стиснутого payload, динамічні виклики функцій, пряме виконання вхідних даних запиту та довгі закодовані рядки. Якщо легітимний код викликає спрацювання, ви можете вимкнути відповідний паттерн у `config/scalpel.php`.

**Сканер `.htaccess`** повідомляє про handler та MIME type mappings, які дозволяють веб-серверу виконувати Python, Perl, CGI або інші скрипти. Він також позначає `Options +ExecCGI`, rewrite rules, що перенаправляють на зовнішні URL, та PHP-директиви на кшталт `auto_prepend_file`.

**Сканер `.user.ini`** повідомляє про PHP-директиви для конкретних директорій, включно з `auto_prepend_file`, `auto_append_file`, `include_path` та `disable_functions`. Зловмисник може використати `auto_prepend_file` для запуску прихованого файлу при кожному запиті.

**Сканер environment** повідомляє про `.env` файл, який відсутній, порожній або нечитабельний, а також будь-який `.env` файл, розміщений у `public/`. В Unix-подібних системах він також перевіряє, чи файл доступний для читання всім користувачам. Він повідомляє про порожній `APP_KEY`, потім порівнює ключі в `.env` з `.env.example`. Це перетинається з інструментами, які [перевіряють environment keys у кількох файлах](https://laravel-news.com/laravel-env-keys-checker), але Scalpel розглядає неочікувані або відсутні ключі як можливі докази вторгнення. Коли `APP_ENV` встановлено в `production`, сканер позначає `APP_DEBUG=true`. Опція `--production` застосовує цю перевірку незалежно від значення `APP_ENV`, а також позначає `APP_ENV=local`.

Ви можете запустити всі сканери або вибрати підмножину:

```bash
php artisan scalpel:scan
php artisan scalpel:scan --only=structural,obfuscated
php artisan scalpel:scan --only=userini
```

## Порівняння з еталоном

Команда `scalpel:baseline` записує SHA-256 хеш, розмір та час модифікації кожного включеного файлу. Команда `scalpel:diff` потім порівнює поточні файли з цим записом та повідомляє про додані, змінені та видалені файли:

```bash
php artisan scalpel:baseline
php artisan scalpel:diff
```

Створюйте еталон лише після того, як додаток перебуває в стані, якому ви довіряєте. Поки еталон не існує, `scalpel:scan` та `scalpel:diff` повідомляють про `MEDIUM` знахідку, що вказує на необхідність створити його. Після кожного розгортання проєкт пропонує запустити `php artisan optimize`, а потім `scalpel:baseline --force` для заміни старого еталона.

Виключення за замовчуванням пропускають шляхи, що часто змінюються, такі як логи, сесії, скомпільовані views та `storage/app`. Директорія `vendor/` пропускається сканерами вмісту, але залишається частиною порівнянь з еталоном, тому файл, доданий до встановленого пакета, все одно з'явиться в diff.

За замовчуванням Scalpel працює в суворому режимі та хешує кожен файл під час кожного порівняння. Опція `--fast` спочатку порівнює розмір файлу та час модифікації, потім повторно використовує старий хеш, коли обидва збігаються. Це зменшує роботу з хешуванням, але порівняння з еталоном може пропустити змінений файл, коли зловмисник зберігає його розмір та час модифікації. Інший сканер все ще може повідомити про файл на основі його вмісту або розташування.

Scalpel може HMAC-підписувати еталони та JSON-звіти, коли `SCALPEL_SIGNING_ENABLED` встановлено в `true`, а `SCALPEL_SIGNING_KEY` містить виділений ключ, який не є вашим `APP_KEY`. Команда diff перевіряє підписаний еталон перед використанням і повідомляє про недійсний або відсутній підпис як `CRITICAL`. Це виявляє еталон, регенерований без ключа підпису, але не може захистити еталон, коли зловмисник може прочитати цей ключ або змінити сам сканер. Увімкніть підписування перед створенням першого еталона. Команда `scalpel:verify` перевіряє підпис збереженого JSON-звіту.

## Тестове сканування

Автор статті протестував Scalpel 1.9.0 у свіжому Laravel 13.31 додатку. З правами доступу до `.env`, встановленими на `0600`, та еталоном на місці, стандартне сканування не виявило жодних знахідок.

Потім було додано чотири нешкідливі тестові файли: виклик `eval(base64_decode(...))` всередині блоку `if (false)`, файл з назвою `avatar.php.jpg`, handler mapping у `.htaccess` та файл `.user.ini` з `auto_prepend_file`.

Запуск чотирьох сканерів вмісту зберіг вивід коротким:

```bash
php artisan scalpel:scan \
--only=structural,obfuscated,htaccess,userini \
--no-banner
```

Повне сканування повернуло дев'ять знахідок, оскільки сканер еталона також повідомив про чотири нові файли та змінений файл `routes/web.php`.

Той самий тест виявив проблему з налаштуваннями за замовчуванням, яку слід врахувати в CI. Запуск `php artisan optimize` скомпілював framework views у `storage/framework/views`. Наступне сканування повідомило про 100 `MEDIUM` знахідок variable-variable та дві `HIGH` знахідки backtick у цих згенерованих файлах. Після `php artisan optimize:clear` та повторного створення еталона сканування завершилося без знахідок.

Структурний сканер дозволяє директорію скомпільованих views Laravel, але сканер обфускованого коду все ще читає її вміст. Додаток, який кешує views у production, повинен протестувати цей шлях перед додаванням Scalpel до deployment gate. Додавання `storage/framework/views` до `content_scan_excluded_paths` уникає цих знахідок, але за ціну пропуску перевірок вмісту для кожного скомпільованого view.

## Вивід CI та Laravel Events

Обидві команди `scalpel:scan` та `scalpel:diff` підтримують форматування виводу у вигляді таблиці, JSON, GitHub Actions annotation та SARIF. Опція `--fail-on` встановлює найнижчу серйозність, що призводить до провалу CI job. За замовчуванням це `HIGH`.

```bash
php artisan scalpel:scan --format=sarif --fail-on=MEDIUM
```

Код виходу `0` означає, що сканування завершилося і нічого не знайдено. Код `1` означає, що принаймні одна знахідка перебуває на рівні `--fail-on` severity або вище. Код `2` охоплює знахідки нижче цієї серйозності або незавершене сканування, тому нечитабельна директорія не призводить до чистого статусу.

Після `scalpel:scan` або `scalpel:diff` пакет відправляє подію `ScanFinished`. Подія містить знахідки, команду, що виконувалася (`scan` або `diff`), та тривалість у мілісекундах. Додаток може слухати цю подію та відправляти власні mail, Slack або webhook сповіщення без парсингу виводу команди.

## Встановлення

Laravel Scalpel вимагає PHP 8.2 або новіше та підтримує Laravel 10-13. Встановіть його через Composer, потім опублікуйте конфігурацію:

```bash
composer require hryagstn/laravel-scalpel
php artisan vendor:publish --tag=scalpel-config
```

Сканер працює в тому ж процесі та з тими ж правами доступу до файлової системи, що й Laravel-додаток. Зловмисник, який може змінити код додатка, також може змінити сканер або його конфігурацію. Проєкт рекомендує зовнішні тригери сканування, директорії коду лише для читання та відправлення результатів у сховище за межами скомпрометованого сервера. Scalpel виявляє докази вторгнення, але не забезпечує захист firewall або containment.

Ви можете переглянути вихідний код та повний довідник команд на [GitHub](https://github.com/hryagstn/laravel-scalpel) або спробувати симулятор команд на [вебсайті Laravel Scalpel](https://hryagstn.github.io/laravel-scalpel/).
