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

29 7 0
Bài giảng An toàn an ninh thông tin: Chương 10 - Bùi Trọng Tùng

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

Bài giảng An toàn an ninh thông tin: Chương 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!

BÀI 10 AN TỒN VÙNG NHỚ TIẾN TRÌNH Bùi Trọng Tùng, Viện Công nghệ thông tin Truyền thông, Đại học Bách khoa Hà Nội 1 Nội dung • Lỗ hổng tràn đệm (Buffer Overflow) • Lỗ hổng tràn số nguyên • Lỗ hổng xâu định dạng • Cơ lập trình an tồn 2 2020 CWE Top 25 • Danh sách 25 lỗ hổng phần mềm nguy hiểm nhất: số Top 10 dạng lỗ hổng truy cập nhớ  +1 lỗ hổng liên quan: CWE-20 3 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 Truyền thông, Đại học Bách khoa Hà Nội 4 Tiến trình gì? • Là chương trình thực • Các tài nguyên tối thiểu tiến trình:  Vùng nhớ cấp phát  Con trỏ lệnh(Program Counter)  Các ghi CPU • Khối điều khiển tiến trình(Process Control Block-PCB): Cấu trúc chứa thơng tin tiến trình 5 Bộ nhớ tiến trình(Linux 32-bit) 0xffffffff Tiến trình coi nhớ thuộc tồn sở hữu Thực tế nhớ ảo với địa ảo, HĐH/CPU ánh xạ sang địa vật lý 0x00000000 6 Bộ nhớ tiến trình(Linux 32-bit) 0xffffffff 0xc0000000 Kernel Thiết lập tiến trình bắt đầu cmdline & env Stack Thay đổi thực thi Heap BSS Xác định thời điểm biên dịch Data Không gian địa thiết bị vào-ra Unused Text 0x08048000 0x00000000 7 Vùng nhớ stack heap Trình biên dịch cung cấp hàm làm thay đổi kích thước vùng nhớ stack thực thi chương trình 0xffffffff 0x00000000 Heap Được quản lý tiến trình hàm cấp phát nhớ động (malloc, calloc) Stack Con trỏ stack push push push return 8 Stack - Thực lời gọi hàm void func(char *arg1, int arg2) { char loc1[4]; int loc2; } byte tham số biến 0xffffffff loc2 loc1 ??? ??? arg1 arg2 caller’s data Các tham số đưa vào stack theo thứ tự ngược Các cục đưa vào stack theo thứ tự 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 vùng nhớ stack tương ứng với lời gọi hàm 10 10 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; Q: loc2 nằm đâu? loc2++; A: -8(%ebp) } • %ebp: trỏ frame • (%ebp): nội dung vùng nhớ trỏ %ebp loc2 ??? Khơng thể đốn thời điểm dịch loc1 ??? arg1 0xffffffff arg2 caller’s data %ebp 12 12 Stack – Trả từ hàm int main() { func(“Hey”, 10); Q: Làm cách để khôi phục %ebp hàm gọi } 0xffffffff loc2 loc1 ??? ??? arg1 arg2 caller’s data %ebp %ebp ? 13 13 Stack – Trả từ hàm int main() { func(“Hey”, 10); Q: Làm cách để khôi phục %ebp hàm gọi } %esp ??? arg1 arg2 caller’s data %ebp 14 14 Stack – Trả từ hàm int main() { func(“Hey”, 10); Q: Làm cách để khôi phục %ebp hàm gọi } %esp 0xffffffff %ebp ??? arg1 arg2 caller’s data %ebp Đưa %ebp vào stack trước biến cục (pushl %ebp) 15 15 Stack – Trả từ hàm int main() { func(“Hey”, 10); Q: Làm cách để khôi phục %ebp hàm gọi } 0xffffffff loc2 loc1 %ebp ??? arg1 arg2 caller’s data %ebp Đưa %ebp vào stack trước biến cục (pushl %ebp) Thiết lập %ebp với %esp (movl %esp %ebp) 16 16 Stack – Trả từ hàm int main() { func(“Hey”, 10); Q: Làm cách để thực thi } tiếp lệnh sau hàm trả 0xffffffff loc2 loc1 %ebp ??? arg1 arg2 caller’s data %ebp Đưa %ebp vào stack trước biến cục (pushl %ebp) Thiết lập %ebp với %esp (movl %esp %ebp) Khi hàm trả về, thiết lập %ebp (%ebp) (movl (%ebp) %ebp) 17 17 Con trỏ lệnh - %eip 0x5bf mov %esp,%ebp 0x5be push %ebp 0x4a7 0x4a2 0x49b 0x493 mov $0x0,%eax call movl $0x804 ,(%esp) movl $0xa,0x4(%esp) %eip Text 18 18 Stack – Trả từ hàm int main() { func(“Hey”, 10); Q: Làm cách để khôi phục %ebp hàm gọi } 0xffffffff loc2 loc1 %ebp %eip arg1 arg2 %ebp caller’s data Đưa %eip lệnh vào stack trước gọi hàm 19 19 Stack – Trả từ hàm int main() { func(“Hey”, 10); Q: Làm cách để khôi phục %ebp hàm gọi } 0xffffffff loc2 Thiết lập %eip 4(%ebp) trả loc1 %ebp %ebp %eip arg1 arg2 caller’s data Đưa %eip lệnh vào stack trước gọi hàm 20 10 20 C/C++ phổ biến(2020) 29 29 Sự phổ biến lỗ hổng BoF Sự phổ biến lỗ hổng Buffer Overflow 1000 900 910 6.21 880 841 800 5.33 5.25 704 700 Số lỗ hổng 4.58 600 4.07 500 400 287 300 200 100 0 2017 2018 2019 Số lỗ hổng 2020 2021 Tỉ lệ (%) 30 15 30 Ví dụ tràn đệ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ụ tràn đệm void func(char *arg1) { char buffer[4]; strcpy(buffer, arg1); return; } int main() { char *mystr = “AuthMe!”; func(mystr); } M A u t buffer h e ! \0 4d 65 21 00 %eip &arg1 32 16 32 Ví dụ tràn đệ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 A u t h e ! \0 %eip 4d 65 21 00 buffer &arg1 33 33 Tràn đệm – Ví dụ khác void func(char *arg1) { int authenticated = char buffer[4]; strcpy(buffer, arg1); if(authenticated){//privileged execution} } int main() { Hàm thực char *mystr = “AuthMe!”; thi nào? func(mystr); } M A u t buffer h e ! \0 4d 65 21 00 authenticated %ebp %eip &arg1 34 17 34 Tràn đệm – Ví dụ khác void func(char *arg1) { int authenticated = char buffer[4]; strcpy(buffer, arg1); if(authenticated){//privileged execution} } int main() { char *mystr = “AuthMe!”; func(mystr); } Người dùng ghi đè liệu tùy ý tới vùng nhớ khác 35 35 Khai thác lỗ hổng tràn đệm • Lỗ hổng tràn đệm cho phép kẻ 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 Code Injection • Vấn đề 1: Nạp mã độc(malcode) vào stack  Phải mã máy  Khơng chứa byte có giá trị  Không sử dụng nạp (loader)  Khơng sử dụng vùng nhớ stack • Vấn đề 2: Nạp địa lệnh thực thi sau kết thúc lời gọi hàm  Xác định %eip  Mức độ khó xác định giá trị %eip phụ thuộc vị trí malcode • Vấn đề 3: Nạp địa trả  Xác định %ebp 37 37 Buffer Overflow – Phịng chống • Secure Coding: sử dụng hàm an tồn có kiểm sốt kích thước liệu đầu vào  fgets(), strlcpy(), strlcat()… • Stack Shield:  Lưu trữ địa trả vào vùng nhớ bảo vệ bị ghi đè  Sao chép địa trả từ vùng nhớ bảo vệ • Stack Guard: sử dụng giá trị canh giữ (canary) để phát mã nguồn bị chèn • Non-executable stack: Không cho phép thực thi mã nguồn stack  Linux: sysctl -w kernel.exec-shield=0  Vẫn bị khai thác kỹ thuật return-to-libc 38 19 38 Sử dụng giá trị canh giữ - Ví dụ callee() { int canary = random; char buffer[]; if(canary!=random) //detect attack else return; } 00 00 00 00 buffer static int random; caller() { random = rand(); callee(); } 4d 65 21 00 &arg1 %eip &arg1 canary Buffer Overflow 4d 65 21 00attack buffer %eip canary 39 39 Buffer Overflow – Phịng chống • Address Space Layout Randomization 0xffffffff Kernel 0xc0000000 Thiết lập tiến trình bắt đầu cmdline & env Stack Thay đổi thực thi Heap Xác định thời điểm biên dịch Không gian địa thiết bị vào-ra Nạp vào với địa bắt đầu vùng ngẫu nhiên BSS Data Text Unused 0x08048000 0x00000000 40 40 20 MỘT SỐ LỖ HỔNG TRUY CẬP BỘ NHỚ KHÁC Bùi Trọng Tùng, Viện Công nghệ thông tin Truyền thông, Đại học Bách khoa Hà Nội 41 41 Lỗ hổng xâu định dạng • Format String: Xâu định dạng vào liệu • Lỗ hổng Format String: xâu định dạng không phù hợp với danh sách tham số • Ví dụ void func() { char buf[32]; if(fgets(buf, sizeof(buf),stdin) == NULL) return; printf(buf); } %ebp %eip printf’s stack frame &fmt Caller’s stack frame 42 21 42 Lỗ hổng xâu định dạng • printf(“%d”);  Hiển thị byte phía trước địa stack frame hàm printf • printf(“%s”);  Hiển thị byte gặp ký tự kết thúc xâu • printf(“%d%d%d…”)  Hiển thị chuỗi byte dạng số nguyên • printf(“%x%x%x…”)  Hiển thị chuỗi byte dạng hexa • printf(“…%n”):  Ghi số byte hiển thị vào vùng nhớ 43 43 Lỗ hổng tràn số ngun • Trong máy tính, số ngun biểu diễn trục số tròn Dải biểu diễn:  Số nguyên có dấu: [–2n – 1, 2n–1 – 1]  Số ngun khơng dấu: [0, 2n – 1] • Integer Overflow: Biến số nguyên chương trình nhận giá trị nằm ngồi dải biểu diễn Ví dụ  Số ngun có dấu: 0x7ff f + = 0x80 0, 0xff f + = 0x0  Số nguyên không dấu: 0xff f + = 0x0, 0x0 – = 0xff f • Ngơn ngữ bị ảnh hưởng: Tất • Việc khơng kiểm sốt tượng tràn số ngun dẫn đến truy cập vùng nhớ mà khơng thể kiểm sốt 44 22 44 Lỗ hổng tràn số ngun – Ví dụ • Lỗ hổng nằm đâu? #define MAX 1024 void vul_func1() { char buff[1024]; int len = recv_len_from_client(); char *mess = recv_mess_from_client(); if (len > 1024) printf (“Too large”); else memcpy(buf, mess, len); } 45 45 Lỗ hổng tràn số nguyên – Ví dụ • Lỗ hổng nằm đâu? int main() { int *arr; int len; printf(“Number of items: ”); scanf(“%d”, &len); arr = malloc(len * sizeof(int)); for(int i = 0; i < len; i++) scanf(“%d”, arr[i]); return 0; } 46 23 46 LẬP TRÌNH AN TỒN Bùi Trọng Tùng, Viện Công nghệ thông tin Truyền thông, Đại học Bách khoa Hà Nội 47 47 Lập trình an tồn • Yêu cầu: Viết mã nguồn chương trình để đạt mục tiêu an tồn bảo mật • Bao gồm nhiều kỹ thuật khác nhau:  Kiểm soát giá trị đầu vào  Kiểm soát truy cập nhớ  Che giấu mã nguồn  Chống dịch ngược  Kiểm soát kết đầu  Kiểm soát quyền truy cập … • Bài đề cập đến số quy tắc nhấn mạnh vào vấn đề truy cập nhớ cách an toàn 48 24 48 An tồn truy cập nhớ • An tồn khơng gian(Spatial safety): thao tác nên truy cập vào vùng nhớ xác định • Nếu gọi:  b: địa ô nhớ vùng nhớ  p: địa cần truy cập tới  e: địa ô nhớ cuối vùng nhớ  s: kích thước vùng nhớ cần truy cập • Thao tác truy cập nhớ an toàn khi: b≤p≤e–s • Lưu ý: Các toán tử tác động p không làm thay đổi b e 49 49 An tồn khơng gian – Ví dụ int x = 0; int *y = &x; // b = &x, int *z = y + 1; // b = &x, *y = 10; //OK: &x ≤ *z = 10; //Fail: &x e e p ≤ = = = p &x + &x + &x ≤ = &x 4, s = 4, s = (&x + 4) - + ≤/ (&x + 4) - char str[10]; //b = &str, e = &str + 10 str[5] = 'A'; //OK: &str ≤ p = &str + ≤ (&str + 10) - str[10] = 'F'; //Fail: &str ≤ p = &str + 10 ≤/ (&str + 10) - • Lỗi truy cập khơng an tồn khơng gian gây lỗ hổng biết 50 25 50 An tồn truy cập nhớ • An tồn thời gian(): thao tác truy cập vào vùng nhớ mà khởi tạo:  Đã cấp phát nhớ  Đã khởi tạo giá trị • Ví dụ: Vi phạm an toàn thời gian int n; printf("%d", n); // Fail int *p; *p = 0; // Fail p = (int *) malloc(sizeof(int)); *P = 0; // OK free(p); *p = 10; // Fail 51 51 Điều kiện truy cập nhớ • Tiền điều kiện(precondition): điều kiện để câu lệnh/hàm thực thi đắn • Hậu điều kiện(postcondition): khẳng định trạng thái đắn đối tượng lệnh/hàm kết thúc • Ví dụ: Xác định điều kiện truy cập nhớ void displayArr(int a[], size_t n) { for(size_t i = 0; i < n, i++) printf(“%d”, a[i]); } 52 26 52 Các ngun tắc lập trình an tồn • Khơng tin cậy thứ mà khơng bạn tạo • Người dùng kẻ ngốc nghếch  Hàm gọi (Caller) = Người dùng • Hạn chế cho kẻ khác tiếp cận quan trọng Ví dụ: thành phần bên cấu trúc/đối tượng  Ngôn ngữ OOP: ngun lý đóng gói  Ngơn ngữ non-OOP: sử dụng token • Khơng nói “khơng bao giờ” • Sau đề cập đến số quy tắc C/C++ • Về chủ đề lập trình an toàn, tham khảo đây: https://security.berkeley.edu/secure-coding-practiceguidelines 53 53 Kiểm tra liệu đầu vào • Các giá trị người dùng nhập • File mở • Các gói tin nhận từ mạng • Các liệu thu nhận từ thiết bị cảm biến (Ví dụ: QR code, âm thanh, hình ảnh,…) • Thư viện bên thứ • Mã nguồn cập nhật • Khác… 54 27 54 Sử dụng hàm xử lý xâu an tồn • Sử dụng hàm xử lý xâu an tồn thay cho hàm thơng dụng strcat, strncat  strlcat strcpy, strncpy  strlcpy gets  fgets, fprintf • Ln đảm bảo xâu kết thúc ‘\0’ • Nếu có thể, sử dụng thư viện an tồn Ví dụ: std::string C++ 55 55 Sử dụng trỏ cách an tồn • Hiểu biết tốn tử trỏ: +, -, sizeof • Cần xóa trỏ NULL sau giải phóng nhớ int x = 5; int *p = (int *)malloc(sizeof(int)); free(p); p = NULL; int **q = (int **)malloc(sizeof(int*)); *q = &x; *p = 5; //Crash  OK **q = 3; 56 28 56 Cẩn trọng sử dụng lệnh goto • Ví dụ: 57 57 Sử dụng thư viện an tồn • Nên sử dụng chuẩn C/C++11 thay cho chuẩn cũ • Sử dụng std::string C++ để xử lý xâu • Truyền liệu: sử dụng Goolge Protocol Buffers Apache Thrift 58 29 58 ... 25 • Danh sách 25 lỗ hổng phần mềm nguy hiểm nhất: số Top 10 dạng lỗ hổng truy cập nhớ  +1 lỗ hổng liên quan: CWE-20 3 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. .. giá trị canh giữ - Ví dụ callee() { int canary = random; char buffer[]; if(canary!=random) //detect attack else return; } 00 00 00 00 buffer static int random; caller() { random = rand(); callee();... str [10] = 'F'; //Fail: &str ≤ p = &str + 10 ≤/ (&str + 10) - • Lỗi truy cập khơng an tồn khơng gian gây lỗ hổng biết 50 25 50 An toàn truy cập nhớ • An tồn thời gian(): thao tác truy cập vào vùng nhớ

Ngày đăng: 20/06/2021, 09:04

Tài liệu cùng người dùng

Tài liệu liên quan