Apie CityBee ir slaptažodžių saugumą
Tags: hashing, security, passwords, citybee
Published: 2021-02-19 14:46:01

*Šis straipsnis parašytas po CityBee skandalo pradėjus plisti netiksliai informacijai apie slaptažodžių saugojimą. Skirta tiek IT specialistams, tiek norintiems labiau suprasti situaciją.*

# Trumpai (TL;DR;)
[Iš įmonės CityBee]((https://www.15min.lt/verslas/naujiena/bendroves/pavogti-treju-metu-senumo-dalies-citybee-klientu-duomenys-663-1456578)), o vėliau ir iš [OlyBet](https://www.15min.lt/mokslasit/straipsnis/technologijos/hakeriai-pardavineja-ir-orakulas-lt-vartotoju-duomenu-baze-257-tukst-el-pasto-adresu-ir-slaptazodziu-646-1457532) bei [filmai.in](https://raidforums.com/Thread-TXT-filmai-in-lithuania-illegal-streaming-site-db) nutekėjus klientų duomenims bei paaiškėjus, jog be viso kito, slaptažodžiai buvo saugomi nesaugiu SHA1 algoritmu, internete pradėjo plisti nuomonės apie tai, kaip įmonė turėjo teisingai saugoti slaptažodžius. Pasisakė visi, nuo IT "specialistų", iki mažai ką bendro su IT turinčių [influencerių](https://youtu.be/wbKznbxe5r4?t=810). 

Beveik visi komentarai apsiriboja tuo pačiu teiginiu: CityBee saugodami slaptažodžius nenaudojo vadinamo "salt" metodo, o tai yra labai blogai ir jei būtų naudotas "salt" - klientų slaptažodžiai būtų buvę žymiai saugesni.

Dauguma apie "salt" kalbančių žmonių mažai ką supranta apie saugumą ir tik daro žalą IT industrijai klaidindami jaunus specialistus. Nepaisant, jog CityBee elgesys buvo aplaidus, tai tas pats, kas po avia-katastrofos, kur iš lėktuvo liko tik blynas, aiškinti, jog lėktuve nebuvo įrengti saugos diržai.

Saugant vartotojų slaptažodžius reikia naudoti specialius tam skirtus algoritmus. Jų yra daugybė, bet mano rekomenduojamas **baigtinis sąrašas**: PBKDF2, BCrypt, Argon2. Tai yra absoliutus minimumas, privalomas kiekvienai internetinei sistemai, nes nereikalauja pastangų ir duoda maksimaliai rezultato. Na, o apie viską išsamiai - žemiau.

# Kaip "koduojami" slaptažodžiai

Slaptažodžiai naudojami daug kur: jungiantis prie kompiuterio, apsaugant failus, registruojantis internetiniuose puslapiuose. Kad būtų paprasčiau, apsiribokime CityBee pavyzdžiu.

Vartotojas registruodamasis CityBee programėlėje nurodo savo pasirinktą slaptažodį. Sistema jį turi kažkur išsaugoti, kad vėliau vartotojui jungiantis galėtų sutikrinti ar slaptažodžiai sutampa. Kadangi įsiminti krūvą slaptažodžių sudėtinga, žmonės visur linkę naudoti tuos pačius arba panašius slaptažodžius. Tarkim, jeigu žmogaus CityBee slaptažodis yra `LinksmasBebras`, didelė tikimybė, jog Gmail, Facebook ar net banko slaptažodis bus `LinksmasBebras1!`. 

Natūralu, jog CityBee negali saugoti slaptažodžio paprastu tekstu (angl. *plain text*), nes tiek duomenų vagys, tiek ir vidiniai įmonės darbuotojai galėtų vartotojams pridaryti daugybę problemų. Išeitys yra dvi: slaptažodžius šifruoti arba "hash'uoti".
 
[Šifravimas (dar klaidingai vadinamas kodavimu, angl. *encryption*)](https://en.wikipedia.org/wiki/Encryption) yra operacija, kurios metu, naudojant slaptą raktą, duomenys užšifruojami taip, jog be rakto jų nebūtų įmanoma perskaityti. Panaudojus tą patį raktą duomenis galima iššifruoti į jų pradinę formą. Šifruoti slaptažodžius nėra labai populiaru, nes sunku saugiai prižiūrėti raktą, kuris irgi gali būti pavogtas arba prieinamas įmonės darbuotojų.
![Šifravimos procesas](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8mjvi629sjx9x8mywwsa.jpg)

[Hash'avimas (liet. *maiša*)](https://en.wikipedia.org/wiki/Hash_function), paprastai pasakius, yra algoritmas iš teksto gauti fiksuoto ilgio simbolių kratinį. Iš to paties teksto visuomet gaunamas tas pats simbolių kratinys. Iš hash funkcijos rezultato nebeįmanoma atstatyti pradinio teksto. Štai paprasta hash funkcija aprašyta žmonių kalba:
```
Sudauginkime teksto kiekvienos raidės eilės numerį abėcėlėje;
Gautą sandaugą padalinkime iš 100;
Liekana bus mūsų hash'as;
Pvz.: "abce" hash'as pagal šį algoritmą yra 1*2*3*5 = "30";
```
[Mūsų asmens kodų paskutinis skaitmuo irgi yra hash'as](https://lt.wikipedia.org/wiki/Asmens_kodas) išskaičiuotas iš prieš jį einančių 10 simbolių.

Hash'avimas skamba kaip idealus būdas saugoti slaptažodžius - galima išsaugoti ir vėliau patikrinti ar įvesto slaptažodžio hash'as sutampa su išsaugota reikšme. O hash algoritmų yra labai daug ir įvairių, CityBee pasirinko gana populiarų, bet senstelėjusį, [SHA1](https://en.wikipedia.org/wiki/SHA-1) algoritmą, jis iš bet kokio ilgio duomenų sugeneruoja 20 baitų ilgio reikšmę. Pvz. teksto `LinksmasBebras` SHA1 rezultatas yra "304c888dc981169e1dca9f31998cece8da2c2458". Iš dviejų skirtingų slaptažodžių gauti tą pačią hash reikšmę teoriškai įmanoma, bet praktiškai nelabai (priešingai nei naudojant aukščiau pavaizduotą supaprastintą algoritmą). Yra ir kitų populiarių hash algoritmų: MD5, SHA256, SHA512 ir pan.

Visas CityBee darbo su slaptažodžiais procesas buvo toks:
1. Vartotojas registruodamasis programėlėje įveda slaptažodį `LinksmasBebras`.
2. Slaptažodis nukeliauja į centrinę CityBee sistemą.
3. Sistema suskaičiuoja gauto slaptažodžio hash'ą naudodama SHA1 algoritmą.
4. Sistema išsaugo gautą hash reikšmę `304c888dc981169e1dca9f31998cece8da2c2458` į duomenų bazę, kartu su kitais vartotojo duomenimis. Registracija sėkminga.

<..>

5. Vartotojas jungdamasis prie sistemos įveda slaptažodį `LinksmasBebras`.
6. Slaptažodis nukeliauja į centrinę CityBee sistemą.
7. Sistema suskaičiuoja gauto slaptažodžio hash'ą naudodama SHA1 algoritmą.
8. Sistema palygina gautą hash reikšmę `304c888dc981169e1dca9f31998cece8da2c2458` su vartotojo hash reikšme iš duomenų bazės. Kadangi sutampa - prisijungimas sėkmingas. 

# Kodėl CityBee slaptažodžius "kodavo" blogai

Primenu, kad iš CityBee, be kita ko, buvo pavogti vartotojų slaptažodžiai SHA1 hash'ų pavidalu. [Ar kaip jie patys klaidina: "užkoduoti"](https://www.linkedin.com/pulse/pam%25C4%2585stymai-apie-citybee-duomen%25C5%25B3-nutek%25C4%2597jim%25C4%2585-marius-vitkevi%25C4%258Dius/?trackingId=xFedLklITIK7NP30nMBPqQ%3D%3D).

Nors iš hash reikšmės ir neįmanoma atkurti pradinio teksto, tačiau niekas netrukdo skaičiuoti visų įmanomų simbolių kombinacijų SHA1 hash'o, kol atrasime ieškomą. Pradėję nuo "a", paskiau "b" ir t.t. ilgainiui (po nesuvokiamos galybės bandymų) prieisime prie `LinksmasBebras`, gausime atsakymą "304c888dc981169e1dca9f31998cece8da2c2458" ir taip sužinosime koks tekstas slėpėsi po šia hash reikšme. Toks visų reikšmių išbandymas vadinamas [brute-force ataka](https://en.wikipedia.org/wiki/Brute-force_attack). 

SHA1 ypatybė yra ta, jog jis sukurtas būti labai efektyvus, kompiuteriui suskaičiuoti teksto SHA1 hash'ą yra vieni juokai. Nepaisant to, jog net mano kompiuteris gali išbandyti kelis milijardus kombinacijų per sekundę, jų yra [tiek daug](https://tmedweb.tulane.edu/content_open/bfcalc.php?uc=2&lc=12&nu=&sc=&ran=&rans=&dict=), jog užtruktume daugybę metų kol prieitume iki `LinksmasBebras`. Tačiau kas trukdo pasiėmus Lietuvių kalbos žodyną išbandyti visų žodžių junginių kombinacijas? Įtraukus visas didžiųjų-mažųjų raidžių kombinacijas, belieka tik keliolika milijardų spėjimų - vienas juokas šiuolaikinei technikai. Apie tai, kaip nulaužinėjami hash'ai - šiek tiek vėliau.

Pasitelkus įvairius genialius būdus, galima sugeneruoti milžiniskas duomenų bazes su potencialiais slaptažodžiais ir jų hash reikšmėmis. Į tokias duomenų bazes patenka ir įvairiais būdais nutekėję realūs slaptažodžiai. Pavyzdžiui, [crackstation.net](https://crackstation.net) leidžia net parsisiųsti savo turimą 15GB slaptažodžių duomenų bazę. Nebereikia nieko laužti, belieka tik surasti domenų bazėje kokį tekstą atitinka jūsų turima hash reikšmė.

# Panacėja, vardu "Druska"
Po CityBee skandalo bent kiek IT sistemose nusimanantys specialistai suskubo aiškinti, jog saugoti slaptažodžius SHA1 pavidalu buvo kvailystė ir CityBee (tiksliau jų sistemos pamatus padėjusi įmonė) turėjo naudoti salt'ą. 

[Salt'inimas](https://en.wikipedia.org/wiki/Salt_(cryptography)), tai yra slaptažodžių saugojimo patobulinimas, kai prie teksto pridedami atsitiktiniai simboliai (salt'as) ir tik tuomet skaičiuojamas hash'as. SHA1 reikšmę reikėtų skaičiuoti iš teksto `LinksmasBebrasE1F53135E559C253`, o rezultatą **ir** salt'ą išsaugoti duomenų bazėje. CityBee registracijos ir prisijungimo procesas naudojant salt būtų buvęs toks:
1. Vartotojas registruodamasis programėlėje įveda slaptažodį `LinksmasBebras`.
2. Slaptažodis nukeliauja į centrinę CityBee sistemą.
3. Sistema sugeneruoja atsitiktinę salt reikšmę, prideda ją prie gauto slaptažodžio ir suskaičiuoja teksto `LinksmasBebrasE1F53135E559C253` hash'ą naudodama SHA1 algoritmą.
4. Sistema išsaugo gautą hash reikšmę `ae679d1015ee8dd586036c9de34ade76c33f1c3a` ir panaudotą salt'ą `E1F53135E559C253` į duomenų bazę, kartu su kitais vartotojo duomenimis. Registracija sėkminga.

<..>

5. Vartotojas jungdamasis prie sistemos įveda slaptažodį `LinksmasBebras`.
6. Slaptažodis nukeliauja į centrinę CityBee sistemą.
7. Sistema pasiima iš duomenų bazės seniau išsaugotą salt reikšmę `E1F53135E559C253`, prideda ją prie įvesto slaptažodžio ir paskaičiuoja teksto `LinksmasBebrasE1F53135E559C253` hash reikšmę.
8. Sistema palygina gautą hash reikšmę su vartotojo hash reikšme duomenų bazėje. Jei sutampa - prisijungimas sėkmingas. 

Įsidėmėkite, kad salt reikšmė saugoma šalia slaptažodžio toje pačioje duomenų bazėje. Jei daroma kaip nors kitaip, tai nebėra salt.

Salt naudojimas išsprendžia dvi problemas:
* Nebeįmanoma naudoti iš anksto sugeneruotos slaptažodžių duomenų bazės, nes net visuose pasaulio diskuose netilps tiek daug teksto kombinacijų.
* Jei du skirtingi vartotojai naudos tą patį slaptažodį, jo hash'as duomenų bazėje bus skirtingas.

Prieš ~15 metų, salt naudojimas buvo gana adekvati apsauga, nes negalėjimas pasinaudoti kažkieno ilgus metus kauptomis duomenų bazėmis reiškė, jog įsilaužėlis turės pats bandyti perrinkinėti kiekvieno vartotojo slaptažodį. 

Atsiradus pirmosioms galingoms vaizdo plokštėms buvo pastebėta, jog hash'us jos moka skaičiuoti daug greičiau nei kompiuterio procesorius. Tūkstančius kartų greičiau. Nuo to laiko viskas pasikeitė ir jau ***prieš daugiau nei 10 metų*** tapo galutinai aišku, jog slaptažodžių saugojimui reikia geresnių priemonių.


# Apie IT saugumą gali kalbėti vos saujelė žmonių

>Few false ideas have more firmly gripped the minds of so many intelligent men than the one that, if they just tried, they could invent a cipher that no one could break. - David Kahn 

Viena iš problemų kuri persekioja kibernetinio saugumo industriją, nekompetetingi žmonės, kurie turėdami paviršutiniškas žinias dedasi šios srities specialistais. Dėl to sistemose ir atsiranda tūkstančiai saugumo spragų. Tai klasikinis [Dunning-Kruger efekto](https://en.wikipedia.org/wiki/Dunning%E2%80%93Kruger_effect) pavyzdys.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w0nzg2q0hvqvc4n465s5.jpg)

Tikri profesionalai, o ypač kriptografijos, dažniausiai būna labai kuklūs ir retai ką nors teigia užtikrintai, nes jie supranta, kad daugelis atsakymų priklauso nuo konteksto, detalių ir auditorijos išsilavinimo. Tad jei jaučiate, jog kažkas jums autoritetingai bando aiškinti apie IT saugumą - tikriausiai galite nustoti to žmogaus klausyti. Šitai, deja, galioja ir man :(

# Kodėl salt'as ne panacėja

Duomenų bazėse internete galima rasti šimtus milijonų nulaužtų slaptažodžių (paskaičiuotų hash'ų). Kalbu apie [tas bazes](https://crackstation.net), kuriose copy-paste pagalba galima iš hash'o atrasti slaptažodį.  
Primenu, jog nebloga vaizdo plokštė sugeba paskaičiuoti kelis milijardus SHA1 hash'ų per sekundę. Taip pat primenu, jog salt'as, jeigu toks būtų, būtų gulėjęs duomenų bazėje šalia slaptažodžio. Tad paskaičiuoti pusės milijardo slaptažodžių SHA1 hash'us, prie kiekvieno pridedant unikalų salt'ą užtruktų nedaug ilgiau, nei to hash'o paieška duomenų bazėje. Tiesa, reikia pastebėti, jog naudojant salt, nebebūtų įmanoma suskaičiuoto slaptažodžio varianto patikrinti visame hash'ų sąraše, o reikėtų paskaičiuoti hash'ą kiekvienam vartotojui atskirai. 

Egzistuojant salt'ui, nebūtų įmanoma pompastiška slaptažodžio hash'o nulaužimo demonstracija naudojant copy-paste. Taip pat pailgėtų didelio slaptažodžių sąrašo nulaužimas, bet esmės tai nepakeistų, tik suteiktų įmonei daugiau argumentų nusimesti kaltę. 

# Kaip nulaužinėjami slaptažodžiai

Yra du pagrindiniai slaptažodžių atakų tipai - online ir offline. Online - tai bandymas prisijungti prie pvz., web sistemos išmėginant įvairius slaptažodžius. Tokios atakos nepraktiškos, nes web sistema gali riboti prisijungimų skaičių, rodyti capcha ir pan.

CityBee atveju aktuali offline ataka - vartotojų slaptažodžių hashus galima pasisiųsti į savo kompiuterį ir neribotai nulaužinėti.

Viena populiariausių ir labiausiai išvystytų programų skaičiuoti hash'ams yra [HashCat](https://hashcat.net/hashcat), ji moka efektyviai išnaudoti vaizdo plokštę ir palaiko daugybę hash algoritmų. Iš esmės ką ji daro, tai užsikrauna nurodytą hash'ų sąrašą ir įvairiais būdais generuoja galimas raidžių kombinacijas, skaičiuoja hash'ą ir ieško ar toks hash'as yra sąraše. Visas įdomumas slepiasi po *"įvairiais būdais"*, apie juos ir pakalbėkime.

Kaip jau minėjau, bukai bandyti įvairias simbolių kombinacijas nepraktiška. Viskas priklauso nuo skaičiavimo pajėgumų, bet išbandyti net 9 simbolių kombinacijas yra keblu ir kiekvienas naujas simbolis eksponentiškai didina reikalingą nulaužimui laiką.

Reikia pasitelkti išmonę, žodynus ir žodžių manipuliavimo taisykles. Žodynai - tai didžiuliai įvairių žodžių sąrašai, pavyzdžiui visi lietuviški žodžiai, aktorių vardai, prieš tai nutekėję slaptažodžiai ir t.t. Taisyklės - tai žodžių manipuliacijų formulės. Pavyzdžiui, imame kiekvieną žodį iš LT žodyno ir atliekam su juo 10000 manipuliacijų: pridedame simbolį *1*, pakeičiame visus simbolius *a* į *@* ir t.t. Taip "nusilaužia" net tokie slaptažodžiai kaip *"Valkyre1986"* ar "K1eti@k@s69". CityBee atveju tai sudaro >50% visų slaptažodžių, priklausomai nuo naudojamo žodyno.

Sudėtingesniems slaptažodžiams atrasti galima naudoti žodynų kombinaciją, t.y. bandyti prie kiekvieno lietuviško žodžio lipdyti visus kitus įmanomus lietuviškus žodžius. Taip nusilaužia visi tokie slaptažodžiai kaip `LinksmasBebras1` ir pan. 

Išsisėmus galima paimti jau nulaužtų slaptažodžių sąrašą ir pradėti kombinuoti jį su žodynais. Kaip sakoma - rinse and repeat. Tokiu būdu nusilaužia sudėtingesni slaptažodžiai, tokie kaip *"labasrytasmazule2020"*, nes jau kažkas turėjo slaptažodį *"labasrytas"* ir jis sėkmingai susikombinavo su papildomu žodžiu bei taisyklėmis.

Tai be galo smagus procesas, dėl to [yra net konkursų](https://contest.korelogic.com), kur susirinkę mėgėjai varžosi, kas daugiau atras slaptažodžių. Žinoma, profesionalai turi sukaupę rimtus žodynus ir taisyklių rinkinius. Naudojantis nesudėtinga įranga ir RX5700XT vaizdo plokšte, per parą pavyko atkurti ~90% visų CityBee slaptažodžių (eksperimentui naudoti tik visiems viešai prienami duomenys). Tikiu, kad panaudojus, pvz., iš Darni Pora ar Filmai.in pavogtus visiškai atvirus slaptažodžius kaip žodyną, pavyktų išspausti dar vieną kitą procentą. Maždaug nuo 90% atkurtų slaptažodžių skaičius sunkiai auga, nes dalis žmonių naudoja password manager'ius, turi susigalvoję sudėtingus slaptažodžius ir pan.

![HashCat-screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z0crixn3aoxs5gf6xv5k.JPG)

Minutėlę pabandykite įsivaizduoti kaip vyktų slaptažodžių nulaužinėjimas vietoj vieno kompiuterio panaudojus tokią vaizdo plokščių fermą:
![VGA farm](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6ay263zu3oyuwimu2fn9.png)
Tokios fermos išpopuliarėjo kartu su Bitcoin bumu (nes BitCoin kasimas irgi paremtas hash'ų skaičiavimu) ir dabar neretai panaudojamos slaptažodžių nulaužinėjimui. 

Slaptažodžiai "nulaužinėjimi" ne tik blogiems tikslams ar hobiui. Lygiai toks pats būdas naudojamas ir įmonėse audituojant savo vartotojus, kad jiems būtų galima pranešti apie žinomus nutekėjusius slaptažodžius. Deja, ne visos valstybės pakankamai supratingos, štai [Vokietija kenčia](https://iclg.com/practice-areas/cybersecurity-laws-and-regulations/germany) nuo drakoniškų įstatymų labai ribojančių darbą saugumo srityje. Kiek žinau, Lietuvoje tai vis dar pilkoji zona, kur kiekvienas atvejis sprendžiamas individualiai ir etiniai įsilaužimai (angl. *ethical hacking*) teisėsaugos vertinami labai selektyviai. Netgi aš, rašydamas šį edukacinį straipsnį, negaliu jaustis visiškai ramiai.

# Kaip reikėtų saugoti slaptažodžius
Labai paprasta, 80% naudos galima pasiekti su visiškai minimaliomis pastangomis. Tereikia vietoj SHA1 ar kito netinkamo algoritmo naudoti vieną iš slaptažodžiams pritaikytų: PBKDF2, Bcrypt, Scrypt, **Argon2** ar pan. Argon2 šiuo metu yra de facto geriausias algoritmas. Apie tai, kaip gauti likusius 20% naudos, reikėtų atskiro straipsnio.

Specialių algoritmų esmė yra tokia, kad jie paskaičiuojami lėtai (angl. *slow hashing*). SHA1 hash'ą paskaičiuoti užtrunka nanosekundes, o, pvz., Argon2 turi konfigūruojamą parametrą (angl. *work factor*), nurodantį, kiek ilgai hash algoritmas atliks operaciją. Jei paskaičiuoti slaptažodžio hash'ą ilgai užtrunka web sistemai, reiškia, jog ilgai užtruks ir tokių slaptažodžių nulaužinėjimas. Be to, Argon2 algoritmas labai prastai skaičiuojamas naudojant vaizdo plokštes ar kitą specialią įrangą.

Yra ir krūva kitų priemonių apsaugoti slaptažodžiams, pavyzdžiui finansų įstaigos naudoja dedikuotą įrangą ([HSM](https://en.wikipedia.org/wiki/Hardware_security_module)), skirtą būtent šifravimo operacijoms atlikti. Svarbiausia nepatikėti tokių svarbių sprendimų žmonėms, kurie turi mažai ką bendro su saugumu, nes tuomet būna "išrandami" įvairūs algoritmai, kurie atneša daugiau gėdos, nei naudos. Pavyzdžiui, šiek tiek prakutęs programuotojas gali pasiūlyti vietoj ar šalia *salt* naudoti [*pepper*](https://en.wikipedia.org/wiki/Pepper_(cryptography)) metodą, kuris gal ir nepakenks, bet didelė tikimybė, jog sukurs klaidinančią saugumo iliuziją. OWASP organizacija teikia rekomendacijas ir siūlo gerąsias saugumo praktikas, įskaitant ir [slaptažodžių saugojimą](https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html).

Mano asmenine nuomone, kiekviena įmonė, dirbanti su klientų duomenimis turėtų užsisakyti išorinio konsultanto ar audito paslaugas. Ir nebūtina tam leisti tūkstančių pinigų, bei pirkti konsultantų siūlomos programinės įrangos. Dažnu atveju pakaktų freelancer'io, kuris padėtų į savo sistemą pažiūrėti iš šalies.
Tikiuosi suprasti duomenų apsaugos svarbą padės karti nukentėjusių įmonių patirtis ir baudos, kurias jos gaus už aplaidumą.

Ir kaip visada - nepaisant to, jog šiame straipsnyje aiškinau techninius dalykus, didžiausia problema išlieka žmonės. Galima naudoti kokius nori algoritmus, bet jei admin'as netyčia sugalvos išsaugoti visą į sistemą įeinantį srautą, [kartu išsisaugos ir asmeniniai duomenys prieš juos tinkamai užšifruojant](https://www.zdnet.com/article/twitter-says-bug-exposed-passwords-in-plaintext).

> If you think cryptography is the answer to your problem, then you don't know what your problem is. - Peter G. Neumann