Trình biên dịch GCC thực hiện một cơ chế bảo mật được gọi là "Stack Guard" để ngăn chặn lỗi tràn bộ đệm.. Ta có thể tắt tính năng bảo vệ này nếu biên dịch chương trình bằng cách sử dụng
Trang 1HỌC VIỆN CÔNG NGHỆ BƯU CHÍNH VIỄN THÔNG
KHOA AN TOÀN THÔNG TIN
MÔN: KIỂM THỬ XÂM NHẬP BÁO CÁO BÀI THỰC HÀNH
Lỗ hổng Buffer Overflow
Họ và tên sinh viên: Lưu Văn Hưng
Mã số sinh viên: B20DCAT088 Lớp: D20CQAT04-B
Nhóm môn học: Nhóm 04_D20
Họ và tên giảng viên: Đinh Trường Duy
Hà Nội 04/2024
Trang 2Mục lục
Bài thực hành: Lỗ hổng Buffer Overflow 3
I Mục đích 3
II Yêu cầu đối với sinh viên: 3
III Nội dung thực hành 3
1 Chuẩn bị lab 3
2 Khởi động lab 3
3 Shellcode 5
4 Chương trình độc hại 6
5 Nhiệm vụ 1: Khai thác lỗ hổng bảo mật 7
6 Nhiệm vụ 2: Ngẫu nhiên hóa địa chỉ .10
7 Nhiệm vụ 3: Stack Guard .11
8 Nhiệm vụ 4: Ngăn xếp không thực thi 11
9 Kết thúc bài lab: Checkwork 12
Trang 3Bài thực hành: Lỗ hổng Buffer Overflow
I Mục đích
Giúp sinh viên hiểu rõ nguyên nhân, cơ chế cũng như cách thức khắc phục, xử lý
lỗ hổng tràn bộ đệm
II Yêu cầu đối với sinh viên:
• Có kiến thức về ngôn ngữ lập trình C
• Tìm hiểu về Stack, Function, Buffer Overflow và các cơ chế bảo vệ của hệ thống
III Nội dung thực hành
1 Chuẩn bị lab
2 Khởi động lab
Chạy lệnh: labtainer -r bufoverflow
trong terminal của Labtainer
• Kết quả trả về một bash shell Các chương trình được mô tả dưới đây sẽ nằm trong thư mục chính
• Tắt các cơ chế bảo vệ có liên quan:
• Ngẫu nhiên hóa không gian địa chỉ Một số hệ thống dựa trên Linux sử dụng ngẫu nhiên hóa không gian địa chỉ (ASLR) để ngẫu nhiên hóa địa chỉ bắt đầu của heap và stack Điều này làm cho việc đoán các địa chỉ chính xác trở nên khó khăn; đoán địa chỉ là một trong những bước quan trọng
Trang 4của các cuộc tấn công tràn bộ đệm Trong bài lab này, ta tắt các tính năng này bằng các lệnh sau:
sudo sysctl -w kernel.randomize_va_space=0
• Trình bảo vệ StackGuard Trình biên dịch GCC thực hiện một cơ chế bảo mật được gọi là "Stack Guard" để ngăn chặn lỗi tràn bộ đệm Khi có biện pháp bảo vệ này, lỗi tràn bộ đệm sẽ không hoạt động Ta có thể tắt tính năng bảo vệ này nếu biên dịch chương trình bằng cách sử dụng tùy chọn -fno-stack-protector Ví dụ: để biên dịch một chương trình example.c với Stack Guard bị tắt, ta có thể sử dụng lệnh sau:
gcc -m32 -fno-stack-protector example.c
Tùy chọn -m32 được sử dụng để tạo các tệp thực thi 32 bit cho bài lab
Ngăn xếp không thể thực thi (Non-Executable Stack) Ubuntu từng cho phép các ngăn xếp thực thi, nhưng điều này hiện đã thay đổi: mã nhị phân của chương trình (và thư viện được chia sẻ) phải khai báo xem chúng có yêu cầu ngăn xếp thực thi hay không, tức là cần đánh dấu một trường trong header chương trình Kernel hoặc trình liên kết động sử dụng đánh dấu này để quyết định xem có nên làm cho ngăn xếp của chương trình đang chạy này có thể thực thi hay không Việc đánh dấu này được thực hiện tự động trong các phiên bản gcc gần đây và theo mặc định, ngăn xếp được đặt là không thể thực thi Để thay đổi điều đó, hãy sử dụng tùy chọn sau khi biên dịch chương trình:
Trang 5Đối với ngăn xếp thực thi:
$ gcc -m32 -z execstack -o test test.c
Đối với ngăn xếp không thực thi:
$ gcc -m32 -z noexecstack -o test test.c
3 Shellcode
Shellcode này chỉ là phiên bản hợp ngữ của chương trình trên Chương trình sau đây chỉ ra cách khởi chạy một shell bằng cách thực thi một mã shell được lưu trữ trong bộ đệm Hãy biên dịch để chạy đoạn mã sau và xem liệu một shell có được gọi hay không
Lưu ý: Trong bài lab này, ta đã đặt lại chương trình bin/sh bằng một shell cũ hơn và không an toàn Nó sẽ kế thừa các quyền setuid được gán với chương trình stack Các shell hiện đại sẽ sử dụng uid thật của tiến trình làm id của chúng, do
Trang 6đó, việc lấy root shell từ các chương trình setuid trở nên khó khăn hơn Tuy nhiên,
mã shell phức tạp hơn có thể chạy chương trình sau để chuyển id người dùng thực thành root Bằng cách này, ta sẽ có một tiến trình root thực sự
Biên dịch mã (đừng quên tùy chọn execstack):
$ gcc -m32 -z execstack -o call_shellcode call_shellcode.c
4 Chương trình độc hại
Trang 7Biên dịch chương trình trên và chuyển quyền thành set-root-uid Có thể thực hiện điều này bằng cách biên dịch chương trình với tài khoản root và chmod tệp thực thi thành 4755 (đừng quên bao gồm các tùy chọn execstack và -fno-stack-protector để tắt ngăn xếp không thực thi và bảo vệ StackGuard):
5 Nhiệm vụ 1: Khai thác lỗ hổng bảo mật
Dưới đây là một mã khai thác đã hoàn thành một phần có tên là “exploit.c” Mục tiêu của đoạn mã này là xây dựng nội dung cho “badfile” Trong mã này đã có
mã shellcode Sinh viên cần code phần còn lại
Tìm vị trí shellcode:
Giá trị của lea: 0x199 tương ứng 409 bytes
Trang 8Giá trị của lea: 0x199 tương ứng 409 bytes
Code bổ sung:
*(buffer+413) = 0x30;
*(buffer+414) = 0xd3;
*(buffer+415) = 0xff;
*(buffer+416) = 0xff;
int shell_offset = sizeof(buffer) – sizeof(shellcode);
for(int i=0; i<sizeof(shellcode); i++)
{
buffer[shell_offset + i] = shellcode[i];
}
Vị trí bổ sung trong file exploit.c
Trang 9Sau khi chúng ta hoàn thành chương trình trên, biên dịch và chạy nó Điều này
sẽ tạo ra nội dung cho "badfile" Sau đó chạy ngăn xếp chương trình dễ bị tấn công
Trang 106 Nhiệm vụ 2: Ngẫu nhiên hóa địa chỉ
Bật ngẫu nhiên hoá địa chỉ, ta có thể thấy sẽ mất rất nhiều thời gian và số lần thử
để có thể có một cuộc tấn công thành công Nếu may mắn ta sẽ vào được root #, nếu không, nhấn Ctrl + C để thoát
sudo /sbin/sysctl -w kernel.randomize_va_space=2
Trang 117 Nhiệm vụ 3: Stack Guard
Trước khi thực hiện nhiệm vụ này, hãy nhớ tắt ngẫu nhiên địa chỉ trước, nếu không bạn sẽ không biết phương pháp bảo vệ nào giúp có được sự bảo vệ
Trong các nhiệm vụ trước đây, ta đã tắt cơ chế bảo vệ "Stack Guard" trong GCC khi biên dịch chương trình Trong nhiệm vụ này, sinh viên có thể cân nhắc lặp lại nhiệm vụ 1 với sự hiện diện của Stack Guard Để làm điều đó, nên biên dịch chương trình mà không có tùy chọn -fno-stack-protector Đối với nhiệm vụ này, hãy biên dịch lại chương trình có lỗ hổng stack.c Để sử dụng Stack Guard, thực hiện lại nhiệm vụ 1 và báo cáo các quan sát của mình Sinh viên có thể báo cáo bất kỳ thông báo lỗi nào đã quan sát được
Trong GCC 4.3.3 và các phiên bản mới hơn, Stack Guard được bật theo mặc định
Do đó, cần phải vô hiệu hóa Stack Guard bằng cách sử dụng tùy chọn đã đề cập trước đó Trong các phiên bản trước đó, nó đã bị tắt theo mặc định Nếu sử dụng phiên bản GCC cũ hơn, có thể không phải tắt Stack Guard
8 Nhiệm vụ 4: Ngăn xếp không thực thi
Bật tính năng bảo vệ ngăn xếp không thực thi
Trang 129 Kết thúc bài lab: Checkwork