Kas Zonel on värske PHP versioon? Alati. Aga sinul?

Kommunikeerides turvaprobleeme tasuks vältida asjatu paanika tekitamist – anna asjakohast infot ja tegele reaalsete, mitte filmistsenaariumi-riskidega.

Eile hakkas mulle erinevatest kanalitest tulema küsimusi Zone serverites kasutusel oleva PHP-alamversiooni kohta. Selle taustaks oli ühe arendusfirma poolt klientidele saadetud kiri:

Magento väljastas teadeande, et PHP’s avastati hiljuti turvaauk, mis lubab kaugkoodi täitmist andmaks täieliku kontrolli kõige üle. Siiani pole ühtegi kinnitatud rünnakut, kuid kuna Magento töötab PHP baasil soovitame kõikidel kaupmeestel võimalikult kiiresti PHP versiooni uuendada.

Turvalisuse tagamiseks võta ühendust oma projektijuhiga.

Teavituse põhjuseks on MS-ISAC 2019-087 nõuanne, mis loetleb üles hulga värskete PHP versioonidega paigatud turvanõrkusi – tõsi, ükski neist ei ole selline, mis annaks alust erakorraliseks paanikaks.

Kas see võiks mõjutada sinu veebirakendust?

Väga vähetõenäoline. Tõsi, kui anda PHP koodile (nt Magentole) ette konkreetse turvanõrkuse ärakasutamiseks sobilikud andmed, siis on tõesti võimalik kutsuda esile olukord, kus andmed käivitatakse koodina ja ründajal on võimalik server üle võtta.

Selleks peab aga küberkurjategija andmed väga spetsiifilisse kohta sokutama, nende lihtsalt otsilahtrisse või tarne-aadressiks sisestamisest ei piisa. Ehk on vaja ka turva-nõrkust Magentos või mõnes teises veebirakenduses, mis kasutajalt tulnud andmed kontrollimatult kasutusele võtab.

Seega hoopis olulisem oleks mõelda selle peale, et Magento 25. juunil väljastatud versioonid paikasid 75 turvanõrkust, nende hulgas hulga kriitilisi. Siinkohal on vahest paras hetk kasutada tuntud kaasamis-vormelit:

Hea kaupmees! Kas sinul on jaanipäevased turvapaigad paigaldamata? Kirjuta kommentaaridesse oma e-poe aadress ja võid võita auhindu, mille on välja pannud MageCart grupeeringud!

Lisaks: Magento 1.x ametlik tugi lõppeb 20.06.2020

Veelgi olulisem on mõelda selle peale, et Magento 1.x end-of-support saabub 20. juunil 2020 – pärast seda rohkem ametlikke turvapaiku ei väljastata.

Mis ilmselt pole paljudele kaupmeestele ka suuremaks mureks, sest pea iga kord, kui ma mõne poe aadressi https://www.magereport.com/ testi sisestan saan teada, et paigaldamata on kõik viimase paari aasta jooksul väljastatud paigad.

Kui ma selle väikse iroonilise märkuse tegemata jätaks… tabaks mind väga sügav masendus. Naljast paremini aitab mõistagi soovitus “Turvalisuse tagamiseks võta ühendust oma projektijuhiga.” – ja palun räägi temaga ennekõike oma e-poe tarkvara versiooni-uuendusest ja paikamisest.

Aga ikkagi, kas Zonel on värske PHP?

Otseloomulikult. Zone tugevus on meie hallatud serveriplatvorm ja sa võid olla kindel, et misiganes veebirakenduse alla jääv komponent – kernel, operatsioonisüsteem, MariaDB, Apache, PHP jne – on pideva jälgimise all. Teavitused turvanõrkustest ja paikadest jooksevad vastavale sise-chati-kanalile, nende võimalik mõju serveripargile selgitatakse välja ja sõltuvalt riskihinnangust tehakse uuendused lähima korralise hoolduse käigus või võetakse ette erakorraline hooldus.

Enamasti teeme hooldustöid öösel 01-06 vahel, aga on olnud ka juhtumeid, kus hommikul avaldatud teoreetilise ohu kohta oli lõunaks turvafoorumites levimas proof-of-concept ründekood ja kõik Virtuaalservereid majutavad serverid said restardi keset kibedat tööpäeva.

Ehk kui sinu Magento – või mistahes muu veebirakendus – on majutatud Zones, siis jagunevad vastutused niimoodi:

Meie uut ZoneOS platvormi kasutavates serverites on täna (13.09.2019) kasutusel:

PHP 5.6.40-pl6-zoneos (cgi-fcgi) (built: Aug 23 2019 12:31:16)
PHP 7.0.33-pl6-zoneos (cgi-fcgi) (built: Aug 23 2019 12:34:44)
PHP 7.1.32-pl1-zoneos (cgi-fcgi) (built: Sep  2 2019 08:57:28)
PHP 7.2.22-pl1-zoneos (cgi-fcgi) (built: Sep  2 2019 08:59:20)
PHP 7.3.9-pl1-zoneos (cgi-fcgi) (built: Sep  2 2019 08:59:57)
PHP 7.4.0RC1 (cgi-fcgi) (built: Sep  4 2019 08:59:55)

Vanemates serverites on valik selline:

PHP 4.4.9 (cgi-fcgi) (built: Sep 17 2013 03:15:34)
PHP 5.1.6 (cgi-fcgi) (built: Sep 23 2013 07:14:11)
PHP 5.2.17 (cgi-fcgi) (built: Jul 11 2016 10:55:56)
PHP 5.3.29 (cgi-fcgi) (built: Nov 10 2016 10:13:49)
PHP 5.4.45 (cgi-fcgi) (built: Nov 10 2016 10:32:41)
PHP 5.5.38 (cgi-fcgi) (built: Apr  1 2018 21:47:01)
PHP 5.6.40 (cgi-fcgi) (built: Feb  8 2019 10:00:13)
PHP 7.0.33 (cgi-fcgi) (built: Sep 13 2019 11:22:05)
PHP 7.1.32 (cgi-fcgi) (built: Sep  2 2019 22:22:28)
PHP 7.2.22 (cgi-fcgi) (built: Sep  3 2019 08:42:57)
PHP 7.3.9 (cgi-fcgi) (built: Sep  3 2019 09:33:50)

Vahet märkad? Uues ZoneOS’is ei ole enam PHP versioone, mis vanemad kui 5.6 ning seda väga proosalisel põhjusel – need on surnud. Schluss! Kaput!

Täpsemalt öeldes on tänaseks surnud ka PHP 5.6 ja 7.0 … ning PHP 7.1 turva-uuendusi antakse välja 1. detsembrini 2019 ehk napid 2.5 kuud:

Aga kas sinul on värske PHP?

Vot nüüd jõudsime olulise küsimuseni :.) Tõenäoliselt mitte.

Kuna iga uue PHP versiooniga kaob osa vanemaid funktsioone ja kohati muutub ka keele süntaks, ei saa me ise sinu veebi poolt kasutatavat versiooni vahetada ilma riskita, et veeb katki läheb.

Näiteks Magento 1.x puhul on olemas isegi PHP 7.2 tugi (kui paigaldada 2018.a lõpus välja tulnud paigad) – aga me näeme oma serverites hulgaliselt Magentosid, mis kasutavad PHP 5.6 või vanemat.

Kuna head turva-paanikat ei tohi raisku lasta, siis kordame veidi laiendatult soovitust:

Turvalisuse tagamiseks võta ühendust oma veebimeistri, -arendaja või projektijuhiga ning palu paigata veebirakendus ning viia see üle värskeimale võimalikule PHP versioonile.

Õigupoolest… saab versiooni vahetada ka ise – ja kui midagi katki läheb saab vana tagasi panna (sh juhul, kui tegemist oli tavapäraselt valikus mitte-oleva versiooniga). Iseteeninduses on juba aastaid punane nupp:

Ning kui sellel klikkida avaneb järgmine vaade:

Ouch! Ilmneb, et ka minu enda kontol oli blogiposti kirjutamise ajal vana PHP versiooni kasutavaid veebe, nii ammuseid kliente kui tööandjaid… ja sekka mõned Zone enda iidsed teenused, mis tänaseks kinni pandud.

Kuidas aga ilma katki-tegemise riskita testida, kas veeb uuema versiooniga toimivad? Sellest juba järgmisel nädalal, püsige kanalil 🙂

WAF ehk veebirakenduse tulemüür

Enamus veebilehtede vastu suunatud rünnakutest kasutab ära mõnda koodis olevat nõrkust, neist levinuimad on ebapiisav kasutajaõiguste või külastaja poolt sisestatud andmete kontroll.

Näiteks võiks kujutada ette olukorda, kus sisestades kommunaalteenuste ettevõtte näitude teatamise lehel aadressi lahtrisse ' OR 1=1;-- kuvatakse kõigi klientide aadressid ja eelmised näidud… sest täpselt selline näeb välja andmebaasi- ehk SQL-süst. Või siis tehakse WordPressi pihta päring, mis lisab õigusi mitte kontrolliva plugina seadistuste kaudu lehele külastajaid kuhugi edasi suunava Javascripti koodi.

Sellised koodi-vead on ka põhjus, miks tuleb kõike avalikus internetis kättesaadavat praktiliselt igapäevaselt uuendada: iga paigatud turvaprobleem  toob hiljemalt 24 tunni jooksul kaasa skannerite laine, mis otsivad haavatavaid veebe.

Lisaks aga on haavatavused, mis ei pruugi veel paika omada – sest arendaja pole probleemist teadlik, ei ole jõudnud seda paigata… või on paigatud, aga uuemas versioonis ja veebi ülemviimine sellele osutub töömahukaks.


Veebirakenduse tulemüür

Sellistel puhkudel võib abi olla veebirakenduse tulemüürist ehk WAFist (web application firewall), mis proovib kahtlased päringud tuvastada ja blokeerida. Zone Virtuaalserverites on kasutusel ModSecurity ning nüüd saab mugavalt aktiveerida ka OWASP ModSecurity Core Rule Set (CRS) tulemüürireegleid:

Valida saab logimise või blokeerimise ja logimise vahel. Kui on plaan ja võimekus logisid analüüsida, siis tasub loomulikult alustada logimisest ning vältida ausate kasutajate häirimist vale-positiivsete tuvastustega… Aga lihtsam on lülitada blokeerimine sisse ning funktsionaalsused läbi testida.

Igal juhul soovitame kontrollida, et sisse oleksid lülitatud ka reaalajas serverisse jõudvad logid.

Umbes 10 minutiga jõuab seadistus Virtuaalserverisse ja kui seejärel proovida näiteks WP otsingusse sisestada ' OR 1=1;-- peaks tulemuseks olema Error403:

Selle tulemusel tekkiavad /logs/apache.ssl.error.log faili järgmised read (loetavuse huvides natuke puhastatud):

[2019-08-21 09:17:19.367098] [client 217.146.xx.x] ModSecurity: Warning. detected SQLi using libinjection with fingerprint 's&1;c' [file "REQUEST-942-APPLICATION-ATTACK-SQLI.conf"] [line "64"] [id "942100"] [data "Matched Data: s&1;c found within ARGS:s: ' OR 1=1;--"] [severity "CRITICAL"] [uri "/"] [unique_id "XVzh78ean2NKORtLccJqvgAAAAM"]

[2019-08-21 09:17:19.367352] [client 217.146.xx.x] ModSecurity: Access denied with code 403 (phase 2). Inbound Anomaly Score Exceeded (Total Inbound Score: 5 - SQLI=5,XSS=0,RFI=0,LFI=0,RCE=0,PHPI=0,HTTP=0,SESS=0)

Logist on näha nii põhjus (SQLi ehk andmebaasisüst), reegli number (942100), selle trigerdanud andmed ja lisaks ka reeglit sisaldanud OWASP CRS faili nimi.

99,99% juhtudest on selline päring seotud turvanõrkuse otsimise või ärakasutamisega, aga vähemalt teoorias võib SQL-friikidele mõeldud poes olla müügil sellenimeline t-särk – samuti võiks tulemüür takistada selle blogipostituse salvestamist.

Lahenduseks on reeglite valikuline väljalülitamine. Selleks saab Virtuaalserveri halduses pea- või alamdomeeni seadetes lisada Apache direktiivide ploki, mille sisuks on loetelu reeglitest:

Vajadusel saab ühele reale sobitada ka rohkem reegleid (tühikuga eraldatuna) või numbrivahemiku (jutumärkides), hea mõte on lisada juurde #-märgiga algav kommentaari-rida ning ümbritseda blokk IfModule tingimusega:

<IfModule mod_security2.c>
  # Keelame särgiotsingut takistavad reeglid:
  SecRuleRemoveById 942100 942140 "942160-942170"
</IfModule>

Kuidas tuvastada vale-positiivseid?

Kasutaja kaebuse peale logides tuhnimine on vaevarikas töö – pealegi ei ole kuvatav veateade ilus ega informatiivne. Mina olen testimiseks kasutanud vealehte, mida kuvatakse päringu blokeerimisel ning mis saadab juhul, kui kasutaja brauseris on JavaScript olemas, teate e-postile ja/või Slacki kanalisse.

Keerulisemate rünnete puhul võib toimuda ka JavaScripti interpreteerimine, lisaks ei piira see lahendus teavituste hulka ehk seda saab kasutada siht-aadressi teavitustega ülekoormamiseks.

Vealehe koodi leiab https://github.com/zone-eu/waf-handler, seadistamis-juhised sealtsamast.

Tulemuseks sellised teavitused:

Kas WAF on hõbekuul, mis lahendab kõik veebirakenduste turvaprobleemid?

Kindlasti mitte – Clarified Security‘s veebirakenduste turvalist arendust õpetav, läbistustestimise ja punase tiimi ehk ründaja rollis veebe lammutav Elar Lang palus kindlasti lisada:

WAF on kasulik “teise liini kaitsemeetmena” ja raskendab ründe läbi viimist ning hoiab heal juhul eemal teadaolevatele turvaaukudele keskendnud skänneritega “skriptijõnglased” AGA:

WAF ei tee korda programmikoodis olevaid turvaauke, need vajavad ikkagi parandamist.

Olles olnud Elari punase veebitiimi tubli töö sihtmärk Locked Shields küberõppusel võin vaid nõustuda – tänu WAFile võib mõni teine veeb osutuda lihtsamini rünnatavaks, aga see ei muuda sind kuulikindlaks.

Pahavara: üks huvitav veebiproksi

Käes on Locked Shields küberõppuse nädal … aga kui sa ei ole LSil, siis on sul kindlasti aega tegeleda päris pahavaraga.

Puhastasin nädalavahetusel järjekordset veebi, kuhu oli sisse pääsetud nõrga admin-kasutaja salasõnaga. Kuna rünne oli toimunud hiljuti, oli mugav võtta ette varukoopia ning sellega võrreldes tuvastada muutunud failid. Ilmnes, et katalooge mööda oli laiali puistatud 35 erinevat tagaust või pahavaralise funktsionaalsusega faili.

Et küberkurjategijate tööd veidi laiemal tutvustada panin välja auhinnad… ja otsustasin koodi Facebookis huvilistele lammutada anda. See blogipost ongi kokku pandud osalt Zone FB-lehe postituse ja Vabakutseliste gruppi jagatu kommentaarides olevatest lahendustest – ning osalt Zone maja-sisestest tähelepanekutest.

Kui tahad enne lahenduse lugemist (või selle kõrvale) koodi vaadata, siis:

Niisiis saab kõik alguse sogastatud koodist:

Kristjan muutis (kasutatud) funktsioonide ja muutujate nimed arusaadavaks ja lisas kommentaarid – saamaks aru, mida koodijupp teeb ja kas seda on üldse ohutu oma arvutis või serveris käivitada:

Kuna muutujas $payLoad olev laeng on URL-kodeeringus mida pahavara-tuvastajatel lihtne läbi näha, on kasutataud täiendavat teisendustabelit selle sogastamiseks:

Olgu lisatud, et algses koodis näeb see eval ehk stringis olevat PHP koodi käivitav funktsioon välja alljärgnev, kurja eval() peitmiseks lihtsamate otsingute eest on funktsiooni nimi eraldi real ning lisaks üks kommentaar:

Kui asendada funktsion eval() näiteks print()’iga saame väljundiks laengu koodi – aga mulle meeldib rohkem tulemus faili kirjutada:

file_put_contents ( '_payload.php', decodePayload( $payLoad, $characterMap ) );

Ja saamegi asuda laengut uurima. Väga levinud tava on keelata ära veateadete väljastamine, aga siin on igaks juhuks võetud maha ka skripti täitmise ajapiirang (mis sisuliselt võimaldab seda kasutada ka teenustõkestusründeks andes kõigile lubatud PHP-protsessidele midagi aegavõtvat teha):

Edasi, otsime päringust maagilist küpsist – AGA Kristjani kommentaar on väikse näpukaga, nimelt väljutakse skriptist kui leitakse mõni küpsis mille väärtus EI VASTA soovitud nimele (küpsise nimi pole seejuures oluline).

Lisaks on koodis aga üks väga tore loogikaviga mille avastas Kurt Moser meie arendustiimist, vaata kas märkad:

Nojah, seda tsüklit ei täideta ja skriptist väljumist ei toimu, kui päringuga pole kaasas ühtki küpsist. Ehk sisuliselt on kogu piirang mõttetu – funktsionaalsele osale saab ligi igaüks.

Edasi läheb huvitavamaks:

Selle jupi juures tasub kindlasti “kastist välja” mõelda – php://input on tavapäraselt kasutusel POST päringute puhul, mitte miski ei keela selle kasutamist ka GET päringus. Sellisel kujul GETi kasutamise võlu seisneb aga selles, et veebiserverid päringu keha harilikult ei logi. Aga olgu siinkohal ka tõestus Elar Langilt:

<?php
var_dump(file_get_contents('php://input'));
?>

$ curl -X GET -s --data "töötab ju" http://localhost/z-server.php
string(11) "töötab ju"

$ curl -X POST -s --data "töötab ju" http://localhost/z-server.php
string(11) "töötab ju"

Järgmise jupi võtan ma aga oma koodiredaktorist, sest see oskab vigu tuvastada:

Jahaa – funktsioon split() kuulutati iganenuks juba PHP versioonis 5.3 ja alates 7.0 on see eemaldatud (tx veelkord Kurtile!). Ehk PHP uuemate versioonide puhul see kood ei tööta ja annab viga – võinoh… kuna vigade väljastamine on ülalpool ära keelatud, siis on tulemuseks Error 500, nagu ilmselt avastas ka ründaja:

94.130.35.51 - - [27/Mar/2019:10:02:21 +0200] "GET /wp-admin/css/colors/sunrise/lngzdhkh.php HTTP/1.1" 500 3527 "" "Mozilla/5.0 (Linux; Android 7.0; SAMSUNG SM-G935F Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/5.4 Chrome/51.0.2704.106 Mobile Safari/537.36" (F9F8DACB-0.001)

Pannes split() asemele explode() saab sellest murest kergesti üle.

decrypt() on sisuliselt XOR krüpteering ehk sama võtmega saab lahti ja kinni – nagu Karl-Sander Erss FBs kommentaaris demos:

> var_dump(decrypt(decrypt('asd'))==='asd');
bool(true)

Kuivõrd võtmeks on $_SERVER[‘HTTP_HOST’]  ja $_SERVER[‘REQUEST_URI’] on ka see kergesti ära-arvatav ehk nagu eelnevalt öeldud saab sellele koodi ära kasutada kesiganes tema olemasolu teab. Nii küpsis kui krüpto on täiesti mõttetud 🙂

Aga … mida see send_data1() siis teeb? Võtab saadud parameetrid (näidisandmed ülalolevas ekraanilaksus) ja teeb nendega HTTP POST või GET-päringu… ja tagastab tulemuse ehk tegu on veebiproksiga:

function send_data1( $data ) {
   $head = "";
   foreach ( $data["headers"] as $key => $value ) {
      $head .= $key . ": " . $value . "\r\n";
   }
   $params = array(
      'http' => array(
         'method'  => $data["method"],
         'header'  => $head,
         'content' => $data["body"],
         'timeout' => $data["timeout"],
      )
   );
   $ctx = stream_context_create( $params );
   $result = @file_get_contents( $data["url"], false, $ctx );
   if ( $http_response_header ) {
      if ( strpos( $http_response_header[0], "200" ) === false ) {
         $result = "HTTP_ERROR\t" . $http_response_header[0];
      }
   } else {
      $result = "CONNECTION_ERROR";
   }
   return $result;
}

Tuleb tunnistada, et file_get_contents() kasutamine koos kontekstiga HTTP-päringu parameetrite määramiseks pole minule kunagi varem ette jäänud, aga väga huvitav meetod. Lisaks: kuna paika pannakse ka timeout ning alguses on skripti täitmise ajapiirang maha võetud… siis võib see väääääga kaua aega võtta ehk olla kasutatav DOS ründeks.

Huvitavat jagub aga veelgi: nimelt EI MÄÄRATA ära HTTP protokolli versiooni ning vaikimisi on selleks HTTP/1.0 – ning minu oletuse kohaselt kasutatakse ülevõetud servereid järgmiste serverite ründamiseks. Hmm, vaatame korraks rünnatud saidi logi, filtreerides õnnestunud HTTP/1.0 päringuid:

Ja tõepoolest, need IPd pärinevad erinevatest pilve- või veebimajutusteenustest. Võib oletada, et ründajatel on oma veebiproksi, mis kasutab ülevõetud serverites olevaid veebiproksisid. See muudab võimatuks lihtsad lahendused nagu IP-põhised piirangud – mh kaitse WordPressi wp-login.php vastu suunatud paroolide jõurünnete tõrjumise “lubame vaid kolm katset samalt IPlt” meetodil.

Tänud kõigile kaasa mõtlemast, loodetavasti saime koos targemaks 🙂

Ära seda soovitust jälgi: täna on rahvusvaheline paroolivahetamispäev

Tõepoolest, väidetavasti on 1. veebruar “change your password day” ning seega äärmiselt sobilik hetk rääkida … tõsiselt halbadest infoturbe-nõuannetest.

Me oleme paroolidega seotust kirjutanud korduvalt: nt Hasso pikem lugu Veel kord paroolidest, siis täpselt seal välja toodud halva parooli-nõuande kasutamise tulemusest Nõrgast paroolist häkitud WordPressini 42 katsega ja loomulikult rahvusvahelise mõõtmega “Paha Panda” varastab postkaste.

Häid nõuandeid jagab aga NIST, mille “Special Publication 800-63B” võtab arvesse seniste parooli-reeglite tekitatud ebaturvalised käitumismustrid. Võid selle spikriks kõrvale võtta ja proovida vastata küsimusele:

Millised järgnevatest EI OLE NIST’i nõuded turvalisele paroolile?

(õiged vastused postituse lõpus)

  1. peab olema vähemalt 10 märki pikk
  2. peab olema vähemalt 8 märki pikk
  3. peab olema vähemalt 6 märki pikk, võib koosneda ainult numbritest
  4. peab sisaldama suur- ja väiketähte, numbrit, märki
  5. peab vähemalt X kuu järel vahetama
  6. ei tohi olla sama, mis viimased X parooli
  7. parooli või kasutajanime sisestamise lahtris ei tohi toimida copy ja paste
  8. ei tohi sisaldada nime, järjestikuseid märke, levinud salasõnu

Kasutasin seda nimekirja just turva-teemalisel esinemisel ja tuleb tunnistada, et paljud kuulajad noogutasid täpselt valede kohtade peal. Põhjuseks see, et IT-osakonnad jõustavad endiselt iganenud reegleid ning neid tirazeeritakse endiselt nii paberil kui digitaalses meedias.

Milline on siis hea ja milline halb reegel?

Hea parooli-nõue on selline, mis ei koorma liigselt kasutajat ning ei sunni teda ebaturvalisele optimeerimisele – inimene pole rumal, küll aga evolutsiooniliselt harjunud leidma kõige tõhustamat teed seatud eesmärgi saavutamiseni. Samas peaks see reegel aitama infosüsteemide arendajatel ja haldajatel meid kaitsta.

Näiteks – selleks, et parooli ei saaks N korda proovides ära arvata, peaks rakendus suutma sellist rünnet tuvastada ja takistada (konto ajutiselt lukustama), ent samas vältida teenustõkestusrünnet läbi kontode lukku ajamise.

Levinud tavad nagu sage vahetamine ja keerukusnõuded annavad aga soovitule vastupidise tulemuse: kasutaja lisab sõnale mõne numbri ja märgi ning siis suurendab sammhaaval numbrit või kasutab selleks aasta-arvu.

Kaks reeglit, mille puhul tasub viidata sellel blogipostile:

  • märgi-põhised keerukusnõuded
  • parooli kohustuslik vahetamine iga X ajavahemiku järel (aga: NIST nõuab vahetamist juhul kui  on kahtlus, et see on lekkinud)

3+2 lihtsat reeglit, mida järgida

  • salasõna asemel räägime sala-fraasist – veidi pikem isekomponeeritud liitsõna või sõnamäng/kalamburism on väga hea (jalgpallisupikulp, lumehangumine, vt insipratsiooni twitter.com/keitivilms)
  • ära kasuta sala-fraasis enda või kasutuskoha nime, levinud (sala)sõnu (Passw0rd!, kalamaja) ja järjestikuseid märgijadasid (q1w2e3r4)
  • oluliste teenuste jaoks (töökoha kasutajakonto, e-post, sotsmeedia) kasuta unikaalset sala-fraasi

Sellega on 98% tööd tehtud, kaks veidi suuremat pühendumist nõudvat soovitust on aga veel:

  • lülita olulistes teenustes (e-post, sotsmeedia) sisse kaheastmeline autentimine (2fa ehk two-factor authentication – nt SMSiga saadetav turvakood)
  • kasuta parooliseifi (LastPass, 1Password, KeePass, BitWarden) unikaalsete paroolide loomiseks ja haldamiseks, pea meeles ainult üks tugev ehk seifi sala-fraas

Viimase punkti juurde vihjeks, et KeePass on täiesti tasuta ja LastPassis saab erakonto teha tasuta (ja kui su tööandja peaks LastPassi ametlikult kasutusele võtma saad era- ja töökontole ligi ühe sisselogimisega – seejuures mõistagi nii, et tööandja EI SAA sinna ligi 🙂

Ja lõpuks…

See paroolivahetuspäev on Gizmodo klikimeelitustrikk aastast 2012, seeria viimane lugu kannab muideks pealkirja Don’t Change Your Password ning jõuab umbes samade soovitusteni ehk “ära vali lolli parooli”.

Kui su IT-osakond Gizmodot adekvaatseks allikaks ei pea, siis olgu öeldud, et maikuus on tulemas World Password Day ning TheRegister on selle kokku võtnud pealkirjaga It’s World (Terrible) Password (Advice) Day!


Õige vastus – NISTi nõuded EI OLE 1, 4, 5, 6, ja 7.

Nõrgast paroolist häkitud WordPressini 42 katsega

Sattusin puhastama ühte WordPressi, mille puhul oli ilmseks sissetungi-viisiks halduri-õigustes kasutaja parooli ära-arvamine.

Vaatamata sellele, et iga turva-nõuanne hakkab pihta tugeva parooliga ja enamus kasutajaid sedaküsimise peale ka esimese meetmena nimetavad… on nõrga parooli kasutamine endiselt reaalne probleem.

Esimene samm: kasutajanimede kogumine

Seekordne näide põhineb ühe reaalse ründe logifailidel, alustuseks otsitakse WordPressi kasutajanimesid lapates läbi autorite arhiivi:

163.172.xxx.xxx [10/Dec/2018:20:39:22] "GET /?author=1 HTTP/1.1" 301
163.172.xxx.xxx [10/Dec/2018:20:39:22] "GET /?author=2 HTTP/1.1" 301
163.172.xxx.xxx [10/Dec/2018:20:39:22] "GET /?author=3 HTTP/1.1" 404

Kood 301 on edasisuunamine: kui proovida minna lehele https://blog.zone.ee/?author=16, siis on selleks https://blog.zone.ee/author/petskratt/ … ja minu kasutajanimi petskratt on selles kenasti näha.

Teine samm: parooli mõistatamine:

Kui kasutajanimi teada, võib hakata proovima sisselogimist:

163.172.xxx.xxx [10/Dec/2018:20:39:25 +0200] "POST /wp-login.php HTTP/1.1" 200 

Selliseid ridu on logis 41 ning kõigi nende puhul on WordPress väljastanud teate, et parool ja/või kasutajanimi ei klapi.

Ma olen selliseid katseid kogunud ja tüüpiliselt on proovitavad mustrid kasutaja petskratt ja veebilehe zone puhul sellised:

petskratt2017
petskratt2018
P@ssw0rd
petskratt1234
petskratt12345
petskratt@123456
12345678
petskratt@zone
zone2018

Siia sobib kenasti Hasso postitus Veel kord paroolidest ehk kuidas aegunud parooli-nõuded on õpetanud kasutajad justnimelt selliseid lihtsalt ära-arvatavaid paroole kasutama.

Ja niimoodi nad siis huupi lappavad, kuni mõne veebi puhul mõne kasutajaga näkkab. Sedapuhku on juba  42. rida on veidi erinev:

163.172.xxx.xxx [10/Dec/2018:20:39:54 +0200] "POST /wp-login.php HTTP/1.1" 302

302 on jällegi edasi-suunamine ning selle sihiks on /wp-admin … Rohkem IP-aadress 163.172.xxx.xxx logis ei esine, sest töö sai tehtud. 32 sekundiga.

Mõni päev hiljem:

103.76.xxx.xxx [12/Dec/2018:06:06:07 +0200] "POST /wp-login.php HTTP/1.1" 302

Kui 163.172.xxx.xxx oli pärit Prantsusmaa internetiteenusepakkuja võrgust, siis 103.76.xxx.xxx külastab meid Indiast, Tamil Nadu osariigist. Kontrollib logini toimimist ja rohkem teda näha pole.

Kolmas samm: parooli ärakasutamine

Ilmselt läheb toimiv kasutajanimi+parool müüki ning uus omanik asub selle abil saiti lammutama:

46.148.xxx.xxx [17/Dec/2018:22:29:54 +0200] "POST /wp-login.php HTTP/1.1" 302
46.148.xxx.xxx [17/Dec/2018:22:29:54 +0200] "GET /wp-admin/ HTTP/1.1" 200
46.148.xxx.xxx [17/Dec/2018:22:39:29 +0200] "POST /wp-admin/update.php?action=upload-theme
46.148.xxx.xxx [17/Dec/2018:22:39:32 +0200] "GET /wp-content/themes/[...]/db.php?u
46.148.xxx.xxx [17/Dec/2018:23:00:32 +0200] "POST /wp-content/themes/[...]/db.php?u

Ehk siis login, oma teema üleslaadimine, selles oleva db.php tagaukse toimivuse kontroll ja ärakasutamine. Kui huvi, siis see näeb välja selline:

IP 46.148.xxx.xxx viitab Kiievile, aga kuulub sealsele veebimajutusteenusele ja kuigi tegemist võib olla ka VPNi või veebi-proksi kasutajaga viitavad mõned logiread skriptitud tegevusele, näiteks selle üleslaadimis-käsu puhul on logis referrer-väljal http://$st2/wp-admin/theme-install.php?browse=featured.

Mida sellise jama vältimiseks teha?

  • ära kunagi kasuta lihtsat parooli – ei enda kontol ega kolleegile / kliendile konto tegemisel (isegi, kui on plaanis see hiljem ära muuta – tõenäoliselt ei muuda seda keegi)
  • vaata üle veebirakenduse admin’i / halduri õigustes kasutajate nimekiri ja kustuta lahkunud töötajad / endised arendajad jms kasutajad, keda enam vaja ei ole (või pane nende rollik subscriber / lugeja)

Lisalugu: aga kelle parool lekkis?

Kuna selles veebis oli mitu haldurit, siis pakkus mulle suurt huvi konkreetse kasutaja tuvastamine. See ei pruugi alati võimalik olla, aga tasub vaatada wp_user_meta tabelis olevaid session_token kirjeid. Sedapuhku oli kasutaja 2 kohta kirjas järgnev:

a:2:{s:64:"bff45f4a[...]";a:4:{s:10:"expiration";i:1547071064;s:2:"ip";s:11:"77.72.xxx.xxx";s:2:"ua";s:124:"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3198.0 Safari/537.36 OPR/49.0.2711.0";s:5:"login";i:1545861464;}s:64:"a3c7456[...]";a:4:{s:10:"expiration";i:1548253873;s:2:"ip";s:11:"91.90.xxx.xxx";s:2:"ua";s:124:"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3198.0 Safari/537.36 OPR/49.0.2711.0";s:5:"login";i:1547044273;}}

Ülalpool näha oleva 46.148.xxx.xxx loginit ei ole enam näha (sest ta ei ole välja loginud? liiga ammu?), küll aga on näha 2 teist IPd, esimese asukohaks annab MaxMind Stoke-on-Trent’i ja teise omaks Odessa. Huvilised võivad tuvastada ka sisselogimise aja… ning logist on kenasti näha nende askeldamised 🙂