Khóa luận SQL Injection - Tấn công và cách phòng tránh

Khóa luận tốt nghiệp - 2010  
ĐẠI HỌC QUỐC GIA HÀ NỘI  
TRƯỜNG ĐẠI HỌC CÔNG NGHỆ  
Phạm Thanh Cường  
SQL Injection  
Tấn công và cách phòng tránh  
KHOÁ LUẬN TỐT NGHIỆP ĐẠI HỌC HỆ CHÍNH QUY  
Ngành: Các Hệ thống thông tin  
HÀ NỘI - 2010  
SQL Injection – Tấn công và cách phòng tránh  
1
Khóa luận tốt nghiệp - 2010  
ĐẠI HỌC QUỐC GIA HÀ NỘI  
TRƯỜNG ĐẠI HỌC CÔNG NGHỆ  
Phạm Thanh Cường  
SQL Injection  
Tấn công và cách phòng tránh  
KHOÁ LUẬN TỐT NGHIỆP ĐẠI HỌC HỆ CHÍNH QUY  
Ngành: Các hệ thống thông tin  
Cán bộ hướng dẫn: TS. Nguyễn Hải Châu  
HÀ NỘI - 2010  
SQL Injection – Tấn công và cách phòng tránh  
2
Khóa luận tốt nghiệp - 2010  
Lời cảm ơn  
Lời đầu tiên em muốn gửi là lời biết ơn chân thành tới thày Nguyễn Hải Châu.  
Trong suốt thời gian thực hiện khóa luận thày đã tạo điều kiện cho em về thời gian và  
những sự giúp đỡ quý báu về kiến thức, sự chỉ dẫn, định hướng và tài liệu tham khảo  
quý báu. Và sau đó em muốn gửi lời biết ơn chân thành nhất tới toàn thể các thày cô  
trong trường. Các thày cô là những người có kiến thức sâu rộng, nhiệt tình với sinh  
viên, và trên hết đó là các thày cô luôn là tấm gương sáng về nghị lực, lòng say mê  
khoa học, và sự chính trực cho chúng em.  
Những lời biết ơn thân thương nhất con xin kính gửi tới bố mẹ. Bố mẹ đã cho  
con cả quá khứ hiện tại và tương lai. Cám ơn những người bạn tốt trong tập thể  
K51CC, những người bạn đã cùng chia sẻ những niềm vui, nỗi buồn trong suốt quãng  
đời sinh viên của tôi. Kỉ niệm về các bạn là những kỉ niệm đẹp nhất của tôi thời sinh  
viên trên giảng đường đại học.  
Cuối cùng em xin kính chúc các thày cô và toàn thể các bạn sinh viên trường  
Đại học Công nghệ một sức khỏe dồi dào, đạt được những thành công trên con đường  
học tập và nghiên cứu khoa học. Chúc trường ta sẽ sớm trở thành ngọn cờ đầu của  
giáo dục nước nhà và Quốc tế.  
SQL Injection – Tấn công và cách phòng tránh  
3
Khóa luận tốt nghiệp - 2010  
Tóm tắt nội dung  
Theo các báo cáo về an ninh mạng gần đây, như của Whitehat Security(1) hay  
trên trang Verizon Business(2), Sans Institute(3), … thì đều cho thấy mức độ phát triển  
nhanh chóng, tính nghiêm trọng của các lỗ hổng bảo mật và sự quan tâm chưa đúng  
mức của các tổ chức tới vấn đề này. SQL Injection là một vấn đề an ninh ứng dụng  
Web được nhấn mạnh trong các báo cáo trên. Khóa luận này có tên “SQL Injection –  
tấn công và cách phòng tránh”, nhằm mục đích trình bày những hình thái cơ bản của  
các cuộc tấn công SQL Injection lên các ứng dụng Web, từ đó rút ra một mô hình kèm  
theo các khuyến nghị cho việc phát triển ứng dụng Web an toàn.  
Nội dung khóa luận sẽ được trình bày sẽ xoay quanh ba nội dung chính. Thứ  
nhất là nguồn gốc hình thành các điểm yếu SQL Injection trong mã nguồn ứng dụng  
và cách nhận biết. Thứ hai là các phương pháp được sử dụng để thăm dò, khai thác,  
lợi dụng các điểm yếu này để tiến hành tấn công vào ứng dụng web. Thứ ba là các  
khuyến nghị trong việc xây dựng ứng dụng Web, kèm theo đó là đề xuất mô hình phát  
triển ứng dụng Web an toàn.  
-----  
SQL Injection – Tấn công và cách phòng tránh  
4
Khóa luận tốt nghiệp - 2010  
Mục lục  
Chương 1. Đặt vấn đ................................................................................................. 8  
1.1.  
1.2.  
Đặc trưng của ứng dụng sử dụng cơ sở dữ liệu........................................... 8  
SQL Injection và tính nghiêm trọng của vấn đề an ninh cơ sở dữ liệu ........ 9  
Khái niệm SQL Injection:.................................................................... 9  
SQL Injection và vấn đề an ninh cơ sở dữ liệu..................................... 9  
1.2.1.  
1.2.2.  
Chương 2. SQL Injection và các cách tấn công phổ biến ......................................... 14  
2.1.  
2.1.1.  
2.1.2.  
Nhận diện điểm yếu SQL injection trong ứng dụng Web.......................... 14  
Thăm dò dựa trên phản hồi ................................................................ 14  
Cơ chế sinh truy vấn SQL bên trong ứng dụng và các phương pháp  
chèn truy vấn SQL............................................................................................ 17  
2.2.  
Các phương pháp tấn công phổ biến......................................................... 20  
Tấn công khai thác dữ liệu thông qua toán tử UNION ....................... 20  
Khai thác thông qua các câu lệnh điều kiện........................................ 26  
Blind SQL Injection – phương thức tấn công nâng cao...................... 29  
Vấn đề qua mặt các bộ lọc tham số đầu vào....................................... 40  
Một số phương pháp qua mặt bộ lọc của tường lửa Web.................... 45  
2.2.1.  
2.2.2.  
2.2.3.  
2.2.4.  
2.2.5.  
Chương 3. Phòng chống SQL Injection .................................................................... 51  
3.1.  
Phòng chống từ mức xây dựng mã nguồn ứng dụng ................................. 51  
Làm sạch dữ liệu đầu vào .................................................................. 51  
Xây dựng truy vấn theo mô hình tham số hóa.................................... 54  
Chuẩn hóa dữ liệu.............................................................................. 62  
Mô hình thiết kế mã nguồn tổng quát................................................. 63  
Các biện pháp bảo vệ từ mức nền tảng hệ thống....................................... 67  
Các biện pháp bảo vệ tức thời............................................................ 67  
Các biện pháp bảo vệ database........................................................... 71  
Đề xuất một số giải pháp.......................................................................... 72  
3.1.1.  
3.1.2.  
3.1.3.  
3.1.4.  
3.2.  
3.2.1.  
3.2.2.  
3.3.  
Phụ lục: .................................................................................................................... 74  
Cấu hình ModSecurity phòng chống SQL Injection.................................................. 74  
1.  
Cài đt......................................................................................................... 74  
SQL Injection – Tấn công và cách phòng tránh  
5
Khóa luận tốt nghiệp - 2010  
2.  
Cấu hình...................................................................................................... 76  
2.1.  
2.2.  
Cấu hình tổng quát................................................................................ 77  
Cấu trúc các luật ................................................................................... 81  
Tài liệu tham kho.................................................................................................... 94  
SQL Injection – Tấn công và cách phòng tránh  
6
Khóa luận tốt nghiệp - 2010  
Bảng tóm tắt các ký hiệu viết tắt  
Ký hiệu  
Database  
DBMS  
Diễn giải  
Cơ sở dữ liệu  
Database Management System  
(hệ quản trị Cơ sở dữ liệu)  
Web Application Firewall  
(tường lửa cho ứng dụng Web)  
Structured Query Language  
(Ngôn ngữ truy vấn có cấu trúc)  
WAF  
SQL  
SQL Injection – Tấn công và cách phòng tránh  
7
Khóa luận tốt nghiệp - 2010  
Chương 1. Đặt vấn đề  
1.1. Đặc trưng của ứng dụng sử dụng cơ sở dữ liệu.  
Không khó để nhận ra rằng hiện tại, những ứng dụng phổ biến nhất và  
chiếm thị phần cũng như doanh thu cao nhất đều là những ứng dụng hỗ trợ tính  
năng quản lý. Dữ liệu là thứ sống còn trong mọi hoạt động nghiệp vụ hiện tại.  
Chính vì lý do đó, các ứng dụng nghiệp vụ hiện tại đều xây dựng trên những mô  
hình phát triển gắn liền với cơ sở dữ liệu. An toàn của dữ liệu được đặt nặng lên  
tính an toàn và bảo mật của ứng dụng Web kết nối tới cơ sở dữ liệu.  
Các mô hình phát triển ứng dụng Web hiện tại được sử dụng phổ biến nhất  
là 3-tier, ngoài ra còn có một số bản cải tiến, mở rộng mô hình này nhằm những  
mục đích riêng.  
Hình 1.1 – Mô hình ứng dụng 3-tier  
Hình 1.2 – Mô hình ứng dụng 4-tier  
Các mô hình trên luôn có một số điểm chung, đó là database server chỉ làm  
nhiệm vụ lưu trữ dữ liệu, database hồi đáp những truy vấn dữ liệu được xây dựng  
SQL Injection – Tấn công và cách phòng tránh  
8
Khóa luận tốt nghiệp - 2010  
theo chuẩn (ví dụ như SQL). Mọi thao tác xử lý dữ liệu input, output của database  
server đều được ứng dụng web ở tầng Logic xử lý. Các vấn đề an ninh phát sinh đa  
phần sẽ nằm ở tầng này.  
1.2. SQL Injection và tính nghiêm trọng của vấn đề an ninh cơ sở dữ  
liệu  
1.2.1. Khái niệm SQL Injection:  
SQL Injection (còn gọi là SQL Insertion) là một hình thức tấn công  
trong đó truy vấn SQL của ứng dụng đã bị chèn thêm các tham số đầu vào  
“không an toàn” do người dùng nhập vào, từ đó mã lệnh được gửi tới máy chủ  
database để phân tích cú pháp và thực thi.  
Hình thái chính của SQL Injection bao gồm việc chèn trực tiếp mã vào  
các tham số mà sẽ được ghép vào các câu lệnh SQL (quá trình này gọi là sinh  
truy vấn SQL động) để tạo thành truy vấn của ứng dụng gửi tới máy chủ  
database. Một cách tấn công khác ít trực tiếp hơn, đó là chèn mã độc vào các  
xâu mà đích đến là việc lưu trữ trong các bảng hoặc từ điển dữ liệu (metadata).  
Khi các chuỗi đó được ghép vào các câu lệnh SQL thì đoạn mã đó sẽ được  
chạy.  
Khi ứng dụng Web thất bại trong việc lọc các tham số đầu vào (được  
dùng làm nguyên liệu cho quá trình sinh SQL động), ngay cả khi dùng hình  
thức tham số hóa (parameterize) thì kẻ tấn công có thể dễ dàng điều chỉnh quá  
trình xây dựng truy vấn SQL. Một khi kẻ tấn công có thể sửa câu truy vấn  
SQL, thì những truy vấn SQL anh ta muốn sẽ được thực thi với quyền của  
người sở hữu ứng dụng, và thiệt hại anh ta có thể gây ra sẽ tùy theo quyền hạn  
được cấp.  
SQL Injection là một dạng tấn công dễ thực hiện, hầu hết mọi thao tác  
người tấn công cần được thực hiện với một trình duyệt web, có thể kèm theo  
một ứng dụng proxy server. Chính vì đơn giản như vậy cho nên bất cứ ai cũng  
có thể học cách tiến hành một cuộc tấn công. Lỗi bắt nguồn từ mã nguồn của  
ứng dụng web chứ không phải từ phía database, chính vì thế bất cứ thành phần  
nào của ứng dụng mà người dùng có thể tương tác được để điều khiển nội  
dung (ví dụ : các form, tham số URL, cookie, tham số referrer, user-agent, …)  
đều có thể được sử dụng để tiến hành chèn truy vấn có hại.  
1.2.2. SQL Injection và vấn đề an ninh cơ sở dữ liệu.  
a. Các thống kê về an ninh  
SQL Injection – Tấn công và cách phòng tránh  
9
Khóa luận tốt nghiệp - 2010  
Chúng ta xem xét các báo cáo an ninh của các ứng dụng Web  
gần đây của Whitehat, một tổ chức có uy tín trong việc nghiên cứu  
và hỗ trợ các vấn đề an ninh mạng.  
Thống kê 10 lỗi bảo mật nghiêm trọng nhất:  
Trích từ nguồn :  
Thống kê 10 lỗ hổng bảo mật phổ biến nhất xuất hiện trên các  
website được khảo sát:  
Kết quả thống kê trình bày tháng 3/2008:  
Hình 1.3 – thống kê 10 điểm yếu phổ biến nhất (2008)  
Kết quả thống kê trình bày tháng 2/2009:  
Hình 1.4 – thống kê 10 điểm yếu phổ biến nhất (2009)  
Thống kê thời gian trung bình cần để khắc phục các lỗ hổng  
bảo mật kể trên  
SQL Injection – Tấn công và cách phòng tránh  
10  
Khóa luận tốt nghiệp - 2010  
Kết quả thống kê trình bày tháng 8/2008  
Hình 1.5 – thống kê thời gian trung bình khắc phục điểm yếu (2008)  
Kết quả trình bày tháng 2/2009  
Hình 1.6 – thống kê thời gian trung bình khắc phục điểm yếu (2009)  
SQL Injection – Tấn công và cách phòng tránh  
11  
Khóa luận tốt nghiệp - 2010  
Thống kê tỉ lệ điểm yếu thường xuyên bị khai thác  
Một thống kê khác về tỉ lệ các điểm yếu thường được các  
hacker khai thác. Thống kê được trích trong một bài báo đăng  
trên tạp chí computerworld tháng 2/2010.  
Địa chỉ  
curity_Issues?taxonomyId=17&pageNumber=1)  
Đường dẫn của thống kê  
HackingIncidents-2009.pdf)  
Hình 1.7 – thống kê các điểm yếu thường được khai thác nhất  
b. Đánh giá các kết quả thống kê  
Dựa vào các thống kê trên có thể rút ra vài nhận xét sau về lỗi  
SQL Injection:  
Là một trong số những lỗi bảo mật phổ biến nhất  
Xác suất gặp phải lỗ hổng bảo mật loại này trong một trang  
web là khá cao  
Được sử dụng nhiều, lý do một phần bởi tính đơn giản, không  
đòi hỏi nhiều công cụ hỗ trợ.  
Thời gian khắc phục các điểm yếu này thường khá lâu, do đó  
hậu quả thường nặng nề hơn.  
Trên thực tế, các cuộc tấn công SQL Injection thường nhắm  
đến các cơ sở dữ liệu mang tính thương mại, ví dụ các trang web  
SQL Injection – Tấn công và cách phòng tránh  
12  
Khóa luận tốt nghiệp - 2010  
thương mại điện tử. Thông thường, các cuộc tấn công này thường sẽ  
tiến hành việc sửa đổi nội dung của database đối tượng và chèn các  
đoạn mã JavaScript độc. Bản chất điểm yếu SQL Injection là xuất  
hiện từ trong quá trình xử lý dữ liệu input của người dùng bên trong  
mã nguồn, do chính thời gian bảo trì mã nguồn thường kéo dài nên  
các lỗi SQL Injection cũng chậm được khắc phục triệt để.  
c. Nhận định  
Với tính nghiêm trọng của các cuộc tấn công, tính dễ thực hiện  
một cuộc tấn công đã khiến cho SQL Injection một thời từng là hiểm  
họa nghiêm trọng đối với các giao dịch thương mại điện tử trên các ứng  
dụng Web được phát triển thiếu an toàn. Hiện nay, việc nghiên cứu SQL  
Injection đã có hệ thống và toàn diện hơn, mối nguy hiểm này đã giảm  
đi, nhưng số liệu thống kê vẫn cho thấy vấn đề này còn chưa được giải  
quyết triệt để.  
Ở nước ta, trong quá trình đào tạo, các lập trình viên ứng dụng  
Web được đào tạo nhiều kiến thức và kỹ năng cần thiết, tuy nhiên các  
kiến thức về bảo mật hầu như không được chú trọng đúng mức. Điều  
này vô hình chung dẫn đến hệ quả là các sản phẩm của họ đều có nguy  
cơ mắc phải những vấn đề về bảo mật, điều mà không đáng có nếu họ  
được trang bị tốt hiểu biết từ đầu.  
Mục đích của khóa luận này tập trung phân tích cơ bản, cách hình  
thành và các kỹ thuật tấn công của một cuộc tấn công SQL Injection tới  
một ứng dụng Web, thông qua đó tổng hợp và đề xuất một mô hình phát  
triển ứng dụng Web an toàn cho các nhà phát triển ứng dụng Web. Các  
kiến thức được đề cập trong khuôn khổ khóa luận này có thể không đảm  
bảo tính thời sự, mới nhất của tình hình các cuộc tấn công hiện tại. Tuy  
nhiên người thực hiện vẫn hy vọng có thể đề cập và cung cấp một cái  
nhìn tổng thể, căn bản nhất cho cộng đồng các nhà phát triển ứng dụng  
web hiện tại và sau này.  
SQL Injection – Tấn công và cách phòng tránh  
13  
Khóa luận tốt nghiệp - 2010  
Chương 2. SQL Injection và các cách tấn công  
phổ biến  
2.1. Nhận diện điểm yếu SQL injection trong ứng dụng Web  
Công việc nhận diện điểm yếu này là công việc đầu tiên trong chuỗi các  
thao tác cần để khắc phục điểm yếu SQL Injection trong ứng dụng. Công việc  
này được thực hiện tương tự các thao tác hacker tiến hành thăm dò lỗi SQL  
Injection của ứng dụng. Chúng ta xét một số công việc cần thực hiện trong quá  
trình thăm dò lỗi SQL Injection.  
2.1.1. Thăm dò dựa trên phản hồi  
Thăm dò dựa trên phản hồi là phương pháp tự nhiên nhất. Chúng  
ta cần tối thiểu là một trình duyệt web, có thể trang bị thêm một ứng  
dụng Proxy (ví dụ Burp proxy, Web Scarab proxy, …) và tiến hành các  
phép thử SQL Injection ngẫu nhiên và tiến hành phân tích, thống kê kết  
quả. Các bước tiến hành gồm có:  
o Xác định tất cả các điểm nhận input từ client  
o Thử và xác định đặc điểm chung của những request có phát sinh kết  
quả bất thường  
o Xác định nguyên nhân các điểm bất thường đó.  
a. Xác định các điểm nhận input từ người dùng.  
Phía client trong mô hình Client/Server trong môi trường Web  
chính là trình duyệt Web. Những điểm nhận input phổ biến nhất  
từ client là đường dẫn (link), khung nhập liệu (form), cookie, …  
Sau khi thực hiện gửi input, trình duyệt Web sẽ sinh một request  
HTTP gửi tới Web server. Định dạng thông điệp request phổ biến  
nhất là GET và POST.  
Cấu trúc thông điệp GET và POST có nhiều điểm khác nhau,  
xong khi tiến hành sửa đổi và chèn nội dung (inject) chúng ta cần  
chú ý tới vị trí của chuỗi truy vấn (query string). Chuỗi truy vấn  
này chứa các chuỗi tham số được gửi lên web server, chuỗi này  
có dạng sau: ?var_1=val_1&var_2=val_2& … &var_n=val_n.  
Trong thông điệp GET chuỗi truy vấn nằm ở đầu thông điệp,  
trong khi ở POST nó nằm ở cuối thông điệp.  
Xét một trang thông tin có đường dẫn:  
SQL Injection – Tấn công và cách phòng tránh  
14  
Khóa luận tốt nghiệp - 2010  
Nội dung trang trên có các đường liên kết (link), khi click  
chuột vào từng liên kết đó sẽ dẫn tới các địa chỉ dạng như:  
Trong trường hợp này thông điệp request là GET bởi chuỗi  
truy vấn (query string) được hiển thị ngay trên trình duyệt. Tham  
số xuất hiện trong trường hợp này là cat_name, ứng với mỗi giá  
trị cat_name thì nội dung trả về sẽ khác nhau. Thực hiện sửa nội  
dung cat_name rồi gửi, với đường dẫn:  
Kết quả trả về sẽ có thể là một thông báo lỗi dạng sau:  
Warning: mysqli_fetch_object() expects parameter 1 to be  
mysqli_result, boolean given in  
/home1/thangmom/public_html/includes/functions.php on  
line 225  
Thử thêm dấu nháy đơn (‘) vào cuối giá trị tham số cat_name,  
ta có kết quả trả về cho đường dẫn:  
http://www.site.com/categories_index.php?cat_name=nothing’  
You have an error in your SQL syntax; check the manual that  
corresponds to your MySQL server version for the right syntax to use  
near '\'' at line 1  
Như vậy chúng ta nhận thấy có những dấu hiệu bất thường  
trong phản hồi ứng với các giá trị tham số được chỉnh sửa khác  
nhau.  
b. Các hình thức trả thông báo lỗi thường gặp  
Những thông báo lỗi trả về ở trên là những thông báo lỗi  
chi tiết, chúng là “trợ giúp đắc lực” cho hacker trong việc khai  
SQL Injection – Tấn công và cách phòng tránh  
15  
Khóa luận tốt nghiệp - 2010  
thác thông tin từ database của ứng dụng. Ngoài cách hiển thị  
chi tiết này ra Webserver còn có vài lựa chọn sau:  
Nội dung lỗi được giấu đi nhằm mục đích gỡ lỗi trong mã  
nguồn  
Trả về một mã lỗi HTTP, ví dụ 500 (Internal Server  
Error), 302 (redirect), …  
ứng dụng bắt lỗi, xử lý nó bằng cách không trả về kết quả  
gì, hoặc trả về một trang thông báo lỗi tổng quát. Trang  
này được cấu hình, ví dụ trong Apache2 là file  
conf.d/localized-error-pages.  
Trường hợp ứng dụng cấu hình một trang mặc định được  
trả về trong trường hợp sinh lỗi là trường hợp khó nhận diện  
điểm yếu hơn cả, bởi có nhiều lý do có thể sinh lỗi, không chỉ  
riêng trường hợp chúng ta chèn tham số.  
Trong các trường hợp điểm yếu SQL Injection tồn tại, có  
một trường hợp khó phát hiện hơn cả, đó là trường hợp Blind  
SQL Injection. Thông thường, các tham số từ chuỗi truy vấn  
được dùng để xây dựng câu truy vấn SQL , ví dụ với đoạn  
URL university.php?searchkey=’vnu’. Có thể được sử dụng  
để xây dựng truy vấn ví dụ như:  
SELECT * FROM university WHERE name like ‘%vnu%’;  
Blind SQL Injection là một dạng tấn công mà không thể  
dựa vào các thông báo lỗi thông thường, mà chỉ có thể dựa  
vào sự khác nhau trong phản hồi giữa hai trương hợp đúng/sai  
của mệnh đề WHERE. Ví dụ, hai truy vấn ứng với hai trường  
hợp tham số nhập vào sau của trang university.php sau:  
Tham số vnu%’ or 1=1-- ta có truy vấn:  
SELECT * FROM university WHERE name like ‘%vnu%’ or  
1=1--%’’  
Tham số vnu’ and 1=0-- ta có truy vấn:  
SELECT * FROM university WHERE name like ‘%vnu%’ and  
1=0--%’’  
SQL Injection – Tấn công và cách phòng tránh  
16  
Khóa luận tốt nghiệp - 2010  
Hai truy vấn trên khác nhau ở chỗ truy vấn thứ nhất có  
mệnh đề WHERE luôn đúng, còn truy vấn thứ hai có mệnh đề  
luôn sai. Nếu kết quả trả về có sự khác biệt giữa hai trường  
hợp tham số này với nhau và với trường hợp tham số không bị  
chỉnh sửa thì rất có thể tồn tại điểm yếu dạng blind SQL  
Injection.  
2.1.2. Cơ chế sinh truy vấn SQL bên trong ứng dụng và các  
phương pháp chèn truy vấn SQL  
a. Cơ chế sinh truy vấn SQL bên trong ứng dụng.  
Tham số được nhập vào sẽ được sử dụng để xây dựng các truy  
vấn SQL nên nó sẽ cần thỏa mãn các ràng buộc cú pháp với thành  
phần trước và sau trong truy vấn gốc. Xét đoạn mã PHP xử lý  
đăng nhập sau:  
<?php  
$uname = isset($_POST['uname']) ? $_POST['uname'] : "";  
$passwd= isset($_POST['passwd']) ? $_POST['passwd'] :  
"";  
$query = "SELECT * FROM tbl_users WHERE username =  
'" + $uname  
+ "' AND password = '"+ $passwd +"'";  
$qr = @mysql_query($query);  
?>  
Xâu truy vấn SQL được sinh ra trong trường hợp trên sử dụng  
trực tiếp giá trị input được người dùng nhập vào, do đó mô hình  
xây dựng truy vấn dạng này được gọi chung là xây dựng truy vấn  
động (dynamic query). Truy vấn thu được sẽ có dạng như sau:  
SELECT * FROM tbl_users WHERE username=’$uname’ AND  
password = ‘$passwd’;  
Trong đó hai giá trị $name và $passwd được nhập từ người  
dùng. Khi thực hiện nhập giá trị username là admin’ or ‘1’=’1  
truy vấn động thu được sẽ như sau:  
SELECT * FROM tbl_users WHERE username=’admin’ or  
‘1’=’1’ AND password=’’;  
SQL Injection – Tấn công và cách phòng tránh  
17  
Khóa luận tốt nghiệp - 2010  
Truy vấn này tuy có cụm luôn đúng, nhưng do toán tử AND  
có độ ưu tiên cao hơn OR do đó truy vấn trên tương đương với:  
SELECT * FROM tbl_users WHERE username=’admin’ AND  
password=’’;  
Trường hợp này rõ ràng đăng nhập thất bại. Tiếp tục thử với  
việc thêm cả cụm ‘ or ‘1’=’1 vào cả password, ta có truy vấn  
được sinh ra:  
SELECT * FROM tbl_users WHERE username=’admin’ or  
‘1’=’1’ AND password=’’ or ‘1’=’1’;  
Truy vấn trên tương đương với:  
SELECT * FROM tbl_users WHERE username=’admin’ or  
password=’’ or ‘1’=’1’;  
Trường hợp này việc xác thực đã thành công do mệnh đề  
WHERE luôn đúng. Ngoài cách trên ta có thể thực hiện chèn  
thêm một đoạn or ‘1’=’1 vào username, tức là admin’ or  
‘1’=’1’ or ‘1’=’1 vào, kết quả thu được cũng tương tự, do  
toán tử AND đã được “khử” trước các toán tử OR.  
b. Các phương pháp chèn tham số  
Tùy thuộc vào câu truy vấn gốc mà các tham số được chèn  
vào sẽ có vị trí khác nhau trong truy vấn đó. Ứng với từng trường  
hợp đó, chúng ta có các mô hình chèn tham số sau:  
Chèn vào giữa truy vấn:  
Chèn vào giữa truy vấn là mô hình chỉ đơn thuần thao tác  
với tham số, không hề tác động đến cấu trúc và các thành  
phần của truy vấn gốc. Việc chèn như minh họa ở phần a.  
chính là chèn vào giữa truy vấn. Mô hình này có thể khái quát  
như sau:  
SQL Injection – Tấn công và cách phòng tránh  
18  
Khóa luận tốt nghiệp - 2010  
Hình 2.1. tham số chèn vào giữa truy vấn  
Chèn và ngắt truy vấn  
Đây là mô hình chèn truy vấn phổ biến nhất, truy vấn được  
chèn vào sẽ bao gồm thêm ở cuối các ký tự comment nhằm  
ngắt truy vấn tại đó, vô hiệu hóa các phần tử trong truy vấn  
gốc nằm phía sau vị trí tham số. Đoạn mã PHP đã nêu được  
cải tiến như sau:  
<?php  
$uname = isset($_POST['uname']) ? $_POST['uname'] : "";  
$passwd= isset($_POST['passwd']) ? $_POST['passwd'] : "";  
if($uname == "" || passwd == ""){  
echo "username or password is missing";  
}else{  
if($passwd == "")  
echo "password is missing";  
else if($uname == "")  
echo "username is missing";  
else{  
$query = "SELECT * FROM tbl_users WHERE  
username = '" + $uname  
+ "' AND password = '"+ $passwd +"'";  
$qr = @mysql_query($query);  
?>  
Với đoạn xử lý trên, các trường username và password  
không thể để trống, tuy nhiên không nhất thiết phải chèn  
nhiều mệnh đề OR, chúng ta chỉ cần đảm bảo có giá trị trong  
SQL Injection – Tấn công và cách phòng tránh  
19  
Khóa luận tốt nghiệp - 2010  
hai trường đó và sử dụng comment để ngắt truy vấn sau khi  
xuất hiện mệnh đề OR 1=1 đầu tiên, ví dụ với username là  
admin’ or 1=1-- và password bất kỳ (khác rỗng) thì truy vấn  
sẽ có dạng:  
SELECT * FROM tbl_users WHERE username = ‘admin’ or  
1=1;  
Và với truy vấn này hacker qua mặt được xác thực do  
mệnh đề WHERE luôn đúng. Một số ký tự comment hay  
dùng:  
Bảng 2.1. Các ký tự comment thường gặp  
Database  
Ký hiệu  
Ý nghĩa riêng  
Oracle và SQL  
Server  
Comment trên một dòng  
-- (double dash)  
Comment trên nhiều dòng  
Comment trên một dòng  
/* */  
MySQL  
-- (theo sau bởi  
dấu cách hoặc ký  
tự điều khiển)  
Comment trên một dòng  
Comment trên nhiều dòng  
#
/* */  
2.2. Các phương pháp tấn công phổ biến  
Các cuộc tấn công nhắm tới lớp database của ứng dụng Web xét theo  
mục đích được chia làm hai nhánh chính: thứ nhất là nhắm tới dữ liệu chứa  
trong database, thứ hai là nhắm tới chính bản thân database. Trường hợp thứ  
nhất thường là kẻ tấn công nhắm tới các thông tin có giá trị như thông tin cá  
nhân, thông tin tài chính, … trường hợp thứ hai thì kẻ tấn công muốn biến  
database thành cửa ngõ để thâm nhập sâu hơn vào trong mạng lưới của tổ chức  
sở hữu ứng dụng Web đang bị tấn công. Chúng ta sẽ xét một số phương pháp  
tấn công phục vụ hai mục đích này.  
2.2.1. Tấn công khai thác dữ liệu thông qua toán tử UNION  
Khai thác thông tin thông qua việc sử dụng UNION là một trong 2  
nhánh chính của việc khai thác dữ liệu thông qua lỗi SQL Injection. Các  
SQL Injection – Tấn công và cách phòng tránh  
20  
Khóa luận tốt nghiệp - 2010  
điểm yếu SQL Injection có thể khai thác được thông qua UNION là  
dạng điểm yếu mà thông tin trả về có thể được hiển thị trực tiếp trên  
thông điệp phản hồi. Loại hình thứ hai đó là thông qua các toán tử điều  
kiện sẽ được đề cập ở phần sau.  
Toán tử union sẽ thực hiện ghép dữ liệu của truy vấn gốc và truy vấn  
khai thác. Điều kiện là hai truy vấn này phải trả về cùng số cột, và các  
cột này có cùng kiểu dữ liệu. Để có thể thực hiện các khai thác thông  
qua toán tử UNION, chúng ta cần thực hiện ban đầu hai giai đoạn, đó là  
tìm số cột, kiểu dữ liệu của các cột, và giai đoạn hai đó là tìm cột nào có  
thể “chứa” thông tin trả về của truy vấn khai thác.  
a. Tìm số cột và kiểu dữ liệu của cột  
Xét một trang web chứa điểm yếu SQL Injection trên biến  
product_id tại đường dẫn sau:  
d=14  
Hình 2.2. trang nạn nhân ban đầu  
Để tìm ra số cột của bảng hiện thời, có hai cách có thể sử  
dụng, sử dụng UNION hoặc sử dụng ORDER BY. Giả sử truy  
vấn của ứng dụng xây dựng để trả về kết quả hiện thời có dạng:  
SELECT * FROM tbl_products WHERE product_id=14;  
SQL Injection – Tấn công và cách phòng tránh  
21  
Khóa luận tốt nghiệp - 2010  
Mệnh đề ORDER BY được sử dụng để sắp xếp kết quả trả về  
bởi truy vấn theo cột được chỉ định. Nếu cột đó không tồn tại,  
một thông báo lỗi trả về. Giả sử ta muốn sắp xếp theo cột thứ 2 ta  
chèn tham số ORDER BY 2 vào giá trị tham số product_id, ví dụ  
ta có truy vấn kiểu sau:  
SELECT * FROM tbl_products WHERE product_id=14 ORDER  
BY 2;  
Hình 2.3. trang nạn nhân, order by 2  
Không có lỗi trả về, vậy bảng hiện tại có ít nhất 2 cột, ta tiếp  
tục tăng số cột dự đoán lên. Chiến thuật đoán này có thể sử dụng  
tìm kiếm nhị phân, tức chúng ta xác định hai mốc lớn nhất và bé  
nhất, từ đó tìm nhị phân giữa hai mốc này. Ví dụ với mốc 20 cột,  
ta thấy trả về lỗi :  
Hình 2.4. trang nạn nhân, order by 20  
Tiếp tục tìm kiếm nhị phân giữa hai mốc 2 và 20, ta tìm được  
số cột là 16.  
Các thông tin khai thác được có thể biểu diễn thuận lợi nhất ở  
dạng xâu ký tự, vì thế, tiếp theo mục đích của chúng ta đó là tìm  
SQL Injection – Tấn công và cách phòng tránh  
22  
Khóa luận tốt nghiệp - 2010  
các cột trong số 16 cột trên có kiểu dữ liệu là xây ký tự, rất đơn  
giản, chúng ta chỉ cần thực hiện UNION với truy vấn khai thác có  
cột cần kiểm tra có giá trị xâu ký tự. Để tránh gây nhiễu kết quả,  
các cột khác để giá trị NULL. Ví dụ truy vấn:  
n+select+char(98),null,null,null,null,null,null,null,null,null,null,null,null,n  
ull,null,null--  
SELECT * FROM tbl_products WHERE product_id=14  
UNION  
SELECT char(98),null,null, null,null,null,null, null,null,null, null,null,  
null,null, null,null  
Kết quả trả về không có lỗi, chứng tỏ cột đầu tiên có kiểu giá  
trị xâu ký tự.  
Hình 2.5. trang web nạn nhân, kiểm tra kiểu cột 1  
Tiếp tục thử với các cột khác để có nhiều lựa chọn khai thác  
sau này. Trong trường hợp của chúng ta, rất may rằng tất cả các  
cột đều có kiểu dữ liệu là xâu ký tự.  
b. Tìm cột có khả năng “chứa” thông tin khai thác được.  
Mục đích của công việc này đó là tìm cột có nội dung được  
hiển thị trên phản hồi, khi đó “nhúng” thông tin khai thác được  
vào đó. Sử dụng các nội dung mang tính “chỉ điểm” cột có thể  
khai thác được như sau:  
SELECT * FROM tbl_products WHERE product_id = 1  
SQL Injection – Tấn công và cách phòng tránh  
23  
Khóa luận tốt nghiệp - 2010  
UNION  
SELECT 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16--  
Nếu thấy bất cứ con số nào trong số các giá trị “chỉ điểm” kia  
xuất hiện bất thường trong phản hồi, ta có thể biết, cột đó có thể  
dùng để “nhúng” thông tin khai thác được. Ví dụ:  
Hình 2.6. tìm cột “mang” dữ liệu  
Như vậy cột số 2 và số 3 có thể sử dụng để mang thông tin  
khai thác được. Để kiểm chứng điều này, chúng ta thay giá trị 2  
bằng một thông tin có ý nghĩa hơn, ví dụ phiên bản MySQL hiện  
dùng, tham số được chèn:  
UNION+select+1,@@version,3,4,5,6,7,8,9,10,11,12,13,14,1  
5,16--  
SQL Injection – Tấn công và cách phòng tránh  
24  
Khóa luận tốt nghiệp - 2010  
Hình 2.7. “nhúng” thông tin khai thác vào cột “mang” dữ liệu  
Kết quả cho thấy, ứng dụng nạn nhân đang sử dụng MySQL  
phiên bản miễn phí (community) v5.0.81 .  
Không chỉ dừng lại ở việc tìm tên phiên bản, mà lúc này kẻ  
tấn công có thể sử dụng bất cứ truy vấn nào để hiển thị thông tin  
tương tự như trên. Ví dụ, chúng ta có thể tìm ra tên user hiện tại  
ứng dụng sử dụng để thao tác với database MySQL bằng truy vấn  
user(), lưu ý tham số này phải được mã hóa dạng URL (url  
encoding) hoặc biểu diễn ở dạng hexa. Ví dụ, user() biểu diễn ở  
dạng mã hóa URL là: “%75%73%65%72%28)”, thay vào vị trí  
cột 2, ta có kết quả:  
SQL Injection – Tấn công và cách phòng tránh  
25  
Khóa luận tốt nghiệp - 2010  
Hình 2.8. khai thác thông tin username  
Kết quả cho thấy user hiện tại thực hiện truy vấn là  
srvhpci1_pinknew@localhost.  
2.2.2. Khai thác thông qua các câu lệnh điều kiện  
Ý tưởng chung của dạng tấn công dựa trên các câu lệnh điều kiện  
này chính là khiến cho database trả về những trạng thái khác nhau phụ  
thuộc vào từng điều kiện được đưa ra. Mỗi điều kiện đưa ra đó có thể  
giúp suy ra được từng bit của một byte dữ liệu cụ thể. Việc đi sâu vào  
dạng tấn công này sẽ được đề cập ở chương Blind SQL Injection, hiện  
tại chúng ta sẽ đề cập tới nguyên tắc chung của nó.  
Một truy vấn dựa vào điều kiện sẽ có dạng như một câu lệnh điều  
kiện trên các ngôn ngữ lập trình ứng dụng thông thường, tức là có dạng:  
IF điều_kiện THEN chuỗi_xử_lý_đúng ELSE chuỗi_xử_lý_sai  
Trên các DBMS cụ thể, có một số truy vấn dạng trên:  
-
Trên SQL Server:  
IF(biểu_thức_boolean) SELECT trường_hợp_đúng ELSE  
trường_hợp_sai  
-
Trên MySQL: SELECT  
IF(biểu_thức_boolean, trường_hợp_đúng, trường_hợp_sai)  
Trên Oracle:  
-
SELECT CASE WHEN biểu_thức_boolean THEN trường_hợp_đúng ELSE  
trường_hợp_sai END FROM DUAL  
Mệnh đề biểu_thức_boolean được gọi là mệnh đề suy luận, và việc nhận  
định kết quả trả về nào ứng với trường hợp mệnh đề đó đúng và kết quả nào  
ứng với trường hợp sai sẽ là vấn đề chính cần giải quyết. Có một vài mô hình  
đã được nghiên cứu và được sử dụng để phân biệt kết quả trong hai trường hợp  
như:  
-
-
Mô hình dựa trên độ trễ phản hồi  
Mô hình dựa trên nội dung phản hồi  
Với mỗi mô hình, chúng đều có ưu điểm, nhược điểm và một vài điều kiện  
cần cân nhắc khi áp dụng. Chúng ta sẽ xem xét các đặc điểm này sau đây.  
a.  
Mô hình dựa trên nội dung phản hồi  
SQL Injection – Tấn công và cách phòng tránh  
26  
Khóa luận tốt nghiệp - 2010  
Đầu tiên chúng ta cần làm rõ tên gọi của mô hình này. Phản hồi ở  
đây chính là nội dung kết quả truy vấn được database trả về. Mô hình  
dựa trên phản hồi này sẽ dựa trên sự khác biệt về nội dung phản hồi so  
với trường hợp nào đó tương đồng để suy ra đúng.  
Trường hợp dễ phân biệt nhất là phân biệt với một thông báo lỗi. Các  
lỗi có lợi thế hơn so với các dạng khác chính là do thời gian thực thi truy  
vấn chứa nó rất nhanh, các lỗi được dùng đa phần được phát hiện ra  
trong thời gian phân tích cú pháp của truy vấn chứ chưa hề được thực thi  
bên trong database, do đó thời gian phản hồi sẽ rất nhanh.  
Trường hợp tham số kiểu số (numeric): một mệnh đề suy luận có thể  
trả về giá trị 0, lỗi khi thực hiện phép chia cho 0 là một ví dụ, minh họa  
với mệnh đề suy luận username của người dùng hiện thời, database đối  
tượng là MySQL:  
'admin%'),1,0))  
Nếu người dùng hiện thời có username bắt đầu bởi cụm “admin” thì  
id có giá trị là 32 chia cho 1, ngược lại là 32 chia cho 0 (sinh lỗi).  
Có thể biểu diễn URL trên ở một dạng khác như sau:  
'admin%'),32,1/0)  
Việc xứ lý sinh lỗi ứng với trường hợp mệnh đề suy luận đúng hay  
sai không quan trọng, bởi nó đã được thể hiện rõ trong cú pháp của câu  
lệnh điều kiện rồi.  
Các lỗi trả về tuy giúp tiết kiệm được nhiều thời gian tuy nhiên  
những cảnh báo lỗi thường được quản trị web cấu hình vô hiệu hóa hoặc  
trả về những trang mặc định khiến việc xác định kết quả mệnh đề suy  
luận khó khăn hơn. Một cách khác dựa vào kết quả trả về đó là thay vì  
sinh lỗi, ta sinh một truy vấn hợp lệ có kết quả khác với truy vấn ban  
đầu của ứng dụng. Ví dụ:  
Request ban đầu:  
SQL Injection – Tấn công và cách phòng tránh  
27  
Khóa luận tốt nghiệp - 2010  
request bị giả mạo nhằm tìm tên username hiện tại:  
e%20‘admin%’),21,23)  
%20‘admin%’),laptop,cellphone)  
Truy vấn giả mạo thứ nhất thay đổi mã sản phẩm sẽ được hiển thị, và  
truy vấn thứ hai thay đổi giá trị từ khóa tìm kiếm.  
b.  
Mô hình dựa trên độ trễ phản hồi  
Mô hình này dựa trên sự khác biệt về thời gian nhận được phản hồi  
từ database server nên còn được gọi là mô hình dựa trên thời gian (time-  
based). Khác với phương pháp nhận biết sự khác biệt của nội dung phản  
hồi đã đề cập, phương pháp này không hề chú ý gì tới nội dung của truy  
vấn trả về, do đó các cấu hình chặn và xử lý thông báo lỗi của quản trị  
viên không ảnh hưởng tới phương pháp này.  
Các độ trễ thực thi của truy vấn chính được sinh ra do các hàm thực  
hiện hoãn thực thi hoặc do việc thực thi một lượng truy vấn phụ lớn. Các  
hàm trên các DBMS hỗ trợ trì hoãn thực thi truy vấn như WAITFOR  
DELAY trên SQL Server, SLEEP trên MySQL,… ví dụ một request sử  
dụng độ trễ để phân biệt trường hợp đúng/sai của mệnh đề suy luận:  
http://site/products.php?id=if((substring(version(),1,1)=’5’),sleep(  
5),21)  
Request trên thực hiện suy luận phiên bản của MySQL, nếu ký tự  
đầu tiên trong phiên bản là 5 (MySQL 5) thì sẽ hoãn phản hồi 5 giây  
bằng lời gọi hàm sleep(5), ngược lại trả về giá trị id là 21 bình thường.  
So sánh thời gian hoàn thành truy vấn so với trường hợp bình thường để  
suy ra thông tin về phiên bản.  
Ngoài cách sinh độ trễ từ các hàm có sẵn trên DBMS, một cách  
khác đảm bảo khả thi hơn, đó là sử dụng các truy vấn ‘lớn’, những truy  
SQL Injection – Tấn công và cách phòng tránh  
28  
Khóa luận tốt nghiệp - 2010  
vấn mà đòi hỏi chi phí thực thi cao, ví dụ những truy vấn ‘lớn’ này như  
các phép truy vấn trên từ điển dữ liệu (data dictionary hay metadata).  
Các vấn đề cụ thể của mô hình này sẽ được trình bày chi tiết trong nội  
dung về Blind SQL Injection.  
2.2.3. Blind SQL Injection – phương thức tấn công nâng cao  
a. Tổng quan  
Blind SQL Injection là một phương pháp thực hiện SQL Injection  
trong điều kiện các thông tin khai thác được không được trình bày  
trực tiếp trên nội dung phản hồi từ database. Blind SQL Injection  
dựa vào việc sử dụng các mệnh đề điều kiện để thực hiện suy luận  
thông tin cần khai thác. Cụ thể, Blind SQL Injection sử dụng chính  
các thông tin cần khai thác làm mệnh đề điều kiện (mệnh đề suy  
luận), và sử dụng các phương pháp khác nhau để “đánh dấu” trường  
hợp đúng/sai của mệnh đề đó.  
Căn cứ vào phương pháp “đánh dấu” trường hợp đúng/sai của  
mệnh đề quan hệ, ta chia ra hai cách chính thực hiện blind SQL  
Injection:  
- Dựa vào nội dung phản hồi (response-based)  
- Dựa vào độ trễ của thời gian phản hồi (time-based)  
Các phương pháp thực hiện blind SQL Injection có thể áp dụng  
cho các mô hình khác mà không gặp trở ngại nào, tuy nhiên chi phí  
thực hiện sẽ luôn cao hơn về mặt thời gian và số truy vấn cần thiết.  
b. Thực hiện tấn công blind SQL Injection dựa trên phản hồi  
Minh họa được thực hiện trên WebGoat, module Blind SQL  
Injection. WebGoat là một project được thực hiện bởi OWASP  
(Open Web Application Security Project), là một bộ mô phỏng  
website trên nền tảng J2EE, chứa đựng tất cả những bài học về  
những lỗi bảo mật thường thấy của ứng dụng Web. Nhiệm vụ của  
chúng ta đó là tìm ra thuộc tính first_name của người dùng có mã  
userid 15643. Chúng ta có một khung kiểm tra mã số người dùng,  
nếu nhập đúng, thông báo trả về “Account number is valid”, ngược  
lại sẽ là “Invalid account number”. Chúng ta đã biết bảng đang tham  
chiếu là user_data.  
Ví dụ:  
SQL Injection – Tấn công và cách phòng tránh  
29  
Khóa luận tốt nghiệp - 2010  
Hình 2.9 . trường hợp sai userid  
Tình huống trên cho phép chúng ta đoán truy vấn SQL được xây  
dựng có dạng:  
SELECT * FROM user_data WHERE userid = $user_input;  
Khía cạnh “blind” của trường hợp này là ở chỗ, ta chỉ có thể thấy  
được duy nhất hai trạng thái trả về, và không thể có một nội dung,  
thông tin nào khác lộ ra trong thông điệp phản hồi.  
Chúng ta thực hiện xây dựng các mệnh đề suy luận để tìm từng  
ký tự trong username của user có userid 15643. Miền giá trị chúng ta  
cần dò là a-zA-Z do đặc thù tên người. để dễ thao tác so sánh trong  
mệnh đề suy luận, chúng ta thực hiện thao tác với từng ký tự thông  
qua mã ASCII của nó. Với ký tự đầu tiên ta biểu diễn nó như sau:  
ascii(substring(SELECT first_name FROM user_data WHERE  
userid=15613,1,1)).  
Truy vấn SQL trả về giá trị first_name của userid 15613, và hàm  
substring(string,begin,length) trả về chuỗi con, cụ thể là ký tự đầu  
tiên trong xâu đó, và hàm ascii(character) sẽ trả về mã ASCII của ký  
tự đầu tiên đang xét.  
Mệnh đề truy vấn được thực hiện bằng cách so sánh giá trị ASCII  
xây dựng ở trên với các mốc như A (65), Z(90), a(97), z(112). Để tiết  
kiệm chi phí cho việc sinh truy vấn, chúng ta thực hiện tìm theo  
nguyên tắc tìm kiếm nhị phân. Cụ thể:  
SQL Injection – Tấn công và cách phòng tránh  
30  

Tải về để xem bản đầy đủ

pdf 96 trang yennguyen 27/04/2025 200
Bạn đang xem 30 trang mẫu của tài liệu "Khóa luận SQL Injection - Tấn công và cách phòng tránh", để 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:

  • pdfkhoa_luan_sql_injection_tan_cong_va_cach_phong_tranh.pdf