intTypePromotion=1
zunia.vn Tuyển sinh 2024 dành cho Gen-Z zunia.vn zunia.vn
ADSENSE

Bài giảng An toàn an ninh thông tin: Bài 10 - Bùi Trọng Tùng

Chia sẻ: Elysale Elysale | Ngày: | Loại File: PDF | Số trang:29

29
lượt xem
4
download
 
  Download Vui lòng tải xuống để xem tài liệu đầy đủ

Bài giảng An toàn an ninh thông tin: Bài 10 An toàn vùng nhớ tiến trình cung cấp cho người học những kiến thức như: Lỗ hổng tràn bộ đệm (Buffer Overflow); Lỗ hổng tràn số nguyên; Lỗ hổng xâu định dạng; Cơ bản về lập trình an toàn. Mời các bạn cùng tham khảo!

Chủ đề:
Lưu

Nội dung Text: Bài giảng An toàn an ninh thông tin: Bài 10 - Bùi Trọng Tùng

  1. BÀI 10. AN TOÀN VÙNG NHỚ TIẾN TRÌNH Bùi Trọng Tùng, Viện Công nghệ thông tin và Truyền thông, Đại học Bách khoa Hà Nội 1 1 Nội dung • Lỗ hổng tràn bộ đệm (Buffer Overflow) • Lỗ hổng tràn số nguyên • Lỗ hổng xâu định dạng • Cơ bản về lập trình an toàn 2 1 2
  2. 2020 CWE Top 25 • Danh sách 25 lỗ hổng phần mềm nguy hiểm nhất: 4 trong số Top 10 là dạng lỗ hổng truy cập bộ nhớ  +1 lỗ hổng liên quan: CWE-20 3 3 1. TỔNG QUAN VỀ TIẾN TRÌNH (NHẮC LẠI) Bùi Trọng Tùng, Viện Công nghệ thông tin và Truyền thông, Đại học Bách khoa Hà Nội 4 2 4
  3. Tiến trình là gì? • Là chương trình đang được thực hiện • Các tài nguyên tối thiểu của tiến trình:  Vùng nhớ được cấp phát  Con trỏ lệnh(Program Counter)  Các thanh ghi của CPU • Khối điều khiển tiến trình(Process Control Block-PCB): Cấu trúc chứa thông tin của tiến trình 5 5 Bộ nhớ của tiến trình(Linux 32-bit) 0xffffffff Tiến trình coi bộ Thực tế đây là bộ nhớ thuộc toàn bộ nhớ ảo với địa chỉ sở hữu của nó ảo, sẽ được HĐH/CPU ánh xạ sang địa chỉ vật lý 0x00000000 6 3 6
  4. Bộ nhớ của tiến trình(Linux 32-bit) 0xffffffff Kernel 0xc0000000 Thiết lập khi tiến cmdline & env trình bắt đầu Stack Thay đổi khi thực thi Heap BSS Xác định ở thời Data điểm biên dịch Text Không gian địa chỉ 0x08048000 Unused của thiết bị vào-ra 0x00000000 7 7 Vùng nhớ stack và heap Trình biên dịch cung cấp các hàm làm thay đổi kích thước vùng nhớ stack khi thực thi chương trình 0x00000000 0xffffffff Heap 3 2 1 Stack Con trỏ push 1 Được quản lý trong tiến stack push 2 trình bởi các hàm cấp push 3 phát bộ nhớ động return (malloc, calloc) 8 4 8
  5. Stack - Thực hiện lời gọi hàm void func(char *arg1, int arg2) { char loc1[4]; int loc2; } 8 byte giữa các tham số và các biến 0xffffffff loc2 loc1 ??? ??? arg1 arg2 caller’s data Các cục bộ được Các tham số đưa đưa vào stack vào stack theo theo thứ tự thứ tự ngược 9 9 Stack frame void func(char *arg1, int arg2) { char loc1[4]; int loc2; } 0xffffffff loc2 loc1 ??? ??? arg1 arg2 caller’s data Stack frame: Một phần của vùng nhớ stack tương ứng với lời gọi của một hàm 10 5 10
  6. Stack frame void main(){ countUp(3);} void countUp(int n) { if(n > 1) countUp(n-1); printf(“%d\n”, n); } 0xffffffff countUp(1) countUp(2) countUp(3) main() Con trỏ stack 11 11 Stack frame void func(char *arg1, int arg2) { char loc1[4]; int loc2; loc2++; Q: loc2 nằm ở đâu? } A: -8(%ebp) • %ebp: con trỏ frame. • (%ebp): nội dung vùng nhớ trỏ bởi %ebp 0xffffffff loc2 loc1 ??? arg1 arg2 caller’s data ??? %ebp Không thể đoán được ở thời điểm dịch 12 6 12
  7. Stack – Trả về từ hàm int main() { ... func(“Hey”, 10); ... Q: Làm cách nào để khôi } phục %ebp của hàm gọi 0xffffffff loc2 loc1 ??? ??? arg1 arg2 caller’s data %ebp %ebp ? 13 13 Stack – Trả về từ hàm int main() { ... func(“Hey”, 10); ... Q: Làm cách nào để khôi } phục %ebp của hàm gọi %esp ??? arg1 arg2 caller’s data %ebp 14 7 14
  8. Stack – Trả về từ hàm int main() { ... func(“Hey”, 10); ... Q: Làm cách nào để khôi } phục %ebp của hàm gọi %esp 0xffffffff %ebp ??? arg1 arg2 caller’s data %ebp 1. Đưa %ebp vào stack trước biến cục bộ (pushl %ebp) 15 15 Stack – Trả về từ hàm int main() { ... func(“Hey”, 10); ... Q: Làm cách nào để khôi } phục %ebp của hàm gọi 0xffffffff loc2 loc1 %ebp ??? arg1 arg2 caller’s data %ebp 1. Đưa %ebp vào stack trước biến cục bộ (pushl %ebp) 2. Thiết lập %ebp bằng với %esp (movl %esp %ebp) 16 8 16
  9. Stack – Trả về từ hàm int main() { ... func(“Hey”, 10); ... Q: Làm cách nào để thực thi } tiếp lệnh sau khi hàm trả về 0xffffffff loc2 loc1 %ebp ??? arg1 arg2 caller’s data %ebp 1. Đưa %ebp vào stack trước biến cục bộ (pushl %ebp) 2. Thiết lập %ebp bằng với %esp (movl %esp %ebp) 3. Khi hàm trả về, thiết lập %ebp bằng (%ebp) (movl (%ebp) %ebp) 17 17 Con trỏ lệnh - %eip ... 0x5bf mov %esp,%ebp 0x5be push %ebp ... ... 0x4a7 mov $0x0,%eax 0x4a2 call 0x49b movl $0x804..,(%esp) 0x493 movl $0xa,0x4(%esp) %eip ... Text 18 9 18
  10. Stack – Trả về từ hàm int main() { ... func(“Hey”, 10); ... Q: Làm cách nào để khôi } phục %ebp của hàm gọi 0xffffffff loc2 loc1 %ebp %eip arg1 arg2 caller’s data %ebp Đưa %eip của lệnh tiếp theo vào stack trước khi gọi hàm 19 19 Stack – Trả về từ hàm int main() { ... func(“Hey”, 10); ... Q: Làm cách nào để khôi } phục %ebp của hàm gọi 0xffffffff loc2 loc1 %ebp %eip arg1 arg2 caller’s data Thiết lập %eip bằng %ebp Đưa %eip của 4(%ebp) khi trả về lệnh tiếp theo vào stack trước khi gọi hàm 20 10 20
  11. Stack – Trả về từ hàm Trong C Mã assembly sau khi dịch return; leave: mov %ebp %esp pop %ebp ret: pop %eip Caller’s Callee’s Caller’s code stack frame stack frame text loc2 loc1 %ebp %eip arg1 arg2 %eip %esp %ebp Con trỏ frame cũ 21 21 Stack – Trả về từ hàm Trong C Mã assembly sau khi dịch return; leave: mov %ebp %esp pop %ebp ret: pop %eip Caller’s Callee’s Caller’s code stack frame stack frame text loc2 loc1 %ebp %eip arg1 arg2 %eip %ebp Con trỏ frame cũ %esp 22 11 22
  12. Stack – Trả về từ hàm Trong C Mã assembly sau khi dịch return; leave: mov %ebp %esp pop %ebp ret: pop %eip Caller’s Callee’s Caller’s code stack frame stack frame text loc2 loc1 %ebp %eip arg1 arg2 %eip %esp %ebp 23 23 Stack – Trả về từ hàm Trong C Mã assembly sau khi dịch return; leave: mov %ebp %esp pop %ebp ret: pop %eip Caller’s Callee’s Caller’s code stack frame stack frame text loc2 loc1 %ebp %eip arg1 arg2 %eip %esp %ebp 24 12 24
  13. Stack – Trả về từ hàm Trong C Mã assembly sau khi dịch return; leave: mov %ebp %esp pop %ebp ret: pop %eip Caller’s Callee’s Caller’s code stack frame stack frame text loc2 loc1 %ebp %eip arg1 arg2 %eip %ebp %esp Các lệnh tiếp theo xóa tham số khỏi stack 25 25 Tổng kết Hàm gọi(trước khi gọi): 1. Đẩy các tham số vào stack theo thứ tự ngược 2. Đẩy địa chỉ trả về vào stack, ví dụ %eip + 2 3. Nhảy tới địa chỉ của hàm được gọi Hàm được gọi: 4. Đẩy %ebp cũ vào stack 5. Thiết lập %ebp tới đỉnh của stack 6. Đẩy các biến cục bộ vào stack truy cập theo độ lệch từ %ebp Hàm được gọi trả về: 7. Thiết lập lại %ebp cũ 8. Nhảy tới địa chỉ trả về Hàm gọi: 9. Xóa các tham số khỏi stack 26 13 26
  14. 2. TẤN CÔNG TRÀN BỘ ĐỆM Bùi Trọng Tùng, Viện Công nghệ thông tin và Truyền thông, Đại học Bách khoa Hà Nội 27 27 Khái niệm • Bộ đệm (Buffer): tập hợp liên tiếp các phần tử có kiểu dữ liệu xác định  Ví dụ: Trong ngôn ngữ C/C++, xâu là bộ đệm của các ký tự  Có thể hiểu theo nghĩa rộng: bộ đệm = vùng nhớ chứa dữ liệu • Tràn bộ đệm (Buffer Overflow): Đưa dữ liệu vào bộ đệm nhiều hơn khả năng chứa của nó • Lỗ hổng tràn bộ đệm: Không kiểm soát kích thước dữ liệu đầu vào. • Tấn công tràn bộ đệm: Phần dữ liệu tràn ra khỏi bộ đệm làm thay đổi luồng thực thi của tiến trình.  Dẫn tới một kết quả ngoài mong đợi • Ngôn ngữ bị ảnh hưởng: C/C++ 28 14 28
  15. C/C++ vẫn rất phổ biến(2020) 29 29 Sự phổ biến của lỗ hổng BoF Sự phổ biến của lỗ hổng Buffer Overflow 1000 7 910 900 880 6.21 841 6 800 5.33 704 5.25 700 5 4.58 600 Số lỗ hổng 4.07 4 500 3 400 287 300 2 200 1 100 0 0 2017 2018 2019 2020 2021 Số lỗ hổng Tỉ lệ (%) 30 15 30
  16. Ví dụ về tràn bộ đệm void func(char *arg1) { char buffer[4]; strcpy(buffer, arg1); return; } int main() { char *mystr = “AuthMe!”; func(mystr); ... } 00 00 00 00 %ebp %eip &arg1 buffer 31 31 Ví dụ về tràn bộ đệm void func(char *arg1) { char buffer[4]; strcpy(buffer, arg1); return; } int main() { char *mystr = “AuthMe!”; func(mystr); ... } M e ! \0 A u t h 4d 65 21 00 %eip &arg1 buffer 32 16 32
  17. Ví dụ về tràn bộ đệm void func(char *arg1) { char buffer[4]; strcpy(buffer, arg1); return; pop %ebp %ebp = 0x0021654d } SEGMENTATION FAULT int main() { char *mystr = “AuthMe!”; func(mystr); ... } M e ! \0 A u t h 4d 65 21 00 %eip &arg1 buffer 33 33 Tràn bộ đệm – Ví dụ khác void func(char *arg1) { int authenticated = 0 char buffer[4]; strcpy(buffer, arg1); if(authenticated){//privileged execution} } int main() { Hàm được thực char *mystr = “AuthMe!”; func(mystr); thi như thế nào? ... } M e ! \0 A u t h 4d 65 21 00 %ebp %eip &arg1 buffer authenticated 34 17 34
  18. Tràn bộ đệm – Ví dụ khác void func(char *arg1) { int authenticated = 0 char buffer[4]; strcpy(buffer, arg1); if(authenticated){//privileged execution} } int main() { char *mystr = “AuthMe!”; func(mystr); ... } Người dùng có thể ghi đè dữ liệu tùy ý tới các vùng nhớ khác 35 35 Khai thác lỗ hổng tràn bộ đệm • Lỗ hổng tràn bộ đệm cho phép kẻ tấn công truy cập (read/write/execute) tùy ý vào vùng nhớ khác • Phương thức khai thác phổ biến nhất: chèn mã nguồn thực thi (code injection) • Ý tưởng X %eip %eip text 00 00 00 00 %ebp %eip &arg1 … Malcode buffer 36 18 36
  19. Code Injection • Vấn đề 1: Nạp mã độc(malcode) vào stack  Phải là mã máy  Không chứa byte có giá trị 0  Không sử dụng bộ nạp (loader)  Không sử dụng vùng nhớ stack • Vấn đề 2: Nạp đúng các địa chỉ lệnh thực thi sau khi kết thúc lời gọi hàm  Xác định đúng %eip  Mức độ khó khi xác định giá trị %eip phụ thuộc vị trí của malcode • Vấn đề 3: Nạp đúng địa chỉ trả về  Xác định đúng %ebp 37 37 Buffer Overflow – Phòng chống • Secure Coding: sử dụng các hàm an toàn có kiểm soát kích thước dữ liệu đầu vào.  fgets(), strlcpy(), strlcat()… • Stack Shield:  Lưu trữ địa chỉ trả về vào vùng nhớ bảo vệ không thể bị ghi đè  Sao chép địa chỉ trả về từ vùng nhớ bảo vệ • Stack Guard: sử dụng các giá trị canh giữ (canary) để phát hiện mã nguồn bị chèn • Non-executable stack: Không cho phép thực thi mã nguồn trong stack  Linux: sysctl -w kernel.exec-shield=0  Vẫn bị khai thác bởi kỹ thuật return-to-libc 38 19 38
  20. Sử dụng giá trị canh giữ - Ví dụ callee() static int random; { caller() int canary = random; { char buffer[]; random = rand(); ... callee(); if(canary!=random) } //detect attack else return; } 00 00 00 00 4d 65 21 00 %eip &arg1 buffer canary Buffer 4d 65 Overflow 21 00attack %eip &arg1 buffer canary 39 39 Buffer Overflow – Phòng chống • Address Space Layout Randomization 0xffffffff Kernel 0xc0000000 Thiết lập khi tiến trình cmdline & env bắt đầu Stack Thay đổi khi thực Nạp vào với địa chỉ thi bắt đầu của mỗi Heap vùng là ngẫu nhiên BSS Xác định ở thời điểm biên dịch Data Text Không gian địa chỉ 0x08048000 của thiết bị vào-ra Unused 0x00000000 40 20 40
ADSENSE

CÓ THỂ BẠN MUỐN DOWNLOAD

 

Đồng bộ tài khoản
2=>2