Differences

This shows you the differences between two versions of the page.

Link to this comparison view

so:curs:mem-sec [2020/04/04 15:28]
razvan.deaconescu
so:curs:mem-sec [2020/04/06 17:33] (current)
alexandru.radovici
Line 16: Line 16:
  
   * Filmări   * Filmări
 +    * 3CA [[https://​web.microsoftstream.com/​video/​631f6edd-2f5b-474e-9f87-ae4edecbd93d]]
     * 3CC, curs 11, partea 1: https://​web.microsoftstream.com/​video/​ff52e02f-c2dc-49d6-b227-2dc9a1026625     * 3CC, curs 11, partea 1: https://​web.microsoftstream.com/​video/​ff52e02f-c2dc-49d6-b227-2dc9a1026625
     * 3CC, curs 11, partea a 2-a: https://​web.microsoftstream.com/​video/​7bae5cdb-0a54-4f2e-b5a5-df039790ac37     * 3CC, curs 11, partea a 2-a: https://​web.microsoftstream.com/​video/​7bae5cdb-0a54-4f2e-b5a5-df039790ac37
 +  ​
 +  * Curs CA [[https://​www.slideshare.net/​alexandruradovici/​sisteme-de-operare-securitatea-memoriei|slideshare]] ​
  
 ===== Demo-uri ===== ===== Demo-uri =====
Line 123: Line 126:
  
 <​code>​ <​code>​
-python ​payloads.py+python3 ​payloads.py
 overwrite func_ptr (32 bits): \x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x5f\x85\x04\x08 overwrite func_ptr (32 bits): \x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x5f\x85\x04\x08
 overwrite return address (32 bits): \x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x46\x85\x04\x08\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x5f\x85\x04\x08 overwrite return address (32 bits): \x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x46\x85\x04\x08\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x5f\x85\x04\x08
Line 254: Line 257:
  
 <​code>​ <​code>​
-checksec buffer-overflow +wget https://raw.githubusercontent.com/slimm609/checksec.sh/master/checksec 
-[*] '/home/razvan/school/so/git-repos/curs.git/curs-07-demo/​buffer-overflow/​buffer-overflow' +[...] 
-    ​Arch: ​    ​amd64-64-little + 
-    ​RELRO: ​   ​Partial RELRO +$ chmod a+x checksec  
-    Stack: ​   ​No canary found + 
-    NX:       NX enabled +./checksec ​--file=buffer-overflow 
-    PIE:      ​No PIE (0x400000) +RELRO           STACK CANARY ​     NX            PIE             ​RPATH ​     RUNPATH Symbols FORTIFY Fortified Fortifiable ​ FILE 
-$ checksec ​buffer-overflow-pie +Partial RELRO   ​No canary found   ​NX enabled ​   ​No PIE          No RPATH   No RUNPATH ​  75 Symbols ​    ​No 0 3 buffer-overflow 
-[*] '/​home/​razvan/​school/​so/​git-repos/​curs.git/curs-07-demo/​buffer-overflow/​buffer-overflow-pie' + 
-    ​Arch: ​    ​amd64-64-little +./checksec ​--file=buffer-overflow-pie 
-    ​RELRO: ​   ​Full RELRO +RELRO           STACK CANARY ​     NX            PIE             ​RPATH ​     RUNPATH Symbols FORTIFY Fortified Fortifiable ​ FILE 
-    Stack: ​   ​No canary found +Full RELRO      No canary found   ​NX enabled ​   PIE enabled ​    No RPATH   No RUNPATH ​  77 Symbols ​    ​No 0 3 buffer-overflow-pie 
-    NX:       NX enabled + 
-    PIE:      ​PIE enabled +./checksec ​--file=buffer-overflow-ssp 
-$ checksec ​buffer-overflow-ssp +RELRO           STACK CANARY ​     NX            PIE             ​RPATH ​     RUNPATH Symbols FORTIFY Fortified Fortifiable ​ FILE 
-[*] '/​home/​razvan/​school/​so/​git-repos/​curs.git/curs-07-demo/​buffer-overflow/​buffer-overflow-ssp' +Partial RELRO   ​Canary found      NX enabled ​   ​No PIE          No RPATH   No RUNPATH ​  76 Symbols ​    ​Yes 0 3 buffer-overflow-ssp
-    ​Arch: ​    ​amd64-64-little +
-    ​RELRO: ​   ​Partial RELRO +
-    Stack: ​   ​Canary found +
-    NX:       NX enabled +
-    PIE:      ​No PIE (0x400000)+
 </​code>​ </​code>​
  
 ==== Injectarea codului. Shellcodes ==== ==== Injectarea codului. Shellcodes ====
 +
 +<note important>​
 +Pentru acest demo trebuie să aveți instalat pe sistem asamblorul NASM. Pe un sistem Debian/​Ubuntu îl puteți instala folosind comanda:
 +<​code>​
 +sudo apt install nasm
 +</​code>​
 +</​note>​
  
 În exploit-urile prezentate mai sus am suprascris code pointeri și am modificat fluxul de execuție al programului apelând o funcție existentă (''​inject_func''​). Această metodă, de refolosire a codului existent în cadrul unui atac, poartă numele de //code reuse attacks//. Din păcate pentru atacator, în cazul unui atac de tipul //code reuse// spațiul posibil de acțiune este limitat la codul existent. Așa că este de preferat un atac de tipul //code injection// care adaugă (injectează) cod în spațiul virtual de adrese al procesului. În general acest cod rezidă într-o zonă de date (unde este citit) care primește permisiuni de execuție. În exploit-urile prezentate mai sus am suprascris code pointeri și am modificat fluxul de execuție al programului apelând o funcție existentă (''​inject_func''​). Această metodă, de refolosire a codului existent în cadrul unui atac, poartă numele de //code reuse attacks//. Din păcate pentru atacator, în cazul unui atac de tipul //code reuse// spațiul posibil de acțiune este limitat la codul existent. Așa că este de preferat un atac de tipul //code injection// care adaugă (injectează) cod în spațiul virtual de adrese al procesului. În general acest cod rezidă într-o zonă de date (unde este citit) care primește permisiuni de execuție.
Line 390: Line 395:
 Programul este compilat cu suport de //Stack Smashing Protection//​ care plasează stack canary pe stivă în funcția ''​process_client()''​. Opțiunea de compilare ''​-fstack-protector''​ este adăugată în fișierul ''​Makefile'':​ Programul este compilat cu suport de //Stack Smashing Protection//​ care plasează stack canary pe stivă în funcția ''​process_client()''​. Opțiunea de compilare ''​-fstack-protector''​ este adăugată în fișierul ''​Makefile'':​
 <​code>​ <​code>​
-CFLAGS = -Wall -Wextra -g -fstack-protector -fno-PIC+CFLAGS = -Wall -Wextra ​-Wno-unused-function ​-g -fstack-protector -fno-PIC
 </​code>​ </​code>​
  
Line 433: Line 438:
 Știm că adresa de retur se găsește pe stivă la adresa ''​rbp+0x8''​. Știm că adresa de retur se găsește pe stivă la adresa ''​rbp+0x8''​.
  
-În realizarea atacului, ținem cont că la ''​fork()''​ (modul de tratare a conexiunilor în implementarea ''​socket_ssp.c''​) se păstrează spațiul de adresă al procesului, se vor păstra și //stack canary//. Așa că le putem suprascrie din clientul TCP octet cu octet până nimerim valoarea acelui octet, conform algoritmului:​ +În realizarea atacului, ținem cont că la ''​fork()''​ (modul de tratare a conexiunilor în implementarea ''​socket_ssp.c''​) se păstrează spațiul de adresă al procesului, se vor păstra și //stack canary//. Așa că le putem suprascrie din clientul TCP octet cu octet până nimerim valoarea acelui octet, conform algoritmului: ​\\ 
-  1. Creăm un mesaj care supascrie doar un octet din //canary value//: umplem spațiul de la buffer la //stack canary// și adăugăm un octet. +1. Creăm un mesaj care supascrie doar un octet din //canary value//: umplem spațiul de la buffer la //stack canary// și adăugăm un octet. ​\\ 
-  2. Trimitem mesajul pe rețea. +2. Trimitem mesajul pe rețea. ​\\ 
-  3. Dacă valoarea nu este cea corectă, procesul copil creat se va încheia cu segmentation fault și conexiune se va încheia. Dacă așa a fost, creștem valoarea cu 1 și încercăm din nou pasul 2. +3. Dacă valoarea nu este cea corectă, procesul copil creat se va încheia cu segmentation fault și conexiune se va încheia. Dacă așa a fost, creștem valoarea cu 1 și încercăm din nou pasul 2. \\ 
-  3'. Când nimerim o valoare, programul nu va genera eroare de tipul //stack smashing detection//​. Se va încheia cu succes, va întoarce mesaj pe rețea și atunci știm că am nimerit octetul și trecem la următorul. +3'. Când nimerim o valoare, programul nu va genera eroare de tipul //stack smashing detection//​. Se va încheia cu succes, va întoarce mesaj pe rețea și atunci știm că am nimerit octetul și trecem la următorul.\\ 
-  4. O dată descoperit un nou octet, mărim mesajul cu un nou octet și trecem la pasul 2.+4. O dată descoperit un nou octet, mărim mesajul cu un nou octet și trecem la pasul 2.
  
 Atacul este descris în fișierul ''​exploit.py''​. Pentru a realiza atacul, avem nevoie de două console: una pe care pornim serverul și una pe care pornim exploit-ul care va crea clienți pentru server. Pornim serverul pe o consolă: Atacul este descris în fișierul ''​exploit.py''​. Pentru a realiza atacul, avem nevoie de două console: una pe care pornim serverul și una pe care pornim exploit-ul care va crea clienți pentru server. Pornim serverul pe o consolă:
Line 447: Line 452:
 și atacul pe altă consolă. Atacul va dura să treacă prin toți octeții și să creeze un proces pentru fiecare socket. În final atacul va reuși și vom apela funcția ''​inject_func()''​. Un exemplu de atac este prezentat în fișierul ''​result.txt'':​ și atacul pe altă consolă. Atacul va dura să treacă prin toți octeții și să creeze un proces pentru fiecare socket. În final atacul va reuși și vom apela funcția ''​inject_func()''​. Un exemplu de atac este prezentat în fișierul ''​result.txt'':​
 <​code>​ <​code>​
-python ​exploit.py+python3 ​exploit.py
 Canary byte 0 is 0x00 Canary byte 0 is 0x00
 Canary byte 1 is 0x0c Canary byte 1 is 0x0c
so/curs/mem-sec.1586003284.txt.gz · Last modified: 2020/04/04 15:28 by razvan.deaconescu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0