# Rozpoznanie zahmleného kódu PHP

> eval, base64_decode a spol.: ako rozpoznať zahmlený kód PHP, ako ho bezpečne hľadať a ako odlíšiť legitímne enkódery od škodlivého kódu.

Zdroj: https://phpsos.de/sk/blog/verschleierter-php-code/  
Stav: 25.10.2026  
Poskytovateľ: PHP SOS, Núdzová pomoc pri PHP a bezpečnosť serverov. Okamžitá pomoc cez WhatsApp: https://wa.me/491736494914?text=Dobr%C3%BD%20de%C5%88%2C%20PHP%20SOS%2C%20potrebujeme%20pomoc%20s%20na%C5%A1%C3%ADm%20serverom%20s%20PHP.%20Spolo%C4%8Dnos%C5%A5%3A%20%E2%80%A6%20Web%3A%20%E2%80%A6

**Stručne:** Zahmlený kód PHP je kód, ktorý bol zámerne urobený nečitateľným, zvyčajne kódovaním a kompresiou, ktoré sa rozlúštia až za behu. Typické vzorce na rozpoznanie sú `eval` spolu s `base64_decode`, `gzinflate` alebo `str_rot13`, veľmi dlhé riadky, hexadecimálne reťazce a názvy funkcií skladané z jednotlivých častí. Hľadajte neškodnými príkazmi grep, kód nikdy nespúšťajte a nálezy porovnajte s pôvodným balíkom.

## Prečo útočníci svoj kód ukrývajú

Kto uloží na server webshell alebo zadné vrátka, chce, aby ostali dlho neodhalené. Čitateľný kód by bol nápadný každému adminovi, ktorý súbor otvorí, a každý skener by ho našiel. Útočníci preto svoj kód balia: kóduje sa, komprimuje a až pri zavolaní sa opäť poskladá a spustí.

Pre PHP2Shell neexistujú potvrdené indikátory kompromitácie (Indicators of Compromise). Zahmlený kód nie je znakom tejto zraniteľnosti, ale všeobecným znakom toho, že niekto votrel kód, bez ohľadu na cestu. Ako webshelly nájsť a odstrániť ako celok, opisuje [Rozpoznanie a odstránenie webshellu](https://phpsos.de/sk/ratgeber/webshell-erkennen/). Tento článok sa sústreďuje na otázku, podľa čoho zahmlený kód spoznáte.

## eval, base64 a spol.: typické stavebné prvky

Zahmlenie sa takmer vždy riadi rovnakým princípom: nečitateľný blok dát sa jednou alebo viacerými funkciami premení späť na kód, ktorý sa potom spustí. Nasledujúce stavebné prvky sa pritom stále objavujú.

| Stavebný prvok | Príklady | Prečo upúta |
|---|---|---|
| Vykonanie | `eval`, `assert` s reťazcom (do PHP 7.x), `create_function` (do PHP 7.x) | vykoná text ako kód |
| Dekódovanie | `base64_decode`, `str_rot13`, `hex2bin`, `strrev`, `convert_uudecode` | robí dáta opäť čitateľnými |
| Dekompresia | `gzinflate`, `gzuncompress`, `gzdecode` | rozbalí vložený kód |
| Skladanie | reťazce `chr()`, spájanie krátkych čiastkových reťazcov, úniky `\x` | skrýva názvy funkcií |
| Dynamické volanie | premenné ako názov funkcie, `call_user_func`, `array_map` s reťazcom | volanie sa nikde neobjaví v čistom texte |
| Prístup k systému | `system`, `exec`, `shell_exec`, `passthru`, `proc_open`, `popen` | príkazy na serveri |

Podľa príručky PHP `assert()` od PHP 8.0 už nevyhodnocuje reťazce ako kód a `create_function()` bola v PHP 8.0 odstránená. Na serveroch so staršími verziami PHP ostávajú oba relevantnými hľadanými pojmami.

Jednotlivý stavebný prvok je zriedka podozrivý, `base64_decode` používa legitímne mnoho aplikácií. Podozrivou sa stáva kombinácia: dekódovanie, ktorého výsledok ide priamo do vykonania.

## Hľadať bezpečne: neškodné príkazy grep

Nasledujúce príkazy prehľadávajú súbory len ako text. Nespúšťajú žiadny kód PHP. Prispôsobte cestu.

```bash
# Vykonanie v kombinácii s dekódovaním alebo dekompresiou
grep -rlE "(eval|assert)\s*\(\s*(base64_decode|gzinflate|gzuncompress|str_rot13|hex2bin)" /var/www --include="*.php*"

# Veľmi dlhé riadky (často zabalený kód)
grep -rlE ".{2000,}" /var/www --include="*.php*"

# Veľa hexadecimálnych únikov alebo reťazcov chr() v jednom riadku
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*"

# Volanie funkcie cez premennú hneď po priradení z reťazcov
grep -rnE "\\\$[a-zA-Z_]+\s*=\s*['\"][a-z_]{4,}['\"]\s*;\s*\\\$[a-zA-Z_]+\s*\(" /var/www --include="*.php*" | head -50
```

Zásahy najprv skontrolujte pomocou `ls -l` a časovej pečiatky a potom ich otvorte len ako text, napríklad pomocou `less`. Podozrivé súbory nikdy nevolajte cez prehliadač, pretože by ich server vykonal.

## Kde sa zahmlený kód typicky nachádza

Zahmlený kód zriedka stojí vo vlastnom nápadnom súbore. Častejšie sa vkladá do existujúcich súborov, celkom na začiatok alebo celkom na koniec, často za mnoho prázdnych riadkov, aby pri otvorení hneď nepadol do oka. Obľúbené sú súbory, ktoré sa načítavajú pri každom volaní: centrálny `index.php`, konfiguračné súbory a funkčné súbory témy.

Mimoriadne nenápadná cesta vedie cez konfiguráciu. Nastavením `auto_prepend_file` načíta PHP pred každým skriptom ďalší súbor. Ak je v `.user.ini` alebo `.htaccess`, ktorý vytvoril útočník, beží jeho kód pri každom zobrazení stránky, bez toho, aby sa zmenil jediný súbor aplikácie. Vložený súbor pritom rád nesie neškodnú príponu ako `.ico` alebo `.png`.

```bash
# Načítava sa pred alebo po každom skripte ďalší kód?
grep -rnE "auto_(prepend|append)_file" /var/www --include=".user.ini" --include=".htaccess" --include="*.conf" 2>/dev/null

# Kód PHP v súboroch s príponou obrázka alebo ikony
grep -rlE "<\?php" /var/www --include="*.ico" --include="*.png" --include="*.jpg" --include="*.gif" 2>/dev/null
```

## Legitímne zahmlenie odlíšiť od škodlivého kódu

Nie každý nečitateľný kód je zlomyseľný. Často sa vyskytujú tri prípady:

1. **Komerčné enkódery:** Niektorí výrobcovia pluginov a softvéru chránia svoj kód nástrojmi ako ionCube alebo SourceGuardian. Súbory sú nečitateľné, no typicky odkazujú na potrebný loader. Porovnajte ich s pôvodným balíkom.
2. **Minifikovaný alebo generovaný kód:** Cache a šablónovacie nástroje vytvárajú dlhé riadky bez zalomení, avšak bez vykonávania dekódovaného textu.
3. **Vložené dáta:** Obrázky alebo písma ako reťazec Base64 v súbore PHP sú neobvyklé, ale neškodné, kým sa výsledok nevykonáva.

Najspoľahlivejším testom je porovnanie so zdrojom: ak súbor pochádza nezmenený z balíka výrobcu, je legitímny. Ak sa nenachádza v žiadnom pôvodnom balíku alebo sa od neho odlišuje, patrí na vyšetrenie.

> **Dôležité:**
> Nepokúšajte sa zahmlený kód rozlúštiť na produkčnom serveri, napríklad nahradením `eval` výpisom a zavolaním súboru. Už jedna chyba pritom spustí škodlivý kód. Analýza patrí do izolovaného prostredia.

## Hranice vyhľadávania podľa vzorcov

Útočníci poznajú bežné hľadacie príkazy. Rozdeľujú názvy funkcií, skladajú ich za behu alebo skutočný kód vyčleňujú do databázy, do súborov obrázkov alebo do konfiguračných záznamov. Vyhľadávanie podľa vzorcov preto nájde veľa, ale nie všetko. Prečo narážajú na hranice aj skenery, vysvetľuje [Skenery malvéru pre weby: čo nájdu a čo nie](https://phpsos.de/sk/blog/grenzen-von-malware-scannern/).

Nález je navyše zriedka jediný. Útočníci používajú vo viacerých súboroch často ten istý stavebný prvok, napríklad nápadné označenie premennej alebo výrazný reťazec znakov na začiatku kódovaného bloku. Po potvrdenom náleze preto cielene hľadajte presne tento reťazec v celom webovom adresári, aj v iných weboch na tom istom serveri. Tak nájdete súrodencov, ktorých nezachytilo žiadne všeobecné vyhľadávanie podľa vzorcov.

Vyhľadávanie doplňte o porovnanie s pôvodnými súbormi a o pohľad do databázy, pozri [Kontrola databázy na votrelecký kód](https://phpsos.de/sk/blog/datenbank-auf-schadcode-pruefen/). Preventívne sa dajú zablokovať nepotrebné systémové funkcie, ako opisuje sprievodca [Správne používanie disable_functions](https://phpsos.de/sk/ratgeber/disable-functions/).

## Ako konkrétne pomáha PHP SOS?

- **Hľadať:** Prehľadáme súbory a databázu rozšírenými vzorcami a porovnáme s pôvodnými balíkmi.
- **Analyzovať:** Podozrivý kód skúmame v izolovanom prostredí bez ohrozenia vášho systému.
- **Vyčistiť:** Prostredníctvom [odstránenia malvéru](https://phpsos.de/sk/leistungen/malware-entfernung/) odstránime všetky súčasti a uzavrieme cestu vstupu.
- **Zabezpečiť:** Obmedzíme funkcie PHP a práva zápisu a sledujeme nové alebo zmenené súbory.


## Časté otázky

**Je eval s base64_decode vždy škodlivý kód?**  
Nie vždy, ale veľmi často. Legitímny kód túto kombináciu takmer nepotrebuje. V súboroch, ktoré nepatria k vašej aplikácii ani k známemu pluginu, je to silný varovný signál.

**Smiem zahmlený kód dekódovať na čítanie?**  
Len bez jeho spustenia a nie na produkčnom serveri. Už náhodné spustenie môže spôsobiť škodu. Analýzu nechajte v pochybnostiach odborníkom, ktorí pracujú s izolovanými prostrediami.

**Prečo môj skener malvéru kód nenájde?**  
Skenery hľadajú známe vzorce. Útočníci svoj kód neustále menia, rozdeľujú názvy funkcií alebo ich skladajú za behu. Prázdny sken preto nie je dôkazom čistého servera.

**Čo komerčne šifrované pluginy?**  
Niektorí výrobcovia chránia svoj kód enkódermi ako ionCube alebo SourceGuardian. Takéto súbory sú nečitateľné, ale legitímne, ak pochádzajú od výrobcu. Porovnajte ich s pôvodným balíkom.

**Pomáha disable_functions proti zahmlenému kódu?**  
Čiastočne. Funkcie ako exec alebo system sa dajú zablokovať, eval však nie, pretože ide o jazykový konštrukt, nie o funkciu. Zablokovanie sťažuje útočníkom ďalší krok, no nezabráni každému škodlivému kódu.

## Zdroje

- [Príručka PHP: assert()](https://www.php.net/manual/de/function.assert.php)
- [Príručka PHP: create_function()](https://www.php.net/manual/de/function.create-function.php)
- [OWASP Cheat Sheet Series](https://cheatsheetseries.owasp.org/)
