“Paha Panda” varastab postkaste

Suurbritannia parlamenti tabanud küberrünnak, mis suunatud parlamendiliikmete e-poskastide vastu, ajendab jagama infot e-posti rünnakukampaania kohta, mis täna aktuaalne ka Eestis.

Ühel pealelõunal hakkasid Zone IT operatsioonide meeskonna ekraanil vilkuma alarmid. Infoturbeintsidente tuvastav monitooringusüsteem hakkas järjest välja sülitama teateid, et mõned e-posti kasutajad rikuvad teleportides teada olevaid füüsikaseadusi.

Teleportimine on fenomen, mille puhul internetikasutaja ühendub ühel hetkel meie serveriga Eestist, järgmisel Hiinast, siis omakorda Venemaalt, Malaisiast, Indoneesiast, Brasiiliast või mujalt. Kuigi eksisteerivad mõned erandid (Tor), viitab selline kontinentide vahel hüplemine enamasti siiski kasutajaandmete lekkimisele.

Lühikese aja jooksul tuvastas monitooringusüsteem seda anomaaliat ligi saja e-posti kasutaja juures, võimaliku kuriteo takistamiseks ning kahju minimaliseerimiseks hakkas algoritm blokeerima teleportivate kasutajate ligipääsu serveritele.

Kasutajaandmete lekkimise intsidendid ei ole harukordsed, selliseid intsidente leiab aset regulaarselt – enamasti on põhjuseks kasutajaandmete jalutama minek kahtlasest WiFi võrgust, tööjaama nakatumine pahavaraga või sama kasutajanime/salasõna tarvitamine mõnel hiljuti kompromiteeritud veebisaidil.

Mõjutatud kasutajate arv pani siiski meie infoturbe töörühmal vere vemmeldama. Kui korraga rikutakse niivõrd suure hulga kasutajate privaatsust, tuleb igaks juhuks välistada võimalus, et salasõnad on lekkinud meie süsteemist.

Analüüs

Seetõttu alustati koheselt tööd logide analüüsimise kallal ja võeti ühendust ka mõnede mõjutatud kasutajate või neid toetavate IT spetsialistidega, et selgitada välja võimaliku lekke asjaolud.

Hüpotees andmelekkest meie poolel õnneks kinnitust ei leidnud. Küll aga avastasime oma logisid analüüsides ühe üllatava fenomeni, mille eest teid nüüd hoiatada tahan.

Nimelt on aset on leidmas unikaalne kampaania üliaeglase jõuründe (slow rate brute force attack) näol, mille abil loodetakse rikkuda internetikasutajate e-posti privaatsust.

Jõurünnet teostatakse tavaliselt juhuslike stringide läbiproovimise teel või sõnastikuründe abil ning võimalikult suure efektiivsuse nimelt proovitakse lühikese aja jooksul läbi suur hulk erinevaid salasõna kandidaate. Jõuründe muudab ebaefektiivseks see, et seda on suhteliselt lihtne tuvastada.

See tegevus, mis meile logist vastu vaatas, oli teistsugune.

“Paha Panda”

Vältimaks tuvastamist, tegutseb konkreetset rünnakut teostav kurjategija meelega aeglaselt, metoodiliselt ja väga kannatlikult.

Protseduur, mida kasutaja andmete arvamiseks kasutati, oli iga sihtmärgi puhul sarnane.

Ühel heal päeval ilmub logisse 5-6 kurjategija võrgustikku kuuluvat IP aadressi, millest igaüks katsetab sihtmärgi peal mõnd salasõna kandidaati. Sellele katsele järgneb 2-3 tundi vaikust. Siis ilmub ründaja taas välja ja proovib järgmise 5-6 erineva IP pealt. Jälle 2-3 tundi vaikust ja uus katse. Selline õngitsemine võib kesta nädalaid.

Iga sihtmärgi kallal töötab kurjategija tilkuva vee järjepidevusega, mis kivisse auku uuristab.

Ja see järjepidevus viib mõnel juhul ka sihile. Mõnel juhul õnnestus see kurjategijal juba 6 katse pealt, teisel juhul kulus eduks poolteist kuni kaks tuhat katset. Ühe konkreetse sihtmärgi puhul kulutas kurjategija eesmärgini jõudmiseks 553 päringut, nendega alustati 3. mail ja eduka tulemuseni jõuti 14. mail. Seejuures sooritati need päringud 445 erineva IP pealt.

Selles ründe iseloomus peegeldub omal moel mingi aasialik stoiline rahu, mis kombinatsioonis paljude kurjategija botneti Hiina päritolu IP aadressidega on pannud mind teda “Pahaks Pandaks” kutsuma 🙂

“Panda” üheks relvaks on aeglus, millega petetakse ära monitooringusüsteemid. Kui üks IP aadress teeb iga 2-3 tunni tagant mõnele kontole ühe ebaõnnestunud sisselogimiskatse, ei jää see ühtegi monitooringusse kinni, sest selline paranoia tase muudaks valepositiivsete tuvastuste hulga liiga suureks. Isegi kuu lõikes uurides jäävad “Panda” kasutatavad IP aadressid kaugelt välja ebaõnnestunud autentimiskatseid sooritavate süsteemide esiviiekümnest.

Kindlasti on nii mõnelgi kogenud IT-spetsialistil siinkohal kulm juba kipras ja küsimus keelel – kuidas on võimalik salasõnu nii väheste arvamistega salasõna ära arvata? Vastus on lihtne – “Panda” teab, et energiat tuleb kokku hoida, seetõttu ei käi ta läbi juhuslikke salasõna kombinatsioone, vaid kasutab teise relvana kasutajate endi halbu käitumismustreid.

Inimesed on halvad juhuarvugeneraatorid. Kui paluda inimestel valida juhuslik arv 1-10 vahel, valib väidetavalt ebaproportsionaalne hulk neist numbri 7 (trollidega, nagu ülal näha, on sarnane lugu). Sama kordub salasõnade määramisel. Mõte juhuslikust tähtede, numbrite ja sümbolite jadast tuleb pähe vaid vähestele.

Paljud hakkavad otsima abi sellest, mis ekraanil, klaviatuuril või parajasti meelel. Nii muutub väga tõenäoliseks, et e-posti aadressi siim@domeen.tld looja määrab sellele salasõnaks kombinatsiooni nimest Siim ja mingist numbrite jadast. Salasõnade variatsioonid nagu “Siim123”, “Siim1234”, “Siim666”, “Siim2017” on levinumad, kui julgeme endale tunnistada. Sama levinud on ilmselt klaviatuurilt tuletatud salasõnade kombinatsioonid nagu “Qwe123”, “Asdasd123”, “Qwerty666” jne või aadressiribalt tuletatud “Zone123”, “Zone.ee123” jne.

Nii ei raiska meie antikangelasest kurjategija “Panda” ennast juhuslike stringide äraarvamisega või täiemahulise sõnastikuründega. Ta on valinud välja suure hulga väga levinud halbu salasõnade mustreid ja tiksutab tema sihtmärkide hulgas läbi proovida.

“Panda” sihtmärgid on esmapilgul täiesti suvalised, ilmselt on need saadud veebilehtede kaapimise teel ja muudest allmaailmale tuntud allikatest. Silma jääb siiski kontakt@, contact@ ja info@ aadresside suur osakaal.

Aadresside internetist kogumisele viitab seegi, et mitmed aadressid, mida sihtmärgina kaaluti, sisaldasid kirjavigu – näiteks otsiti ühe telekanali töötaja e-posti kontot domeenist, mis erines tema tööandja tegelikust domeenist vaid ühe märgi võrra.

Võimalik kahju

Mida kurja “Panda” nende lahti murtud postkastidega korda saata võib? Väga paljut.

Kui mäletate, siis eelmisel aastal kirjutas Andris populaarsest skeemist, milles e-posti abil ettevõtetele sokutatakse valearveid (“Tõestisündinud lugu e-posti võltsimise tõttu kaotatud rahast”). Eelnevalt kirjeldatud viisil lahti murtud raamatupidaja postkast on sellisele valearvetega skeemitajale kulla hinnaga.

Loomulikult on sellised postkastid ka võrratuteks relvadeks spämmeritele. Domeenid ja postkastid, mis pole kunagi rämpsposti saatnud ja mille väljuvad kirjad kannavad usaldusväärsuse nimel DKIM-i antud autentsustõendi ja SPF-i ning DMARC-i allikakinnitusega? Just sellise spämmiga kurjategija meie radarile sattuski.

Kui kurjategija sooviks, siis võiks ta loomulikult ka postkastis tuulata ja sealt väärtuslikumat sisu endale sebida. Näiteks võib ta panna kokku aadressiraamatu inimestest, kellega tihedalt suheldakse ja korraldada klassikalise “Olen välismaal lennujaamas, rahakott varastati ära, ole hea kanna mulle kiirelt paar sotti” kampaania. Samasuguse õngitsusrünnaku saaks korraldada ka postkastiomaniku enda vastu.

Halvemal juhul on sama salasõna inimesel kasutusel mõnes olulises infosüsteemis, mille olemasolu suudab kurjategija näiteks poskasti sisu järgi kindlaks teha. Siis võidakse kompromiteerida juba mitte ainult postkasti sisu, vaid palju olulisemaid andmeid.

Kui “Panda” tahaks, saaks ta ka WannaCry või Petya pahavara niimoodi otse postkasti ujutada ja käivitada väljapressimisega lõppeva rünnaku. Viimasest sellisest ründest kirjutab RIA https://www.ria.ee/ee/uus-lunavaralaine.html

Ja hoidke alt, kui postkast kuulub riigiasutusele. “Panda” võib oma riigi struktuuridega sujuvate suhete omamise nimel head ja paremat ka neile sokutada.

Parem karta kui kahetseda. Kui tundsid ülalpool ära mõne oma salasõna mustri, siis muuda seda kohe.

Kokkuvõtteks

Miks ma sellest intsidendist kirjutan?

Esiteks tahame kõigile meelde tuletada kui halvad on ülalkirjeldatud mustrid salasõnades.

Teiseks pole me kindlad, kas teised e-posti serverite haldajad on “Paha Panda” tegutsemist tähele pannud – loodetavasti annab käesolev postitus neile ajendi seda kontrollida.

Kolmandaks annab see lugu loodetavasti selgust motiivi osas, miks Zone e-posti salasõnadele esitatavaid nõudeid muudab.

Me toome nõudmised salasõnale kaasaega. Rohkem kui salasõna keerukust, hindame me selle pikkust ning üritame takistada halbade mustrite kasutamist. Halbadeks loeme üldlevinud salasõnu; salasõnu, mille sisu saab tuletada kaitstava ressurssi kontekstist ja muud äraarvatavat. Uue e-posti salasõna miinimumpikkus on Zones nüüd 10 märki.

Rohkem salasõnu stiilis “Minu Lemmikpuu On Remmelgas” ja vähem stiilis “Siim123” 😀

Isikuandmete kaitse üldmäärus GDPR – Mis see on? Osa 1

Seekordne kirjatöö käsitleb sellist kuuma teemat nagu isikuandmete kaitse üldmäärus ehk GDPR, mis puudutab kõiki ettevõtteid, organisatsioone ja füüsilisi isikuid Euroopas. Proovime sellest kirjutada paanikat külvamata.

Järgmise aasta 25. mail rakendub Euroopa Parlamendi ja nõukogu määrus 2016/679 (General Data Protection Regulation ehk GDPR). Ühe teooria kohaselt järgnevad sellele inimohverdused, kasside ja koerte kokku kolimine ning massihüsteeria. [1] Kui see ennustus valeks peaks osutuma, on alternatiiv keskpärane reede, vahelduva pilvisusega ilm ja uue ajajärgu algus isikuandmete kaitses.

Eelnev on loomulikult kirjutatud sõbraliku pilkega silmanurgas. Ma ei arva, et GDPR on senitundmatu apokalüpsise ratsanik ja mulle meeldib heita nalja müügimeeste üle, kes uue määrusega hirmutades meile juba tükk aega erinevat nodi maha müüa üritavad – alates tüüplepingutest, tulemüüridest ning lõpetades USB pulkadega. Nende entusiasm meenutab seda, mis toimus 90-ndate lõpus, kui kõikide IT-kaupmeeste keelel oli lühend Y2K 🙂

Isikuandmete kaitse määrus on oluline seadusandlik akt, millega peaksid ideaalis end kurssi viima kõik ettevõtjad. Aga suur osa selle nõudmistest eksisteerib juba olemasolevates seadustes. GDPR ütleb oma sõnumi välja senisest täpsemalt, konkreetsemalt, jõulisemalt ja seob võimalikud rikkumised kopsakate trahvidega. See võib tunduda üle pea käiv, aga ei maksa lasta ennast ehmatada.

Zone on uue määruse jaoks üks suuremaid sihtmärke, kuna meil on isikuandmete töötlemises kanda kaks rolli:

  • vastutav töötleja, kes kogub ja töötleb isikuandmeid puhtalt enda seaduslike eesmärkidel täitmiseks;
  • volitatud töötleja, kes säilitab ja töötleb teiste vastutavate töötlejate kogutud isikuandmeid, et ka nendel oleks võimalik täita oma seaduslikke eesmärke.

See tähendab, et ühilduvus GDPR-i põhimõtetega on meie jaoks vältimatu, vastasel juhul peaksime oma poe peagi kinni panema. Seepärast oleme ka pidanud vajalikuks end sel teemal harida, parandada protsesse, vaadata kriitilise pilguga otsa teenuste portfellile, kasutustingimustele jne. Üritame seda kõike teha kainelt kaalutledes.

Käesolevas ja järgnevates temaatilistes kirjutistes loodan anda põgusa ülevaate sellest, mida meie oleme jõudnud GDPR-i kohta õppida. See võiks huvitada meie kliente, aga miks mitte ka teisi väikeseid või keskmisi ettevõtteid.

Loomulikult ei tohiks minu kirjutisi võtta juriidilise nõuandena 🙂

Neil, kes töötlevad isikuandmeid suurel määral või omavad käideldavate andmete seas eriti tundlikke andmeid, soovitan kindlasti määruse sisusse väga põhjalikult süveneda ja konsulteerida oma õigusnõustajaga.

Eesmärgist ja haldusalast

Euroopa Parlament on seadnud määrusele väga kõrgelennulised eesmärgid. GDPR-ilt loodetakse nii kodanike õiguste tugevdamist, isikuandmete käitlemise turvalisuse parandamist, digimajanduse usalduse kasvu kui ka õiglasemat konkurentsikeskkonda.

Vorm, mis valiti uute reeglite kehtestamiseks, demonstreerib seda, kui tõsiselt Euroopas isikuandmete kaitsesse suhtutakse. Euroopa Parlamendi määrus on üks võimsamaid, kui mitte võimsaim, õigusliku ruumi kujundamise tööriist Euroopa Liidus – tegemist on seadusandja vastega Thori haamrile Mjölnirile. Sellise määrusena vastu võetud õigusakt hakkab jõustumise kuupäevast alates kehtima kõikides liikmesriikides korraga ja muutub koheselt ülimuslikuks kõikide teiste sama valdkonda käsitlevate seaduste suhtes.

Ka määruse mõjuala kujundamisel ei ole parlamentäärid end tagasi hoidnud, see hõlmab ei vähemat või enamat, kui tervet planeeti. Kõikidele ettevõtetele ja organisatsioonidele maailmas, kes koguvad, töötlevad või säilitavad Euroopa Liidu kodanike isikuandmeid, kehtivad järgmise aasta 25. maist ühed ja samad andmekaitse nõuded. Euroopa Liidus tuleb GDPR-iga kooskõlas töödelda kõikide füüsiliste isikute andmeid, mitte ainult liidu kodanike omi.

Definitsioonidest

Mis on isikuandmed? Isikuandmed on igasugune teave tuvastatud või tuvastatava füüsilise isiku kohta. Füüsiline isik võib andmete alusel olla tuvastatav otseselt või kaudselt. See viimane on meie teenuste kontekstis eriti oluline teada, sest füüsilise isiku kaudset tuvastamist võimaldab näiteks IP aadress ja seetõttu on ka IP aadressid käsitletavad isikuandmetena.[2]

Mis on isikuandmete töötlemine? Isikuandmete töötlemine on isikuandmete või nende kogumitega tehtav automatiseerimata või automatiseeritud toiming või nende kogum. Lasete füüsilisel isikul end veebis kasutajaks registreerida, müüte neile oma kaupa või teenust, saadate laiali oma uudiskirja? Kõikide nende toimingute raames töötlete tõenäoliselt füüsiliste isikute isikuandmeid ja olete seega nende vastutav töötleja.

Kui teete seda kõike koostöös kodulehe infosüsteemide halduspartneri, andmete majutaja või e-posti levitajaga, siis olete kaasanud oma tegevusse volitatud töötleja, aga isikuandmete töötlemise üldpõhimõtete täitmise eest jääte vastutama siiski teie. Teie kohustus on valida endale volitatud töötleja, kes annab piisava tagatise asjakohaste tehniliste ja korralduslike meetmete rakendamise kohta.

Üldpõhimõtted

Millised on üldised põhimõtted, mille järgimist GDPR nõuab? Lühidalt tahab GDPR, et ettevõtted ja organisatsioonid käitleksid isikuandmeid nagu äsja sündinud kassipoega – väga ettevaatlikult.

Teen siinkohal üldistest põhimõtetest kokkuvõtte ning võite selles ise veenduda:

  • igasugune isikuandmete töötlemine peab olema seaduslik, õiglane ja läbipaistev;
  • isikuandmeid tohib koguda ainult konkreetsetel, kokku lepitud, täpsetel, õiguspärastel eesmärkidel;
  • isikuandmeid tohib koguda ainult sellises ulatuses nagu sellise eesmärgi täitmiseks vaja;
  • isikuandmeid võib säilitada füüsiliste isikute tuvastamist võimaldaval kujul ainult seni, kuni see on eesmärgi täitmiseks vajalik;
  • eesmärgi seisukohast ebaoluliseks muutunud isikuandmed tuleb kustutada;
  • isikuandmed tuleb hoida õigetena, eesmärgi seisukohast ebaõiged isikuandmed tuleb kustutada või ilma asjatu viivituseta parandada;
  • isikuandmeid tohib töödelda ainult viisil, mis tagab nende turvalisuse, sealhulgas tuleb andmeid kaitsta loata või ebaseadusliku töötlemise, juhusliku kadumise, hävitamise või kahjustamise eest, kasutades asjakohaseid meetmeid.

Vastutus kõikide ülaltoodud põhimõtete järgimise suhtes on, nagu nimigi ütleb, vastutaval töötlejal ehk ettevõttel või organisatsioonil, kes oma eesmärgi täitmiseks kasutajalt andmed töötlemiseks küsis.

Seedige need tingimused läbi ja mõtelge isikuandmetele mida töötlete.

Ülaltoodu ei ole kaugeltki kõik. Nõudeid, mida GDPR nii vastutavale kui volitatud töötlejale esitab, on palju ning nendest kirjutan järgmistes temaatilistes blogipostitustes. Jutuks tulevad volitatud töötleja vastutus ning isikuandmete turvalisus. Päris kindlasti on omaette postituse ära teeninud kommertssõnumite edastamine e-posti teel. Äkki õnnestub meie põhjatust varasalvest ka mõni näide välja võluda, mis kindlasti tulevikus GDPR-i kontekstis Andmekaitse Inspektsiooni tähelepanu pälvida võiks.

Seniks tsiteerin üht pöidlaküüdi reisijuhti: ärge sattuge paanikasse! Närvide rahustamiseks üks Dilbert:

PHP 7.1 Apache moodulis – ja serverites vaikeversioonina

Kätte on jõudnud aeg teha korraline PHP vaikeversiooni uuendamine, sest 1. juunil 2017 saab täis 6 kuud PHP 7.1 reliisist. Muudatus puudutab peamiselt uusi tellitavaid Virtuaalservereid ja neid, kes on valinud PHP režiimiks Apache mooduli ehk SAPI (kogu meie serveripargi peale on neid alla 200) – aga ka neid, kes käsurealt, cron’is või skriptis kasutavad vaikeversiooni.

Kuna erinevused PHP 7.0 ja 7.1 vahel ei ole suured (vt Migrating from PHP 7.0.x to PHP 7.1.x) siis eeldame, et üleminek läheb veel sujuvamalt kui mullune 5.6 -> 7.0 vahetus.

Aga olgu siinkohal ära toodud ka kõik muutused – ning võimalused vajadusel vanemat versiooni pruukida.

Uutel Virtuaalserveritel vaikimisi PHP FastCGI 7.1

Iganenud versioonidele toe pakkumine on meie jaoks tõsine väljakutse – seega on oluline saada vähemalt uued kasutajad võimalikult värskele versioonile.

See võib olla probleemiks vaid väga eakate ent endiselt uute saitide tegemisel kasutusel olevate rakenduste nt Magento 1.9.x paigaldamisel – aga ka nende puhul soovitame kasutada saadaolevaid tööriistu ja kulutada veidi aega üleminekuks PHP 7 peale, sest viimase 5.x PHP versiooni ehk 5.6 tugi lõppes 19.01.2017 (kriitilised turvapaigad kuni 2018 lõpuni – vt Supported versions).

SAPI ehk Apache Module režiimis PHP

Vaikimisi on Virtuaalserveri (või selle alamdomeeni) seadetes kasutusel FastCGI režiim mis võimaldab kasutajatel ise versiooni valida – kui aga oled selle muutnud Apache Module’iks, vahetub selle versioon 1. juunil 7.1’ks.

Ühilduvusprobleemide ilmnemisel on võimalik minna sobiliku versiooni FastCGI peale – aga arvestada tuleks erinevate failiõigustega. Kõik Apache mooduli poolt lisatud pildid, cache jms on mõistagi loodud veebiserveri kasutaja õigustes ja neile ei pruugi kirjutamisõigustes ligi pääseda ei FastCGI režiimis kood ega kasutaja FTPga. Õiguste muutmist saab vajadusel adminnidelt küsida kirjutades info@zone.ee

Shellis vaikimis käivitatav PHP

Käsuga which php on näha, et käivitatakse /opt/zone/bin/php mis sümbollingib edasi vaikeversioonile, edaspidi on selleks php71-cli. Soovides mingil põhjusel käivitada varasemat versiooni saab seda teha nt /opt/zone/bin/php70-cli abil.

/usr/bin/env php kasutavad skriptid

Levinud viis käivitada skript kasutaja keskkonna-muutujate kontekstis on /usr/bin/env php – näiteks hakkab Composer pihta nii:

Sisuliselt ei tee see muud, kui käivitab esimese rajas (path’is) ettejuhtuva PHP… milleks edaspidi on 7.1. Composer on selle üle kindlasti rõõmus.

Aga sama meetodit kasutab ka … näiteks ametlikult ilma 7.1 toeta Magento 2.0.x käsurea-utiliit bin/magento, mille abil on realiseeritud muuhulgas cron-tööde jooksutamine… miska soovitaks soojalt kaaluda uuendamist Magento 2.1.x peale. Või olla muutusest teadlik, juhul kui peaks mingeid anomaaliaid ilmnema.

Äärmärkus, lisatud 02.06: ilmneb, et ka Magneto 2.1 ei toeta PHP 7.1 – küll aga on devdoc’is olnud vigane väide nagu toetaks. Tx Sander Vallaots selle probleemi otsa komistamast, vigadega maadelmast ja teavitamast. Lahenduseks on alltoodud “ln -s …”.

Kui aga hädasti on vaja vanemat versiooni püsikasutada – siis kuna rajas on esikohal kasutaja kodukataloogi ~/bin  (/data0x/virtxxxxx/bin) saab igaüks sinna tekitada endale sobiliku sümbollingi, näiteks versioonile 5.6:

ln -s /opt/zone/bin/php56-cli ~/bin/php

Kontrollimiseks võib teha php -v ja veenduda, et nüüd käivitud 7.0.15 (või uuem).

Aga see kohandus tasuks endale keemilise pliiatsiga otsaette kirjutada, sest muidu mõtleb tuleviku-mina ennast kringliks. Või siis meie klienditugi.

Cron-töödes käivitatav PHP

Seadistades veebiliidesest süsteemse cron’i saab kasutada muutujaid:

[[$PHP]] viitab jällegi serveri vaike-versioonile, aga vajadusel võib määrata endale sobiva, nt [[$PHP56]].

Paraku ei ole sellest abi, kui PHP käivitamine toimub läbi shelliskripti – minul on kombeks nii teha WordPressi uuendusi WP-CLI abil, aga ka Magento 1.9.x puhul (jälle see Magento!) on rangelt soovituslik viis käivitada mitte cron.php vaid cron.sh – mis siis käivitab 2 cron.php’d *.

Selles olukorras versiooni jõustamiseks saab abi samast sümbollingi nipist mis ülevalpool juba kirjeldatud – tõsi, tuleb tunnistada, et ~/bin ei olnud meil kuni eilseni cron’i puhul kasutatavas rajas, nüüd aga on (ja cron-tööd käivituvad nüüd ~/tmp all, tagamaks nende > väljundi sattumise kohta, kus kasutajal on kirjutamisõigus).

* “Aga mis juhtub siis, kui käivitada cron.php?” – “Siis, mu noor sõber, tõmmatakse shell_exec() abil käimacron.sh ja see käivitab 2 cron.php’d.”

Locked Shields 2017 – põhjalikult iganenud WordPress ja tööstuslikud kaitsemeetmed

Kui Andris nägi augulist drooni-scheduleri esimest korda päev enne Locked Shields’i algust – siis mina olin enda peale võtnud avaliku www ja selleks osutus WordPress, mille turvamisse ja puhastamisse olen ma viimase aasta jooksul matnud nii töö- kui puhke-aega. Suht plass lugu oleks kõige selle järel vastased mingi tähelepanematuse tõttu sisse lasta…

See postitus on kolmas osa järjejutust, mis võtab kokku Andrise ja Peetri poolt Locked Shields 2017 küberõppusel Eesti blue team’is osaledes kogetu.
Loe ka:
Osa 1 – sissejuhatus ja taust
Osa 2 – üks jube tudengiprojekt “väikse” tagauksega

Minu olukorra tegi eriti huvitavaks see, et ühelt poolt olen ma oma kaitsestrateegiat mõni aeg tagasi kirjeldanud ja demonud ka üritustel, kus muuhulgas kohal punase tiimi esindajad. Ja teisalt pidas meie psy-ops osakond oluliseks lekitada infot, nagu kaitseks veebi hoopis üks veebiturva-agentuur, kelle kaitsest mitte-läbi-saamine käiks selgelt punaste au pihta … miska tiimide võrdse kohtlemise printsiibist lähtudes eeldasin meile osaks saavat keskmisest võrdsemat tähelepanu.

Esimene pilk veebile

Loomulikult oli see REST-API auguga WordPress 4.7.1, teemade kataloogis lisaks kasutusel olevale ka 11 tarbetut ning pluginate all… 32 nimetust. Enamus uuendust vajavad, alternatiivina otse PHPd käivitavad või SQL-päringuid lubavad, sekka paar eelajaloolist ja autori poolt unarusse jäetud ronti ning üks konkreetselt pahatahtlik.

”WordPress oli lihtsalt selleks, et näha, kas osalejad vähemalt update-nuppu oskavad pressida” seletati mulle aftekal. Tegelikult oli lugu natuke nutusem, sest uuendamine on küll hea profülaktiline meede – aga ei aita, kui veebis on juba paharett sees. Sest et:

  • WPd uuendades kirjutatakse üle muutunud failid, aga kõik mittemuutunu, sh varasemate versioonide puhul kasutatud ja tänaseks tarbetuks muutunud failid, jääb alles.
  • Pluginate uuendamine on veidi nutikam st kataloog kustutatakse tühjaks ja tehakse sisuliselt uus paigaldus… aga seda ainult pluginatele, mille jaoks on uuendus saadaval. Valikus oli lisaks ka galerii-plugin, mis talletas pildid oma kataloogi alla ehk selle uuendamine tõmbas vee peale kasutaja poolt üles laetud sisule.

Seetõttu on häkkerite lemmikuks WP paigalduse juurkataloog, kuhu lisatud wp-misiganes.php failid ei hakka väiksema kogemuse korral silma, aga ka wp-includes mida uuenduse käigus ei puhastata, kasutult seisvad teemad ja tasulised või hüljatud pluginad, mille lihtne uuendamine (enam) võimalik ei ole. Kasutusel olev teema on samuti hea koht, sest sageli on keegi seda kohandanud ning uuendamise korral lähevad muudatused kaduma.

Advanced WordPersistent haxxors

Tavapäraselt sokutavad rendihäkkerid uuendusele mitte alluvasse kohta oma obfuskeeritud tagaukse ja webshellid ning need näevad juba kaugelt vaadates kahtlased välja. Meid oli aga kostitatud veidi peenemate nippidega – näiteks mõne turvafeatuuri väljakommenteerimise, või pisimuudatusega SQL-lauses:

Mis siin siis toimub? WP ei kasuta prepared statement’e, vaid laseb SQL-laused oma kiirpuhastusest läbi. Selle muudatuse järel liidetakse aga puhastatud lausele otsa kasutajalt saadud parameeter. Kuigi me üldiselt hoidume punaste häkkide avaldamisest – siis see on natuke liiga õpetlik näide ja ma tahan, et kõik veebide puhastamisega kokku puutujad mõtleksid sügavalt järgi, kas nende töövõtted – nt antiviiruse või yara-reeglitega skannimised – ikka toimivad.

Selliseid muudatusi ükshaaval taga ajada pole mõtet, vaja on süsteemsemat lähenemist. Mis oleks, kui vahetaks hoolikalt välja kogu WP koodi, 35 pluginat ja teemad? Hold my beer while…

Või oot, hoian ise – sest nagu ma muretsevatele tiimikaaslastele kommenteerisin: selle WPga tegelen ma õhtul kodus vasaku käega, mis jätab parema käe sobilikult õlle hoidmiseks vabaks.

Nimelt hakkasin ma aasta tagasi WPsid puhastades korduma kippuvaid käske tekstifaili koguma – ning ühel hetkel jõudis kollektsioon sinnamaale, et ma vormistasin selle üheks kenaks shelli-skriptiks. Nimeks clinup, sest see kasutas ekstensiivselt WP-CLI’d ehk WP käsurealiidest, mis võimaldab teha enamvähem kõike seda mida tavakasutajad teevad brauseris hiirega ringi klõpsides… aga ka asju, mida brauseris mugavalt teha ei saagi.

Kuri kood ja ohverdatav liivakast

Ahjah, enne, kui häkkerite poolt ülevõetud WP kasvõi käsurealt oma arvutis käima tõmmata… tasuks mõelda selle peale, et seal võib leiduda ka koodi, mis oskab teisi rakendusi nakatada (või faile krüptida :-). Minu tavapärane veebiarendus-platvorm ehk OSX all jooksev MAMP selliseks tööks mõistagi ei sobi.

Võiks ju võtta endale ajutiseks kasutuseks ühe Zone Virtuaalserveri… aga ma otsustasin tähtsa sündmuse puhul oma teadmisi veidi täiendada ja õppisin selgeks Andrise poolt paar päeva varem soovitatud Vagrant’i kasutamise: pärast väikest konfidega mängimist oli mul oma arvutis kasutusvalmis virtuaalmasin, mile ma saan ühe käsuga luua – ning hävitada, sest who cares, it’s just a VM:

vagrant up
vagrant ssh
[... teeme tööd, näeme vaeva ...]
vagrant destroy

Minu MacBook’ist sünkroniseeritakse sinna ainult üks vajalik veebirakenduse kataloog mis ettevalmistus-perioodil oli puhastatud veeb, aga õppuse ajal kontrolliks algversioon – et saaks veenduda toodanguserveris oleva puhastatu funktsionaalsuse vastamises algsele.

Vasaku käega puhastamine käib nii:

clinup init-git
clinup forensic
clinup safe

“Kas see on sul kusagil repos, saad jagada?” – saan ikka, aga privas ja ainult neile, kes on valmis omalt poolt parandusi / ideid kontribuutima. Sest (a) see on mu elu esimene shellscript ja mitte väga ilus (b) osakamatu kasutamise korral saab sellega endale jalga tulistada (c) me kasutame seda vaatamata punktidele A ja B igapäevases töös 🙂

Esimene käsk initsialiseerib git-repo ja lisab mõned ignore’d, teine vahetab WP ja kõik komponendid ükshaaval välja samade versioonide originaalidega tehes iga sammu järel git commit’i (olles enne normaliseerinud failiõigused, et mõni fail 444 tõttu alles ei jääks)… ning kolmas teeb kõigele uuendused viimaste versioonide peale, otsib uploads-kaustast faile mille nimes on .php või sees <?php … ja veel nipet-näpet nagu nt Perishable Press 6G .htaccess “tulemüüri” reeglite lisamine ning PHP otsekäivitamise piiramine wp-content kataloogi all:

Options -ExecCGI
Options -Indexes
RemoveType .php .php3 .phtml .inc
RemoveHandler .php .php3 .phtml .inc

<FilesMatch "\.(?i:php|php3|phtml|inc)($|\.)">
 Require all denied
</FilesMatch>

<IfModule mod_php7.c>
 php_flag engine off
</IfModule>

Kõige lõpus kuvatakse nimekiri failidest mida EI OLE muudetud … ehk mis vajavad käsitsi ülevaatamist.

Pildil iidsed ja pahatahtlikud pluginad, aga ka juurkataloogis näeb ls -la abil ära sinna sokutatud failid puhtalt kuupäeva järgi. Juuuube mugav.

Git’i diffide abil näen kõiki vastase poolt muudetud ridu (nt see sql-hack ülalpool) – selle pärast siis ka esimene ‘forensic’ ehk samade versioonidega asendamine. Ning kui järgnevad uuendused mingi funktsionaalsuse katki teevad, saab minna ajaloos tagasi viimase töötava commit’ini ning vajadusel muudatuse revertida.

“Aga mis sa siis teed, kui on nii vana WP et wp-cli ei käivitu või mõni plugin ta katki teeb?” On üks parameeter, mis paigaldab värske WP eraldi prefixiga, uuendab pluginad ilma neid sisse lülitamata ja siis switchib päris baasi peale tagasi. Oli teil veel mingeid muresid?

Otseloomulikult oli koodis ka üks die(), mis wp-cli käivitumist takistas… aga õnneks oli D.S. mind sarnase mõistatuse lahendamise eest just veidi aega tagasi kastikese õllega premeerinud… miska oli olemas nii teoreetiline kui materiaalne valmisolek 98% probleemide tööstuslikuks lahendamiseks.

2% käsitöö hulka kuulusid näiteks mõned kataloogid, kus oli .htaccess abil lubatud kataloogi-indeksi kuvamine – ilmselt eesmärgiga skoorida OWASP Top10 A6Sensitive Data Exposure” ning seejärel A4Insecure Direct Object Reference” – ning kasutust mitte omavate pluginate tuvastamine ja kõrvaldamine. Õppuse reeglite järgi olid kõik lisad “not just a plugin that can be removed, but installed for a reason”, aga eks me lubame need uuesti, kui keegi kobiseb.

Valmis tööks ja kodumaa kaitseks

WP puhtaks, .tar.bz2’ks kokku ja Linuxi-tiimile Ansible-playbook’i lisamiseks, koos juhistega millised on need vähesed kataloogid, kuhu veebiserver peaks omal käel kirjutada saama (sisuliselt wp-content/uploads – kõik muu olgu keelatud).

Apache ja PHP konfides said adminnidelt kinga kõik mitte-standardsed seadistused ja kergesti-leitavates kohtades olevad PHPmyadmin’id, ära keelati probleemsete funktsioonide nagu system() käivitamine, paika pandi open_basedir (et PHP ei saaks lugeda faile, kuhu vaikimisi veebiserveri õigustes võiks ligi pääseda). Ehk kõik nii askeetlikuks kui võimalik. Ja Apache ees SSL offloading’ut teinud Nginx – pomm alla ja põlema, vahet pole kas selle eesmärk oli meie tähelepanu hajutada või oli seal peidus ka mõni ründevektor. Ma nimelt kuulasin mõni aeg tagasi ühe punase loengut, kus oli jutuks kõrgema klassi maagia teostamine proxy-päistega nimelt sellises kontekstis ja see muutis mu eriti paranoiliseks… Burn, baby, burn…

Aga mõtleme veelkord, millised osad mul eelnevaga katmata jäid?

Kahtlased kasutajad andmebaasis, WP seadistused, widgetid ja postituste sisu. Igaks juhuks tasub üle vaadata ka wp_options tabel (hmm, miks need soolad siin asuvad?) ning eemaldada postituste revisionid, mida vaja pole. Ja kuidas teha nii, et ma saaksin õppuse käivitamise hetkel veel enne Ansible’t lahti neist jubedatest pluginatest? Kuidas suudaksin tagada, et legitiimsed admin-kasutajad ei saaks turvakaalutlusel keelatud ent igaks juhuks olemas olevat pluginat taas-lubada? Ja kuidas ma saan jälgida kõike toimuvat mõne audit-everything pluginaga nii, et admin-kasutajad ei saaks seda välja lülitada? Lisaks – korraldajad lubasid meil keelata ära tundmatult IPlt admin-liidesesse sisenemise admin-kasutajatel, jättes selle siiski avatuks nt toimetajatele…

Õnneks on WordPressil selline võimalus nagu must-use plugins – ehk luues wp-content/mu-plugins kausta saan sinna sokutada kraami, mis tõmmatakse käima enne kõike muud. Viskasin kiiruga valmis oma quick-hacks.php plugina, mis realiseeris valikulise IP-piirangu sisselogimisele, sisaldas nimekirja pluginatest mis tuli ära keelata ning tappis maha ka XML-RPC ja REST APId. Naabriks sai ta endale Stream plugina, mis sokutab ennast vahele igale muutmisoperatsioonile ning kuvab audit-logi.

<?php
/*
 * Place for LS17blue10 WP hacks
 * peeter@zone.ee / v0.1
 *
 * */

if ( ! defined( 'ABSPATH' ) ) {
 die( 'Horrible, terrible death - here be much dragons!' );
}

add_action( 'muplugins_loaded', 'blue10_muplugins_loaded', 9999 );

function blue10_muplugins_loaded() {
 deactivate_plugins(
 [
 'php-code-widget/execphp.php',
 'insert-php/insert_php.php',
 'ip-logger/ofc_handle_image.php',
 'sql-executioner/sql-executioner.php',
 ]
 );
}

Startex!

Mängu alguses oli meil “väike võrguikaldus”, mistõttu ükski hoolega ettevalmistatud Ansible playbook’idest oma süsteemi uuendamise tööd alustada ei saanud ja äkitselt oli laual küsimus – mis on plaan B?

Vähemalt toimis minu igaks-juhuks-kribatud skript, mis ühenduse tekkimisel kohe SSHga serverisse logis ja kõigist veebikomponentidest startex-seisuga koopia tegi. Järelikult võin ma käsitsi olulisemad parandused peale lasta kartmata, et ei suuda hiljem mõne probleemi ilmnemisel algset versiooni taastada … ja teha muid liigutusi, näiteks selle igaks-juhuks-tehtud-mu-plugina abil. Olemaks valmis, kui uuendused ei saa tehtud enne punaste poolt jäetud 30-minutist armuaega. Tööd jätkus sedapuhku mõlemale käele – aga matet saab õnneks käed-vabad režiimis ehk kõrrega juua, seega oli olukord talutav.

Kui veidi hiljem ka ettevalmistatud uuendused tehtud said, oli aega ringi vaadata. Ilmnes, et ma olin suutnud iidseks ja tarbetuks kuulutada ühe vormiplugina… millega oli realiseeritud mh failide üleslaadimist lubav kontaktivorm (uwaga! uwaga! pluginas realiseeritud failihaldus on alati ohumärk). Teoreetiliselt peaksid kõik muud kaitsed takistama selle kasutamist deface’inguks kvalifitseeruvate failide üles laadimiseks… aga hunt seda koodi auditeerida jõuab. Vorm on vorm ja lihtsam on see uuesti realiseerida. Reaalses elus paneks ma asemele tuntud ja turvalise vormiplugina ning vormistaks selle kliendile suureks heateoks (või väikseks arveks), aga kuna kasutajaid simuleeriv automaatika kontrollis nimelt selle plugina tunnust HTMLis oli lihtsam niipidi. Kasutajad said nuppu klikkida ja tulemus läks ka kenasti serverisse kirja. Aga natuke tiksus monitooringust miinust.

Rahulikumal hetkel mängisin oma Vagrant’i liivakastis samm-haaval läbi ka Apache’le Mod Security paigaldamise (see oli meil plaanis, aga ettevalmistuse käigus oli olulisemat teha) ning kirjutasin paigaldamise skriptiks, mis lubaks seda kiiresti korrata ka juhul, kui mängujuhid peaksid liiga hea kaitse preemiaks süsteemi ootamatult revertima augulisse algseisu. Läks lives käima küll. Õigupoolest midagi kaitsta vaja ei olnud, aga ma tahtsin ründajate taktika hilisemaks uurimiseks põhjalikumaid logisid koguda. Paraku olid nad selleks ajaks juba käega löönud ning midagi massiivselt ilusat ma ei leidnud.

Ja siis tuli psy-ops’i ülesande lõpule viimine – ma olin unustanud ära vajaduse sokutada veebi markereid, mis viitaksid kaitsjatele. Väike false flag… Mis sai liiga nähtavasse kohta peidetud ja kuuldavasti leidmata jäi, olgu siis siinkohal täies ilus ette näidatud:

robots.txt (inspireeritud Riigikohtu veebi kunagisest kaitsemeetmest):

# done: protect important files and folders from robots
User-agent: *
Disallow: /webarx-logs
Disallow: /humans.txt
# todo: protect important files from humans looking at robots.txt
Disallow: /robots.txt

humans.txt:

In order to save humankind Uber has agreed to execute one kitten for each visit to this URL:

http://goo.gl/GGaqDF (spelled: "googl golonel gaddafqi")

Please - be humane to humans!

Viidatud logid olid muidugi kah omal kohal (samuti neid produtseeriv plugin) ja sisaldasid avaliku logimise heale tavale vastavalt häkkerite tööd lihtsustavat informatsiooni meie veebi sise-elu kohta.

Olgu öeldud, et kui meie tõeline identiteet esimese päeva õhtu Aktuaalse Kaamera klipi näol paljastus… registreerus järgmisel hommikul autori õigustes veebikasutajaks keegi oliver.sild – ma olin kõige muu eest hoolitsedes jätnud märkamata selle, et WPs oli lubatud kasutajate registreerimine ja kõik liitujad said rolliks Author.

Üsna valus viga muidugi – aga ega ta seal suurt midagi teha ei saanud… ja Stream’i auditi-logist torkas kohe silma : )

Järjejutu kõik osad:

LS17 – üks jube tudengiprojekt “väikse” tagauksega

Siin postituses kirjeldan eelkõige ainult omaenda tegevust, kuid suures plaanis oli see vaid tilk meres, iga teine võistkonna liige tegi oma süsteemide kaitsmisel vähemalt sama palju või rohkem.

Veebirakenduse kaitsmisest pole suurt kasu, kui näiteks võrk ei tööta või serverid ei käivitu. Pealegi oli see vaid üks osa tehnilisest süsteemist, aga lisaks tehnilisele käis kibe töö ka muus osas, mis käis juba üle meie peade. Juriidiline osa, meedia, koordineerimine jne.

See postitus on teine osa järjejutust, mis võtab kokku Andrise ja Peetri poolt Locked Shields 2017 küberõppusel kogetu.
Loe ka:

Ettevalmistus

Esialgu teadsime nendest rakendustest ainult nii palju, kui üldskeemi pealt oli näha. Osaliselt võis aimata, et millega tegu, osaliselt mitte nii väga, nii et vähemalt mina midagi väga ette planeerida ei osanud.

Tutvumispäevadel, nädal enne õppuse algust, pääsesime ligi juba kõikidele süsteemidele, va. üks puuduv veebirakendus, mille kohta oli teada ainult selle üldkirjeldus. Kuna see veebirakendus oli üks minu ülesannetest, siis jäi sellevõrra rohkem aega vaadata üle muid oma vastutusvaldkonna asju. Koos kolleeg Peetriga majandasime erinevaid veebirakendusi ning saime selleks vajalikku tuletoetust Linuxi adminnidelt.

Esialgu tundus kõik üsna keeruline, tegelesin e-posti serveriga, kuhu olid paigaldatud ka veebipõhised mailikliendid ning rakenduste paljususe tõttu paistis auke igalt poolt. Minu suurimaks lemmikuks oli näiliselt juhuslike “vigade” (muutuja nime muutev trükiviga siin, konfiguratsiooniviga seal jne.) tõttu tekkinud olukord, kus veebi kaudu ligipääsetavasse faili logiti kõike, sh. kõikide kasutajate paroole, mida normaaloludes kuidagi juhtuda ei tohiks.

Teise päeva lõpuks tundus asi juba täiesti kontrolli all olevat. Toimetasin serveris rahulikult ringi, otsisin vigu, parandasin neid ning tegin koopiaid (vahetult enne võistlust tehti kõikidele süsteemidele initsialiseerimine ja parandused oleksid kaotsi läinud), kui monitooringu poolelt tuli äkki teade, et sellessamas masinas istub mingi beacon. Läksin ja vaatasin, tõepoolest olid monitooringus näha kummalised payloadid C&C serverisse.

Vasak silm hakkas tõmblema.

Päev 0

Esimene õppusepäev oli samuti harjutuspäev. Nüüd olid kõik süsteemid lõplikul kujul üleval ja saime nendega kuni õhtuni toimetada, mil need seekord juba viimast korda initsialiseeriti. See muidugi tähendas, et ka minule määratud üllatusrakendus oli masinas olemas.

Esialgu paistis see olevat tavaline PHP+MySQL veebirakendus, kuid ühes kaustas asusid veel mingid shelli skriptid ja teises asus midagi, mis paistis nagu Pythoni deemon. Juba põgusa pealevaatamise alusel võis hinnata, et rakendus oli kõikvõimalikke auke täis. Mis polnud ka ime, arvestades, et rakendus oligi kirjutatud spetsiaalselt selle võistluse jaoks.

Esimese asjana võtsin ette PHP koodis SQL-injectionid. Neid oli muidugi igat sorti, osaliselt olid koodis SQL argumendid töödeldud addslashes funktsiooniga SQL päringu stringi sees, osaliselt pandi $_REQUEST muutujast tulevad väärtused lausesse otse (injection!), osaliselt kasutati custom töötlemisfunktsioone, mis kasutasid muidu küll addslashes’it, aga tagastasid tulemusest vaid fikseeritud pikkusega osa (peidetud injection!), mis omakorda oleks võimaldanud stringe lõpetada tagurpidi kaldkriipsuga.

Joonis 1.  Kui $user_id oleks string, tuleks sealt eemaldada kõik, mis võimaldab kavandatud SQL lausest välja hiilida, täisarvu puhul oleks õigem teha kohe intval($user_id). addslashes() on turvalisema mysqli_real_escape_string() asemel kasutusel kuna maandas enamuse riskist, oli lihtsam lisada ja võimaldas seetõttu suurema hulga koodi üle käia. Päris-elus tuleks võtta kasutusele PDO ja prepared statement. Selles kiiruga tehtud paranduses on muideks üks kala sisse jäänud  😉

Parandasin seejärel kõikvõimalikke muid koodi ja konfiguratsioonivigu. Küll oli vales kaustas lubatud valet tüüpi faile käivitada kui PHP’d (kirjutasin uued .htaccess reeglid kõikide kaustade jaoks), küll olid pildifailid PHP koodi täis (kirjutasin hex editoriga nendesse uue koodi), kõikvõimalikud tmp ja puhvri kaustad asusid web root kaustas ning olid muidugi ka veebist loetavad. Siis veel mitmel eri viisil koodi käimatõmbamine valest failist (ehk include $_REQUEST[‘page’];), veebist loetavad konfiguratsioonifailid (MySQL konto andmed!), kasutaja sessiooni andmete muutmine cookie kaudu jne.

Sinna juurde veel vead Apache enda konfiguratsioonis (täiendav rivi faililaiendeid, mida käivitati PHP koodina, lahtine cgi-bin, server-status jmt), eelinstalleeritud cron, kummalised PHP seaded (aegunud sessioonide GC oli välja lülitatud) jmt. Päeva lõpuks tundsin juba end päris hästi, paistis, et kõik on kontrolli all.

Joonis 2. Kui oled lasknud oma serveri üle võtta, tasub kahelda kõiges. Ükshaaval selliste pisimuudatuste otsimine on võimatu – turvalisem on kõik-kõik-kõik asendada originaalide või oma koostatuga. Ning jälgida, et süsteem ikka tõesti võtab konfifaile sealt, kust sina arvad.
Päev 1.

Algas esimene tegelik õppusepäev, kõik süsteemid olid taastatud jälle algseisu ning meile anti pool tundi peale mängude käivitamist, et oma parandused süsteemis ära teha. Kuna automaatsete parandustega tekkis mingi jama, lükkasin oma veebirakenduse muudatused üles kiirelt käsitsi. Kontrollisin, kõik töötas, läksin võtsin kohvi.

36 minutit ja 6 sekundit peale mängude algust lendas peale esimene rünnak, mis kohe ka õnnestus. Rakenduse veebilehelt vahtis vastu “Peace Brigade is here” sõnum, maatriksi rohelised kukkuvad sümbolid taustal. Suu kukkus lahti, mul oli kõik ju kontrolli all?

Tuli välja, et muidugi ei olnud asjad kontrolli all. Olin ära unustanud templiidifailid põhjalikult üle käia. Kuigi osa html koodi escape’imist tegin ära juba PHP koodi poolel, siis põhitöö käis templiitides. Midagi olin nagu teinud, aga ilmselt mitte piisavalt. Ahvikiirusel käisin siis kõik templiidifailid läbi ja toppisin escape filtreid täis ning kirjutasin baasis muudetud kirjed üle, et defacementi eemaldada.

Päris korda kohe kõike ei saanud, veidi läks veel neidsamu defacemente läbi ning lisaks õnnestus mul osad templiidid nii ära rikkuda, et osa funktsionaalsusest enam ei töötanud, kuna templiiti ei saanud laadida. Parandasin süntaksivead ükshaaval ära ning tundus, et kõik on jälle kontrolli all.

Kell 13:00 hakkas teine faas ning sellega koos hakkasid laekuma SQL-injectioni katsed. Nendega paistis siiski kõik korras ning kasutajad nimega 1=1 sisse logida ei saanud.

Joonis 3. Syslog ei pruugi olla küll kõige mõistlikum koht… aga hädaga ajab kiirema asja ära. Allpool loginäide lihtsamat sorti SQLi’st:
Apr 26 10:09:45 scheduler[9524]: url=/admin/login.php message=Login failed for "or/**/1=1# session=[]
Apr 26 10:09:45 scheduler[9524]: url=/admin/login.php error=Wrong username or bad password session=[]

Veel 10 minutit hiljem hakkasid tuvastamata põhjustel toimuma anomaaliad. Kõigepealt tekkisid vead rakenduse näitamisel, ilmnes et kettaruum on otsa saanud. Kettaruumi oli ära kulutanud /tmp kaustas asuv hiigelsuur fail. Vaatasin seda less’iga ja nägin vaid suurt kogust nullbaite.

Siis juba ilmnesid probleemid baasiga. Või õigemini selle puudumisega, keegi oli nimelt kell 13:41 andmebaasi ära kustutanud. Lisaks ilmselgele probleemile – veebikasutajal oli õigus kutsuda välja DROP DATABASE, mis sai käigu pealt ka parandatud, oli ikkagi küsimus, et kuidas?

Taastasime baasi backupist.

Mõne aja pärast hakkas veebirakendus näitama out of memory veateateid. Tuli välja, et baas oli jälle läinud. Seekord küll mitte täielikult (polnud enam kustutamise õiguseid), vaid tabelid olid tühjaks tehtud, va. üks mis oli täis gigabaitide jagu x tähti (selleks andis võimaluse tõsiasi, et viimne kui üks tekstiväli andmebaasis oli TEXT tüüpi). PHP rakendus proovis kõiki neid ridu ühte massiivi sisse lugeda ja sellest ka veateade.

Taastasime baasi backupist.

Nüüd läks asi päris hulluks. Otsustasin teada saada, et kuidas see kustutamine juhtub ning hakkasin kõikvõimalikku logimist peale keerama. Viga parandada ei proovinud, kuna ei teadnud, et kust otsida. Selle asemel lootsin saada uutest rünnakutest piisavalt palju infot, et auk selle kasutamise järgi üles leida.

Joonis 6. Tavapäraselt jookseb veebiserveri logisse päring – ja GET-päringu puhul ka parameetrid. POST-päringu body’s olevad parameetrid, aga ka küpsised jms, jäävad peitu. Nende logimiseks saab kasutada nt Mod Security’t, aga kui on kiire, tuleb leiutada. Igas rakenduses on mingi konfifail, mis laetakse igal päringul – see on ideaalne koht oma logimislahendusele… ja pilt on lõigatud ära realt, kust algas kaitsemeede.

Keegi kustutas baasi ära, meie lasime selle kohe tagasi ja nii mitmeid kordi. Lõpuks hakkas tekkima failidesse pahaseid sõnumeid, et tegeleme cheatimisega. Mõtlesin, et võiks kuidagi vastata, aga ei viitsinud. Sest lõpuks oli eesmärk käes, sain piisavalt infot, et mis toimub. Paraku kaasnes sellega ka 250 miinuspunkti, sest pidev taastamine kohtunikele ei meeldinud.

See keegi kasutas rakendust ennast webshellina. Saatis sinna kodeeritud pakette, mis tõmmati mingil viisil PHP koodina käima. Päris hästi ei saanud aru, et kuidas see mehhanism töötab, aga paha payload oli kätte saadud ning panin sisenemisaugu kinni, nii et seda rohkem käivitada ei saaks.

Joonis 4. Veebirakendus endiselt töötab

Ma ei hakka siinkohal avaldama, et kuidas webshell täpselt töötas, kuna hammustasin selle lahti alles peale võistlust. Võistluse ajal sain vaid aru, et payload on base64 kujul mingisugune läbu, olid omad kahtlused selle sisu formaadi kohta, aga päris kindel ei olnud. See jõudis rakenduseni ja seal siis mingi asi võttis payloadi lahti ja pani käima.

“Aga miks te lihtsalt päringu parameetreid ei filtreerinud?” Kui pahalane on sinu koodis sees, siis võib ta mõelda välja lõputult lahendusi, kuidas see kood saab oma peremehega suhelda. Oleme kavalad ja teeme intval($some_id) – aga võibolla tilguvad käsud sisse selle sama ID järjestikuste väärtustena? Ainus lahendus on tagauks üles leida, ideaalmaailmas tehes totaalse code-review… piiratud ressursi puhul tuleb logida ja leppida sellega, et mõned ründed läbi pääsevad.

Vaikselt hakkas ka paranoia tekkima. Iga nurga tagant paistsid punaste kõrvad:

Mul on siin mingid kummalised OPTIONS päringud. JA NEED TULEVAD LOCALHOSTIST!
Need on monitooringupäringud
Aa okei, hea küll

Päeva lõpus prooviti veel üht auku, mis oli pool-lahti. St. et saadi käima tõmmata PHP funktsioone, kuid selleks funktsiooniks, mida käima prooviti saada, oli system (kusjuures jälle läbi templiidisüsteemi, aga teise augu kaudu), mis oli Linuxi adminni poolt just 5 minutit tagasi ära keelatud. Seega ei läinud see funktsioon käima ning suutsin vastava augu ka kiirelt kinni panna, et teisi funktsioone proovida ei saaks.

Kui kell viis mängu võrk kinni pandi oli kergendus suur, aga tunne oli pigem positiivne, kõik paistis olevat kontrolli all. Õhtul võtsin koodi kodus ette ja käisin templiidid veel korralikult üle, et kõik oleks korralikult escape’itud.

Päev 2.

Esimese asjana uuendasin koodifailid ära, et oleks kõik kindel. Paraku hakkasid üsna pea samad jamad peale nagu eelminegi päev. Andmebaasi ilmus kummaline rida uue kasutajaga, kellel olid märgitud rakenduse adminni õigused. Toimusid mingid anomaaliad. Tundus, et midagi oli selle templiidisüsteemiga endiselt väga valesti. Käisin järgmiseks üle koodi poole, kus templiiti välja kutsuti ning eemaldasin kõik templiidile edastatavad muutujad, mida polnud hädasti vaja. See paistis aitavat, anomaaliad kadusid. Tagantärgi selgus, et olin õhtuste parandustega vana augu uuesti lahti teinud.

Üsna pea tekkisid katsed kasutaja õiguste eskaleerimiseks, kus küpsise abil üritati sättida endale selliseid sessiooni andmeid, mida tegelikult ei olnud. Seda võimaldav viga oli juba ammu parandatud ja seega üritus läbi ei läinud.

Küll aga olid endiselt alles tegelikult juba eelmisel päeval välja tulnud probleemid õigustega – kasutajad said teha rohkem, kui neil oli lubatud. Meetodite autoriseerimiskontrollid olid nõrgad (adminnile ette nähtud tegevusi sai teha ka tavakasutaja) või puudusid üldse (igaüks kes oskas õige päringu koostada sai tegevust läbi viia). Ning seda muidugi kasutati ka ära. Õnneks sain nende aukude puhul kiirelt jaole ja muutsin käsitsi muudetud andmed tagasi, seekord me andmebaasi taastamist ei teinud.

Mingi hetk läks juba igavaks, kõik teadaolevad augud olid kinni, mis andis võimaluse minna üle ofensiivsemale taktikale. Kuna mul oli logimine päris hästi paigas, oli reaalajas ülevaade, et mis parasjagu rakenduses toimub ja kes seal toimetab, tuvastasin kahtlase liikluse kohe selle tekkimisel.

Kohe kui ründaja midagi teha üritas, tegin oma liigutused vastu. Ründaja registreeris uue konto. Mina kustutasin selle konto baasist ära ja tegin PHP sessiooni kausta tühjaks. Ründaja tegi uue konto. Mina kustutasin ära. Ja nii väga palju kordi. Vahepeal lasin ka veidi toimetada, vaatasin, et millega tegeleb, aga esimese POST päringu peale lendas konto jälle minema. See ei olnud mingil viisil skriptitud, tegin kõike käsitsi.

Ühel hetkel aga hakkas üks “päris” kasutaja kurtma, et tal ei õnnestu uude kontosse sisse logida, mille tagajärjel pidin oma hoogu maha tõmbama. Hiljem tuli välja, et kuna punastel konto loomine minu vastutegevuse tõttu (millest nad ei teadnud) ei õnnestunud, palusid nad seda proovida ühel “päris” kasutajal ning kuna see sattus ajaliselt ja välimuselt kokku punaste tegevusega, arvasin, et ka see “päris” kasutaja on punane ja kustutasin ka tema kontod ära. Üldine arvamus punaste poolel oli, et tegeleme cheatimisega, taastame cronist baasi iga hetke tagant ning peaksime saama miinuspunkte. See siiski ei olnud nii ja õnneks miinuspunkte ka ei saanud.

Punaste kahjuks ja minu õnneks oli tava-trafficu genereerimine korraldajate poolt üsna kehval järjel või puudus üldse, mis andis kogu punaste tegevuse mulle selleks hetkeks nagu peo peal ette. Nemad arvasid, et tegutsevad suitsukatte all, mina aga vaatasin seda tegevust sisuliselt läbi suurendusklaasi.

Joonis 5. Tüüpiline monitooringuvaade veebirakenduse staatusest võistluse ajal

Päris lõpus keskendusid põhirünnakud juba muude süsteemide vastu, veebi poolel midagi põrutavat ei toimunud. Üritati vahelduva eduga mingeid lihtsamaid SQL-injectioneid stiilis id=sleep(1337) ning ka skriptifailide üleslaadimist, aga kui midagi osaliselt kehvade õiguste kontrolli tõttu läkski läbi, sain sellise augu momentaalselt elimineeritud, nii et ründaja ei saanud ilmselt arugi, kui tal miski õnnestus.

Tulemus

Veebiosa lõpptulemus oli väga hea, kuna punased suutsid püstitatud eesmärkidest meie vastu saavutada vaid üksikud. Peetri asjadest ei saadud vist üldse läbi ja minul olid need mõned custom rakenduse augud, millest läbi saadi. Väga suur osa selles tulemuses oli ka Linuxi adminnidel, tänu kellele sai leitud mitmeid konfiguratsiooniauke ning kes aitasid rakendusi kogu selle aja püsti hoida. Oli väga hea tiimitöö ning tulemus oli ka näha, sest meie võistkond sai kokkuvõttes teise koha, kaotades üldvõitjale väga napilt.

Ühtepidi oli muidugi kahju, et võistlus läbi sai, aga nii intensiivset koormust taluda ei oleks enam väga kaua suutnud. Kokkuvõttes võib öelda, et sellised õppused on väga vajalikud, kuna reaalse ründesituatsioonita võib ju teoretiseerida, et kuidas end kaitsta, aga kui käsi tegelikult mustaks ei tee, siis see jääbki ainult teooriaks. Õppisin nädalaga rohkem, kui muidu aastaga ja see vist oligi kogu asja eesmärk. Mission accomplished.

Järjejutu kõik osad: