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 - Bùi Trọng Tùng
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
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
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ộ
nhớ thuộc toàn bộ
sở hữu của nó
Thực tế đây là bộ
nhớ ảo với địa chỉ
ảo, sẽ được
HĐH/CPU ánh xạ
sang địa chỉ vật lý
0x00000000
6
3
6
Bộ nhớ của tiến trình(Linux 32-bit)
0xffffffff
0xc0000000
Kernel
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
0x08048000
0x00000000
Không gian địa chỉ
của thiết bị vào-ra
Unused
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
0xffffffff
0x00000000
3
Heap
2
1
Stack
Con trỏ push 1
Được quản lý trong tiến
trình bởi các hàm cấp
phát bộ nhớ động
(malloc, calloc)
stack
push 2
push 3
return
8
4
8
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
loc1
???
arg1
loc2
???
arg2 caller’s data
Các tham số đưa
vào stack theo
thứ tự ngược
Các cục bộ được
đưa vào stack
theo thứ tự
9
9
Stack frame
void func(char *arg1, int arg2)
{
char loc1[4];
int loc2;
}
0xffffffff
loc1
???
arg1
loc2
???
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
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
loc1
arg1
loc2
???
arg2 caller’s data
???
%ebp
Không thể đoán
được ở thời
điểm dịch
12
6
12
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
loc1
???
arg1
loc2
???
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
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
%ebp
arg1
loc2
???
arg2
caller’s data
loc1
%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
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
%ebp
arg1
loc2
???
arg2
caller’s data
loc1
%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 <func>
0x49b movl $0x804..,(%esp)
0x493 movl $0xa,0x4(%esp)
...
%eip
Text
18
9
18
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
%ebp
arg1
loc2
%eip
arg2
caller’s data
loc1
%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
%ebp
arg1
loc2
%eip
arg2
caller’s data
loc1
%ebp
Đưa %eip của
lệnh tiếp theo
vào stack trước
khi gọi hàm
Thiết lập %eip bằng
4(%ebp) khi trả về
20
10
20
Stack – Trả về từ hàm
Mã assembly sau khi dịch
Trong C
return;
leave:
ret:
mov %ebp %esp
pop %ebp
pop %eip
Caller’s
Caller’s
stack frame
Callee’s
stack frame
code
text
%ebp
arg1
%eip
arg2
loc2
loc1
%esp
%ebp
%eip
Con trỏ frame cũ
21
21
Stack – Trả về từ hàm
Mã assembly sau khi dịch
Trong C
return;
leave:
ret:
mov %ebp %esp
pop %ebp
pop %eip
Caller’s
Caller’s
stack frame
Callee’s
stack frame
code
text
%ebp
arg1
%eip
arg2
loc2
loc1
%ebp
%esp
%eip
Con trỏ frame cũ
22
11
22
Stack – Trả về từ hàm
Mã assembly sau khi dịch
Trong C
return;
leave:
ret:
mov %ebp %esp
pop %ebp
pop %eip
Caller’s
Caller’s
stack frame
Callee’s
stack frame
code
text
%ebp
arg1
%eip
arg2
loc2
loc1
%ebp
%eip
%esp
23
23
Stack – Trả về từ hàm
Mã assembly sau khi dịch
Trong C
return;
leave:
ret:
mov %ebp %esp
pop %ebp
pop %eip
Caller’s
Caller’s
stack frame
Callee’s
stack frame
code
text
%ebp
arg1
%eip
arg2
loc2
loc1
%ebp
%eip
%esp
24
12
24
Stack – Trả về từ hàm
Mã assembly sau khi dịch
Trong C
return;
leave:
ret:
mov %ebp %esp
pop %ebp
pop %eip
Caller’s
Caller’s
stack frame
Callee’s
stack frame
code
text
%ebp
arg1
%eip
arg2
loc2
loc1
%ebp
%eip
%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
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
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
910
7
6
5
4
3
2
1
0
880
900
6.21
841
800
700
600
500
400
300
200
100
0
5.33
5.25
704
4.58
4.07
287
2017
2018
2019
2020
2021
Số lỗ hổng
Tỉ lệ (%)
30
15
30
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);
...
}
&arg1
%eip
00 00 00 00
buffer
%ebp
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
&arg1
%eip
A
u
t
h
4d 65 21 00
buffer
32
16
32
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
&arg1
%eip
A
u
t
h
4d 65 21 00
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
thi như thế nào?
char *mystr = “AuthMe!”;
func(mystr);
...
}
M
e
! \0
%ebp
&arg1
%eip
A
u
t
h
4d 65 21 00
buffer
authenticated
34
17
34
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
%eip
%eip
X
Malcode
%eip
text
00 00 00 00
buffer
%ebp
&arg1
…
36
18
36
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
Sử dụng giá trị canh giữ - Ví dụ
callee()
{
static int random;
caller()
int canary = random;
{
char buffer[];
...
if(canary!=random)
//detect attack
else return;
random = rand();
callee();
}
}
&arg1
arg1
%eip
00 00 00 00 4d 65 21 00
buffer
canary
Buffer Overflow attack
canary
buffer
39
39
Buffer Overflow – Phòng chống
• Address Space Layout Randomization
0xffffffff
0xc0000000
Kernel
cmdline & env
Thiết lập khi tiến trình
bắt đầu
Stack
Thay đổi khi thực
thi
Nạp vào với địa chỉ
bắt đầu của mỗi
Heap
vùng là ngẫu nhiên
BSS
Data
Xác định ở thời
điểm biên dịch
Text
Không gian địa chỉ
của thiết bị vào-ra
0x08048000
Unused
40
0x00000000
20
40
Tải về để xem bản đầy đủ
Bạn đang xem 20 trang mẫu của 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 - Bùi Trọng Tùng", để tải tài liệu gốc về máy hãy click vào nút Download ở trên
File đính kèm:
bai_giang_an_toan_an_ninh_thong_tin_chuong_10_an_toan_vung_n.pdf

