Kuidas veebilehe koodist pahavara üles leida

Andris Reinman
Jaga:

Antud blogipostitus on 88 kuud vana ning ei pruugi olla enam ajakohane.

malware

Pahavara on mitmesugust, seda on nii erineva otstarbega kui ka erineva tehnilise teostusega. Kui nakatunud JavaScripti failid ründavad eelkõige lehekülje kasutajat, näiteks kasutaja krediitkaardiandmete varastamiseks, siis nakatunud või serverisse sokutatud php-failid on pigem hõivatud serveri ressursside kasutamisega. See oleks nii võrguühenduse kasutamine spämmi saatmiseks, arvutusvõimsuse kasutamine bitcoinide kaevandamiseks ja muud taolised tegevused.

Muidugi tegelevad ka serveris olevad pahavarad kohati andmete vargusega, kuid tavaliselt on massiliselt leviv pahavara siiski “rumal” ja mõeldud teostama mingit suhteliselt lihtsat tegevust. Eelkõige siis selle tõttu, et igasugune vargus eeldab täpsemat sihtimist, suvaliselt kõike maailmas salvestatut kokku kuhjata läheb kallimaks, kui potentsiaalne tulu. Krediitkaardi andmeid saab varastada ju ainult siis, kui saab eeldada, et need andmed võivad üldse eksisteerida, spämmi võib aga saata kasvõi nutipirnist või -röstrist. See muidugi ei tähenda, et andmeid või identiteete varastavat pahavara ei peaks kartma, muidugi peab, lihtsalt et kui mingi pahavara on serverisse jõudnud, siis suurema tõenäosusega on see just “rumalat” laadi. Rumal siinkohal tähendaks sellist pahavara, mis ei tea ega hooli keskkonnast, kuhu on sattunud, oluliseks on ainult selle poolt pakutav arvutusvõimsus jmt. ressurss.

Veebiressursi omanikena me samas taolist pahavara enda kodulehele ei taha. Krediitkaardi andmete vargus tähendab suurt plekki meie äritegevusele, spämmi saatmine omakorda võib tähendada, et meie kinnitus- ja muud kirjad klientidele ei jõua enam kohale, kuna kõik meie serverist tulev tembeldatakse kahtlase ajaloo tõttu automaatselt spämmiks. Bitcoini kaevandamine või DDoS-botnetis osalemine muudab meie kodulehe nii aeglaseks, et kliendid lähevad konkurendi juurde. Seega on selgelt meie huvides, et igasugune pahavara võimalikult kiirelt avastada ja eemaldada.

Tänapäeval on õnneks olemas mitmeid automaatseid vahendeid pahavara avastamiseks, kuid kohati võib olla vajalik ka käsitsi faile üle vaadata. Päris kõiki faile ei ole ilmselt mõtet selle jaoks läbi käia, peamiselt tasuks keskenduda nendele failidele, mida on hiljuti muudetud või mis on täitsa uued.

Muutmisaja järgi faile sorteerida saab kasvõi käsurealt, näiteks järgmise käsuga:

find . -printf "%T@ %Tc %p\n" | sort -rn

kuid sellest ei pruugi olla alati abi kuna pahavara võib proovida faili muutmisaega ära peita. Tavaliselt käib see nii, et pahavara otsib üles samas kaustas oleva kõige vanema faili ning määrab iseendale sama muutmisaja. Kuidas sellisest petmisest mööda saada, võib lugeda ühest varasemast postitusest.

Ütleme, et oleme nüüd leidnud serverist mõned php-failid, mida on hiljuti muudetud ja tahaksime kontrollida, et kas need on kahtlased või mitte. Vaatakski mõningaid mustreid, mis võivad viidata pahavara olemasolule.

1. Uued failid

Kui meie serverisse on installitud WordPress ning ühtäkki tekib wp-includes kausta uus php-fail (rakenduse seadistusest sõltuvalt ei pruugi php-faili laiend olla alati .php, see võib olla ka .inc vmt.), siis võib see olla märk kahtlasest tegevusest, kuna wp-includes kausta sisu peaks muutuma ainult WordPressi versiooni uuendamise käigus. Samas ei tähenda see veel 100% kindlusega pahavara olemasolu, süüdi võib olla hoopis mõni kehvavõitu plugin, mis ei järgi ettenähtud parimaid praktikaid.

2. Pikad koodiread

Tihti pakitakse ja obfuskeeritakse pahavara võimalikult kitsalt kokku, mis võib ka tähendada seda, et pahavara kood paigutatakse ühele või paarile reale koodifailis. PHP jaoks ei ole reavahetusi tarvis, seega võib koodirida olla ka megabaidi pikkusega. Samas inim-programmeerija jaoks on omane kasutada palju lühemaid ridu, näiteks 120 sümbolit vmt. kuna pikemat rida on lihtsalt keeruline hoomata. Seega kui ülejäänud kood kasutab lühikesi ridu, siis ülipikad read lühikeste vahel on kindlasti kahtlased.

3. Miksitud koodistiil

Vahel peidetakse (eelkõige kommertstarkvara puhul) rakenduse kood obfuskeerimise taha. St. et kood lastakse läbi automaatse süsteemi, mis näiteks muudab ära kõik muutujate ja funktsioonide nimed (uued nimed on lühikesed juhuslike sümbolite jadad), eemaldab kommentaarid, üleliigsed tühikud, reavahetused jmt. mille tulemusena muutub kood raskesti loetavaks. JavaScripti, HTML’i ja CSS puhul on see täiesti tavaline praktika ka tasuta tarkvara puhul, kuid seal ei kaitsta koodi mitte konkurendi silmade eest, vaid selline töötlemine tagab lühema koodi ja seega ka kiirema kodulehe ja väiksema ressursikulu – 200 kB JavaScripti laadimise asemel peab kasutaja brauser laadima võibolla ainult 120 kB.

Ühesõnaga, koodi obfuskeerimine on iseenesest levinud praktika, kuid see võib tekitada ka mõningaid kahtlusi. Näiteks serveri poolse koodi obfuskeerimine on siiski pigem haruldane ja võiks täiendavat huvi tekitada. Eriti kahtlane on selline olukord, kus failis olev kood on muidu niiöelda inimloetav, aga vahepeal on mingid koodiread, mis viitavad obfuskeerimisele (loetamatute nimedega muutujad ja funktsioonid, koodi “treppimise” puudumine). Samuti on kahtlane kui muidu on kood obfuskeeritud, aga siis on kuskil faili lõpus või alguses justnimelt loetav kood.

4. Base64 kasutamine

Base64-kodeeringu kasutamine on tegelikult üsna tavaline, sest see annab võimaluse edastada binaarset infot üle tavalise teksti. Base64 puhul võetakse suvaline binaarne väärtus (st. baitide jada) ja esitatakse seda kasutades 64 erinevat sümbolit, mille hulka kuuluvad suured ja väikesed ladina tähed, numbrid ja mõned kirjavahemärgid. Näiteks teksti “Veebi turvalisusel on ka äriline mõõde” base64-kodeeritud esitus näeb välja nii:

VmVlYmkgdHVydmFsaXN1c2VsIG9uIGthIMOkcmlsaW5lIG3DtcO1ZGU=

Siit peaks kohe näha olema ka põhjus, et miks pahavara base64 kodeeringut väga armastab – see muudab teksti inimsilmale loetamatuks. Arvuti jaoks ei ole väga vahet, et kas mingi tekst on esitatud tavaviisil või base64-kodeeringus, küsimus on lõpuks vaid bittide asetuses (base64-kodeering kasutab 24 bitise info salvestamiseks 4 baiti tavapärase 3 asemel).

Base64 ilmnemise tunnuseks on eelkõige pikad ja seosetud tekstiread, kus puuduvad tühikud (küll võivad olla reavahetused) ning mis tihti lõppevad ühe või rohkema võrdusmärgiga. Võrdusmärk teksti lõpus tähistab puuduvate bittide täidist (base64 minimaalne “sümboli” pikkus on 3 baiti ning kui sisendist jääb selle jaoks puudu, siis täidetakse puudu jääv osa võrdusmärkidega).

$_jmo12r_='VGhlIHBhcnRpY3VsYXIgY2hvaWNlIG9mIGNoYXJhY3RlcnMg
dG8gbWFrZSB1cCB0aGUgNjQgY2hhcmFjdGVycyByZXF1aXJlZCBmb3IgYmF
zZSB2YXJpZXMgYmV0d2VlbiBpbXBsZW1lbnRhdGlvbnMuIFRoZSBnZW5lch
...
lciB2YXJpYXRpb25zLCB1c3VhbGx5IGRlcml2ZWQgZnJvbSBCYXNlNjQsIH
oYXJlIHRoaXMgcHJvcGVydHkgYnV0IGRpZmZlciBpbiB0aGUgc3ltYm9scy
aG9zZW4gZm9yIHRoZSBsYXN0IHR3byB2YWx1ZXM7IGFuIGV4YW1wbGUggdH
aXMgVVRGLTcu==';

Meie peaksime otsima koodist base64_decode funktsiooni kasutamist, mis muudab base64-vormingus teksti tagasi esialgsele binaarkujule. Selle vastandfunktsioon base64_encode on pahavara puhul palju haruldasem, kuna kodeerimise töö on pahavara autor juba eelnevalt ära teinud, nüüd tuleks base64 lihtsalt lahti dekodeerida.

Kusjuures base64_decode funktsiooni olemasolu ei tähenda veel automaatselt pahavara, kuna seda võidakse kasutada ka täiesti legaalsetel eesmärkidel. Mida me peaksime pigem vaatama on funktsiooni sisend – kas meile on arusaadav, et mis see on ja kust see tuleb? Juhul kui sisendiks on muutuja, mille nimi on juhuslikest sümbolitest, siis on see kindlasti kahtlane. Samuti on kahtlane, kui dekodeeritav sisend on väga pikk, näiteks mitmeid kilobaite.

Alati ei kasuta pahavara base64 dekodeerimiseks base64_decode funktsiooni, kuna seda on suhteliselt kerge tuvastada. Selle asemel implementeeritakse mõnikord vastav algoritm ise, mis viibki meid järgmise punktini.

5. Bitioperatsioonid

Bitioperatsioonid võimaldavad manipuleerida baitides üksikute bittidega ja see on täpselt see, mida läheb vaja näiteks base64 dekodeerimise algoritmi jaoks. Kui me näeme, et koodis on funktsioon, mis käivitatakse base64-laadse sisendiga ja mis kasutab muu hulgas operaatoreid >>, << ja &, siis suure tõenäosusega on tegu just base64 dekodeerimisega.

Täiendavalt on ohu märgiks veel üks oluline bitioperatsioon, nimelt ^ ehk XOR.

6. XOR-krüpteerimine

XOR-šiffer on üks lihtsamaid viise andmete peitmiseks. Seda on lihtne implementeerida, see on väga kiire ja samas tõhus – kui võti on vähegi pikem, siis on algset teksti üsna raske taastada. Seega pole ime, et pahalased seda hea meelega kasutavad.

Vajalik on see tavaliselt pahavara koodi peitmiseks. Kood on failis teksti kujul olemas, kuid koodi tekst on XOR-krüpteeritud. Pahavara kood käivitub veebipäringu peale, mis dekrüpteerib peidetud koodi, kasutades päringus edastatud salavõtit. Juhul kui me ei suuda sellist päringut koos päringu andmetega maha logida (võti on reeglina POST päringu argumendina, seega tavaliselt seda ei logitagi), siis me pahavara koodi ka ise lahti ei saa. Selline meetod hoiab pahavara uinuvas oleks, iseenesest see midagi ei tee, me ei saa ka selle sisu vaadata, aga ründaja saab selle oma päringuga aktiveerida. Tüüpiliselt on see siis omane erinevatele botnetidele.

Kõige lühem XOR-šifri implementatsioon näeks välja järgmine ($code on pahavara lähtekood teksti kujul ja $secret on veebipäringuga edastatud salakood):

for($i = 0; $i < strlen($code); $i++)
  $code[$i] = ($code[$i] ^ $secret[$i % strlen($secret)]);

Sarnast koodi nähes võiks tekkida kahtlus, kas skript ei sisalda mitte pahavara.

Siit aga tekib kohe järgmine punkt, nimelt on vaja sellise teksti kujul salvestatud kood ju rakenduse koodina käima saada ja selles aitab meid eval.

7. eval koodi käivitamiseks

eval on üks jubedamaid PHP (ja ka muude keelte) võimalusi, kuna see lubab interpreteerida tavalist teksti programmikoodina. Kui ründaja leiab võimaluse anda ette mõnele koodis leiduvale eval käsule enda koostatud teksti, on see täiuslik tagauks – ründaja kood pannakse käima nii, nagu oleks see veebirakenduse enda osa. Tavaliselt küll sokutavad ründajad selle eval’i serverisse erinevate turvaaukude kaudu ise, sest küll hiljem jõuab mõelda, et mida selle abil üldse käivitada. Juba ainuksi eval’i esinemine koodifailis on seetõttu kahtlane.

Paraku aga on eval’il ka täiesti legitiimset kasutust ja seetõttu automaatselt neid faile, milles esineb eval, siiski pahavaraks pidada ei saa. Samas on võimalik kahtlast tegevust siiski tuvastada.

Kõige levinum viis eval’it eesmärgipäraselt kasutada, on kujul:

eval('$mingimuutuja=...')

Ühesõnaga, muutujale antakse mingisuguse serialiseerimise käigus koostatud koodi abil väärtus. Pahavara puhul näeb see tegevus välja reeglina hoopis teine, sisend tuleb mingist juhusliku nimega muutujast või koostöös base64_decode funktsiooniga kusagilt pikemast inimloetamatust tekstimassiivist:

eval(base64_decode('ZWNobyAiT2xlbiB2aWlydXMhIjs='));

või

eval($r['_weretwt_']);

Kui eval võtab oma sisendi POST päringust, mitte ei kasuta staatilist tekstiväärtust, siis see viitab kas webshell’ile või botnetile, kus ründaja saab kasutada oma kontrolli all olevaid masinaid sundida tegema seda, mida parasjagu vaja on.

8. Stringmuutujate kasutamine funktsioonidena

Kuigi täiesti lubatud ja kohati ka kasutatud, on stringimuutujate kasutamine funktsioonidena siiski pahavara tunnus. Siinkohal kehtib jälle rusikareegel – kui on aru saada, et millega tegu, siis tõenäoliselt ei ole pahavara, vastasel korral pigem on.

$r = "printf";
$z = 123;
$r($z); // funktsiooni nimi tuleb stringist

Lisapunktid tulevad selle eest, kui funktsiooni nimetus tuleb globaalsest skoobist, see on küll üsna pahavara moodi

$GLOBALS['seosetutekst']($sisend);

9. TCP ühendused

Viimaseks punktiks tooksin välja veel võrguühenduste avamise ning eriti UDP ühenduste loomise. Juhul kui meil on “tavaline” tarkvara, näiteks WordPress vms. siis ei ole sellel tarkvaral reeglina mitte mingisugust põhjust avada kuskile UDP ühendusi. Taustal seda muidugi võib toimuda, näiteks DNS nimepäringute käigus, aga koodis endas vastavaid funktsioone kasutada ei tohiks. UDP puhul võivad erandiks olla siiski logimoodulid, mis saadavad logikirjeid üle UDP, kuid see peaks siis olema muust koodist selgelt eraldatud.

Kui pahavara teeb avab TCP ühendusi portidesse 25, 465, 587, 2525, siis on tegu spämmi saatmisega. Portide 80 ja 443 kaudu postitatakse reeglina rämpskommentaare. Muude portide puhul võib arvata, et tegu on botneti C&C serveriga, kust käidakse endale uut “tegevust” küsimas.

Seega peaksime otsima koodist funktsioone fsockopen ja stream_socket_client. Loomulikult teeb ka tavaline tarkvara võrgupäringuid, kuid tavaliselt avatakse kindel veebiaadress kasutades curl API’t (levinud teek keerukate võrgupäringute tegemiseks), “toorete” ühenduste avamist tuleb ette palju harvem ja reeglina selgelt arusaadavas kontekstis, näiteks HTTP päringute tegemise klassi meetodites juhul kui curl näiteks puudub.

Kusjuures, pahavara kasutab ka ise hea meelega curli teeke, aga kuna curl ei ole kõikides serverites saadaval, siis tuleb paralleelselt implementeerida ka socketi põhised päringud.

Kokkuvõtteks

Üldiselt tasub koodi analüüsimisel otsida eelkõige anomaaliaid, st. stiilierinevusi ülejäänud koodist ning privilegeeritud funktsioonide (eval, fsockopen jne.) kasutamist. Ja jälle – rusikareegel – kui saame aru, mis toimub, siis suure tõenäosusega ei ole tegu pahavaraga, kui aga kasutatakse seosetuid ja juhuslikke muutujanimesid, andmed tuletatakse base64-kodeeritud tekstist, kasutatakse XOR krüpteeringut jne. siis suure tõenäosusega toimub midagi kahtlast. Arusaamise all pean silmas seda, et me ei pruugi loomulikult hoomata kõike seda mida kood teeb, aga see tundub vähemalt olevat loogilises kontekstis. Seega kui tegu on RSS voo parsimise klassiga, siis meetodite nimed kirjeldavad RSS vooga seotud toiminguid, näiteks $rss->get_feed_item(), aga mitte $KcyezF->grebuZ().

Kindlasti ei piirdu pahavara esinemise sümptomid ainult nende 9 punktiga ning osavamad pahavara loojad kasutavad mitmesuguseid võtteid oma tegevuse peitmiseks. Suurem osa pahavarast on ikkagi “rumal,” see on mõeldud täitma mingit kindlat ülesannet ja selle peitmisega pole väga vaeva nähtud, kuna see teeks arendamise aeglasemaks ning kasu oleks sellest vähe – pahavara otsimise ja eemaldamisega tegeleb kahjuks väga väike osa veebiressursside omanikest.

Iga vastutustundliku veebiomaniku kohta on lugematu hulk paikamata Joomlaid ja WordPresse, mida üle võtta ja isegi kui ühe veebi pealt teenib ründaja vaid sente, on see tegevus automaatne ning massiliselt skaleeruv, mis tasub pahavaraga tegelemise ründajale kindlasti ära. Seega läheb see probleem ajas ainult tõsisemaks ja mõistlikum oleks juba kohe praegu oma veebi korrasolekuga tegeleda, mitte jääda mõnd suuremat pauku ootama.

Populaarsed postitused

CloudFest 2024: AI annab riistvarale uue hingamise

Ingmar Aasoja
Läinud nädalal istus Zone tiim lennukisse ja sööstis taaskord CloudFesti põnevasse maailma, et heita pilk veebimajutusteenuste arengusuundadele. Meie...

Zone+ WordPressi Assistent: kuidas AI abiga sekunditega veebileht luua

Jaanus Putting
See aeg on läbi, mil vajadus kodulehe järele tähendas telefoniraamatust või guuglist veebidisaineri kontaktide otsimist. Tõenäoliselt üks viimase...

Aegunud PHP on aegunud PHP

Hasso Tepper
Kui esimene tänapäevane PHP versioon 25 aastat tagasi avalikuks tehti, oli internet hoopis teistsugune. Nõudmised veebilehtedele olid tagasihoidlikud...

Zone Veebiakadeemia - kuidas end Internetis nähtavaks teha

blogi
Zone Veebiakadeemia uusima episoodiga hakkame tutvustama ägedaid Zone koostööpartnereid. Seekord on meil külas Nobel Digitali tootejuht ja partner...