Lühidalt: Hägustatud PHP kood on kood, mis on tahtlikult loetamatuks tehtud, enamasti kodeeringu ja pakkimisega, mis lahutatakse alles töö ajal. Tüüpilised tuvastusmustrid on eval koos base64_decode, gzinflate või str_rot13-ga, väga pikad read, hex-märgijadad ja funktsiooninimed, mis pannakse kokku osadest. Otsige kahjutute grep-käskudega, ärge koodi kunagi käivitage ja võrrelge leide originaalpaketiga.
Miks ründajad oma koodi peidavad
Kes paigutab serverisse veebishelli või tagaukse, tahab, et see jääks kauaks avastamata. Loetav kood jääks silma igale administraatorile, kes faili avab, ja iga skanner leiaks selle. Seetõttu pakivad ründajad oma koodi: see kodeeritakse, tihendatakse ning pannakse alles väljakutsumisel uuesti kokku ja käivitatakse.
PHP2Shelli kohta ei ole kinnitatud kompromiteerimistunnuseid (Indicators of Compromise). Hägustatud kood ei ole selle turvaaugu tunnus, vaid üldine märk, et keegi on koodi sisse toonud, olenemata teest. Kuidas veebishelle tervikuna leida ja eemaldada, kirjeldab Veebishelli tuvastamine ja eemaldamine. See artikkel keskendub küsimusele, millest hägustatud koodi ära tunda.
eval, base64 ja kaaslased: tüüpilised ehituskivid
Hägustamine järgib peaaegu alati sama põhimõtet: loetamatu andmeplokk muudetakse ühe või mitme funktsiooniga tagasi koodiks, mis seejärel käivitatakse. Järgmised ehituskivid ilmuvad seejuures üha uuesti.
| Ehituskivi | Näited | Miks see silma jääb |
|---|---|---|
| Käivitamine | eval, assert märgijadaga (kuni PHP 7.x), create_function (kuni PHP 7.x) |
käivitab teksti koodina |
| Dekodeerimine | base64_decode, str_rot13, hex2bin, strrev, convert_uudecode |
teeb andmed jälle loetavaks |
| Lahtipakkimine | gzinflate, gzuncompress, gzdecode |
pakib sisseehitatud koodi lahti |
| Kokkupanek | chr()-ahelad, lühikeste tükkide liitmine, \x-escape'id |
peidab funktsiooninimed |
| Dünaamiline väljakutse | muutujad funktsiooninimena, call_user_func, array_map märgijadaga |
väljakutset ei ole kusagil selgelt näha |
| Süsteemiligipääs | system, exec, shell_exec, passthru, proc_open, popen |
käsud serveris |
PHP käsiraamatu kohaselt ei hinda assert() alates PHP 8.0-st märgijadasid enam koodina ja create_function() eemaldati PHP 8.0-s. Vanemate PHP versioonidega serverites jäävad mõlemad olulisteks otsingusõnadeks.
Üksik ehituskivi on harva kahtlane, base64_decode'i kasutavad näiteks paljud rakendused legitiimselt. Kahtlaseks muutub kombinatsioon: dekodeerimine, mille tulemus liigub otse käivitamisse.
Ohutu otsimine: kahjutud grep-käsud
Järgmised käsud otsivad faile ainult tekstina. Need ei käivita PHP-koodi. Kohandage tee.
# Käivitamine koos dekodeerimise või lahtipakkimisega
grep -rlE "(eval|assert)\s*\(\s*(base64_decode|gzinflate|gzuncompress|str_rot13|hex2bin)" /var/www --include="*.php*"
# Väga pikad read (sageli pakitud kood)
grep -rlE ".{2000,}" /var/www --include="*.php*"
# Palju hex-escape'e või chr()-ahelaid ühel real
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*"
# Funktsiooni väljakutse muutuja kaudu vahetult märgijadadest tehtud omistamise järel
grep -rnE "\\\$[a-zA-Z_]+\s*=\s*['\"][a-z_]{4,}['\"]\s*;\s*\\\$[a-zA-Z_]+\s*\(" /var/www --include="*.php*" | head -50
Kontrollige leide esmalt käsuga ls -l ja ajatempliga ning avage need seejärel ainult tekstina, näiteks käsuga less. Ärge kutsuge kahtlasi faile brauseri kaudu, sest see paneks serveri neid käivitama.
Kus hägustatud kood tüüpiliselt asub
Hägustatud kood asub harva omaette silmatorkavas failis. Sagedamini lisatakse see olemasolevatesse failidesse, päris algusesse või päris lõppu, sageli pärast paljusid tühje ridu, et see avamisel kohe silma ei torkaks. Armastatud on failid, mis laaditakse igal väljakutsel: keskne index.php, seadistusfailid ja teema funktsioonifailid.
Eriti märkamatu tee läheb seadistuse kaudu. Sättega auto_prepend_file laadib PHP enne iga skripti täiendava faili. Kui see asub ründaja loodud failis .user.ini või .htaccess, töötab tema kood igal lehepäringul kaasa, ilma et ühtegi rakenduse faili oleks muudetud. Sisse haaratud fail kannab seejuures meelsasti kahjutut laiendit nagu .ico või .png.
# Kas enne või pärast iga skripti laaditakse täiendavat koodi?
grep -rnE "auto_(prepend|append)_file" /var/www --include=".user.ini" --include=".htaccess" --include="*.conf" 2>/dev/null
# PHP kood pildi- või ikoonilaiendiga failides
grep -rlE "<\?php" /var/www --include="*.ico" --include="*.png" --include="*.jpg" --include="*.gif" 2>/dev/null
Legitiimse hägustamise eristamine kahjulikust koodist
Mitte iga loetamatu kood ei ole kahjulik. Kolm juhtu esineb sageli:
- Kommertskodeerijad: Mõned plugina- ja tarkvaratootjad kaitsevad oma koodi tööriistadega nagu ionCube või SourceGuardian. Failid on loetamatud, kuid viitavad tüüpiliselt vajalikule laadijale. Võrrelge neid originaalpaketiga.
- Minifitseeritud või genereeritud kood: Vahemälud ja mallimootorid loovad pikki ridu ilma reavahetusteta, ent ilma dekodeeritud teksti käivitamiseta.
- Sisseehitatud andmed: Pildid või kirjatüübid Base64 märgijadana PHP-failis on ebatavalised, kuid kahjutud, kuni tulemust ei käivitata.
Kõige usaldusväärsem test on võrdlus allikaga: kui fail pärineb muutmata kujul tootja paketist, on see legitiimne. Kui see ei asu ühegi originaalpaketi sees või erineb sellest, tuleb seda uurida.
Ärge püüdke hägustatud koodi tootmisserveris lahti krüpteerida, näiteks asendades eval väljundiga ja kutsudes faili. Juba üks viga sealjuures käivitab kahjuliku koodi. Analüüs kuulub isoleeritud keskkonda.
Mustriotsingu piirid
Ründajad tunnevad levinud otsingukäsud. Nad jagavad funktsiooninimed osadeks, panevad need töö ajal kokku või viivad tegeliku koodi andmebaasi, pildifailidesse või seadistuskirjetesse. Mustriotsing leiab seetõttu palju, kuid mitte kõike. Miks ka skannerid siin piirideni jõuavad, selgitab Veebisaitide kahjuliku tarkvara skannerid: mida nad leiavad ja mida mitte.
Leid ei ole lisaks harva ainus. Ründajad kasutavad mitmes failis sageli sama ehituskivi, näiteks silmatorkavat muutujanime või iseloomulikku märgijada kodeeritud ploki alguses. Otsige pärast kinnitatud leidu seetõttu sihipäraselt täpselt seda märgijada kogu veebikataloogist, ka teistest samas serveris olevatest veebisaitidest. Nii leiate õed-vennad, mida ükski üldine mustriotsing ei kaasanud.
Täiendage otsingut võrdlusega originaalfailidega ja pilguga andmebaasi, vt Andmebaasi kontroll sissetoodud koodi suhtes. Ennetavalt saab mittevajalikke süsteemifunktsioone blokeerida, nagu on kirjeldatud juhendis disable_functions õige kasutamine.
Kuidas PHP SOS konkreetselt aitab?
- Otsimine: Läbime failid ja andmebaasi laiendatud mustritega ning võrdleme originaalpakettidega.
- Analüüsimine: Uurime kahtlast koodi isoleeritud keskkonnas, ohustamata teie süsteemi.
- Puhastamine: Kahjuliku tarkvara eemaldamisega eemaldame kõik osad ja sulgeme sissetungitee.
- Kaitsmine: Piirame PHP funktsioone ja kirjutusõigusi ning jälgime uusi või muudetud faile.
Korduma kippuvad küsimused
Kas eval koos base64_decode'iga on alati kahjulik kood?
Mitte alati, kuid väga sageli. Legitiimne kood seda kombinatsiooni peaaegu ei vaja. Failides, mis ei kuulu teie rakenduse ega tuntud plugina juurde, on see tugev hoiatusmärk.
Kas tohin hägustatud koodi lugemiseks dekodeerida?
Ainult seda käivitamata ja mitte tootmisserveris. Juba kogemata käivitamine võib kahju teha. Jätke analüüs kahtluse korral spetsialistidele, kes töötavad isoleeritud keskkondades.
Miks minu kahjuliku tarkvara skanner koodi ei leia?
Skannerid otsivad teadaolevaid mustreid. Ründajad muudavad oma koodi pidevalt, jagavad funktsiooninimed osadeks või panevad need töö ajal kokku. Tühi skannimine ei ole seetõttu tõend puhta serveri kohta.
Mis saab kommertslikult krüpteeritud pluginatest?
Mõned tootjad kaitsevad oma koodi kodeerijatega nagu ionCube või SourceGuardian. Sellised failid on loetamatud, kuid legitiimsed, kui need pärinevad tootjalt. Võrrelge neid originaalpaketiga.
Kas disable_functions aitab hägustatud koodi vastu?
Osaliselt. Funktsioone nagu exec või system saab blokeerida, eval'i aga mitte, sest see on keelekonstruktsioon, mitte funktsioon. Blokeering raskendab ründajatel järgmist sammu, kuid ei takista iga kahjulikku koodi.