kolmapäev, 28. oktoober 2015

Miks STARTTLS on paha?

STARTTLS on meetod kliendi ja serveri vahelise turvamata ehk vabatekstilise ühenduse üleviimiseks krüpteeritud ühendusele. Klientrakendus saadab sellisel juhul serverile käsu STARTTLS (või STLS või kuidas iganes käsu nimetus juhtub olema), server aktsepteerib seda, seejärel toimub tavapärane võtmevahetus ning edasi liiguvad kõik andmed juba krüpteeritud kujul. Kõige rohkem kasutatakse seda e-posti protokollides (SMTP, IMAP, POP3), kuid ka mujal (XMPP, LDAP jne.). Tundub nagu päris hea idee või mis? Kõik me ju armastame krüptot?

Noh, ei ole hea idee. Tegu on järjekordse sea-selga-sadul lahendusega. Kõigepealt oli meil siga ehk mingi hästi toimiv vabateksti protokoll, seejärel avastasime, et oleks vaja kuidagi kasutada ka krüpteeringut ehk sadulat, paneme nüüd kaks asja kokku ja ongi hobune. Oleks nagu seesama vana vabateksti protokoll, kõigest pisikese laienduse lisamise abil saame edaspidi andmeid edastada krüpteeritult, segamata seejuures vanade rakenduste tööd, mis krüpteeringut kasutada ei mõista.

Mida siis STARTTLS võrreldes täielikult krüpteeritud ühendusega meile praktikas annab? Ükski normaalne ("normaalne" ei ole kahjuks sama, mis "kõik") server ei luba tänapäeval kasutajal edastada paroole üle turvamata ühenduse. Selline autentimiskatse blokeeritakse mõistlikult seadistatud serveri poolt üsna kiirelt. Mida aga saab teha autentimata serveris? Tuleb välja, et ei saagi suurt midagi (välja arvatud muidugi MTA serverid, millest tuleb juttu allpool). Näiteks nii SMTP kui ka IMAP puhul on autentimata olekus lubatud vaadata vaid serveri poolt toetatud laiendusi (SMTP puhul näitab neid EHLO käsk, IMAP puhul CAPABILITY), samas IMAP serverid näitavad autentimata olekus tihti vaid neid laiendusi, mida on vaja otseselt autentimiseks, seega ei ole sellest infost suurt kasu.

Võrdleme näiteks Apple iCloud IMAP serveri CAPABILITY väljundit:

Autentimata olekus:
* NK11P00MM-ISCREAM001 14F39 XAPPLEPUSHSERVICE IMAP4 IMAP4REV1 SASL-IR AUTH=ATOKEN AUTH=PLAIN
Autenditud olekus:
* XAPPLEPUSHSERVICE IMAP4 IMAP4REV1 ACL QUOTA LITERAL+ NAMESPACE UIDPLUS CHILDREN BINARY UNSELECT SORT CATENATE URLAUTH LANGUAGE ESEARCH ESORT THREAD=ORDEREDSUBJECT THREAD=REFERENCES CONDSTORE ENABLE CONTEXT=SEARCH CONTEXT=SORT WITHIN SASL-IR SEARCHRES XSENDER X-NETSCAPE XSERVERINFO X-SUN-SORT ANNOTATE-EXPERIMENT-1 X-UNAUTHENTICATE X-SUN-IMAP X-ANNOTATEMORE XUM1 ID IDLE
Ühesõnaga, juhul kui meil on võimalik valida algusest peale krüpteeritud ühenduse (IMAP puhul siis IMAPS pordil 993) ja algselt vabatekstilise, kuid STARTTLS abil krüpteeritud olekusse üleminekuga ühenduse vahel (IMAP puhul siis pordil 143), siis STARTTLS ei anna meile praktikas mitte mingisugust eelist, küll aga teeb lahenduse keerulisemaks. Mis viibki meid järgmise punkti juurde.

STARTTLS implementeerimine tarkvaras

Ilmneb, et vabatekstiliselt ühenduselt krüpteeritud ühendusele üleminek ei olegi nii hästi programmeerimiskeelte ja teekide poolt toetatud kui võiks arvata. Halval juhul pole seda võimalust üldse (valida on kas vabateksti või krüpteeritud ühenduse vahel, kuid mitte hilisema muutmise vahel), veidi paremal juhul on see küll võimalik, aga implementatsioon võib olla bugine (sest see on keeruline ning harva vaja minev featuur). Eriti halval võimalusel, nagu veel suhteliselt hiljuti oli Chrome brauseri laienduste jaoks mõeldud chrome.socket API puhul, on ainult vabateksti võimalus ning krüpteeritud ühenduste loomise võimalus puudub sootuks. Kui programmeerimiskeele teegid üleminekut ei võimalda, on alternatiivselt võimalik SSL/TLS kiht ise implementeerida (lõppude lõpuks käib kõik ju üle sellesama tcp ühenduse, ainult vorm muutub), aga selle tulemuseks on algselt ühe probleemi morfeerumine umbes kuueks tuhandeks veel suuremaks probleemiks ja seega on see kõige viimane tee üldse, mida mööda minna.

Turvaprobleemid

Kui algusest peale krüpteeritud ühenduse puhul on kõik selge, me kas kasutame krüpteeringut või me lõpetame töö, siis üleminekuga ühenduse korral pole kõik sugugi nii ühene. Vaatame näiteks niiöelda tavalist STARTTLS kasutusjuhtu:

Joonis 1. Klient läheb serveriga suheldes üle krüpteeritud ühendusele


Kõik on lihtne ja selge. Klient näeb võimalust STARTTLS kasutamiseks ning läheb üle krüpteeritud ühendusele. Vaatame nüüd veidi keerulisemat juhtu:

Joonis 2. Kliendi ja serveri vahel olev MITM peidab STARTTLS võimaluse ning klient jääb kasutama vabatekstiliselt ühendust

Siin on asjad juba vähem selged. Seekord ei ühendu klient mitte autentse serveriga, vaid MITM ründaja serveriga (selline olukord võib igapäevaelus tekkida näiteks siis, kui ollakse parasjagu ühendunud mõnda "tasuta" wifi võrku, mille ruuteris olev DNS server saadab kõik ühendused ründaja serverisse). MITM server muutub siinkohal passiivseks proksiks, kuid kõigepealt avab ta tegelikku serverisse turvatud ühenduse, kliendile esitab aga andmed nagu server ei toetakski üldse krüpteeringut. Klient läheb seepeale turvamata ühendusega edasi (ühtegi reeglit pole ju rikutud), server aga omakorda arvab, et ühendus on krüpteeritud ja kõik korras.

Protokollilised probleemid

Ütleme, et meil on MTA server, mis soovib edastada kirju meie jaoks tundmatusse MX serverisse A. Avame vabatekstilise ühenduse serverisse A pordil 25, saadame oma EHLO ja vastu saame info, et server toetab STARTTLS laiendust. Väga tore, algatame ülemineku. Nüüd aga tekib tõrge, serveri nimi on A, kuid sertifikaat on nimele B või on see aegunud või on see ise-allkirjastatud, ühesõnaga – sert on vigane. Mis teha?

Juhul kui me eeldaksime, et ühendus peab olema kindlasti krüpteeritud, siis tekiks siinkohal veaolukord ja kiri jääks edastamata. Kuid STARTTLS puhul ei ole asjad nii lihtsad. Liiklus pordil 25 ei ole mõeldud olema krüpteeritud, seega vabatekstiliste andmete edastamine oleks nagu OK. Vigane sert võib tähendada MITM'i ja sellise ühenduse kaudu andmete edastamine nagu ei oleks OK, vastasel korral ei oleks ju krüptost mitte mingit kasu.

RFC2595, mis käsitleb STARTTLS implementeerimist, on lahendanud asja muidugi geniaalselt:
The decision about whether acceptable authentication or privacy was achieved is made locally, is implementation-dependent, and is beyond the scope of this document.
Praktika

Teoorias tundub asi päris kole, aga kuidas on praktikas? Praktikas on veel koledam. Lisaks võimalikele küberkollidele kasutavad sarnaseid krüpto mahajooksmise võimalusi ka täiesti legaalsed ettevõtmised, näiteks suured mobiilifirmad. Tavaliselt tehakse seda nii, et filtreeritakse ridu kujul "250-STARTTLS". Selline rida jäetakse üldse välja või asendatakse see näiteks reaga "250-XXXXXXXA". Tulemuseks on see, et klient ei näe serveri pakutud võimalust krüptole üleminekuks ja jääb vabatekstilisele ühendusele. Eelkõige on see probleem pordil 25 olevate MTA serveritega, mitte niivõrd 587 MSA serveritega. Seega ei oota server ka autentimist ning muudatus ei tule kunagi välja. Võrguoperaator aga saab nii vabalt jälgida oma võrgus toimuvat meililiiklust.

Lisaks ISPidele tegelevad sama asjaga kohati ka terved riigid. Näiteks hiljutise Google'i e-posti turvalisuse teemalise uuringu järgi blokeeritakse Tuneesiast Gmaili serveritesse tehtavatel ühendustel tervelt 94% juhtudest STARTTLS kasutamine.

Mis on kogu jutu mõte?

Kõik algas sellest, et aastal 1997 registreeriti IANA port 465 protokollile SMTPS ehk krüpteeritud SMTP. Juba aasta pärast võeti see aga tagasi, sest vahepeal oli välja mõeldud STARTTLS, mis tollal tundus kõikide murede lahendaja – selmet registreerida kaks porti, üks vabateksti ja üks krüpteeritud ühenduse jaoks, võis registreerida vaid ühe ja teha mõlemat. Seega aastast 1998 ei ole enam sellist asja nagu SMTPS pordil 465. Sellel pordil asub täna hoopis protokoll nimega URL Rendesvous Directory for SSM. Elu teeb siiski omad korrektiivid ja suur osa SMTP serveritest, sh. ka oluliseimad nagu Gmail, toetavad endiselt (ehk siis juba 17 aastat peale ametliku toe lõppemist) krüpteeritud ühendust pordil 465. See on üks suuri vastuolusid reaalsuse ja paberil kirjas oleva vahel ja ilmselgelt on seal ka põhjus – nimelt STARTTLS on halb, kasutada tuleks krüpteerimist juba baidist nr 1. ning mitte oodata kuni mõni MITM meie ühenduse ära rikub.



Lisalugemist

kolmapäev, 21. oktoober 2015

Kahefaktorilisest autentimisest

Iga vähegi küberhügieenist hooliv inimene kasutab võimaluse korral alati kahefaktorilist autentimist. Lühidalt tähendab see seda, et kuhugi sisse logiv kasutaja esitab lisaks oma tavalisele paroolile (ehk esimene faktor) ka mingi muu kinnituse (teise faktori), tavaliselt siis sellise, mis eeldab ligipääsu mingile kindlale füüsilisele esemele. Esimene laiem kokkupuude kahefaktorilise autentimisega toimus Eestis juba üle 15 aasta tagasi, mil ilmusid internetipangad koos paroolikaartidega, seega siinmaal on see juba tuttav nähtus. Paroolikaart (vahet polegi, et kas ühe- või korduvkasutavate paroolidega) oligi sellisel juhul kasutaja tavaparooli kõrval selleks teiseks faktoriks.

Siinkohal teeksingi väikese ülevaate võimalikest teise faktori lahendustest ning seda keskendudes mudelile kus tavatarbija soovib brauseri kaudu sisse logida mõnele veebilehele, näiteks internetipanka või sotsiaalvõrgustiku lehele vms.

Korduvakasutatav paroolikaart

Pangad on tänuväärselt olnud kohaliku küberhügieeni edendamise veduriks ja nii taibati juba kohe alguses, kui internetipank oli veel alles väheste tehnofriikide jaoks, võtta kasutusele paroolikaart. Korduvakasutatav paroolikaart on tänaseks ilmselgelt kõikidest võimalustest kõige ebaturvalisem, kuid omal ajal oli see muidugi suur samm edasi. Korduvkasutatavat kaarti on lihtne kopeerida ja vastavad rünnakud tekkisid ka üsna pea, kus inimestele hakkas laekuma "Гanzapangast" kalastuskirju teemal, et pank on kasutaja paroolid ära unustanud ja nüüd tuleks need saadetud vormil uuesti sisestada. Esimesed Гanzapankurid kukkusid kiirelt vahele, aga pretsedent oli sellega loodud.

Ühekordsete paroolidega kaart

Ühekordsete paroolidega kaart on juba kraad kangem, aga sellevõrra ebamugavam. Kuna neid kaarte tuli tihti uuendada (mis on juba iseenesest tüütu), siis oli pabermaterjal võrreldes korduvkasutavate kaartide plastikust kiirem ka kuluma. Kuigi endiselt kopeeritav, on ajaline faktor siinkohal oluline, sest koodikaart aegub üsna pea ja seega kaotavad kopeeritud paroolid millalgi kehtivuse. Lisaks, kui tegu on kasutaja vabal valikul kasutatavate koodidega ("vali kood ja kriipsuta läbi" lähenemine), siis ei tea ründaja, et millised koodid on juba kasutatud ja seega on kergem sisestada valesid paroole ning end automaatse lukustussüsteemi taha jätta.

PIN-kalkulaator

Sajandi alguse poole hakati välja andma ka PIN-kalkulaatoreid, mis on elektrooniline seadeldis ühekordsete koodide genereerimiseks. Tavaliselt töötab selline seade nii, et sisestad seadme korpusel oleva klahvistiku kaudu 5-kohalise numbrilise PIN koodi ja aparaat näitab selle peale oma ekraanil 8-kohalist ajutist PIN koodi, mida saabki pangale sisselogimiseks esitada. Mis alusel see ajutine kood genereeritakse, ma täpselt ei tea. Seade on praktikas turvaline, kuna seda ei saa kopeerida. Kuigi suhteliselt populaarne, siis laiadesse massidesse see siiski kunagi ei jõudnud, seadeldis ei ole tasuta ja see töötab ainult selle väljastanud pangaga. See on ka natuke kohmakas, nagu oleks vaja veel üht telefoni kaasas kanda.

ID-kaart

Järgmiseks tekkis kõigile tuttav ID-kaart. Selle puhul on autentimise aluseks kliendisertifikaat. Teadaolev, aga vähe kasutatud SSL/TLS võimalus on nõuda kehtivat x509 sertifikaati mõlemalt osapoolelt. Kõige tavalisem kasutusjuht ehk see, kui avad brauseris suvalise https:// algusega veebilehe aadressi, näeb ette, et kehtiva serdi esitab ainult server. Protokoll võimaldab küsida serti ka kasutajalt ja seda ID-kaardiga sisse logimine tähendabki. Server nõuab kliendi sertifikaati, brauser üritab seda laadida ID-kaardilt ja küsib ID-kaardi lahtilukustamiseks PIN koodi. Seejärel kontrollib server, et esitatud sert oleks allkirjastatud õige CA (ehk SK) poolt ja et seda poleks tühistusnimekirjades. Kui parool ka veel klapib (reeglina ID-kaardi ja Mobiil-ID puhul eraldi parooli siiski ei küsita), siis ongi kasutaja autenditud. Tänastel kaartidel on 2048 bitised RSA võtmed, mis on praktikas täiesti turvaline ja võltsimiskindel.

Mobiil-ID

Hilisem ID-kaardi lisa ehk Mobiil-ID töötab veidi teisiti, kuna seal otseühendust mobiilis asuva SIM-kaardi ja serveri vahel tekkida ei saa. Selle asemel genereerib server allkirjastamiseks mingi ühekordse väärtuse, saadab selle Mobiil-ID süsteemi ja saab sealt vastu autentimissessiooni 4-kohalise identifikaatori (ma ei tea kuidas see genereeritakse, tõenäoliselt tuletatakse allkirjastatavatest andmetest) ning kuvab selle kasutajale. Mobiil-ID süsteem saadab päringu koos sessiooni identifikaatorigaa SMS teel kasutaja telefoni, kasutaja allkirjastab päringu ja saadab samuti SMS teel allkirjaga vastuse tagasi. Kui vastus jõuab autentivasse serverisse, siis kontrollib see, et kas allkiri vastab kasutaja sertifikaadile ja sobivuse korral ongi kasutaja autenditud. SIM kaardil peaks samuti olema 2048 bitised RSA võtmed ja seega on Mobiil-ID sama turvaline kui ID-kaartki, kuigi turvalisust vähendab (vähemalt teoorias) musta kastina kasutaja ja autentiva serveri vahelisi päringuid vahendav Mobiil-ID süsteem.

TOTP/2FA (Google Authenticator)

Mujal maailmas nn. smartcard'e, mida nii ID-kaart kui ka Mobiil-ID oma olemuselt on, tavakasutajatele eriti pakutud pole. Kõige levinum teise faktori lahendus on TOTP põhine 2FA ühekordsete koodide generaator, mis reeglina väljendub kasutaja mobiilis oleva rakendusena. Rakendus kuvab hetkel kehtivaid koode ning arvutab need iga 30 sekundi järel uuesti ringi. TOTP koodid pole muud kui HMAC-SHA1 räsid, kus nn. seemneväärtus ehk seed on HMAC salajaseks komponendiks ning hetke aeg (teisendatuna 30 sekundi täpsuseks ehk siis floor(UNIX_TIMESTAMP/30)) on sisendiks, millest tehakse HMAC räsi. Saadud 20 baidine räsi teisendatakse kindla algoritmi alusel 6-kohaliseks numbriks.

Server teab samuti salajast seemneväärtust ning arvutab ka omalt poolt kontrolliks sama räsi. Kuna eri seadmete ajad võivad veidi erineda, siis arvutab server igaks juhuks mitu võimalikku väärtust, mõned minutid ajas ette ja taha. Kui üks leitud väärtustest klapib kasutaja pakutuga, siis ongi kasutaja autenditud.

Ajapõhised koodid ei ole siinkohal ainsad võimalikud, toetatud on ka muud OTP paroolid (näiteks HOTP, millel TOTP põhineb), kuid TOTP peaks olema enam levinud. Sellist autentimist toetavad muu hulgas Facebook, Google (s.h Gmail, Youtube jmt.), Dropbox, Outlook.com, tinglikult ka Skype ning paljud muud teenused.

Google Autheticator rakendus TOTP koodide genereerimiseks.
Tähelepanelik vaatleja saab kindlasti aru, et ekraanitõmmist on modifitseeritud ja koodid ei ole ehtsad.
FIDO/U2F

Uusimaks laiemale üldsusele mõeldud teiseks faktoriks on FIDO/U2F protokolli järgivad seadmed, mis peamiselt on USB porti ühenduvad võtmekujulised vidinad. Autentimisprotseduur näeb välja nii, et kui veebisait küsib võtit, siis sisestab kasutaja võtmeseadme arvuti USB porti (see võib seal juba eelnevalt olla, ei pea iga kord uuesti sisestama ja välja võtma) ning vajutab seadmel olevale nupule. Rohkem midagi teha pole vaja, veebileht tuvastab võtme ja suhtleb sellega taustal edasi ja õnnestumise korral logitakse kasutaja automaatselt sisse, mis teeb selle tõenäoliselt kõige mugavamaks lahenduseks üldse.

Yubikey poolt toodetud Githubi brändinguga U2F võtmed, mida müüdi kampaania korras hinnaga $5 tükk

Protokoll ise on veidi laiem, aga vaatlen siin vaid kõige odavamaid (ja eeldatavasti enam levikut saavat) lahendust. Hetkel toetab selliseid võtmeid vaid Chrome, kuid Firefox on protokolli toe samuti töösse võtnud ning on ka alust loota, et Microsoft lisab U2F toe oma Edge brauserisse. U2F võtmed teeb eriliseks see, et need on täiesti anonüümsed, sama võtit saab kasutada mitme eri teenusepakkuja juures ning teenusepakkuja ei saa omakorda jälgida, et kus seda võtit veel on kasutatud. Selline tulemus saavutatakse nii, et iga teenusepakkuja jaoks genereerib seade uue ja unikaalse avaliku ja salajase võtme paari (kasutades elliptilist kurvi secp256r1). Samas odavatel USB võtmetel endal sisemälu puudub ja seega seda genereeritud võtit nagu kuhugi salvestada pole. Protokoll lahendab probleemi nii, et seade krüpteerib salajase võtme ning edastab siis nii avaliku kui ka krüpteeritud salajase võtme seadme registreerimisel teenusepakkujale. Seade ise peab sellisel juhul teadma ainult krüpteerimiseks kasutatud salajast parooli.

Dropbox teenuses U2F võtme seadistamine
Pildil on Dropboxi vaade U2F võtme seadistamiseks. Kui nüüd sisestada arvutisse U2F toega USB võti ja vajutada võtmel olevale nupule, genereeriks seade võtmepaari ja saadaks need brauserile. See ongi lühidalt kogu registreerimisprotseduur.

Kui aga tahame registreeritud võtmega autentida, siis saadab server brauseri kaudu USB võtmesse registreerimisel saadud kasutaja salajase võtme ja allkirjastamiseks minevad andmed. Seade dekrüpteerib salajase võtme endale teada oleva parooliga, kasutab seejärel saadud salajast võtit andmete allkirjastamiseks ja saadab allkirjastatud andmed brauserile tagasi. Edasi kontrollib server USB seadmest saadud allkirjastatud andmeid registreerimisel saadud avaliku võtme vastu ja kui need klapivad, siis ongi kasutaja autenditud.

Google'sse sisselogimine U2F võtmega peale kasutajanime ja parooli edukat sisestamist

U2F võtmete suurim pluss on brauseritootjate tugi. Protokoll on välja töötatud koostöös Googlega, selle tugi on Chrome brauserisse sisse ehitatud (ei vaja eraldi pluginat nagu näiteks ID-kaart) ja teistesse saab tulevikus. Seega tegu on brauseritootjate jaoks "esimese kategooria kodanikuga" ja pole vaja karta, et brauseri või operatsioonisüsteemi uuendamise korral kõik jälle katki läheks. U2F põhist sisselogimist toetavad juba kõik Google teenused (Gmail, Youtube, Analytics, Adsense, Adwords jne.), Dropbox, Box, Github jpt. Mitmed teenused (näiteks LastPass) on äraootaval seisukohal, et kuni ka teised brauseri peale Chrome U2F toe endale lisavad, seega võib eeldada, et tulevikus vastavate teenuste arv kasvab jõudsalt. Eriti arvestades, et selle tuge on väga lihtne lisada, sest vajalik API on brauserisse sisse ehitatud ja selle kasutamiseks pole vaja midagi täiendavat installida.

U2F vs ID-kaart

Kui võrrelda U2F seadmeid ID-kaardiga, siis on U2F seadme eelis muu hulgas hinnas (teostatavad toimingud on palju lihtsamad ja RSA asemel kasutatakse vähem nõudlikku elliptiliste kurvide krüptot, siis selle võrra võib seade olla väiksema jõudlusega). U2F ei vaja ka keskset autentsuse tagajat, nagu ID-kaardi puhul on selleks Sertifiseerimiskeskus (see on samas nii pluss kui ka miinus, kuna keskse autoriteedi puudumisel ei saa neid võtmeid keegi kehtetuks tunnistada). Konkreetse U2F võtme autentsuse tagab kasutaja ise, kui võtme süsteemi lisab. Mõlemal juhul on põhisaladus (ID-kaardi puhul salajane võti ning U2F seadme puhul siis võtmete krüpteerimise parool) seadme kiibil ning ei välju sealt kunagi. U2F suurimaks plussiks on aga kindlasti suurte teenusepakkujate nagu Google poolne tugi, mida ID-kaart endale kunagi ei saa.

Ühesõnaga, keskse autoriteedi puudumise tõttu ei saa U2F võtit kasutada otseselt ID-kaardi kui elektroonilise dokumendi asemel, küll aga saab seda kasutada kindla konto autentimiseks, kus teenusepakkuja juba teab, et kes parasjagu sisse logib, kuid soovib täiendavat kinnitust. U2F võti pakub sama kategooria turvalisust, aga veidi väiksema hinna eest (ID-kaardi hind algab 25€, Yubikey U2F võtme "tavahind" on $18), suhteliselt anonüümselt (iga teenuse jaoks genereerib seade uue võtmepaari ning võtmeid ei taaskasutata eri teenuste vahel), ja garanteeritud töökindlusega (erinevalt siis ID-kaardi lahendustest, kus asjad "vahel töötavad, vahel mitte"). U2F seadme puhul pole vaja ka eraldi kaardilugejat, kuna seade ise käib USB pessa. U2F tuge on teenusepakkujatel kergem lisada, see ei vaja mingeid müstilisi spetsifikatsioone ja pluginaid. Gmaili kontole ei saa tõenäoliselt kunagi ID-kaardiga sisse logida, aga U2F võtmega saab seda juba täna.

---- järgneb täiendus algsele loole ----

SMS-2FA

Mul endal läks küll täiesti meelest ära, aga õnneks juhtis Facebookis Peeter Marvet tähelepanu veel ühele laialt levinud teisele faktorile ehk siis SMS põhisele koodide saatmisele. Sellisel juhul saadab teenus SMS teel kasutaja telefoni ühekordse koodi, mida saab hetkel pooleli oleva autentimise lõpetamiseks kasutada. Suureks boonuseks on see, et nii saab kohe teada, kui keegi on suutnud kasutaja parooli ära varastada ja proovib seda kuskil kasutada (SMS saadetakse reeglina pärast parooli edukat sisestamist, seega parool peab ründajal juba teada olema). Miinuseks aga kerge privaatsuse riive, kuna telefoninumbrit on võimalik kasutada profileerimiseks ning erinevate teenuste kontode kokkuühendamiseks ja tegevuse jälgimiseks (kasutajanimi võib ju teenusest teenusesse muutuda, aga mobiilinumber jääb samaks). Samas kui teenus juba niikuinii mingil muul põhjusel kasutaja telefonimbrit vajab ja täiendavat privaatsuse riivet ei teki, siis muidugi on tegu üsna hea lahendusega kuna SIM on praktiliselt kopeerimiskindel ning samuti ei pea telefon olema "nutikas," kõlbab iga vana Nokia või Ericsson. SMS-põhine autentimine on "tavainimesele" reeglina kõige arusaadavam, kuna see ei nõua lisatarkvara ega seadmeid.

Miinuspoolelt veel probleemid mobiili leviga (näiteks lõpetab piirkonna ainus mast töö või siis on hoopis ülekoormus) ja roaming võimaluse olemasoluga välismaal (mõlemad kehtivad ka Mobiil-ID kohta). Samuti võivad SMS transpordi torud olla "umbes" kuna tavaliselt on saatjaks mõni USA teenus ja sõnum peab läbima pika maa, enne kui mõnda Eesti telefoni potsatab.

Näiteks hiljuti külastasin üht rahvusvaheliste majandussanktsioonidega piiratud territooriumi ning seal rahvusvaheline roaming ei töötanud, telefoni tuli hoopis panna kohalik SIM kaart, mis muutis ühe hetkega kasutuks nii Mobiil-ID kui ka SMS-2FA.



Kasutatud lühendid
  • SSL/TLS – SSL (Secure Sockets Layer) on vanem ja TLS (Transport Layer Security) uuem krüptograafiline protokoll võrgusuhtluse turvamiseks. Wikipedia
  • x509 – Rahvusvahelise Telekommunikatsiooni Liidu (ITU) standard avaliku võtme infrastruktuurile digisertifikaatide jaoks. Wikipedia
  • CA – (Certification authority) on organisatsioon, mis annab välja ja kinnitab digisertifikaate. Wikipedia
  • SK – AS Sertifitseerimiskeskus, meie enda kohalik CA
  • RSA – (Rivest-Shamir-Adleman) on avaliku võtmesüsteemiga krüpteerimise algoritm andmeedastuses. Wikipedia
  • 2FA – on kahefaktoriline autentimine. Wikipedia
  • OTP – (One-time password) ühekordseks kasutamiseks mõeldud parool, mis sõltuvalt implementatsioonist kaotab kehtivuse parooli kasutamisel või kindla aja möödudes või järgmise ühekordse parooli genereerimisel. Wikipedia
  • TOTP – (Time-based One-time Password Algorithm) on algoritm ajapõhise parooli leidmiseks, mille komponentideks on salajane seemnevõti ning hetke aeg. Wikipedia
  • HMAC – (Hash-based message authentication code) on konstruktsioon krüptograafilise räsi leidmiseks, mille komponendiks peale räsitavate andmete on salajane parool.  Wikipedia
  • SHA-1 – (Secure Hash Algorithm 1) on krüptograafiline räsifunktsioon, mis genereerib räsitavatest andmetest 20 baidise räsi. Wikipedia
  • HMAC-SHA1 – on HMAC konstruktsioon, mis kasutab räsifunktsioonina SHA-1 funktsiooni.
  • FIDO Alliance – (Fast IDentity Online) on konsortsium turvaliste online autentimismeetodite väljatöötamiseks. Koduleht
  • U2F – (Universal 2nd Factor) on avatud standard 2FA täiustamiseks, kasutades USB ja NFC põhiseid seadmeid. Wikipedia

teisipäev, 13. oktoober 2015

Bugi OSX Mail App rakenduses

Tundub, et OSX Mail App lendab õhku kui IMAP server saadab EXPUNGE teate juhul kui postkastis pole mailirakenduse arvates ühtegi kirja. Ilmselgelt on tegu sünkroniseerimisveaga, aga kas see just tähendab, et peaks exceptionit visates õhku lendama, pole päris selge. Pigem peaks käituma nagu alati juhul kui tekib sünkroniseerimisprobleem, nimelt avatud mailbox sulgeda, see seejärel uuesti avada ja vaadata, et mis seal siis nüüd on.

teisipäev, 6. oktoober 2015

Probleemid QQ webmailiga

QQMail on üks suurimaid Hiina e-maili pakkujaid. Ei julge täpset kasutajanumbrit pakkuda, aga mõnisada miljonit kasutajat võiks sellel ikka olla (kokku on QQ kasutajaid miljardi ringis, aga kõik ei ole neist e-maili kasutajad, QQ toodete portfell on päris suur). Igatahes on see üks maailma suurtest Gmaili, Hotmaili ja Yahoo kõrval ja seega tuleb e-maili tarkvara luues ka QQ'ga arvestada.

Huvitaval kombel ongi QQ webmailil üks spetsiifiline probleem ja seda nimelt manuste unikood failinimedega. Aarvestades et Hiinas on unikood au sees ja ASCII mitte, siis on see tõesti imelik.

Kui standardi järgi asub failinimi Content-Disposition päisekirje filename argumendina, siis paljud e-posti rakendused (etteruttavalt, ka QQ webmail) kasutavad mittestandardset name argumenti Content-Type päises. Mitte-ASCII sümbolite kasutamiseks failinimes tuleb see kodeerida ja korrektseks kodeeringuks on RFC2231 Parameter Value Continuation, mis võimaldab jaotada pikemaid failinimesid väiksemateks osadeks (et mitte rikkuda rea pikkuse piirangut) ning nendes olevad mitte-ASCII sümbolid kodeerida urlencoding-laadses kodeeringus.

Failinime "😁😂.jpg" kodeerimine käiks sellisel juhul nii:
Content-Disposition: attachment;
    filename*0*=utf-8''%F0%9F%98%81%F0%9F%98%82.jpg

RFC2047 kirjeldab veidi vanema kodeeringu mehhanismi, encoded-word kodeeringu mis võimaldab koderida päiseridade väärtusi.

Kirja pealkiri "Spämm 😁😂" võiks välja näha nii:
Subject: =?UTF-8?Q?Sp=C3=A4mm_=F0=9F=98=80?=

Encoded-word nagu ka continuation on atom tüüpi väärtused, mis tähendab, et neid ei saa, vähemalt standardi järgi, kasutada päisekirjete argumentide puhul jutumärkide vahel. Mittestandardselt saab muidugi küll ja seda QQ teebki.

Ühesõnaga, selle asemel et kasutada korrektset continuation kodeeringut, kasutab QQ failinimede puhul encoded-word väärtusi jutumärkide vahel. Veel huvitavam, lisaks sellele, et QQ ei genereeri väljuvaid kirju standardi järgi, ei oska QQ ka sissetulevaid kirju õigesi käsitleda.

Näiteks kui manuse päises on failinimi defineeritud vastavalt standardile:
Content-Disposition: attachment;
    filename*0*=utf-8''%F0%9F%98%81%F0%9F%98%82.jpg

Siis QQ webmailis seda kirja vaadates, kuvatakse manuse linki nii:


Seega tuleb kirjadele lisada failinimi kaks korda. Ühe korra standardi järgi filename argumendina ja ühe korra mittestandardse name argumendina:
Content-Disposition: attachment;
    filename*0*=utf-8''%F0%9F%98%81%F0%9F%98%82.jpg
Content-Type: image/jpeg;
    name="=?UTF-8?Q?=F0=9F=98=81=F0=9F=98=82=2Ejpg?="

Ja nüüd saab ka QQ kõigest aru:

reede, 2. oktoober 2015

Mis on see salapärane moodulus?

Septembris kerkis üles viga ID kaardi sertifikaade genereerimisel, kus väidetavalt olevat mingisugune moodulus negatiivne, aga teadjamad räägivad, et see ei saa seda kuidagi olla ja seega on viga kõigest formaalne. Hea ülevaate probleemist leiab näiteks RIA blogist. Ei hakkakski siin probleemi olemust üle kirjeldama, keskenduks pigem tollele müstilisele moodulusele, et mis asi see üldse on ja miks see negatiivne olla ei saa. Järgnev jutt ei ole krütpograafiline ega matemaatiline teadustekst, vaid for dummies from a dummie, nii et kannatage ära ja jätke parandused kommentaaridesse.

Kõige lihtsamalt võttes on moodulus, nagu nimigi viitab, jäägiga jagamistehte jagaja. Modernse krüptograafia aluseks on hiigelpikad algaarvud, näiteks 2048 bitiga esitatud täisarvul on veidi üle 600 nulli ning selline moodulus ehk jagaja määrab sisuliselt ära numbriskaala, millel toimetame. Võrdluseks autode puhul võiks mooduluseks olla see number, mis on spidomeetril kõige suurem, näiteks 160 km/h. Auto mootor saab tekitada liikumiskiirust vahemikus 0 kuni 160, aga mitte vähem ega rohkem. Jah, osad detailid protsessi käigus võivad liikuda küll kiiremini – näiteks punkt auto ratta välisküljel võib vastavalt asukohale liikuda autost kiiremini, aeglasemalt või olla üldse paigal, aga auto liikumiskiirus jääb siiski sinna määratud vahemikku. Sama on ka krüptoarvutustega.

Et juttu veidi ilmestada, siis koostame siinkohal lihtsa jagatud võtmega ROT põhise krüptolahenduse, kuid fikseeritud saladuse (tavaliselt 13) asemel arvutame jagatud saladuse osapoolte salajasest ja avalikust võtmest Diffie-Hellman võtmevahetuse abil. Sellisel juhul saavad kasutatud võtit teada ainult mõlemad osapooled, aga mitte seda sõnumit pealt kuulavad kolmandad isikud.

Meil on kaks osapoolt, vanad tuttavad Alice ja Bob, kes lepivad kokku, et nende kasutatud võtmevahetuse avalikeks konstantideks on eelpool mainitud moodulus, milleks valitakse 23 (seega prime p=23) ja generaatoriks valitakse 5 (ehk g=5), mis määravadki kasutatava numbriskaala. Järgmiseks valib Alice endale meelepärase salajase võtme, milleks saab algarv 7 (ehk a=7, pange tähele, et see jääb g ja p vahele) ning Bob valib endale salajaseks võtmeks algarvu 11 (ehk b=11).

Salajast võtit loomulikult kellelegi edastada ei tohi ja seetõttu peavad Alice ja Bob tuletama oma salajasest võtmest ka avaliku võtme. Selle leiame tehtega

A←ga mod p

Kus A on Alice avalik võti, g on generaator 5, a on salajane võti 7 ning p on 23.

Alice avalik võti = 57 % 23 = 78125 % 23 = 17

Sama teeme ka Bobi võtmega:

Bobi avalik võti = 511 % 23 =  48828125 % 23 = 22

Seega on Alice salajaseks võtmeks 7 ning avalikuks võtmeks 17, viimase väärtuse edastab ta ka Bobile. Bobi salajaseks võtmeks on omakorda 11 ning avalikuks 22, mille ta edastab Alicele.

Järgmiseks tuleks tuletada nendest väärtusest ühisosa ehk jagatud võti. Selle leiame oma salajasest võtmest ja vastaspoole avalikust võtmest tehtega

S←Ba mod p

Kus B on Bobi avalik võti 22, a on Alice salajane võti 7 ning p on 23.

Jagatud võti Alice jaoks = 227 % 23 = 2494357888 % 23 = 22

Ning sama tehe Bobi jaoks

Jagatud võti Bobi jaoks = 1711 % 23 = 34271896307633 % 23 = 22

Nüüd teavad nii Bob kui Alice, et salajase info omavahel vahetamiseks tuleb kasutada ROT22 algoritmi. Kuna me ei ela enam Rooma impeeriumis, vaid vahepeal on paar tuhat aastat edasi läinud, siis kasutame 26 kohalise tähetabeli asemel tervelt 256 kohalist (ehk siis toimetame 1 baidi raames).

Alice tahab saata Bobile sõnumit "saladus" (baitidena 73:61:6c:61:64:75:73). Sõnumi krüpteerimiseks kodeerib ta selle jagatud saladusega, liigutades kõiki baite 22 võrra suuremaks ja saab väärtuse 89:77:82:77:7a:8b:89. Bob omakorda saanud sellise sõnumi, kerib jagatud võtme võrra baidid madalamaks ja saabki sõnumi sisu lugeda. Profit!

Kokkuvõtteks

Kui vastata esialgsele küsimusele, siis moodulus ei saa tõesti olla negatiivne ja seda seetõttu, et skaala millel toimetame (ning moodulus määrabki skaala ülemise otsa) on alati positiivne. Täiendavalt võis tähele panna, et juba niivõrd lihtsa lahenduskäigu korral läksid tehetes kasutatud väärtused juba päris suureks (näiteks jagatud saladuse leidmisel korraks läbi käinud väärtus 34 271 896 307 633), mis siis veel "päris" krüptost rääkida.



Täiendus

Kuna Facebookis küsiti, et mis bitt see ikkagi täpselt siis mooduluse negatiivseks muudab, siis kopipeistin siia arhiveerimise mõttes ka oma vastuse:
Küsimus on ASN.1 INTEGER väärtuse korrektses koostamises, see on siis see numbritüüp mida kasutatakse avaliku võtme mooduluse salvestamiseks sertifikaadis. Konkreetselt on sellel numbrivormingul selline tingimus, et esimene bitt näitab märki: kui see on 0, siis on tegu positiivse arvuga, kui aga 1, siis negatiivne. Kui number on piisavalt väike, siis jääb selle biti jaoks kenasti ruumi, aga suurte numbrite korral lähevad kõik bitid kasutusse ja seega tuleks tekitada juurde veel üks täidisbait, mis koosneb ainult nullidest (ei muuda numbri väärtust, küll aga tekitab vajaliku esimese nullbiti). Mis on nende sertifikaatide juures valesti, ongi see, et too täidisena mõeldud nullbait on numbriväärtuse eest puudu, aga numbriväärtus ise on niivõrd suur, et kasutab esimese biti ise ära. OpenSSL aga seda märki üldse ei vaata, sest kuna see ei saa olla muud kui positiivne, siis nullbaiti (kui see on olemas) lihtsalt ignoreeritakse.

Näide minu enda sertidega. Vana serdi puhul on mooduluse esimene väärtusbait 0xB9, mis bittidena väljendub 10111001. Nagu näha, on vasakpoolne bitt täidetud ja selleks, et seda numbrit mitte negatiivseks pöörata, on moodulus esitatud mitte B9:…, vaid 00:B9:… seega kõik klapib. Uue serdi puhul on esimene numbribait 0x97 ehk 10010111 (samuti on esimene bitt täidetud), kuid moodulus ei ole mitte 00:97:…, vaid 97:…. OpenSSL teisendab selle oma kõhuks ikkagi õigeks numbriks, õigemini ta lihtsalt ei arvesta esimese biti kui eriterminiga, aga vähem andestavad implementatsioonid, mis käsitlevad numbri kodeeringut korrektselt, loevad selle asemel välja ühe vigase negatiivse numbri (kuna esimene bitt läheb märgina kasutusse, siis muutub lisaks märgile ka terve number valeks)

Ja jätkuvalt – minu arvamus ei ole mitte kuidagi teaduslik ning selles võib esineda vigu kuna kõik vastavad teadmised olen saanud guugeldades ja oma loogikaga tuletades. Võrdluseks, täpselt samade uurimismeetoditega on teised inimesed jõudnud torusiili lastele sisse jootmiseni, nii et beware. Kui tead paremini või leiad jutus vea, siis anna sellest teada.

neljapäev, 1. oktoober 2015

Koodi deployment veebiserverisse

Vanadel headel aegadel oli koodi saatmine serverisse väga lihtne ning selleks võlusõnaks oli FTP. Näiteks töötasin umbes 10 aastat tagasi ühes veebiagentuuris, kus tegime PHP põhiseid veebilehti. Deployment nägi seal välja ülilihtne, nimelt kasutasime koodi kirjutamiseks Zend Editori, millel oli sisse ehitatud FTP tugi. Kui tahtsime midagi (live's) muuta, siis avasimegi editori, klikkisime ikoonil Open ja valisime FTP serveris asuva faili. Peale muudatuse tegemist klikkisime ikoonil Save, editor salvestas faili otse üle FTP serverisse ja oligi muudatus deploy'tud. Seejärel tuli brauseriaknas vajutada klahvile F5 ning muudatus saigi nähtavaks, mis saaks olla veel mugavam?

Paraku olid sellisel lähenemisel omad probleemid. Esiteks muidugi ei olnud ju selline uuendus kuidagi versioonitud. Kuna tegu oli lihtsalt faili üle kirjutamisega, siis muudatus kuskile kirja ei läinud ja seega ei olnud võimalik ka kergelt muudatust tagasi keerata. Kodukootud varunduslahenduseks oli lihtsalt aegajalt kõik serveris olevad failid FTP kaudu korraga alla laadida ja zip faili salvestada. Kui nüüd oli vaja mingeid muudatusi tagasi võtta, siis tuli vastav zip fail üles leida (eeldusel, et olid viitsinud/taibanud selle varukoopia üldse teha), lahti pakkida ja õige fail üles leida. Halval juhul tuli pöörduda hostingupakkuja poole ja neilt viimast backup'i lunida.

Aegajalt tuli ette ka race condition'it, juhul kui mitu arendajat sama faili kallal toimetasid ja siis üksteise muudatusi oma muudatustega üle salvestasid. Seda juhtus samas väga harva, kuna reeglina oli üks arendaja projekti kohta.

Minu totaalne lemmik oli salvestamine võrguprobleemide korral. Mida see üldse tähendab, et editor salvestab mingi faili FTP'sse? See tähendab, et kõigepealt avatakse FTP kaudu serveris fail kirjutamiseks ja seda nii, et faili pikkus lühendatakse 0 baidini ja seejärel siis kirjutatakse sellesse avatud faili selle faili uuenenud sisu. Mingist transaktsioonilisest faili kirjutamisest võis sellisel puhul vaid unistada. Praktikas juhtus tihti nii, et editor avas faili (ehk lühendas selle 0 baidini) kuid siis tekkis võrguprobleem ja Zend Editor viskas selle peale pikema jututa pildi taskusse. Tulemus? Serveris oli nüüd vana faili asemel 0 baidine fail ning lokaalses masinas polnud ka enam faili sisu saadaval, kuna editor oli kokku jooksnud.

Sarnane probleem tekkis tihti ka mahu ületamise tõttu. Veebihostingu paketid olid suhteliselt väikesed ja ikka juhtus, et klient oli laadinud sinna mingeid hiigelsuuri pilte ja pdf faile jne. nii et kettamaht oli täis saanud ja isegi üle läinud, sest FTP lubab viimase faili kettale kirjutada, isegi kui sellega läheb quota lõhki. Kui nüüd üritada nüüd sellises keskkonnas mingit faili muuta, siis faili avamine õnnestub (ehk siis lühendamine 0 baidiseks), aga sinna faili midagi kirjutada enam ei õnnestu, kuna quota on juba varasemalt lõhki. Kui selleks muudetavaks failiks juhtus olema index.php või siis rakenduse konfiguratsioonifail, siis oli tulemus teada – veebileht oli jälle "maas".

Tänapäeval on asjad tunduvalt muutunud, ainult poolearuline kasutab rakenduse üleslaadimiseks serverisse FTP'd ja seda kasvõi juba turvalisuse tõttu (ka FTPS ei pruugi olla turvaline, kuna vaikimisi on krüpteeeritud ainult command channel ehk see, kustkaudu liiguvad paroolid, aga mitte data channel, kustkaudu liiguvad failid). Võimalusi on nüüd igasuguseid, tutvustaksin lähemalt poor-man herokut ehk git'i kaudu deploy'mist.

Eeldused:
  • Meie rakendus (selles näites tavaline PHP baasil toimiv veebileht) kasutab versioonihalduseks git'i
  • Olemas on ssh ligipääs serverisse (sama kasutajana, kelle õigustes peavad olema rakenduse failid)

Samm 1. Seadista remote repository

Loo serveris repo kaust (sõltuvalt asukohast võib olla vajalik teha seda root kasutaja õigustes), suvaline asukoht kõlbab, aga näites teeme selle asukohta /var/opt

cd /var/opt
mkdir webapp.git
cd webapp.git
git init --bare

Selle tagajärjena on meil olemas täiesti tühi git repo asukohas /var/opt/webapp.git.

Samm 2. Update hook

Selle jaoks, et taolisesse tühja reposse millegi saatmine ka midagi reaalselt muudaks, seadistame update sündmuse tegevuse, milleks on bash skript asukohas hooks/update.

cd /var/opt/webapp.git/hooks
nano update

Avanenud tekstitoimetisse võib kopeerida järgmise failisisu (eeldusel, et /var/www/webapp/htdocs on kaust, kus hakkavad asuma rakenduse failid)

#!/bin/bash
GIT_WORK_TREE=/var/www/webapp/htdocs git checkout "$3" -f

Järgmiseks tuleks anda sellele failile käivitusõigused

chmod +x update

Nüüd tuleks jälgida, et rakenduse failide kaust eksisteerib ja et kõik failiõigused on paigas

mkdir -p /var/www/webapp/htdocs
chown www-data:www-data /var/www/webapp
chown -R www-data:www-data /var/www/webapp/
chown www-data:www-data /var/opt/webapp.git
chown -R www-data:www-data /var/opt/webapp.git/

Ja sellega ongi server seadistatud.

Samm 3. Lokaalne seadistus

Kohalikus git koodirepos, kus asuvad siis rakenduse failid, tuleks lisada uus git remote asukoht, tavaliselt on selle nimeks origin, kuid deploy jaoks kasutame hoopis nimetust production.

git remote add production www-data@example.com:/var/opt/webapp.git

www-data on siis see kasutaja kelle õiguses serveris toimetame ning example.com on ssh serveri hostname.

NB! Tavaline "origin" remote asukoht jääb endiselt alles kuna git hajuslahendus, nii jääb origin suunama koodihoidlasse ja production veebiserverisse. Lisaks võib teha veel staging vmt.

Samm 4. Deploy!

Nüüd ongi kõik seadistused tehtud ja edasi ei ole muud, kui muudatusi deploy'ma hakata. Iga kord kui oled uuendanud koodi ja selle ära commit'inud, võid jooksutada käsu

git push production master

kus master on siis aktiivne branch. Git laeb muudatused remote reposse, seal käivitub update hook, mis omakorda (eeldusel et commit õnnestub), kopeerib kõik vajalikud failid veebifailide kausta.

Profit!


Tagasi Bloggeris

Tüdinesin ära ise oma blogi majutamisest tuleneva tüliga ja kolisin Bloggerisse tagasi. Vahepealsed postitused läksid kahjuks kaduma, osa on õnneks loetav veel siit. Konkreetselt oli probleemiks siis Ghost blogisüsteemi majutamine. Iga kord kui uuendasin serveris Node.js versiooni (hetkel on stable versiooniks v4.1.1) lõpetas Ghost töö. Heal juhul tuli lihtsalt sqlite dependency uuesti installida, halval juhul, peamiselt kui tegu oli Node põhiversiooni muudatusega (nagu näiteks nüüd 0.12 pealt uuendamine 4.1 versioonile), siis viskas Ghost üldse käpad püsti, et sqlite installimine pole võimalik ja tuleb oodata uuendust. Üsna frustreeriv. Igatahes, nüüd olen siis juurte juures tagasi. Blogger on kohati üsna totakas, aga see on kõige stabiilsem lahendus, mida ma tean. WordPress.com on mugavam, aga kõvasti aeglasem, Tumblr'is ei tööta jälle kommenteerimine, ise hostida midagi ma enam ei taha ja nii ma siia sattusingi.