Pe scurt: Codul PHP ofuscat este cod făcut intenționat ilizibil, de obicei prin codificare și compresie care se rezolvă abia la rulare. Tiparele tipice de recunoaștere sunt eval împreună cu base64_decode, gzinflate sau str_rot13, rânduri foarte lungi, șiruri hexazecimale și nume de funcții compuse din bucăți. Căutați cu comenzi grep inofensive, nu executați niciodată codul și comparați constatările cu pachetul original.
De ce își ascund atacatorii codul
Cine depune un webshell sau o ușă din spate pe un server vrea ca ea să rămână mult timp nedescoperită. Codul lizibil ar atrage atenția oricărui administrator care deschide fișierul, iar orice scaner l-ar găsi. De aceea atacatorii își ambalează codul: este codificat, comprimat și reasamblat și executat abia la apelare.
Pentru PHP2Shell nu există Indicators of Compromise confirmate. Codul ofuscat nu este o trăsătură a acestei vulnerabilități, ci un semn general că cineva a introdus cod, indiferent pe ce cale. Cum găsiți și eliminați webshell-urile în ansamblu descrie Recunoașterea și eliminarea webshell-urilor. Acest articol se concentrează pe întrebarea cum recunoașteți codul ofuscat.
eval, base64 și altele: componentele tipice
Ofuscarea urmează aproape întotdeauna același principiu: un bloc de date ilizibil este retransformat de una sau mai multe funcții în cod, care este apoi executat. Componentele următoare apar mereu.
| Componentă | Exemple | De ce iese în evidență |
|---|---|---|
| Execuție | eval, assert cu șir de caractere (până la PHP 7.x), create_function (până la PHP 7.x) |
execută text ca cod |
| Decodificare | base64_decode, str_rot13, hex2bin, strrev, convert_uudecode |
face din nou datele lizibile |
| Decompresie | gzinflate, gzuncompress, gzdecode |
despachetează codul încorporat |
| Compunere | lanțuri chr(), concatenarea unor fragmente scurte, escape-uri \x |
ascunde numele funcțiilor |
| Apel dinamic | variabile ca nume de funcție, call_user_func, array_map cu șir de caractere |
apelul nu apare nicăieri în clar |
| Acces la sistem | system, exec, shell_exec, passthru, proc_open, popen |
comenzi pe server |
Conform manualului PHP, assert() nu mai evaluează șiruri de caractere ca cod începând cu PHP 8.0, iar create_function() a fost eliminat în PHP 8.0. Pe serverele cu versiuni PHP mai vechi, ambele rămân termeni de căutare relevanți.
O singură componentă este rareori suspectă, base64_decode îl folosesc legitim multe aplicații. Suspectă devine combinația: o decodificare al cărei rezultat curge direct într-o execuție.
Căutarea fără risc: comenzi grep inofensive
Comenzile următoare parcurg fișierele doar ca text. Nu execută niciun cod PHP. Adaptați calea.
# Execuție combinată cu decodificare sau decompresie
grep -rlE "(eval|assert)\s*\(\s*(base64_decode|gzinflate|gzuncompress|str_rot13|hex2bin)" /var/www --include="*.php*"
# Rânduri foarte lungi (adesea cod împachetat)
grep -rlE ".{2000,}" /var/www --include="*.php*"
# Multe escape-uri hex sau lanțuri chr() într-un singur rând
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*"
# Apel de funcție printr-o variabilă imediat după o atribuire din șiruri de caractere
grep -rnE "\\\$[a-zA-Z_]+\s*=\s*['\"][a-z_]{4,}['\"]\s*;\s*\\\$[a-zA-Z_]+\s*\(" /var/www --include="*.php*" | head -50
Verificați potrivirile mai întâi cu ls -l și cu marcajul de timp și deschideți-le apoi doar ca text, de exemplu cu less. Nu apelați niciodată fișierele suspecte prin browser, deoarece astfel serverul le-ar executa.
Unde se află de obicei codul ofuscat
Codul ofuscat se află rar într-un fișier propriu, vizibil. Mai des este inserat în fișiere existente, chiar la început sau chiar la sfârșit, adesea după multe rânduri goale, pentru ca la deschidere să nu sară imediat în ochi. Sunt îndrăgite fișierele încărcate la fiecare apelare: index.php central, fișierele de configurare și fișierele de funcții ale unei teme.
O cale deosebit de discretă duce prin configurație. Cu setarea auto_prepend_file, PHP încarcă un fișier suplimentar înaintea fiecărui script. Dacă aceasta se află într-un .user.ini sau .htaccess creat de un atacator, codul lui rulează la fiecare accesare de pagină, fără ca vreun singur fișier al aplicației să fi fost modificat. Fișierul inclus poartă de bună voie o extensie inofensivă, precum .ico sau .png.
# Se încarcă cod suplimentar înainte sau după fiecare script?
grep -rnE "auto_(prepend|append)_file" /var/www --include=".user.ini" --include=".htaccess" --include="*.conf" 2>/dev/null
# Cod PHP în fișiere cu extensie de imagine sau icon
grep -rlE "<\?php" /var/www --include="*.ico" --include="*.png" --include="*.jpg" --include="*.gif" 2>/dev/null
Deosebirea ofuscării legitime de codul malițios
Nu orice cod ilizibil este rău intenționat. Trei cazuri apar frecvent:
- Encodere comerciale: Unii producători de pluginuri și software își protejează codul cu unelte precum ionCube sau SourceGuardian. Fișierele sunt ilizibile, dar trimit de obicei la loader-ul necesar. Comparați-le cu pachetul original.
- Cod minimizat sau generat: Cache-urile și motoarele de șabloane produc rânduri lungi fără întreruperi, însă fără execuția unui text decodificat.
- Date încorporate: Imaginile sau fonturile ca șir Base64 într-un fișier PHP sunt neobișnuite, dar inofensive, atât timp cât rezultatul nu este executat.
Cel mai de încredere test este compararea cu sursa: dacă fișierul provine neschimbat din pachetul producătorului, este legitim. Dacă nu se află în niciun pachet original sau diferă de el, trebuie investigat.
Nu încercați să decriptați codul ofuscat pe serverul de producție, de exemplu înlocuind eval cu o afișare și apelând fișierul. Chiar și o singură greșeală aici execută codul malițios. Analiza aparține unui mediu izolat.
Limitele căutării după tipare
Atacatorii cunosc comenzile uzuale de căutare. Ei împart numele funcțiilor, le compun la rulare sau mută codul propriu-zis în baza de date, în fișiere imagine sau în intrări de configurare. O căutare după tipare găsește de aceea mult, dar nu tot. De ce și scanerele ating aici limite explică Scanere de malware pentru site-uri: ce găsesc și ce nu.
O constatare este în plus rareori singura. Atacatorii folosesc adesea în mai multe fișiere aceeași componentă, de exemplu o denumire de variabilă remarcabilă sau un șir de caractere marcant la începutul blocului codificat. După o constatare confirmată, căutați de aceea țintit exact acest șir de caractere în întregul director web, inclusiv în alte site-uri de pe același server. Astfel găsiți frații pe care nicio căutare generală după tipare nu i-a surprins.
Completați căutarea cu compararea cu fișierele originale și cu o privire în baza de date, vezi Verificarea bazei de date pentru cod introdus. Preventiv, funcțiile de sistem care nu sunt necesare pot fi blocate, așa cum descrie ghidul Utilizarea corectă a disable_functions.
Cum ajută PHP SOS concret?
- Căutare: Parcurgem fișierele și baza de date cu tipare extinse și comparăm cu pachetele originale.
- Analiză: Examinăm codul suspect într-un mediu izolat, fără a vă pune sistemul în pericol.
- Curățare: Prin eliminarea malware-ului eliminăm toate componentele și închidem calea de pătrundere.
- Securizare: Limităm funcțiile PHP și drepturile de scriere și monitorizăm fișierele noi sau modificate.
Întrebări frecvente
Este eval cu base64_decode întotdeauna cod malițios?
Nu întotdeauna, dar foarte des. Codul legitim are rareori nevoie de această combinație. În fișiere care nu aparțin aplicației dumneavoastră sau unui plugin cunoscut, este un semnal puternic de alarmă.
Am voie să decodific codul ofuscat pentru a-l citi?
Doar fără a-l executa și nu pe serverul de producție. Chiar și o execuție accidentală poate produce daune. În caz de îndoială, lăsați analiza pe seama specialiștilor care lucrează cu medii izolate.
De ce nu găsește scanerul meu de malware codul?
Scanerele caută tipare cunoscute. Atacatorii își modifică permanent codul, împart numele funcțiilor sau le compun la rulare. Un rezultat gol al scanării nu este de aceea o dovadă a unui server curat.
Ce se întâmplă cu pluginurile criptate comercial?
Unii producători își protejează codul cu encodere precum ionCube sau SourceGuardian. Astfel de fișiere sunt ilizibile, dar legitime dacă provin de la producător. Comparați-le cu pachetul original.
Ajută disable_functions împotriva codului ofuscat?
Parțial. Funcții precum exec sau system pot fi blocate, eval însă nu, deoarece este o construcție a limbajului, nu o funcție. Blocarea îngreunează atacatorilor pasul următor, dar nu împiedică orice cod malițios.