Tải bản đầy đủ (.docx) (214 trang)

16 phat hien loi va lo hong bao mat phan mem phu luc 40 tr

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (1.32 MB, 214 trang )

BAN CƠ YẾU CHÍNH PHỦ
HỌC VIỆN KỸ THUẬT MẬT MÃ

TS ĐẶNG VŨ SƠN
ThS VŨ ĐÌNH THU

GIÁO TRÌNH

TÌM VÀ PHÁT HIỆN LỖ HỔNG PHẦN MỀM

1


BAN CƠ YẾU CHÍNH PHỦ
HỌC VIỆN KỸ THUẬT MẬT MÃ

TS ĐẶNG VŨ SƠN
ThS VŨ ĐÌNH THU

GIÁO TRÌNH

TÌM VÀ PHÁT HIỆN LỖ HỔNG PHẦN MỀM

2


MỤC LỤC
........................................................................................................................ii
DANH MỤC TỪ VIẾT TẮT..................................................................................vi
DANH MỤC CÁC HÌNH....................................................................................vii
DANH MỤC CÁC BẢNG..................................................................................viii


LỜI NÓI ĐẦU...................................................................................................ix
CHƯƠNG I TỔNG QUAN VỀ PHẦN MỀM VÀ LỖ HỔNG PHẦN MỀM..................1
1.1. Khái niệm phần mềm........................................................1
1.2. Quy trình phát triển phần mềm........................................3
1.2.1. Mơ hình thác nước.......................................................3
1.2.2. Mơ hình phát triển tiến hố.........................................4
1.2.3. Mơ hình xoắn ốc Boehm..............................................5
1.2.4. Các quy trình linh hoạt................................................5
1.3. Lỗ hổng phần mềm và hiểm họa.......................................6
Câu hỏi ôn tập chương 1:.........................................................8
2.

CHƯƠNG 2 CÁC DẠNG LỖ HỔNG PHẦN MỀM.........................................9
2.1. Cách thức phân loại...........................................................9
2.2. Các dạng lỗ hổng phần mềm phổ biến...........................10
2.2.1. Tràn bộ đệm..............................................................10
2.2.2. Chuỗi định dạng sai..................................................34
2.2.3. Không kiểm tra dữ liệu đầu vào................................37
2.2.4. Chạy đua...................................................................46
2.2.5. Cơ chế xác thực, phân quyền thực yếu.....................48
Câu hỏi ơn tập chương 2:.......................................................49

3.

CHƯƠNG 3
CÁC PHƯƠNG PHÁP TÌM LỖ HỔNG PHẦN MỀM......50
3.1. Phân tích tĩnh..................................................................50
3.1.1. Phân tích từ vựng......................................................50
3.1.2. Phân tích cú pháp.....................................................51
3.1.3. Phân tích dịng dữ liệu..............................................52

3.1.4. Sử dụng kỹ thuật dịch ngược mã nguồn (REReverse Engineering ).........................................................53
3.2. Phân tích động................................................................55
3.2.1. Chèn lỗi.....................................................................56
3.2.2. Kiểm thử mờ..............................................................56
3


Câu hỏi ôn tập chương 3........................................................58
4.

CHƯƠNG 4 KHAI THÁC LỖ HỔNG PHẦN MỀM.......................................59
4.1. Giới thiệu về khai thác lỗ hổng phần mềm.....................59
4.2. Cách thức khai thác một sỗ lỗ hổng điển hình................59
4.2.1. Xác định lỗ hổng phần mềm.....................................59
4.2.2. Khai thác lỗi tràn bộ đệm..........................................60
4.2.3. Khai thác lỗi sai định dạng chuỗi..............................84
4.2.4. Khai thác lỗ hổng gây ra do lỗi không kiểm soát đầu
vào....................................................................................111
4.3. Khai thác lỗ hổng phần mềm sử dụng phần mềm
Metasploit Framework..........................................................115
Khai thác lỗ hổng phần mềm sử dụng các module có sẵn
của Metasploit:..................................................................119
4.4. Xây dựng mã khai thác lỗ hổng phần mềm..................120
4.4.1. Một số kiến thức cần biết........................................120
4.4.2. Các dạng Shellcode.................................................122
4.4.3. Viết Shellcode khai thác lỗ hổng phần mềm...........125
Câu hỏi ôn tập chương 4......................................................131

5.


CHƯƠNG 5 PHÁT TRIỂN VÀ SỬ DỤNG PHẦN MỀM AN TOÀN..............132
5.1. Phát triển phần mềm an toàn.......................................132
5.1.1. Yêu cầu tiền SDL: đào tạo an ninh..........................132
5.1.2. Pha 1: Yêu cầu.........................................................134
5.1.3. Pha 2: Thiết kế........................................................136
5.1.4. Pha 3: Thực thi........................................................137
5.1.5. Pha 4: Xác minh......................................................138
5.1.6. Pha 5: Phát hành.....................................................139
5.2. Sử dụng phần mềm an toàn..........................................142

TÀI LIỆU THAM KHẢO...................................................................................144
PHỤ LỤC.......................................................................................................145
1. Khai thác lỗ hổng phần mềm sử dụng các module có
sẵn của Metasploit............................................................145
2. Viết Module khai thác lỗ hổng phần mềm dựa trên
Metasploit Framework.......................................................159
4


5


DANH MỤC TỪ VIẾT TẮT
STT

Từ viết
tắt

1


SANS

2

XSS

Cross Site Scripting

3

CGI

Common Gateway
Interface

4

PVF

Potentially
Vulnerable Function

5

HTML

Hyper Text Mult

6


NOP

No Operation
Performed

7

DLL

Dynamic Link Library

Tên tiếng Anh

6

Ý nghĩa


DANH MỤC CÁC HÌNH
Hình 1.1 Phát triển phần mềm theo mơ hình tiến hố.............4
Hình 2.1. Tràn bộ đệm............................................................11
Hình 2.2 Stack........................................................................13
Hình 2.3 Push.........................................................................13
Hình 2.4 Pop...........................................................................14
Hình 2.4 Sơ đồ vị trí các hàm trong Ngăn xếp.......................15
Hình 2.5 Trạng thái của ngăn xếp sau khi hàm function_A()
gọi hàm function_B()..............................................................16
Hình 2.6 Bố trí ngăn xếp bộ nhớ............................................18
Hình 2.7 Ngăn xếp cho hàm authenticate(), trước khi bị khai
thác lỗi tràn bộ nhớ................................................................19

Hình 2.8 Ngăn xếp cho hàm authenticate(), sau khi bị khai
thác lỗi tràn bộ nhớ................................................................20
Hình 2.9 Ghi đè lên địa chỉ trả về...........................................21
Hình 2.10 Danh sách liên kết trước và sau khi thực hiện thay
đổi..........................................................................................25
Hình 2.11 Sự thay đổi Ngăn xếp khi thực thi chương trình bị lỗi
off-by-one...............................................................................33
Hình 2.12 Minh họa bộ nhớ khi thực hiện khai thác lỗi định
dạng chuỗi..............................................................................36
Hình 2.13 Thơng báo minh họa lỗi XSS..................................46
Hình 3.1 Mơ hình phân tích từ vựng.......................................54
Hình 3.2 Ví dụ đồ thị luồng điều khiển...................................57
Hình 4.1 Ngăn xếp của chuỗi định dạng................................90
Hình 4.2 Bộ nhớ lưu trữ chuỗi giá trị nhập vào......................96
Hình 4.3. Kiến trúc Metasploit Framework...........................116
Hình 4.6 Kết quả sau khi thực thi shellcode thêm người dùng.
.............................................................................................131

7


DANH MỤC CÁC BẢNG
Bảng 3.1: Kết quả thu được sau khi phân tích từ vựng..........55

8


LỜI NĨI ĐẦU
Tìm và phát hiện lỗ hổng phần mềm là một lĩnh vực quan
trọng trong An tồn thơng tin, đây cũng là một lĩnh vực khó

địi hỏi người làm lĩnh vực này phải có một kiến thức tốt về rất
nhiều nội dung liên quan đến phần mềm và an tồn phần
mềm
Giáo trình này là tài liệu dùng để giảng dạy cho sinh viên
chun ngành an tồn thơng tin tại Học viện Kỹ thuật Mật mã.
Giáo trình trình bày những nội dung cơ bản về quy trình phát
triển phần mềm, các lỗi phần mềm thường gặp, các phương
pháp phát hiện lỗ hổng phần mềm, cũng như cách thức xây
dựng một module khai thác lỗ hổng phần mềm. Giáo trình có
thể sử dụng làm tài liệu tham khảo rất hữu ích cho những ai
quan tâm đến an tồn thơng tin cụ thể là lĩnh vực tìm và phát
hiện lỗ hổng phần mềm.
Trong quá trình xây dựng giáo trình, các tác giả đã cố
gắng để cập đến các nội dung của lĩnh vực phát hiện lỗ hổng
phần mềm, tuy nhiên đây là lĩnh vực khó do vậy khó có thể
tránh được những thiếu sót. Hy vọng trong những lần chỉnh
sửa bổ sung về sau sẽ hồn thiện giáo trình hơn để phục vụ
tốt hơn cho chương trình đào tạo kỹ sư An tồn thơng tin tại
Học viện Kỹ thuật Mật mã.

Nhóm tác giả

9


CHƯƠNG I TỔNG QUAN VỀ PHẦN MỀM VÀ LỖ HỔNG PHẦN
MỀM
1.1. Khái niệm phần mềm
Phần mềm máy tính hay gọi tắt là phần mềm là một tập
hợp những câu lệnh hoặc chỉ thị được viết bằng một hoặc nhiều

ngôn ngữ lập trình theo một trật tự xác định, và các dữ liệu hay
tài liệu liên quan nhằm tự động thực hiện một số nhiệm vụ hay
các chức năng hoặc giải quyết một vấn đề cụ thể nào đó.
Phần mềm thực hiện gửi các chỉ thị trực tiếp tới phần cứng
hoặc bằng cách cung cấp dữ liệu để phục vụ các chương trình
hay phần mềm khác. Phần mềm khác với phần cứng ở chỗ là
phần mềm không thể sờ hay đụng vào, và nó cần phải có phần
cứng mới có thể chạy được.
Trước đây, để tạo ra chương trình máy tính người ta phải
làm việc trực tiếp với các con số 0 hoặc 1 (sử dụng hệ số nhị
phân), hay còn gọi là ngôn ngữ máy. Công việc này vô cùng khó
khăn, chiếm nhiều thời gian, cơng sức và đặc biệt dễ gây ra lỗi.
Để khắc phục nhược điểm này, người ta đề xuất ra hợp ngữ,
một ngôn ngữ cho phép thay thế dãy 0 hoặc 1 này bởi các từ
gợi nhớ tiếng Anh. Tuy nhiên, cải tiến này vẫn còn chưa thật
thích hợp với đa số người dùng máy tính, những người ln
mong muốn các lệnh chính là ý nghĩa của các thao tác mà nó
mơ tả. Vì vậy, ngay từ những năm 1950, người ta đã xây dựng
ngôn ngữ lập trình mà câu lệnh của nó gần với ngơn ngữ tự
nhiên như ngơn ngữ lập trình FORTRAN. Ngơn ngữ này được gọi
là ngơn ngữ lập trình bậc cao.
Chương trình máy tính thường được tạo ra bởi con người,
những người này được gọi là lập trình viên, tuy nhiên cũng tồn
tại những chương trình được sinh ra bởi các chương trình khác.
Phân loại phần mềm:
1


Phân loại theo cách thức hoạt động:
Phần mềm hệ thống: Dùng để vận hành máy tính và các

phần cứng máy tính, ví dụ như các hệ điều hành máy tính
Windows, Linux, Unix, các thư viện động (còn gọi là thư viện liên
kết động; tiếng Anh: dynamic linked library - DLL) của hệ điều
hành, các trình điều khiển (driver), phần sụn (firmware) và
BIOS. Đây là các loại phần mềm mà hệ điều hành liên lạc với
chúng để điều khiển và quản lý các thiết bị phần cứng.
Phần mềm ứng dụng: Để người sử dụng có thể hồn thành
một hay nhiều cơng việc nào đó, ví dụ như các phần mềm văn
phịng (Microsoft Office, OpenOffice), phần mềm doanh nghiệp,
phần mềm quản lý nguồn nhân lực, phần mềm giáo dục, cơ sở
dữ liệu, phần mềm trị chơi, chương trình tiện ích, hay các loại
phần mềm độc hại.
Các phần mềm chuyển đổi mã bao gồm trình biên dịch và
trình thơng dịch: các loại chương trình này sẽ đọc các câu lệnh
từ mã nguồn được viết bởi các lập trình viên theo một ngơn ngữ
lập trình và dịch nó sang dạng ngơn ngữ máy mà máy tính có
thể hiểu đưọc, hay dịch nó sang một dạng khác như là tập tin
đối tượng (object file) và các tập tin thư viện (library file) mà
các phần mềm khác như hệ điều hành chẳng hạn có thể hiểu để
vận hành máy tính thực thi các lệnh.
Phân loại theo theo khả năng ứng dụng:
Những phần mềm không phụ thuộc, nó có thể được bán cho
bất kỳ khách hàng nào trên thị trường tự do. Ví dụ: phần mềm
về cơ sở dữ liệu như Oracle, đồ họa như Photoshop, Corel Draw,
soạn thảo và xử lý văn bản, bảng tính,...
Ưu điểm: Thơng thường đây là những phần mềm có khả
năng ứng dụng rộng rãi cho nhiều nhóm người sử dụng.
Khuyết điểm: Thiếu tính uyển chuyển, tùy biến.
2



Những phần mềm được viết theo đơn đặt hàng hay hợp
đồng của một khách hàng cụ thể nào đó (một cơng ty, bệnh
viện, trường học,...). Ví dụ: phần mềm điều khiển, phần mềm hỗ
trợ bán hàng,...
Ưu điểm: Có tính uyển chuyển, tùy biến cao để đáp ứng
được nhu cầu của một nhóm người sử dụng nào đó.
Khuyết điểm: Thơng thường đây là những phần mềm ứng
dụng chuyên ngành hẹp.
1.2. Quy trình phát triển phần mềm
Quy trình phát triển phần mềm là một cấu trúc bao gồm tập
hợp các thao tác và các kết quả tương quan sử dụng trong việc
phát triển để sản xuất ra một phần mềm. Đây được coi là một
thành phần tập con của vòng đời phát triển hệ thống. Có bốn
thao tác là nền tảng của hầu hết các quy trình phát triển phần
mềm là:
 Đặc tả phần mềm: Định nghĩa các chức năng của phần mềm
và điều kiện để các chức năng này hoạt động.
 Phát triển phần mềm: Để phần mềm đạt được như đặc tả thì
phải trải qua quy trình phát triển phần mềm này.
 Đánh giá phần mềm: Phần mềm cần phải được đánh giá để
chắc chắn rằng nó có các chức năng và hoạt động đúng như
khách hàng mong muốn.
 Sự tiến hóa của phần mềm: Phần mềm phải tiến hóa để thỏa
mãn nhu cầu thay đổi của khách hàng.
Sau đây là một số mơ hình phát triển phần mềm tiêu biểu:
1.2.1. Mơ hình thác nước
Mơ hình này làm cho ý nghĩa việc sản xuất phần mềm được
thấy rõ hơn qua các giai đoạn như sau:
Phân tích các yêu cầu và định nghĩa: Tìm hiểu hệ thống hiện

có, khó khăn và những mong muốn của khách hàng. Sau đó các
3


yếu tố này được tổng hợp lại và thống nhất bởi cả người phát
triển và khách hàng.
Thiết kế phần mềm và hệ thống: Thiết kế hệ thống các quy
trình, các thành phần và các yêu cầu về cả phần mềm lẫn phần
cứng. Thiết kế phần mềm là việc biểu thị các chức năng hệ
thống phần mềm mà có thể được xây dựng thành một hay
nhiều chương trình khả thi.
Xây dựng và thử nghiệm các đơn vị: Trong giai đoạn này,
phần mềm phải được xây dựng là một tập hợp nhiều chương
trình hay nhiều đơn vị nhỏ. Thử nghiệm các đơn vị để kiểm tra
xem các đơn vị đáp ứng các yêu cầu đã đặt ra trong thiết kế.
Tổng hợp và thử nghiệm tồn bộ: Các đơn vị hay các
chương trình riêng lẻ được tích hợp lại và thử nghiệm tổng thể
xem đã đáp ứng được các yêu cầu đã đặt ra trong thiết kế tổng
thể hay chưa. Sau khi thử nghiệm và chứng tỏ được phần mềm
đã đáp ứng được yêu cầu khách hàng, phần mềm sẽ được cung
ứng cho khách hàng.
Sản xuất và bảo trì: Thơng thường đây là pha lâu nhất của
chu kỳ sống sản phẩm. Phần mềm được cài đặt và được dùng
trong thực tế. Bảo trì bao gồm điều chỉnh các lỗi mà chưa được
phát hiện trong các giai đoạn trước của chu kì sống. Bảo trì
cũng bao gồm việc thực hiện nâng cấp hệ thống khi có u cầu
mới.
Chỗ yếu của mơ hình này là nó khơng linh hoạt. Các bộ
phận của dự án chia ra thành những phần riêng khi thực hiện
phát triển phần mềm. Hệ thống phân phối đơi khi khơng dùng

được vì không thỏa mãn được yêu cầu của khách hàng. Tuy
nhiên mơ hình này phản ảnh thực tế cơng nghệ và đây vẫn là
mơ hình cơ sở cho đa số các hệ thống phát triển phần mềm phần cứng.

4


1.2.2. Mơ hình phát triển tiến hố

Hình 1.1 Phát triển phần mềm theo mơ hình tiến hố
Phân tích mơ hình: Mơ hình phát triển tiến hóa này hiệu quả
hơn mơ hình thác nước. Tuy nhiên, nó vẫn cịn các khuyết điểm:
Quy trình thì khơng nhìn thấy rõ được: Các nhà quản lý cần
phân phối thường xuyên để tính được sự tiến triển.
Phần mềm thường được cấu trúc nghèo nàn: Sự thay đổi
liên tục dễ làm đổ vỡ cấu trúc của phần mềm, tạo ra sự khó
khăn và tốn phí.
Thường địi hỏi những kỹ năng đặc biệt: Hầu hết các hệ
thống phát triển theo cách này được tiến hành bởi các nhóm
nhỏ có kỹ năng cao cũng như các cá nhân phải năng động.
Mơ hình này thích hợp với việc phát triển các loại phần mềm
nhỏ và các loại phần mềm có vịng đời ngắn.
1.2.3. Mơ hình xoắn ốc Boehm
Đây là mơ hình phát triển từ mơ hình thác nước cho thấy
mức độ tổng quát hơn các pha sản xuất của một sản phẩm. Mơ
hình được đề xuất bởi Boehm vào năm 1988. Mơ hình này có thể
chỉ ra các rủi ro có thể hình thành trong mơ hình quy trình phát
triển tổng qt.
Mơ hình Boehm có dạng xoắn ốc. Mỗi vịng lặp đại diện cho
một pha của quy trình phần mềm. Vịng trong cùng tập trung về

tính khả thi, vịng kế về định nghĩa các yêu cầu, kế đến là thiết
kế, ...
5


Khơng có một pha nào được xem là cố định trong vịng
xoắn. Mỗi vịng có 4 phần tương ứng với một pha.
Cài đặt đối tượng: Chỉ ra các đối tượng của các giai đoạn
của dự án. Những vấn đề khó khăn hay cấp thiết của quy trình
và của sản phẩm được xác định và lên kế hoạch chi tiết. Xác
định các yếu tố rủi ro của dự án. Các phương án thay thế tùy
theo các rủi ro này có thể được dự trù.
Lượng định và giảm thiểu rủi ro. Tiến hành phân tích mỗi
yếu tố rủi ro đã xác định. Các bước đặt ra để giảm thiểu rủi ro.
Phát triển và đánh giá: Sau khi đánh giá các yếu tố rủi ro,
một mơ hình phát triển cho hệ thống được lựa chọn.
Lên kế hoạch: Đề án được xem xét và quyết định có nên
hay khơng tiếp tục pha mới trong vịng lặp.
1.2.4. Các quy trình linh hoạt
Là quy trình mà trong đó cấu trúc khởi động sẽ nhỏ nhưng
linh động và lớn dần theo đề án phần mềm nhằm tìm ra các khó
khăn trước khi nó trở thành vấn đề có thể dẫn tới những thiệt
hại cho q trình phát triển. Quy trình này nhấn mạnh sự gọn
nhẹ và tập trung hơn là các phương pháp truyền thống. Các quy
trình linh hoạt dùng các thơng tin phản hồi thay vì dùng các kế
hoạch, như là một cơ chế diều khiển chính. Các thơng tin phản
hồi có được từ các thử nghiệm và các phiên bản phát hành của
phần mềm.
Các quy trình linh hoạt thưịng có hiệu quả hơn các phương
pháp cũ, nó dùng ít thời gian lập trình để sản xuất ra nhiều chức

năng hơn, chất lượng cao hơn, nhưng nó khơng cung cấp một
khả năng lên một kế hoạch lâu dài.
Lập trình cực hạn, gọi tắt là XP, là loại quy trình linh hoạt
được biết đến nhiều nhất. Trong XP, các pha được xúc tiến trong
các bước cực nhỏ nếu so với các quy trình kiểu cũ, gọi là các
6


"toán" xử lý. Bước đầu tiên cho đến các bước sau có thể chỉ tốn
một ngày hay một tuần, thay vì phải tốn nhiều tháng như trong
phương pháp thác nước. Đầu tiên, một người viết các thử
nghiệm tự động để cung cấp các mục tiêu cụ thể cho sự phát
triển. Kế đến là giai đoạn viết mã (bởi một cặp lập trình viên);
giai đoạn này hồn tất khi mà các mã viết qua được tất cả các
thử nghiệm và không có yêu cầu thêm thử nghiệm cần thiết nào
nữa. Thiết kế và kiến trúc được điều chỉnh và nâng cao ngay
sau giai đoạn viết mã này bởi người đã viết mã trong giai đoạn
trước. Hệ thống chưa hoàn tất nhưng hoạt động được này được
khai thác hay được đem ra minh họa cho khách hàng mà trong
số đó có người trong đội phát triển phần mềm. Thời điểm này
những người thực nghiệm lại bắt đầu viết các thử nghiệm cho
những phần quan trọng kế tiếp của hệ thống.
1.3. Lỗ hổng phần mềm và hiểm họa
Một lỗ hổng phần mềm là một điểm yếu hoặc là một lỗi
trong phần mềm có thể bị khai thác bởi một kẻ tấn công để làm
thay đổi hoạt động bình thường của phần mềm.
Trong hầu hết các trường hợp lỗ hổng phần mềm được công
bố thì các lỗ hổng này được phát hiện khi người dùng sử dụng
và đưa vào dữ liệu sai khác như đưa vào dữ liệu có độ dài vượt
quá ngưỡng cho phép và phần mềm sẽ bộc lộ lỗ hổng khi xử lý

các dữ liệu này. Chính việc đưa vào các dữ liệu không đúng được
kẻ tấn công sử dụng để tìm lỗ hổng và tìm cách chèn các mã
độc hại vào hệ thống, cho phép kẻ tấn cơng có thể chạy các
đoạn mã riêng và thực hiện các hành vi khác.
Các lỗ hổng phần mềm thường là những khe hở chính mà kẻ
tấn cơng thường tập trung khai thác để xâm nhập vào các hệ
thống máy tính – từ các máy chủ đến các máy cá nhân của
người dùng cuối.

7


Những hệ thống phần mềm càng phức tạp và lớn thì hiển
nhiên việc kiểm sốt sự xuất hiện những lỗ hổng càng khó, bất
kể các kỹ sư thiết kế có trình độ cao đến đâu. Và chính những
phần mềm này lại thường chiếm vai trò chủ chốt, cũng như tác
động đến nhiều ngóc ngách của hệ thống. Nhờ tận dụng những
lỗ hổng của những phần mềm này, kẻ xấu có thể thực hiện
những thay đổi nhất định lên hệ thống của người dùng, hay nắm
được quyền điều khiển, truy cập các thông tin nhạy cảm.
Trong thực tế, các lỗ hổng có thể bị khai thác sử dụng cho
mục đích xấu tồn tại trên bất cứ phần mềm nào. Thậm chí có
những phần thiết kế khó có thể bị cho là lỗi cho đến khi xuất
hiện những công nghệ cho phép người ngồi khai thác nó và
nhà phát triển phải thiết kế lại cách sản phẩm của mình vận
hành. Khi cập nhật phần mềm mới, ngoài việc thêm vào các
chức năng mới cho phần mềm, hay cải thiện hiệu năng hoạt
động cho sản phẩm, nhà sản xuất còn thực hiện sửa chữa các
lỗi của sản phẩm để đảm bảo cho sản phẩm an toàn hơn. Với
các sản phẩm phổ biến trên thị trường, được phát hành bởi các

công ty, tổ chức hoạt động một cách chuyên nghiệp, điều này là
rất cần thiết.
Tuy vậy, khi có phiên bản phần mềm mới thì sẽ có những
người phát hiện ra lỗi mới của sản phẩm, những người này có
thể khơng phải là người phát triển phần mềm đó, do vậy các
hãng phần mềm lớn thường tổ chức các cuộc thi khai thác lỗ
hổng trên phần mềm của họ, sau đó tuyển mộ nhân tài từ các
cuộc thi đó.
Trong nhiều trường hợp khi nhà phát triển phần mềm đã
phát hiện ra lỗ hổng thì việc khắc phục lỗ hổng có thể mất
nhiều thời gian hơn việc kẻ tấn công viết ra công cụ khai thác lỗ
hổng, và thực hiện phá hoại, xâm nhập trái phép hệ thống hay
trộm cắp dữ liệu bằng cơng cụ đó. Đó cũng chính là lý do mà
các bài viết về lỗ hổng bảo mật thường chỉ xuất hiện vài tháng

8


sau khi lỗ hổng đã được sửa. Các lỗ hổng này có thể được báo
cho nhà sản xuất để sửa chữa.
Trong trường hợp kẻ xấu phát hiện ra lỗ hổng trước và
khơng cơng bố, sau đó phát triển cơng cụ khai thác lỗ hổng và
âm thầm phát tán. Thậm chí giới tội phạm còn đem các lỗ hổng
này ra giao dịch, trao đổi ngầm với nhau, hay bán kèm với
những bộ phần mềm được viết ra chuyên để phục vụ việc tìm
hiểu, khai thác lỗ hổng. Nhà phát triển phần mềm hồn tồn
khơng biết đến sự tồn tại của lỗ hổng đó nên khơng thể nói đến
việc sửa chữa lỗ hổng. Cũng chính vì cuộc tấn cơng được thực
hiện khi nhà phát triển chưa biết về sự tồn tại của lỗ hổng này,
lỗ hổng này còn được gọi là lỗ hổng zero-day.

Có rất nhiều dạng lỗ hổng phần mềm khác nhau, trong
chương tiếp theo sẽ trình bày về các lỗ hổng phần mềm tiêu
biểu thường gặp đối với một phần mềm.

Câu hỏi ơn tập chương 1:
1. Phần mềm là gì? Có những dạng phần mềm gì?
2. Có những quy trình phát triển phần mềm gì, trình bày các
quy trình phát triển phần mềm đó và các ưu, nhược điểm
của các quy trình đó.
3. Lỗ hổng phần mềm là gì? Những hiểm họa do lỗ hổng
phần mềm gây ra.
4. Trình bày những ngun nhân chính gây ra lỗ hổng phần
mềm? Có thể loại trừ hết mọi lỗ hổng phần mềm được
không?

9


1. CHƯƠNG 2 CÁC DẠNG LỖ HỔNG PHẦN MỀM

1.4. Cách thức phân loại
Như đã nói ở chương trước, các lỗ hổng phần mềm trên một
hệ thống là các điểm yếu có thể tạo ra sự ngưng trệ dịch vụ,
thêm quyền với người sử dụng hoặc cho phép truy cập bất hợp
pháp vào hệ thống. Các lỗ hổng này tồn tại ngay chính tại hệ
điều hành như trong các hệ điều hành Windows, Unix, Linux;
hoặc trong các ứng dụng mà người dùng thường xuyên sử dụng
như Microsoft office, Web Browser, các phần mềm cơ sở dữ liệu

Phần lớn các lỗ hổng phần mềm là do lỗi lập trình gây ra.

Việc sử dụng khơng đúng cú pháp của ngơn ngữ lập trình,
khơng kiểm soát chặt chẽ dữ liệu đầu vào, cũng như sai sót khi
tính các giá trị biên chính là các lỗi gây lỗ hỗng phần mềm và
cho phép kẻ tấn cơng có thể lợi dụng các lỗi này để tấn cơng hệ
thống.
Có nhiều tổ chức khác nhau phân loại các lỗ hổng theo cách
khác nhau. Theo cách phân loại của Bộ quốc phòng Mỹ, các loại
lỗ hổng trên một hệ thống được phân loại như sau:
 Lỗ hổng loại C: Các lỗ hổng này cho phép thực hiện các cuộc
tấn cơng từ chối dịch vụ (DoS). DoS là hình thức tấn công sử
dụng các giao thức ở tầng Internet trong bộ giao thức TCP/IP để
làm hệ thống ngưng trệ dẫn đến tình trạng từ chối người dùng
hợp pháp truy cập hay sử dụng hệ thống. Các dịch vụ có chứa lỗ
hổng cho phép thực hiện các cuộc tấn công DoS có thể được
nâng cấp hoặc sửa chữa bằng các phiên bản mới hơn của các
nhà cung cấp dịch vụ. Hiện nay chưa có giải pháp hồn thiện
nào để khắc phục các lỗ hổng loại này. Chủ yếu các lỗ hổng loại
này thường thấy ở các dịch vụ Web. Ví dụ, trình duyệt web của
người dùng bị nhiễm một đoạn mã độc, khi các người dùng kích
hoạt trình duyệt này lập tức đoạn mã độc sẽ thực hiện gửi liên
tiếp các gói tin đến máy chủ đích mà kẻ tấn cơng muốn tấn
10


cơng, số lượng gói tin gia tăng làm cho hệ thống quá tải và
ngừng dịch vụ.
 Lỗ hổng loại B: Lỗ hổng loại này có mức độ nguy hiểm trung
bình, cho phép người sử dụng nội bộ có thể leo thang đặc quyền
hoặc truy cập trái phép. Những lỗ hổng loại này thường xuất
hiện trong các dịch vụ trên hệ thống. Người dùng nội bộ là người

dùng được phép truy cập vào hệ thống với những quyền hạn
nhất định. Một dạng khác của lỗ hổng loại B xảy ra đối với các
phần mềm viết bằng ngôn ngữ C và C++. Những chương trình
viết bằng các ngơn ngữ này thường sử dụng một vùng đệm – là
một vùng nhớ dùng để lưu trữ các dữ liệu trước khi xử lý, và
chương trình khơng kiểm sốt chặt chẽ các giá trị đầu vào. Kẻ
tấn công lợi dụng lỗi này để nhập vào các ký tự đặc biệt nhằm
làm tràn bộ đệm, từ đó thực hiện các lệnh hay đoạn mã đặc biệt
trên hệ thống.
Lỗ hổng loại A: Lỗ hổng loại A có mức độ rất nguy hiểm;
đe dọa đến tính tồn vẹn và bảo mật của hệ thống. Các lỗ hổng
này cho phép người sử dụng ở ngồi có thể truy nhập vào hệ thống bất hợp
pháp. Lỗ hổng rất nguy hiểm, có thể làm phá hủy tồn bộ hệ thống. Lỗ hổng
này xuất hiện ở các hệ thống quản trị yếu kém hoặc khơng kiểm
sốt được cấu hình mạng …
1.5. Các dạng lỗ hổng phần mềm phổ biến
1.5.1. Tràn bộ đệm
Các tiến trình có thể được đưa vào bộ nhớ theo một cách
nào đó mà hệ điều hành lựa chọn, nhưng hầu hết toàn bộ các
hệ thống hiện nay tuân theo một số qui ước chung. Thơng
thường, 1 tiến trình được tổ chức thành các vùng chính sau đây:
- Mã chương trình: Phần này chứa các chỉ thị thực thi chương
trình có thể được biên dịch và thực hiện bởi bộ xử lý. Mã
chương trình bao gồm các mã biên dịch cho việc thực thi
chương trình và các mã bổ sung nằm trong các thư viện
chia sẻ của chương trình. Các thư viện chia sẻ thường
khơng nằm cùng mã chương trình chính.
11



- Dữ liệu chương trình: Phần này được sử dụng để lưu các
biến của chương trình khơng bao gồm các thành phần của
hàm cục bộ. Nó bao gồm cả các biến toàn cục và các biến
tĩnh. Vùng dữ liệu này cũng thường chứa một vùng nhớ
động, được gọi là “program heap”, để chứa các biến cấp
phát động.
- Ngăn xếp chương trình: Được sử dụng như một bộ lưu trữ
động cho các hàm đang thực thi, và nó giữ cho thứ tự gọi
hàm được thực hiện đúng mong muốn.
Vùng đệm là một khu vực bộ nhớ được sử dụng cho việc lưu
trữ tạm thời dữ liệu. Bộ đệm có thể được xây dựng với số lượng
và kích thước bất kỳ, bao gồm cả các khối cấp phát bộ nhớ
khơng có kiểu không xác định. Bộ đệm được sử dụng như là
vùng lưu trữ các giá trị đầu vào của người dùng và lắp ráp các
thông điệp nhận được từ một hệ thống từ xa.
Tràn bộ đệm là loại lỗi thông thường, dễ tránh, nhưng lại
phổ biến và nguy hiểm nhất. Năm 2009, tổ chức SANS đưa ra
báo cáo về 25 lỗi lập trình nguy hiểm nhất trong đó vẫn có lỗi
tràn bộ đệm.
Tràn bộ đệm là lỗi xảy ra khi dữ liệu xử lý thường là dữ liệu
đầu vào dài quá giới hạn của vùng nhớ chứa nó. Nếu phía sau
vùng nhớ này chứa những dữ liệu quan trọng tới quá trình thực
thi của chương trình thì dữ liệu dư có thể sẽ làm hỏng các dữ
liệu quan trọng này. Tùy thuộc vào cách xử lý của chương trình
đối với các dữ liệu quan trọng mà việc khai thác lỗi có thể thực
hiện đến mức là điều khiển chương trình thực hiện tác vụ mong
muốn. Lỗ hổng loại này thường xảy ra trên ngôn ngữ C và C++.

12



Hình 2.1. Tràn bộ đệm
Trong hình 2.1 mơ tả vị trí và q trình tràn bộ đệm. Dữ liệu
nhập vào tăng dần từ hình 2.1 (A), hình 2.1 (B) đến hình 2.1 (C)
và ghi đè lên một phần dữ liệu quan trọng. Qua đó, ta có thể
nhận thấy ba điểm thiết yếu của việc tận dụng lỗi tràn bộ đệm:
 Dữ liệu quan trọng phải nằm phía sau dữ liệu bị tràn. Như hình
2.1, nếu dữ liệu quan trọng nằm bên trái thì dù dữ liệu nhập vào
có nhiều đến đâu thì cũng khơng ảnh hưởng đến dữ liệu quan
trọng.
 Phần dữ liệu tràn phải tràn tới được dữ liệu quan trọng. Đơi khi
ta có thể làm tràn bộ đệm với một số lượng ít dữ liệu, chưa đủ
dài để có thể làm thay đổi giá trị của dữ liệu quan trọng nằm
cách xa đó.
 Cuối cùng, dữ liệu quan trọng bị thay đổi vẫn phải còn ý nghĩa
với chương trình. Trong nhiều trường hợp, tuy ta có thể thay đổi
dữ liệu quan trọng, nhưng trong q trình đó ta cũng thay đổi

13


các dữ liệu khác và khiến cho chương trình bỏ qua việc sử dụng
dữ liệu quan trọng. Xem xét ví dụ dưới đây:
Ví dụ 2.1 Mã chương trình bị lỗi tràn bộ đệm
Func (char *ch)
{
char buffer[100];
strcpy(buffer,ch);
}


Ta thấy rằng biến buffer chỉ được cấp phát 100 ký tự. Tuy
nhiên, biến ch thì lại khơng giới hạn số ký tự. Do đó, nếu biến ch
nhập vào có số ký tự lớn hơn số lượng ký tự mà biến buffer có
thể chứa là 100 thì sẽ xảy ra lỗi tràn bộ đệm. Khi đó ứng dụng
sẽ báo lỗi và khơng thể trả lời các yêu cầu từ người dùng.
1.5.1.1. Tràn bộ đệm trên Stack

Trong khoa học máy tính, một ngăn xếp (cịn gọi là bộ xếp chồng,
tiếng Anh: stack) là một cấu trúc dữ liệu trừu tượng hoạt động theo
nguyên lý "Vào sau ra trước" (Last In First Out-LIFO). Phần tử nào được
thêm vào sau cùng sẽ là phần tử được lấy ra đầu tiên.
Stack là một phần của bộ nhớ. Khi chương trình được nạp vào bộ
nhớ thì phân đoạn stack nằm ngay sau phân đoạn heap. Stack được cấp
phát bởi hệ điều hành cho mỗi thread khi thread được tạo. Khi thread kết
thúc, stack sẽ được xóa bỏ. Kích thước của stack được định nghĩa khi
được tạo và không thể thay đổi. Kết hợp với LIFO khơng địi hỏi cơ chế
quản lý phức tạp nên hoạt động trên stack khá nhanh. Tuy nhiên, nó bị
giới hạn trong kích cỡ.
Mọi phần tử trong Stack phải cùng kiểu dữ liệu và có thể là bất kỳ
kiểu dữ liệu nào. Một Stack gồm có phần đáy (bottom) và phần đỉnh (top).
Phần tử nằm ở đỉnh Stack được gọi là Top Item. Mọi thao tác thêm, xóa
phần tử đều diễn ra ở đỉnh Stack.

14


Hình 2.2 Stack
Stack đơn giản chỉ là một danh sách. Do đó, nó có hầu hết các thao
tác như trên danh sách như thêm, xóa,... tuy nhiên cách cài đặt sẽ khác đi
một chút. Các thao tác cơ bản nhất của Stack là:

Push : Thêm một phần tử vào Stack

Hình 2.3 Push
Pop : Lấy một phần tử ra khỏi Stack

Hình 2.4 Pop
15


Stack lưu biến cục bộ, lời gọi hàm và những thông tin khác mà không cần
lưu trữ trong thời gian lớn. Mỗi lần gọi hàm, các tham số của hàm được push
vào stack, và các giá trị được lưu vào các thanh ghi (EIP, EBP). Khi hàm kết
thúc, giá trị đã lưu của EIP được lấy ra từ stack và đặt trở lại EIP, từ đó ứng dụng
có thể trở lại hoạt động bình thường.
Mỗi tiến trình có một ngăn xếp thực thi hay cịn gọi là “ngăn
xếp chương trình”, “ngăn xếp lời gọi” hoặc đơn giản chỉ là
”ngăn xếp”. Ngăn xếp thực thi cung cấp nền tảng cần thiết cho
các hàm được sử dụng trong mọi ngôn ngữ lập trình có cấu trúc.
Các hàm có thể được gọi theo một thứ tự tùy ý, và chúng có thể
có tính đệ qui hoặc đệ qui lẫn nhau. Ngăn xếp thực thi cung cấp
chức năng này với các bản ghi thao tác, mỗi bản ghi là một
chuỗi các lời gọi từ hàm tới hàm và do đó chúng có thể được lần
theo khi hàm trả về. Một bản ghi thao tác cũng có thể bao gồm
dữ liệu cần thiết được cấp phát tại mỗi thời điểm một hàm được
gọi, chẳng hạn như các biến cục bộ, trạng thái lưu trữ, và các
tham số của hàm.
Do mỗi ngăn xếp thực thi là một phần cơ sở của các chương
trình, chúng được thực thi với sự trợ giúp của CPU thay vì một
phần mềm quản lí. Các bộ xử lý thường có các thanh ghi đặc
biệt trỏ tới đỉnh của ngăn xếp, và có thể được thay đổi bởi các

thao tác mã máy push() hoặc pop(). Trên CPU Intel x86, thanh
ghi này được gọi là thanh ghi ESP (là viết tắt của “extended
stack pointer”)
Trên các hệ thống CPU mới nhất, các ngăn xếp được đánh
địa chỉ giảm dần. Điều này có nghĩa là từ một địa chỉ mức cao
trên bộ nhớ ảo và giảm dần xuống các địa chỉ thấp hơn. Một
thao tác push trừ một giá trị địa chỉ từ con trỏ ngăn xếp và do
đó con trỏ ngăn xếp sẽ trỏ về địa chỉ thấp hơn của bộ nhớ.
Tương tự như vậy, thao tác pop sẽ cộng thêm một giá trị địa chỉ
vào con trỏ ngăn xếp, và chuyển nó đến địa chỉ cao hơn trong
bộ nhớ.
16


×