This shows you the differences between two versions of the page.
uso:laboratoare:laborator-08:concepts [2020/12/07 22:53] liza_elena.babu [Stocarea parolelor] |
uso:laboratoare:laborator-08:concepts [2021/11/16 09:40] (current) liza_elena.babu [Funcționalități shell] |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | ===== Concepte ===== | ||
- | ==== Prezentarea și securizarea datelor (encodare, criptare, hashing) ==== | ||
- | === Encodare === | + | ===== Concepte ===== |
- | **Encodarea** este folosită când dorim să prezentăm o serie de date sub o altă formă. De exemplu, când există caractere neprintabile în datele noastre, nu le putem afișa sub forma unui string. **Base64** este un cunoscut exemplu de algoritm de encodare pentru că transformă orice vector de octeți într-un string de caractere printabile. | + | ^ Comandă ^ Descriere scurtă ^ |
+ | | **''cat''** | afișare conținut fișier | | ||
+ | | **''seq''** | generare secvență de numere | | ||
+ | | **''grep''** | extrage linii care conțin o anumită expresie regulată | | ||
+ | | **''cut''** | extragere anumite coloane | | ||
+ | | **''sed''** | filtru de text avansat, folosit pentru substituții | | ||
+ | | **''wc''** | contorizare număr de linii, cuvinte sau caractere | | ||
+ | | **''head''** | afișare a primelor linii sau caractere | | ||
+ | | **''tail''** | afișare a ultimelor linii sau caractere | | ||
+ | | **''for''** | parcurgere listă de elemente pentru aplicarea de comenzi pentru fiecare element în parte | | ||
+ | | **''if''** | condiție de execuție a unor comenzi | | ||
+ | | **''$(comm)''** | expandarea unei comenzi (//command expansion//) - înlocuirea cu output-ul comenzii | | ||
+ | | **''comm1 | comm2''** | legarea a două comenzi: output-ul primei comenzi devine input pentru cea de-a doua comandă | | ||
+ | | **''$var'' sau ''${var}''** | valoarea variabilei ''var'' | | ||
+ | | **''${#var}''** | lungimea valorii variabilei ''var'' (în caractere) | | ||
+ | | **''${var:2:3}''** | un subșir al valorii variabilei ''var'': de la indexul ''2'' se extrag ''3'' caractere | | ||
- | <note> | ||
- | Este important de precizat faptul că encodarea **nu ascunde/securizează** informații, ci doar le prezintă sub o altă formă. | ||
- | </note> | ||
- | Folosind comanda **base64** fără niciun parametru putem să encodăm un text. | + | Pentru acest laborator vom folosi comenzi și noțiuni prezentate în laboratoarele de până acum în special laboratorul trecut ([[:uso:laboratoare:laborator-07]]). Vor fi puține comenzi nou introduse; cel mai mult ne va interesa cum, dându-se o situație practică, vom putea folosi shell-ul pentru automatizare. |
- | <code bash> | + | |
- | student@uso:~$ echo -n "Base64 is not encryption!" | base64 | + | |
- | QmFzZTY0IGlzIG5vdCBlbmNyeXB0aW9uIQ== | + | |
- | </code> | + | |
- | Utilizând parametrul **-d** putem decoda un text encodat. | + | **Automatizarea sarcinilor** se referă la delegarea / degrevarea acțiunilor utilizatorilor către programe în sistemul de calcul. Un program va face automat, de sine stătător, acțiuni pe care le-ar face utilizatorul, rezultând în timp mai puțin consumat de utilizator. |
- | <code bash> | + | |
- | student@uso:~$ echo -n "QmFzZTY0IGlzIG5vdCBlbmNyeXB0aW9uIQ==" | base64 -d | + | |
- | Base64 is not encryption! | + | |
- | </code> | + | |
+ | Acțiunile care sunt candidate pentru automatizare sunt în general acțiuni repetitive, nu foarte simple și neinteractive. Automatizarea acestora va elibera utilizator de la executarea repetată, plictisitoare, manuală a acestora. | ||
- | {{ :uso:laboratoare:new:10-sec:image_base64.jpg?500 |}} | + | ==== Perspective pentru automatizare ==== |
- | === Criptarea === | + | Automatizarea sarcinilor urmărește eficiență, în special temporală. Cu cât face mai rapid acțiuni repetitive, cu atât este mai bine. Acțiunile repetitive necesită interacțiune minimă cu utilizatorul, pentru a eficientiza timpul |
- | Să presupunem că Alice și Bob doresc să comunice pe Internet. Pentru început, cei doi folosesc un canal simplu prin care transmit mesajele în clar. Problema care apare este că Trudy, care este rău intenționat, poate asculta ce vorbesc Alice și Bob și va și înțelege mesajele deoarece ele sunt transmise în clar. | + | Când automatizăm, folosim scripting și funcționalități existente. Un principiu esențial al automatizării este //don't repeat yourself// (nu reinventăm roata). Dacă există comenzi sau funcționalități existente, le folosim pe acelea. Altfel spus, urmărim atât eficiența execuției cât și eficiența dezvoltării. |
- | {{ :uso:laboratoare:new:10-sec:image_trudy.jpg?500 |}} | + | Eficiența execuției o putem realiza nu doar prin scripting, ci și prin acțiuni precum: |
+ | * folosirea de scurtături de taste | ||
+ | * folosirea funcționalităților de tipul //command completion// sau //history search// | ||
+ | * folosirea de alias-uri de comenzi | ||
+ | * folosirea de șabloane: //globbing// sau expresii regulate (//regular expressions//) | ||
- | **Criptarea** înseamnă ascunderea datelor folosind un algoritm public și o cheie secretă. În cazul nostru, Alice **criptează** mesajul pe care dorește să îl transmită, iar Bob îl **decriptează**. Alice și Bob au aceeași cheie secretă negociată într-un moment de timp anterior comunicării. **Trudy** vede în continuare mesajele, știe algoritmul de criptare (deoarece e public), dar nu cunoaște cheia de decriptare, deci nu poate vedea conținutul lor. Un exemplu de algoritm de criptare este **AES**. | + | Atunci când folosim scripting în shell, ne folosim de funcționalități existente ale shell-ului, pe care le vom descrie mai jos. |
- | <note> | + | ==== Scripting ==== |
- | **Criptarea** presupune ascunderea/securizarea datelor într-o manieră recuperabilă. Adică ele vor putea fi ulterior **decriptate**. | + | |
- | </note> | + | |
- | Folosind utilitarul **openssl** putem să criptăm conținutul unui fișier. | + | Scripting presupune folosirea unui limbaj interpretat (numit limbaj de scripting). Acesta poate fi un limbaj precum Python, Perl sau Ruby sau poate fi chiar shell-ul CLI (interpretorul de comenzi). Limbajele de scripting au avantajul **dezvoltării rapide**: adăugăm și testăm rapid funcționalități noi. |
- | <code bash> | + | Shell scripting are avantajul folosirii comenzilor existente în shell (comenzi de lucru cu fișiere, cu procese, comenzi de filtrare de text). Pentru acțiuni rapide (de tipul //quick'n'dirty//), shell scripting este o soluție foarte bună. Atunci când avem prelucrări numerice sau prelucrări de șiruri, shell scripting poate fi insuficient și este indicat să apelăm la un limbaj de scripting mai complet, precum Python, Ruby sau Perl. |
- | student@uso:~$ echo -n "plaintext content" > plaintext_file.txt | + | |
- | student@uso:~$ openssl aes-256-cbc -in plaintext_file.txt -out encrypted_file.enc -pass pass:"uso rules" | + | |
- | student@uso:~$ ls | + | |
- | encrypted_file.enc plaintext_file.txt | + | |
- | </code> | + | |
- | Utilizând parametrul **-d** putem decripta fișierul ''encrypted_file.enc''. | + | ==== Funcționalități shell ==== |
- | <code bash> | + | |
- | student@uso:~$ openssl aes-256-cbc -d -in encrypted_file.enc -out decrypted_file.txt -pass pass:"uso rules" | + | |
- | student@uso:~$ cat decrypted_file.txt | + | |
- | plaintext content | + | |
- | </code> | + | |
+ | Funcționalitățile shell-ului sunt folosite în eficiența rulării comenzilor și în automatizare. Le-am folosit și amintit pe parcursul ultimelor laboratoare, în special în laboratorul trecut. Astfel de funcționalități sunt: | ||
+ | * redirectarea comenzilor în fișiere, folosind operatorii de redirectare: ''%%>%%'', ''%%<%%'', ''%%>>%%'' | ||
+ | * redirectarea ieșirii unei comenzi către intrarea altei comenzi: operatorul ''%%|%%'' (//pipe//) | ||
+ | * variabile shell | ||
+ | * escaping folosind //backslash//, ghilimele sau apostrofuri | ||
- | === Hashing === | + | Pe parcursul acestui laborator vom folosi funcțioalități ale shell-ului care sunt în special folosite în shell scripting: |
+ | * expresii regulate | ||
+ | * argumente în linia de comandă | ||
+ | * comenzi interne shell pentru controlul fluxului: ''if'', ''for'', ''while'' | ||
- | **Hash-ul** este o funcție [[https://en.wikipedia.org/wiki/One-way_function|one-way]]. Ea primește un input oricât de mare (1 byte, un cuvânt, un fișier, un întreg HDD, etc) și returnează un string de o dimensiune fixă în funcție de tipul de hash folosit. Hash-urile sunt rezistente la **coliziuni**, adică este extrem de greu de găsit 2 input-uri care să producă același hash. Mai mult, un singur bit schimbat în input va genera un output complet diferit. Exemple de algoritmi de hashing: md5 (învechit), SHA-1, SHA-256. | + | ==== Automatizarea prin shell scripting ==== |
- | <note> | + | Automatizarea prin shell scripting presupune, în mod uzual, **o secvență de comenzi**. Aceste comenzi sunt adăugate într-un script unde vor fi rulate la comun, fără a fi nevoie de rularea manuală a fiecărei comenzi. |
- | Hash-urile sunt folosite pentru verificarea integrității unui fișier (dacă chiar și un bit diferă, atunci va avea alt hash) și la stocarea parolelor. | + | |
- | </note> | + | |
- | Folosind comanda **md5sum** fără niciun parametru putem să generăm hash-ul unui text. | + | Pentru a configura rulare unei secvențe de comenzi putem condiționa rularea scriptului folosind **variabile sau argumente în linia de comandă**. Acestea pot genera un comportament diferit al scriptului în funcție de valorile lor. |
- | <code bash> | + | Pe baza variabilelor, argumentelor din linia de comanda sau datelor de intrare, un script poate lua **decizii condiționate**. Verificarea unei condiții poate duce la un comportament sau altul. |
- | student@uso:~$ echo -n "plaintext content" | md5sum | + | |
- | f88d6c9eab9c6a2ef3cfd3c59832b4d6 - | + | |
- | </code> | + | |
+ | În rularea unui script adesea vom dori ca o acțiune să țintească mai multe fișiere sau procese sau șiruri. Pentru aceasta, vom urmări folosirea de **bucle pentru parcurgerea de liste de elemente**. | ||
- | {{ :uso:laboratoare:new:10-sec:lab10_hash1.png?500 |}} | + | Comenzile folosite pot primi ca argument sau la intrarea standard ieșirea altor comenzi. În shell scripting folosim funcționalități de înlănțuire a comenzilor precum **//command expansion// sau //pipe-uri//** ducând la rezultate mai complexe. |
- | + | ||
- | ==== Stocarea parolelor ==== | + | |
- | + | ||
- | 1. Cea mai naivă abordare de stocare a parolelor într-o bază de date este în clar. Dacă un atacator reușește să obține acces la baza de date respectivă, nu doar că obține acces la toate conturile, ci și la orice alt cont al unui utilizator de pe alt site unde a fost folosită aceeași parolă. Este evident că această abordare nu este **sigură**. | + | |
- | + | ||
- | ^ User ^ Password ^ | + | |
- | | Mihai | mereverzi | | + | |
- | | Radu | usoemisto | | + | |
- | | Andrei | usoemehmateemisto | | + | |
- | + | ||
- | 2. O altă variantă (mai sigură) ar fi să nu stocăm parolele în clar, ci să stocăm **hash-ul** parolei în baza de date. Astfel, când un utilizator se loghează, facem hash-ul parolei introduse de el și îl comparam cu cel din baza de date. | + | |
- | + | ||
- | ^ User ^ Password ^ | + | |
- | | Mihai | 43eff133cceacbf1354369568b486450 | | + | |
- | | Radu | 4491fea305731261a83f75672e25bb88 | | + | |
- | | Andrei | 96f3e4decfcd7cd02c3027f0b6416b6e | | + | |
- | + | ||
- | Abordarea este într-adevăr mai bună, dar încă nu complet sigură. Deși hash-urile nu pot fi sparte direct (dintr-un hash să obținem mesajul inițial), ele pot fi atacate folosind dicționare. Un dicționar este o mulțime de corespondențe ''(hash_mesaj) -> (mesaj)''. Pentru a sparge un hash, putem folosi dicționare mari online precum [[https://crackstation.net/|acesta]]. Dacă avem norocul ca hash-ul să se afle în dicționar, atunci obținem parola în clar. De obicei, acest lucru se întâmplă pentru toate parolele ce folosesc cuvinte cunoscute sau au o dimensiune/complexitate mică. | + | |
- | + | ||
- | {{ :uso:laboratoare:new:10-sec:image_crack.png?800 |}} | + | |
- | + | ||
- | Pentru baza de date de mai sus, parola lui Mihai a putut fi spartă, dar cea a lui Andrei nu. Andrei a avut o parola mai lungă, dar acest lucru nu asigură neapărat siguranța ei. | + | |
- | + | ||
- | 3. O abordare finală ar fi să folosim un salt pentru hash-uirea parolei. Salt-ul este un string random de câteva caractere random ce se folosește în felul următor la construirea unui hash: Hash(salt | parolă), unde "|" înseamnă concatenare. Astfel, salt-ul previne atacul cu dicționar de mai sus deoarece este foarte puțin probabil ca hash-ul respectiv să existe într-un dicționar. Salt-ul se stochează în clar în baza de date. | + | |
- | + | ||
- | ^ ^ Salt ^ Password ^ | + | |
- | | Mihai | dfd454ddf | f98ad20d2f42dcd4e53a4d1f40f9c1a5 | | + | |
- | + | ||
- | Pentru Mihai, este: Hash(dfd454ddfmereverzi). | + | |
- | + | ||
- | {{ :uso:laboratoare:new:10-sec:image_crack_2.png?800 |}} | + | |
- | + | ||
- | ==== Liste de cuvinte ==== | + | |
- | **John the Ripper** este un utilitar de spargere al parolelor. În cadrul acestui demo dorim sa aflăm parolele utilizatorilor din sistem. Pentru a reduce timpul de brute-force al utilitarului **John** vom crea o listă de cuvinte. | + | |
- | + | ||
- | Instalare **John The Ripper** | + | |
- | <code bash> | + | |
- | student@uso:~$ sudo apt-get update | + | |
- | student@uso:~$ sudo apt-get install john | + | |
- | </code> | + | |
- | + | ||
- | Copiem hash-urile parolelor în fișierul mypasswd.txt. | + | |
- | <code bash> | + | |
- | student@uso:~$ sudo unshadow /etc/passwd /etc/shadow > mypasswd.txt | + | |
- | </code> | + | |
- | + | ||
- | Creăm o listă de cuvinte care ne-ar putea ajuta sa ghicim parola unui calculator dintr-o universitate. | + | |
- | <code bash> | + | |
- | student@uso:~$ echo -ne "school\nuniversity\nstudent" > wordlist.txt | + | |
- | </code> | + | |
- | + | ||
- | Rulăm utilitarul **John the Ripper**. | + | |
- | <code bash> | + | |
- | student@uso:~$ john --wordlist=wordlist.txt mypasswd.txt | + | |
- | Loaded 3 password hashes with 3 different salts (crypt, generic crypt(3) [?/64]) | + | |
- | Remaining 2 password hashes with 2 different salts | + | |
- | Press 'q' or Ctrl-C to abort, almost any other key for status | + | |
- | 0g 0:00:00:00 100% 0g/s 50.00p/s 100.0c/s 100.0C/s school..student | + | |
- | Session completed | + | |
- | </code> | + | |
- | + | ||
- | Pentru a vizualiza rezultatele rulăm următoarea comandă | + | |
- | <code bash> | + | |
- | student@uso:~$ john --show mypasswd.txt | + | |
- | student:student:1000:1000:Student User,,,:/home/student:/bin/bash | + | |
- | + | ||
- | 1 password hash cracked, 1 left | + | |
- | </code> | + | |
- | Utilitarul ne indică faptul că parola **student** este parola utilizatorului ''student''. | + | |
- | + | ||
- | ==== HTTP vs HTTPS ==== | + | |
- | + | ||
- | Protocolul de rețea **HTTP** aduce beneficii din multe puncte de vedere. Unul dintre dezavantajele lui este faptul că toate datele sunt trimise în clar. Astfel, un atacator precum Trudy va putea intercepta și înțelege un pachet HTTP. | + | |
- | + | ||
- | Acest start suplimentar necesar de criptare este adus de **HTTPS**, detaliat mai pe larg [[https://ro.wikipedia.org/wiki/HTTPS|aici]]. | + | |
- | + | ||
- | {{ :uso:laboratoare:new:10-sec:image_https.png?500 |}} | + | |