# Разпознаване на замъглен PHP код

> eval, base64_decode и други: по какво разпознавате замъглен PHP код, как да търсите безопасно и как да отличавате легитимните енкодери от злонамерен код.

Източник: https://phpsos.de/bg/blog/verschleierter-php-code/  
Актуалност: 25.10.2026  
Доставчик: PHP SOS, Спешна помощ за PHP и сигурност на сървъри. Незабавна помощ по WhatsApp: https://wa.me/491736494914?text=%D0%97%D0%B4%D1%80%D0%B0%D0%B2%D0%B5%D0%B9%D1%82%D0%B5%2C%20PHP%20SOS%2C%20%D0%B8%D0%BC%D0%B0%D0%BC%D0%B5%20%D0%BD%D1%83%D0%B6%D0%B4%D0%B0%20%D0%BE%D1%82%20%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%20%D1%81%20%D0%BD%D0%B0%D1%88%D0%B8%D1%8F%20PHP%20%D1%81%D1%8A%D1%80%D0%B2%D1%8A%D1%80.%20%D0%A4%D0%B8%D1%80%D0%BC%D0%B0%3A%20%E2%80%A6%20%D0%A3%D0%B5%D0%B1%D1%81%D0%B0%D0%B9%D1%82%3A%20%E2%80%A6

**Накратко:** Замъгленият PHP код е код, умишлено направен нечетим, най-често чрез кодиране и компресия, които се разгръщат едва по време на изпълнение. Типични шаблони за разпознаване са `eval` заедно с `base64_decode`, `gzinflate` или `str_rot13`, много дълги редове, шестнадесетични низове и имена на функции, съставяни от части. Търсете с безобидни команди grep, никога не изпълнявайте кода и сверявайте находките с оригиналния пакет.

## Защо нападателите крият кода си

Който оставя уеб шел или задна вратичка на сървър, иска тя да остане дълго неоткрита. Четим код би направил впечатление на всеки администратор, отворил файла, и всеки скенер би го намерил. Затова нападателите опаковат кода си: той се кодира, компресира и едва при извикването се сглобява отново и се изпълнява.

За PHP2Shell няма потвърдени Indicators of Compromise. Замъгленият код не е признак на тази уязвимост, а общ знак, че някой е вмъкнал код, независимо по кой път. Как да намерите и премахнете уеб шелове изцяло, описва [Разпознаване и премахване на уеб шел](https://phpsos.de/bg/ratgeber/webshell-erkennen/). Тази статия се концентрира върху въпроса по какво разпознавате замъглен код.

## eval, base64 и други: типичните градивни елементи

Замъгляването следва почти винаги един и същ принцип: нечетим блок данни се превръща от една или няколко функции обратно в код, който после се изпълнява. Следните елементи се появяват отново и отново.

| Елемент | Примери | Защо прави впечатление |
|---|---|---|
| Изпълнение | `eval`, `assert` с низ (до PHP 7.x), `create_function` (до PHP 7.x) | изпълнява текст като код |
| Декодиране | `base64_decode`, `str_rot13`, `hex2bin`, `strrev`, `convert_uudecode` | прави данните отново четими |
| Декомпресия | `gzinflate`, `gzuncompress`, `gzdecode` | разархивира вграден код |
| Сглобяване | вериги `chr()`, свързване на кратки части, `\x` escape последователности | крие имената на функции |
| Динамично извикване | променливи като име на функция, `call_user_func`, `array_map` с низ | извикването не се появява никъде в явен вид |
| Достъп до системата | `system`, `exec`, `shell_exec`, `passthru`, `proc_open`, `popen` | команди на сървъра |

Според PHP наръчника `assert()` от PHP 8.0 вече не оценява низове като код, а `create_function()` е премахната в PHP 8.0. На сървъри със по-стари версии на PHP и двете остават релевантни термини за търсене.

Отделен елемент рядко е подозрителен, `base64_decode` например ползват легитимно много приложения. Подозрително става съчетанието: декодиране, чийто резултат тече директно в изпълнение.

## Безопасно търсене: безобидни команди grep

Следните команди претърсват файловете само като текст. Те не изпълняват PHP код. Пригодете пътя.

```bash
# Изпълнение, комбинирано с декодиране или декомпресия
grep -rlE "(eval|assert)\s*\(\s*(base64_decode|gzinflate|gzuncompress|str_rot13|hex2bin)" /var/www --include="*.php*"

# Много дълги редове (често пакетиран код)
grep -rlE ".{2000,}" /var/www --include="*.php*"

# Много шестнадесетични escape последователности или вериги chr() в един ред
grep -rlE "(\\\\x[0-9a-fA-F]{2}){20,}" /var/www --include="*.php*"
grep -rlE "(chr\s*\(\s*[0-9]+\s*\)\s*\.\s*){8,}" /var/www --include="*.php*"

# Извикване на функция през променлива веднага след присвояване от низове
grep -rnE "\\\$[a-zA-Z_]+\s*=\s*['\"][a-z_]{4,}['\"]\s*;\s*\\\$[a-zA-Z_]+\s*\(" /var/www --include="*.php*" | head -50
```

Проверете попаденията първо с `ls -l` и времевия печат и ги отваряйте после само като текст, например с `less`. Никога не извиквайте подозрителни файлове през браузъра, защото така сървърът би ги изпълнил.

## Къде обикновено стои замъгленият код

Замъгленият код рядко стои в собствен, набиващ се на очи файл. По-често се вмъква в съществуващи файлове, съвсем в началото или съвсем в края, често след много празни редове, за да не прави впечатление веднага при отваряне. Любими са файлове, които се зареждат при всяко извикване: централният `index.php`, конфигурационните файлове и файловете с функции на темата.

Особено незабележим път минава през конфигурацията. С настройката `auto_prepend_file` PHP зарежда преди всеки скрипт допълнителен файл. Ако тя стои в `.user.ini` или `.htaccess`, създадени от нападател, кодът му работи при всяко извикване на страница, без да е променен нито един файл на приложението. Включваният файл обича да носи безобидно разширение като `.ico` или `.png`.

```bash
# Зарежда ли се допълнителен код преди или след всеки скрипт?
grep -rnE "auto_(prepend|append)_file" /var/www --include=".user.ini" --include=".htaccess" --include="*.conf" 2>/dev/null

# PHP код във файлове с разширение на изображение или икона
grep -rlE "<\?php" /var/www --include="*.ico" --include="*.png" --include="*.jpg" --include="*.gif" 2>/dev/null
```

## Отличаване на легитимно замъгляване от злонамерен код

Не всеки нечетим код е злонамерен. Три случая се срещат често:

1. **Комерсиални енкодери:** Някои производители на добавки и софтуер защитават кода си с инструменти като ionCube или SourceGuardian. Файловете са нечетими, но по правило сочат към нужния loader. Сверете ги с оригиналния пакет.
2. **Минифициран или генериран код:** Кешовете и шаблонните машини създават дълги редове без прекъсвания, но без изпълнение на декодиран текст.
3. **Вградени данни:** Изображения или шрифтове като низ Base64 в PHP файл са необичайни, но безобидни, докато резултатът не се изпълнява.

Най-надеждният тест е сверката с източника: ако файлът идва непроменен от пакета на производителя, той е легитимен. Ако не стои в никой оригинален пакет или се различава от него, подлежи на разследване.

> **Важно:**
> Не се опитвайте да разшифровате замъглен код на продуктивния сървър, например като замените `eval` с изход и извикате файла. Дори една грешка при това изпълнява злонамерения код. Анализът принадлежи в изолирана среда.

## Граници на търсенето по шаблони

Нападателите познават обичайните команди за търсене. Те разделят имената на функции, съставят ги по време на изпълнение или изнасят същинския код в базата данни, в файлове с изображения или в конфигурационни записи. Търсенето по шаблони затова намира много, но не всичко. Защо и скенерите стигат тук до граници, обяснява [Скенери за зловреден софтуер за уебсайтове: какво намират и какво не](https://phpsos.de/bg/blog/grenzen-von-malware-scannern/).

Находката освен това рядко е единствената. Нападателите често ползват в няколко файла един и същ елемент, например забележимо име на променлива или характерна последователност от знаци в началото на кодирания блок. След потвърдена находка затова потърсете целенасочено точно тази последователност в цялата уеб директория, и в други уебсайтове на същия сървър. Така намирате братя, които никое от общите търсения по шаблони не е обхванало.

Допълнете търсенето със сверка с оригинални файлове и с поглед в базата данни, вижте [Проверка на базата данни за вмъкнат код](https://phpsos.de/bg/blog/datenbank-auf-schadcode-pruefen/). Превантивно ненужните системни функции могат да се блокират, както е описано в ръководството [Правилно използване на disable_functions](https://phpsos.de/bg/ratgeber/disable-functions/).

## Как помага PHP SOS конкретно?

- **Търсене:** Претърсваме файловете и базата данни с разширени шаблони и сверяваме с оригинални пакети.
- **Анализ:** Изследваме подозрителния код в изолирана среда, без да застрашаваме Вашата система.
- **Почистване:** С [премахване на зловреден софтуер](https://phpsos.de/bg/leistungen/malware-entfernung/) премахваме всички съставни части и затваряме пътя на проникване.
- **Защита:** Ограничаваме PHP функциите и правата за запис и наблюдаваме нови или променени файлове.


## Често задавани въпроси

**eval с base64_decode винаги ли е злонамерен код?**  
Не винаги, но много често. Легитимният код почти не се нуждае от това съчетание. Във файлове, които не принадлежат към Вашето приложение или към позната добавка, то е силен предупредителен сигнал.

**Мога ли да декодирам замъглен код, за да го прочета?**  
Само без да го изпълнявате и не на продуктивния сървър. Дори непреднамерено изпълнение може да причини щети. При съмнение оставете анализа на специалисти, които работят с изолирани среди.

**Защо моят скенер за зловреден софтуер не намира кода?**  
Скенерите търсят познати шаблони. Нападателите непрекъснато променят кода си, разделят имената на функции или ги съставят по време на изпълнение. Празното сканиране затова не е доказателство за чист сървър.

**Какво да кажем за комерсиално криптирани добавки?**  
Някои производители защитават кода си с енкодери като ionCube или SourceGuardian. Такива файлове са нечетими, но легитимни, ако идват от производителя. Сверете ги с оригиналния пакет.

**Помага ли disable_functions срещу замъглен код?**  
Отчасти. Функции като exec или system могат да се блокират, eval обаче не, защото е езикова конструкция, а не функция. Блокировката затруднява следващата стъпка на нападателите, но не предотвратява всеки злонамерен код.

## Източници

- [PHP наръчник: assert()](https://www.php.net/manual/de/function.assert.php)
- [PHP наръчник: create_function()](https://www.php.net/manual/de/function.create-function.php)
- [OWASP Cheat Sheet Series](https://cheatsheetseries.owasp.org/)
