# Prepoznati zamagljeni PHP kod

> eval, base64_decode i slično: po čemu prepoznati zamagljeni PHP kod, kako ga bezopasno tražiti i razlikovati legitimne enkodere od zlonamjernog koda.

Izvor: https://phpsos.de/hr/blog/verschleierter-php-code/  
Stanje: 25.10.2026  
Pružatelj: PHP SOS, PHP hitna pomoć i sigurnost poslužitelja. Hitna pomoć putem WhatsAppa: https://wa.me/491736494914?text=Pozdrav%20PHP%20SOS%2C%20trebamo%20pomo%C4%87%20s%20na%C5%A1im%20PHP%20poslu%C5%BEiteljem.%20Tvrtka%3A%20%E2%80%A6%20Web-stranica%3A%20%E2%80%A6

**Ukratko:** Zamagljeni PHP kod je kod koji je namjerno učinjen nečitljivim, uglavnom kodiranjem i kompresijom koje se razrješuju tek tijekom rada. Tipični obrasci prepoznavanja su `eval` zajedno s `base64_decode`, `gzinflate` ili `str_rot13`, vrlo dugi retci, heksadecimalni nizovi znakova i nazivi funkcija sastavljeni od dijelova. Tražite bezopasnim grep naredbama, kod nikad ne izvršavajte i nalaze usporedite s izvornim paketom.

## Zašto napadači skrivaju svoj kod

Tko na poslužitelj odloži web shell ili stražnja vrata, želi da dugo ostanu neotkriveni. Čitljiv kod upao bi u oči svakom administratoru koji otvori datoteku, a svaki bi ga skener pronašao. Zato napadači svoj kod pakiraju: kodira se, komprimira i tek se pri pozivu ponovno sastavlja i izvršava.

Za PHP2Shell nema potvrđenih Indicators of Compromise. Zamagljeni kod nije obilježje te ranjivosti, nego opći znak da je netko ubacio kod, bez obzira na put. Kako općenito pronaći i ukloniti web shellove, opisuje članak [Prepoznati i ukloniti web shell](https://phpsos.de/hr/ratgeber/webshell-erkennen/). Ovaj prilog usredotočen je na pitanje po čemu prepoznati zamagljeni kod.

## eval, base64 i slično: tipični građevni blokovi

Zamagljivanje gotovo uvijek slijedi isto načelo: nečitljivi blok podataka jedna ili više funkcija pretvara natrag u kod koji se potom izvršava. Sljedeći se građevni blokovi stalno ponavljaju.

| Građevni blok | Primjeri | Zašto upada u oči |
|---|---|---|
| Izvršavanje | `eval`, `assert` s nizom znakova (do PHP-a 7.x), `create_function` (do PHP-a 7.x) | izvršava tekst kao kod |
| Dekodiranje | `base64_decode`, `str_rot13`, `hex2bin`, `strrev`, `convert_uudecode` | podatke ponovno čini čitljivima |
| Dekompresija | `gzinflate`, `gzuncompress`, `gzdecode` | raspakirava ugrađeni kod |
| Sastavljanje | lanci `chr()`, nizanje kratkih dijelova, `\x` escape sekvence | skriva nazive funkcija |
| Dinamički poziv | varijable kao naziv funkcije, `call_user_func`, `array_map` s nizom znakova | poziv se nigdje ne pojavljuje otvorenim tekstom |
| Pristup sustavu | `system`, `exec`, `shell_exec`, `passthru`, `proc_open`, `popen` | naredbe na poslužitelju |

Prema PHP priručniku `assert()` od PHP-a 8.0 više ne evaluira nizove znakova kao kod, a `create_function()` je uklonjena u PHP-u 8.0. Na poslužiteljima sa starijim PHP verzijama oba ostaju relevantni pojmovi za pretragu.

Pojedini građevni blok rijetko je sumnjiv, `base64_decode` primjerice mnoge aplikacije legitimno koriste. Sumnjiva postaje kombinacija: dekodiranje čiji rezultat izravno teče u izvršavanje.

## Bezopasno tražiti: bezazlene grep naredbe

Sljedeće naredbe pretražuju datoteke samo kao tekst. Ne izvršavaju nikakav PHP kod. Prilagodite put.

```bash
# Izvršavanje u kombinaciji s dekodiranjem ili dekompresijom
grep -rlE "(eval|assert)\s*\(\s*(base64_decode|gzinflate|gzuncompress|str_rot13|hex2bin)" /var/www --include="*.php*"

# Vrlo dugi retci (često pakirani kod)
grep -rlE ".{2000,}" /var/www --include="*.php*"

# Mnogo heksadecimalnih escape sekvenci ili lanaca chr() u jednom retku
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*"

# Poziv funkcije preko varijable odmah nakon dodjele iz nizova znakova
grep -rnE "\\\$[a-zA-Z_]+\s*=\s*['\"][a-z_]{4,}['\"]\s*;\s*\\\$[a-zA-Z_]+\s*\(" /var/www --include="*.php*" | head -50
```

Pogotke najprije provjerite naredbom `ls -l` i vremenskim žigom, a zatim ih otvarajte samo kao tekst, primjerice s `less`. Sumnjive datoteke nikad ne pozivajte preko preglednika, jer bi ih poslužitelj tada izvršio.

## Gdje se zamagljeni kod tipično nalazi

Zamagljeni kod rijetko stoji u zasebnoj, upadljivoj datoteci. Češće se umeće u postojeće datoteke, sasvim na početak ili na kraj, često nakon mnogo praznih redaka kako pri otvaranju ne bi odmah upao u oči. Omiljene su datoteke koje se učitavaju pri svakom pozivu: središnja `index.php`, konfiguracijske datoteke i datoteke funkcija teme.

Posebno neupadljiv put vodi preko konfiguracije. Postavkom `auto_prepend_file` PHP prije svake skripte učitava dodatnu datoteku. Ako stoji u `.user.ini` ili `.htaccess` koji je napadač stvorio, njegov kod radi pri svakom pozivu stranice, a da nije izmijenjena nijedna datoteka aplikacije. Uključena datoteka pritom rado nosi bezazlen nastavak poput `.ico` ili `.png`.

```bash
# Učitava li se prije ili poslije svake skripte dodatni kod?
grep -rnE "auto_(prepend|append)_file" /var/www --include=".user.ini" --include=".htaccess" --include="*.conf" 2>/dev/null

# PHP kod u datotekama s nastavkom slike ili ikone
grep -rlE "<\?php" /var/www --include="*.ico" --include="*.png" --include="*.jpg" --include="*.gif" 2>/dev/null
```

## Razlikovati legitimno zamagljivanje od zlonamjernog koda

Nije svaki nečitljivi kod zlonamjeran. Tri su slučaja česta:

1. **Komercijalni enkoderi:** Neki proizvođači dodataka i softvera svoj kod štite alatima poput ionCubea ili SourceGuardiana. Datoteke su nečitljive, ali tipično upućuju na potreban loader. Usporedite ih s izvornim paketom.
2. **Minificiran ili generiran kod:** Predmemorije i mehanizmi predložaka stvaraju duge retke bez prijeloma, ali bez izvršavanja dekodiranog teksta.
3. **Ugrađeni podaci:** Slike ili fontovi kao Base64 niz u PHP datoteci su neuobičajeni, ali bezazleni dok se rezultat ne izvršava.

Najpouzdaniji test je usporedba s izvorom: ako datoteka nepromijenjena potječe iz paketa proizvođača, legitimna je. Ako se ne nalazi ni u jednom izvornom paketu ili odstupa od njega, treba je istražiti.

> **Važno:**
> Ne pokušavajte dešifrirati zamagljeni kod na produkcijskom poslužitelju, primjerice zamjenom `eval` ispisom i pozivom datoteke. Već jedna pogreška pritom izvršava zlonamjerni kod. Analiza pripada u izolirano okruženje.

## Granice pretrage po obrascima

Napadači poznaju uobičajene naredbe za pretragu. Dijele nazive funkcija, sastavljaju ih tijekom rada ili stvarni kod izmještaju u bazu podataka, slikovne datoteke ili konfiguracijske unose. Pretraga po obrascima stoga pronalazi mnogo, ali ne sve. Zašto i skeneri ovdje nailaze na granice, objašnjava članak [Skeneri zlonamjernog softvera za web-stranice: što pronalaze, a što ne](https://phpsos.de/hr/blog/grenzen-von-malware-scannern/).

Nalaz je uz to rijetko jedini. Napadači u više datoteka često koriste isti građevni blok, primjerice upadljivo ime varijable ili upečatljiv niz znakova na početku kodiranog bloka. Nakon potvrđenog nalaza zato ciljano potražite upravo taj niz znakova u cijelom web-direktoriju, i u drugim web-stranicama na istom poslužitelju. Tako pronalazite srodnike koje nijedna opća pretraga obrascima nije obuhvatila.

Pretragu dopunite usporedbom s izvornim datotekama i pogledom u bazu podataka, vidi [Provjeriti bazu podataka na ubačeni kod](https://phpsos.de/hr/blog/datenbank-auf-schadcode-pruefen/). Preventivno se nepotrebne sistemske funkcije mogu blokirati, kako opisuje vodič [Ispravno koristiti disable_functions](https://phpsos.de/hr/ratgeber/disable-functions/).

## Kako PHP SOS konkretno pomaže?

- **Tražiti:** Pretražujemo datoteke i bazu podataka proširenim obrascima i uspoređujemo s izvornim paketima.
- **Analizirati:** Sumnjiv kod istražujemo u izoliranom okruženju, bez ugrožavanja Vašeg sustava.
- **Očistiti:** Uz [uklanjanje zlonamjernog softvera](https://phpsos.de/hr/leistungen/malware-entfernung/) uklanjamo sve sastavnice i zatvaramo put upada.
- **Zaštititi:** Ograničavamo PHP funkcije i prava pisanja te nadziremo nove ili izmijenjene datoteke.


## Česta pitanja

**Je li eval s base64_decode uvijek zlonamjeran kod?**  
Ne uvijek, ali vrlo često. Legitiman kod tu kombinaciju jedva treba. U datotekama koje ne pripadaju Vašoj aplikaciji ili poznatom dodatku to je jak znak upozorenja.

**Smijem li zamagljeni kod dekodirati radi čitanja?**  
Samo bez njegova izvršavanja i ne na produkcijskom poslužitelju. Već nehotično izvršavanje može nanijeti štetu. U slučaju sumnje analizu prepustite stručnjacima koji rade u izoliranim okruženjima.

**Zašto moj skener zlonamjernog softvera ne pronalazi kod?**  
Skeneri traže poznate obrasce. Napadači svoj kod stalno mijenjaju, dijele nazive funkcija ili ih sastavljaju tijekom rada. Prazan rezultat skeniranja stoga nije dokaz čistog poslužitelja.

**Što je s komercijalno šifriranim dodacima?**  
Neki proizvođači svoj kod štite enkoderima poput ionCubea ili SourceGuardiana. Takve su datoteke nečitljive, ali legitimne ako potječu od proizvođača. Usporedite ih s izvornim paketom.

**Pomaže li disable_functions protiv zamagljenog koda?**  
Djelomično. Funkcije poput exec ili system mogu se blokirati, eval nasuprot tome ne, jer je jezična konstrukcija, a ne funkcija. Blokada napadačima otežava sljedeći korak, ali ne sprječava svaki zlonamjerni kod.

## Izvori

- [PHP priručnik: assert()](https://www.php.net/manual/de/function.assert.php)
- [PHP priručnik: create_function()](https://www.php.net/manual/de/function.create-function.php)
- [OWASP Cheat Sheet Series](https://cheatsheetseries.owasp.org/)
