Trenutno stanje: PHP2Shell. Dve kritični ranljivosti PHP (CVSS 9,2) omogočata izvedbo škodljive kode brez prijave. Popravki od 21. 10. 2026.Kaj je zdaj treba storiti →

Prepoznavanje zakrite kode PHP

Neberljiva koda PHP z eval in base64_decode je klasičen znak vnesene škodljive kode. Katere vzorce iščete, kako jih najdete brez nevarnosti in kdaj je zakritje legitimno.

Stanje 5 min branjaOdkrivanje in forenzika

Na kratko: Zakrita koda PHP je koda, ki je bila namenoma narejena neberljiva, večinoma s kodiranjem in stiskanjem, ki se razreši šele med izvajanjem. Tipični vzorci za prepoznavanje so eval skupaj z base64_decode, gzinflate ali str_rot13, zelo dolge vrstice, šestnajstiški nizi in imena funkcij, sestavljena iz delov. Iščite z neškodljivimi ukazi grep, kode nikoli ne izvajajte in najdbe primerjajte z izvirnim paketom.

Zakaj napadalci svojo kodo skrivajo

Kdor na strežnik odloži webshell ali stranska vrata, želi, da dolgo ostanejo neodkrita. Berljiva koda bi padla v oči vsakemu skrbniku, ki datoteko odpre, in vsak pregledovalnik bi jo našel. Zato napadalci kodo pakirajo: kodirana je, stisnjena in šele ob priklicu znova sestavljena in izvedena.

Za PHP2Shell ni potrjenih indikatorjev ogroženosti (Indicators of Compromise). Zakrita koda ni značilnost te ranljivosti, ampak splošen znak, da je nekdo vnesel kodo, ne glede na pot. Kako webshelle v celoti najdete in odstranite, opisuje Prepoznavanje in odstranjevanje webshellov. Ta prispevek se osredotoča na vprašanje, po čem zakrito kodo prepoznate.

eval, base64 in drugo: tipični gradniki

Zakritje skoraj vedno sledi istemu načelu: neberljiv podatkovni blok ena ali več funkcij spremeni nazaj v kodo, ki se potem izvede. Naslednji gradniki se pri tem pojavljajo vedno znova.

Gradnik Primeri Zakaj je opazen
Izvajanje eval, assert z nizom (do PHP 7.x), create_function (do PHP 7.x) besedilo izvede kot kodo
Dekodiranje base64_decode, str_rot13, hex2bin, strrev, convert_uudecode podatke naredi spet berljive
Razširjanje gzinflate, gzuncompress, gzdecode razpakira vdelano kodo
Sestavljanje verige chr(), združevanje kratkih delov, ubežne sekvence \x skrije imena funkcij
Dinamičen klic spremenljivke kot ime funkcije, call_user_func, array_map z nizom klic nikjer ni v jasnem besedilu
Dostop do sistema system, exec, shell_exec, passthru, proc_open, popen ukazi na strežniku

Po priročniku PHP assert() od PHP 8.0 nizov ne vrednoti več kot kodo, create_function() pa je bila v PHP 8.0 odstranjena. Na strežnikih s starejšimi različicami PHP ostajata oba pomembna iskalna izraza.

Posamezen gradnik je redko sumljiv, base64_decode na primer mnoge aplikacije uporabljajo legitimno. Sumljiva postane kombinacija: dekodiranje, katerega rezultat teče neposredno v izvajanje.

Iskanje brez nevarnosti: neškodljivi ukazi grep

Naslednji ukazi datoteke preiskujejo samo kot besedilo. Kode PHP ne izvajajo. Pot prilagodite.

# Izvajanje v kombinaciji z dekodiranjem ali razširjanjem
grep -rlE "(eval|assert)\s*\(\s*(base64_decode|gzinflate|gzuncompress|str_rot13|hex2bin)" /var/www --include="*.php*"

# Zelo dolge vrstice (pogosto zapakirana koda)
grep -rlE ".{2000,}" /var/www --include="*.php*"

# Veliko šestnajstiških ubežnih sekvenc ali verig chr() v eni vrstici
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*"

# Klic funkcije prek spremenljivke neposredno po dodelitvi iz nizov
grep -rnE "\\\$[a-zA-Z_]+\s*=\s*['\"][a-z_]{4,}['\"]\s*;\s*\\\$[a-zA-Z_]+\s*\(" /var/www --include="*.php*" | head -50

Zadetke najprej preverite z ls -l in časovnim žigom, nato jih odprite samo kot besedilo, na primer z less. Sumljivih datotek nikoli ne prikličite prek brskalnika, saj bi jih strežnik s tem izvedel.

Kje zakrita koda tipično sedi

Zakrita koda redko stoji v lastni, opazni datoteki. Pogosteje je vstavljena v obstoječe datoteke, povsem na začetek ali povsem na konec, pogosto za mnogimi praznimi vrsticami, da ob odpiranju ne pade takoj v oči. Priljubljene so datoteke, ki se naložijo ob vsakem priklicu: osrednji index.php, konfiguracijske datoteke in funkcijske datoteke teme.

Posebej neopazna pot vodi prek konfiguracije. Z nastavitvijo auto_prepend_file PHP pred vsakim skriptom naloži dodatno datoteko. Če stoji v .user.ini ali .htaccess, ki ju je ustvaril napadalec, njegova koda teče ob vsakem priklicu strani, ne da bi bila spremenjena ena sama datoteka aplikacije. Vključena datoteka pri tem rada nosi neškodljivo končnico, kot sta .ico ali .png.

# Ali se pred ali po vsakem skriptu nalaga dodatna koda?
grep -rnE "auto_(prepend|append)_file" /var/www --include=".user.ini" --include=".htaccess" --include="*.conf" 2>/dev/null

# Koda PHP v datotekah s končnico slike ali ikone
grep -rlE "<\?php" /var/www --include="*.ico" --include="*.png" --include="*.jpg" --include="*.gif" 2>/dev/null

Ločevanje legitimnega zakritja od škodljive kode

Ni vsaka neberljiva koda zlonamerna. Pogosti so trije primeri:

  1. Komercialni kodirniki: Nekateri proizvajalci vtičnikov in programske opreme svojo kodo ščitijo z orodji, kot sta ionCube ali SourceGuardian. Datoteke so neberljive, a praviloma kažejo na potreben nalagalnik (loader). Primerjajte jih z izvirnim paketom.
  2. Minificirana ali ustvarjena koda: Predpomnilniki in mehanizmi predlog ustvarjajo dolge vrstice brez prelomov, vendar brez izvajanja dekodiranega besedila.
  3. Vdelani podatki: Slike ali pisave kot niz Base64 v datoteki PHP so nenavadni, a neškodljivi, dokler se rezultat ne izvaja.

Najzanesljivejši preizkus je primerjava z virom: če datoteka nespremenjena izvira iz paketa proizvajalca, je legitimna. Če ni v nobenem izvirnem paketu ali od njega odstopa, jo je treba raziskati.

Pomembno

Zakrite kode ne poskušajte dešifrirati na produkcijskem strežniku, na primer tako, da eval zamenjate z izpisom in datoteko prikličete. Že napaka pri tem izvede škodljivo kodo. Analiza sodi v izolirano okolje.

Meje iskanja po vzorcih

Napadalci poznajo običajne iskalne ukaze. Imena funkcij razdelijo, jih sestavijo med izvajanjem ali pravo kodo preselijo v podatkovno bazo, slikovne datoteke ali konfiguracijske vnose. Iskanje po vzorcih zato najde veliko, a ne vsega. Zakaj tudi pregledovalniki tu naletijo na meje, pojasnjuje Pregledovalniki škodljive programske opreme za spletne strani: kaj najdejo in česa ne.

Najdba je poleg tega redko edina. Napadalci v več datotekah pogosto uporabijo isti gradnik, na primer opazno oznako spremenljivke ali značilen niz na začetku kodiranega bloka. Po potrjeni najdbi zato ciljno iščite natanko ta niz v celotnem spletnem imeniku, tudi v drugih spletnih straneh na istem strežniku. Tako najdete sorojence, ki jih nobeno splošno iskanje po vzorcih ni zajelo.

Iskanje dopolnite s primerjavo z izvirnimi datotekami in pogledom v podatkovno bazo, glejte Preverjanje podatkovne baze glede vnesene kode. Preventivno je mogoče nepotrebne sistemske funkcije zakleniti, kot opisuje vodnik Pravilna uporaba disable_functions.

Kako PHP SOS pomaga konkretno?

  • Iskanje: Datoteke in podatkovno bazo preiščemo z razširjenimi vzorci in primerjamo z izvirnimi paketi.
  • Analiza: Sumljivo kodo raziščemo v izoliranem okolju, ne da bi ogrozili vaš sistem.
  • Čiščenje: Z odstranjevanjem škodljive programske opreme odstranimo vse sestavne dele in zapremo pot vdora.
  • Zaščita: Omejimo funkcije PHP in pravice pisanja ter nadzorujemo nove ali spremenjene datoteke.

Pogosta vprašanja

Ali je eval z base64_decode vedno škodljiva koda?

Ne vedno, a zelo pogosto. Legitimna koda te kombinacije skoraj ne potrebuje. V datotekah, ki ne sodijo k vaši aplikaciji ali znanemu vtičniku, je močan opozorilni znak.

Ali smem zakrito kodo za branje dekodirati?

Samo brez izvajanja in ne na produkcijskem strežniku. Že nenamerno izvajanje lahko povzroči škodo. Ob dvomih analizo prepustite strokovnjakom, ki delajo z izoliranimi okolji.

Zakaj moj pregledovalnik škodljive programske opreme kode ne najde?

Pregledovalniki iščejo znane vzorce. Napadalci svojo kodo nenehno spreminjajo, razdelijo imena funkcij ali jih sestavijo med izvajanjem. Prazen pregled zato ni dokaz za čist strežnik.

Kaj pa komercialno šifrirani vtičniki?

Nekateri proizvajalci svojo kodo ščitijo s kodirniki, kot sta ionCube ali SourceGuardian. Take datoteke so neberljive, a legitimne, če izvirajo od proizvajalca. Primerjajte jih z izvirnim paketom.

Ali disable_functions pomaga proti zakriti kodi?

Deloma. Funkcije, kot sta exec ali system, je mogoče zakleniti, eval pa ne, ker je jezikovna konstrukcija in ne funkcija. Zapora napadalcem otežuje naslednji korak, ne prepreči pa vsake škodljive kode.

Viri

Takojšnji stik

Vsaka ura šteje. Pišite nam zdaj.

Na kratko opišite sistem, različico PHP in opažanje. Odzovemo se, razjasnimo stanje in delamo na daljavo, dokler incident ni zaključen in dokumentiran.

Takojšnja pomoč