This shows you the differences between two versions of the page.
so:cursuri:curs-12 [2013/05/20 16:21] razvan.deaconescu [Demo-uri] |
so:cursuri:curs-12 [2019/05/11 15:36] (current) razvan.deaconescu |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== Curs 12 - Securitatea sistemelor de operare ====== | + | ====== Curs 12 - Implementarea sistemelor de fișiere ====== |
- | <html> | + | * [[http://prezi.com/i7gfiypqqpje/?utm_campaign=share&utm_medium=copy&rc=ex0share|Curs 12 - Implementarea sistemelor de fișiere (Vizualizare Prezi)]] |
- | <iframe src="http://prezi.com/embed/0oxmg6hvis3u/?bgcolor=ffffff&lock_to_path=0&autoplay=0&autohide_ctrls=0&features=undefined&disabled_features=undefined" width="550" height="400" frameBorder="0"></iframe> | + | * [[http://elf.cs.pub.ro/so/res/cursuri/SO_Curs-12.pdf|Curs 12 - Implementarea sistemelor de fișiere (PDF)]] |
- | </html> | + | |
- | * [[http://prezi.com/0oxmg6hvis3u/so-curs-12/?kw=view-0oxmg6hvis3u&rc=ref-31844697 | Curs 12 - Securitatea sistemelor de operare (Vizualizare Prezi)]] | + | * [[https://docs.google.com/document/d/1yQIKPYfAiUehhdSf1D10f3lIH3hnd5xXVyL2ftBH3iQ/edit?usp=sharing|Notițe de curs]] |
- | * [[http://elf.cs.pub.ro/so/res/cursuri/SO_Curs-12.pdf | Curs 12 - Securitatea sistemelor de operare (PDF)]] | + | |
* Suport curs | * Suport curs | ||
- | * Operating System Concepts | + | * Operating System Concepts Essentials |
- | * Capitolul 14 -- Protection | + | * Capitolul 10: File-System Implementation |
- | * Capitolul 15 -- Security | + | * Secțiunile 10.1 -- 10.8 |
- | * Secțiunile 15.1, 15.2, 15.5 | + | |
* Modern Operating Systems | * Modern Operating Systems | ||
- | * Capitolul 9 -- Security | + | * Capitolul 6: File Systems |
- | * Secțiunile 9.4, 9.6 | + | * Secțiunile 6.3, 6.4 |
+ | |||
+ | <html> | ||
+ | <center> | ||
+ | <iframe src="https://prezi.com/embed/i7gfiypqqpje/?bgcolor=ffffff&lock_to_path=0&autoplay=0&autohide_ctrls=0&features=undefined&disabled_features=undefined" width="550" height="400" frameBorder="0"></iframe> | ||
+ | </center> | ||
+ | </html> | ||
===== Demo-uri ===== | ===== Demo-uri ===== | ||
- | Pentru parcurgerea demo-urilor, folosiți [[http://elf.cs.pub.ro/so/res/cursuri/curs-12.zip|arhiva aferentă]]. | + | Pentru parcurgerea demo-urilor, folosiți [[http://elf.cs.pub.ro/so/res/cursuri/curs-12-demo.zip|arhiva aferentă]]. |
- | - Bitul de set-user-ID-on-execution | + | - Folosiți comanda ''stat'' pentru a afișa informații despre inode-ul corespunzător unui fișier, director, link simbolic, char device, block device:<code bash> |
- | * Intrați în directorul ''1-setuid/''. | + | stat /etc/passwd |
- | * Consultați fișierul ''setuid-test.c''. | + | stat /usr/lib/ |
- | * Compilați fișierul folosind comanda ''make''. | + | stat /usr/bin/cc |
- | * Trebuie să aveți drept de sudo pentru a reuși întreg procesul. | + | stat /dev/null |
- | * Folosiți ''ls -l'' pentru a obține informații complete despre executabilul ''setuid-test''. | + | stat /dev/loop0 |
- | * Observați că executabiul este deținut de ''root'' și că are bitul de set-user-ID activat. | + | |
- | * Ca utilizator neprevilegiat rulați executabilul:<code bash> | + | |
- | ./setuid-test | + | |
</code> | </code> | ||
- | * Observați cele trei tipuri de identificatori de utilizatori: //user id//, //effective user ID//, //saved set-user-ID//. | + | * Afișați informații despre un socket Unix, după ce îl căutați în ierarhia ''/var/run/'':<code bash> |
- | * Detalii în [[http://man7.org/linux/man-pages/man7/credentials.7.html|pagina de manual credentials]]. | + | sudo find /var/run -type s |
- | * Observați că se poate reveni la utilizator privilegiat, dacă cel puțin unul dintre identificatorii de utilizatori este 0 (''root'') (//temporary privilege drop//). | + | sudo stat /var/run/udev/control |
- | * În momentul în care nici unul dintre identificatorii de utilizatori nu mai este 0, nu se poate reveni la utilizator privilegiat (//permanent privilege drop//). | + | |
- | - Exemplu de [[http://www.shell-storm.org/shellcode/|shellcode]] | + | |
- | * Intrați în directorul ''2-shellcode/''. | + | |
- | * Consultați fișierul ''shellcode-samples.c''. | + | |
- | * Urmăriți cele trei variabile de tip shellcode. | + | |
- | * Acele variabile se găsesc în forma binară și în fișierul ''binary-shellcodes''. | + | |
- | * Folosiți ''objdump'' pentru a dezasambla fișierul:<code bash> | + | |
- | objdump -D -b binary -mi386 binary-shellcodes | + | |
</code> | </code> | ||
- | * Se afișează instrucțiunile dezasamblate; au fost plasate niște instrucțiuni de tip ''nop'' între cele trei shellcode-uri. | + | * Aflați dimensiunea fișierului ''/sbin/init'' folosind ''stat'':<code bash> |
- | * Observați apelul ''int $0x80'', reprezentând trap pentru acces în kernel space (//apel de sistem//). | + | stat -c %s /sbin/init |
- | * Shellcode-ul din variabila ''shellcode_write'' realizează un apel ''write'', iar shellcode-urile din variabilele ''shellcode_exec'', respectiv ''shellcode_exec_sh'' deschid o sesiune de shell. | + | </code> |
- | * Pentru compilare va trebui să folosiți un sistem pe 32 de biți, precum mașina virtuală de Linux de SO. | + | * Urmăriți modificările timpilor de acces pe fișier (//access time//, //modify time//, //change time//) folosind comenzile de mai jos:<code bash> |
- | * Compilați fișierul folosind comanda ''make''. | + | cd /tmp |
- | * Rulați fișierul obținut:<code bash> | + | touch a.txt |
- | ./shellcode-samples | + | stat a.txt |
+ | cat a.txt | ||
+ | stat a.txt | ||
+ | chmod a+rw a.txt | ||
+ | stat a.txt | ||
+ | echo "abc" > stat.txt | ||
+ | stat a.txt | ||
+ | </code> | ||
+ | * //access time// este timpul de acces al fișierului, deschis pentru citire. | ||
+ | * //modify time// este timpul de modificare a datelor fișierului. | ||
+ | * //change time// este timpul de modificare a metadatelor fișierului (informații din inode). | ||
+ | - Creați un fișier simplu și urmăriți numărul de link-uri ale acestuia:<code bash> | ||
+ | cd /tmp | ||
+ | touch first.txt | ||
+ | ls -i first.txt | ||
+ | ls -l first.txt | ||
+ | </code> | ||
+ | * A doua coloana de la rularea ''ls -l'' este numărul de link-uri, inițial 1. | ||
+ | * Creați un fișier ca hard link la primul:<code bash> | ||
+ | ln first.txt second.txt | ||
+ | </code> | ||
+ | * Observați că inode-ul este același iar numărul de link-uri este egal cu doi:<code bash> | ||
+ | ls -i first.txt second.txt | ||
+ | ls -l first.txt second.txt | ||
+ | </code> | ||
+ | * Creați un al treilea link și observați numărul de link-uri egal cu 3:<code bash> | ||
+ | ln second.txt third.txt | ||
+ | ls -i first.txt second.txt third.txt | ||
+ | ls -l first.txt second.txt third.txt | ||
+ | </code> | ||
+ | * Ștergeți primele două link-uri/nume și obsevați păstrarea inode-ului și reducerea numărului de link-uri la 1 pentru ultimul nume:<code bash> | ||
+ | unlink first.txt | ||
+ | rm second.txt | ||
+ | ls -i third.txt | ||
+ | ls -l third.txt | ||
+ | </code> | ||
+ | * ''unlink'' și ''rm'' pot fi folosite interschimbabil. | ||
+ | - Urmăriți numărul de link-uri/nume aferente unui director gol. Numărul este 2: un link este numele efectiv al directorului, iar altul este referința '.' (punct, //dot//) către director însuși:<code bash> | ||
+ | cd /tmp | ||
+ | mkdir /tmp/test-d | ||
+ | ls -ld /tmp/test-d | ||
+ | </code> | ||
+ | * Creați un subdirector al directorului ''/tmp/test-d/''. Numărul de link-uri va crește la 3, cu ajutorul referinței '..' (punct punct, //dot dot//) de la subdirector:<code bash> | ||
+ | mkdir /tmp/test-d/test-subd | ||
+ | ls -ld /tmp/test-d | ||
+ | </code> | ||
+ | * Creați un subfișier al directorul ''/tmp/test-d/''. Numărul de link-uri nu se va modifica, întrucât fișierul nu are o referință la directorul părinte:<code bash> | ||
+ | touch /tmp/test-d/test-f | ||
+ | ls -ld /tmp/test-d | ||
+ | </code> | ||
+ | - Creați un director simplu și vedeți ce spațiu ocupă pe disc, folosind comanda ''stat'':<code bash> | ||
+ | cd /tmp | ||
+ | mkdir /tmp/fill-d | ||
+ | stat -c %s /tmp/fill-d | ||
+ | </code> | ||
+ | * Copiați scriptul ''create-long-filenames'' din arhivă și rulați-l în directorul proaspăt creat:<code bash> | ||
+ | cd /tmp/fill-d | ||
+ | # TODO: copy script | ||
+ | ./create-long-filenames | ||
+ | </code> | ||
+ | * Observați conținutul directorului și noua dimensiune a acestuia:<code bash> | ||
+ | ls -l /tmp/fill-d | ||
+ | stat -c %s /tmp/fill-d | ||
</code> | </code> | ||
- | * Observați că se deschide o nouă sesiune de shell. | + | * Dimensiunea directorului a crescut datorită numărului de intrări în director. |
- | * Înlocuiți, în ''main'', variabila ''shellcode_exec'' cu ''shellcode_exec_sh'' și, respectiv, ''shellcode_write'', recompilați si rulați, din nou, fișierul obținut. | + | * Dimensiunea directorului este multiplu de dimensiunea blocului sistemului. |
- | - Exploit de tip stack buffer overflow | + | - Citirea intrărilor dintr-un director; simularea comenzii ''ls'' |
- | * Intrați în directorul ''3-exploit/''. | + | * Intrați în directorul ''5-dirent/''. |
- | * Consultați fișierul ''exploit.c''. | + | * Consultați fișierul ''dirent.c''. |
- | * Se încearcă suprascrierea valorii de retur a funcției ''main'' din cadrul parametrului ''argv[1]''. | + | |
- | * Pentru compilare va trebui să folosiți un sistem pe 32 de biți, precum mașina virtuală de Linux de SO. | + | |
* Compilați fișierul folosind comanda ''make''. | * Compilați fișierul folosind comanda ''make''. | ||
- | * Opțiunile de compilare dezactivează stack smashing (''-fno-stack-protector'') și reactivează execuția de cod de pe stivă (''-z execstack''). | + | * Rulați executabilul obținut dându-i ca argument un director:<code bash> |
- | * Consultați fișierul ''run-exploit.sh''. | + | ./dirent tmp |
- | * Acesta compilează fișierul, dacă nu este compilat, dezactivează ASLR (//Address Space Layout Randomization//) și trimite un argument conținând un shellcode programului. | + | ./dirent /usr |
- | * Argumentul trimis conține un shellcode (21 de octeți), urmat de un padding de 23 de caractere ''a'' și adresa de start a bufferului. | + | ./dirent /var/run |
- | * Adresa de start a buffer-ului este suprascrisă în zona cu adresa de retur a funcției ''main''. Când funcția ''main'' se încheie se face jump pe stivă și se execută shellcode-ul. | + | ./dirent /usr/lib |
- | * Padding-ul este necesar pentru a acoperi cei 32 de octeți ai buffer-ului și un padding de aliniere pe stivă dispus de compilator între buffer și salvarea frame pointer-ului (ebp) pe stivă. | + | |
- | * Urmăriți dispunerea argumentelor pe stivă în [[:so:laboratoare:laborator-04#stiva|laboratorul 4]]. | + | |
- | * Rulați scriptul:<code bash> | + | |
- | ./run-exploit.sh | + | |
- | </code> și observați deschiderea unui nou shell. | + | |
- | - Protejarea la stack buffer overflow folosind stack smashing protection | + | |
- | * Intrați în directorul ''4-stack-smash/''. | + | |
- | * Consultați fișierul ''stack-smash.c''. | + | |
- | * Observați că bufferul a este suprascris folosind ''memcpy'' cu un șir de dimensiune mai mare, ajungând să producă un stack buffer overflow cu riscul de suprascriere a adresei de retur a funcției main. | + | |
- | * Folosiți comanda ''make'' pentru a compila două executabile: | + | |
- | * ''stack-smash-no-protector'': fără suport de stack smashing; | + | |
- | * ''stack-smash-protector'': cu suport de stack smashing. | + | |
- | * Rulați cele două executabile:<code bash> | + | |
- | ./stack-smash-no-protector | + | |
- | ./stack-smash-protector | + | |
</code> | </code> | ||
- | * Observați că nu se întâmplă nimic nevalid în cazul primei rulări, dar apare mesaj specific de eroare în cazul celei de-a doua rulări. | + | * Observați afișarea intrărilor și a tipului acestora. |
- | * Programul a fost testat pe un sistem pe care comportamentul este cel de mai sus. | + | * Structura ''struct dirent'' reține informațiile legate de o intrare dintr-un director. |
- | * Dacă pe sistemul vostru nu merge, alterați dimensiunea șirului ''TEST_STRING''. | + | * Un director este, pe disc, un inode ale cărui bloc-uri conține un vector de intrări asemănătoare cu ''struct dirent''. |
+ | * Intrările sunt citite de pe disc folosind apelul ''readdir'', similar folosirii apelului ''read'' pentru fișiere. | ||
+ | * La fel ca fișierele obișnuite (//regular files//) și directoarele folosesc intern un cursor de fișier care este actualizat după fiecare apel ''readdir''. |