NỘI DUNG
Hacking Database:
SQL Injection
GVHD: Nguyễn Duy
Nhóm 19
SV1: Nguyễn Mạnh Tuấn - 08520439
SV2: Nguyễn Hữu Tú - 08520452
SV3: Trần Quang Vũ - 08520479
SV4: Lưu Xuân Khoa – 08520498
MMT03/UIT
I. Lý thuyết
1. Khái niệm
SQL injection là một kỹ thuật cho phép những kẻ tấn công lợi dụng lỗ hổng của việc kiểm tra dữ
liệu đầu vào trong các ứng dụng web và các thông báo lỗi của hệ quản trị cơ sở dữ liệu trả về để
inject (tiêm vào) và thi hành các câu lệnh SQL bất hợp pháp.
SQL injection có thể cho phép những kẻ tấn công thực hiện các thao tác delete, insert, update…
trái phép trên cơ sở dữ liệu của ứng dụng, thậm chí là server mà ứng dụng đó đang chạy.
SQL injection là lỗ hổng thường gặp nhất của các website trên internet. Nó là lỗi của các ứng
dụng web chứ không phải vấn đề ở cơ sở dữ liệu hay web server. Hầu hết các lập trình viên đều
kém trong vấn đề phòng chống SQL injection.
2. Mục tiêu
Mục đích chính của SQL injection là truy cập vào cơ sở dữ liệu bất hợp pháp hoặc khai thác
thông tin từ các cơ sở dữ liệu đó.
Dựa trên cách sử dụng và xử lý dữ liệu người dùng cung cấp, SQL injection có thể được sử dụng
để thực hiện các kiểu tấn công sau:
• Authentication Bypass: hacker có thể đăng nhập vào ứng dụng mà không cần cung cấp
username và password, thậm chí có thể chiếm quyền quản trị.
• Information Disclosure: người tấn công lấy các thông tin nhạy cảm được lưu giữ trên cơ
sở dữ liệu.
• Compromised Data Integrity: thực hiện deface trang web, chèn nội dung độc hại lên
trang web, hoặc thay đổi nội dung cơ sở dữ liệu.
• Compromised Availability of Data: người tấn công xóa thông tin trên cơ sở dữ liệu, xóa
log, hoặc thông tin kiểm chứng trên cơ sở dữ liệu.
• Remote Code Execution: cho phép người tấn công làm hại hệ thống của host.
2
3. Cơ chế:
Cơ chế hoạt động của một website
Mục tiêu tấn công của SQL injection chính là các lỗ hổng trong web application chứ không phải
bản thân cơ sở dữ liệu. Thông qua việc khai thác lỗi của web application, người tấn công có thể
tiếp cận cơ sở dữ liệu và khai thác/phá hủy dữ liệu trên đó. Các ứng dụng này bị lỗi là do trong
quá trình phát triển đã không tuân theo các quy chuẩn về code bảo mật và việc xử lý dữ liệu lưu
trữ trong các cơ sở dữ liệu quan hệ (relational database). Tất cả các cơ sở dữ liệu quan hệ (SQL
Server, Oracle, IBM DBZ và MySQL) đều có thể bị tấn công bởi kiểu tấn công này.
4. Ngữ cảnh và mục đích đạt được khi tấn công
a. Vượt qua kiểm tra đăng nhập:
Sau khi người dùng nhập username, password và click nút submit, username và password này sẽ
được gửi đến ứng dụng và xử lý chúng. Một câu truy vấn SQL sẽ được tạo ra và lấy các hàng
3
khớp với thông tin người dùng cung cấp. Người dùng lúc đó sẽ được chứng thực và chuyển đến
trang yêu cầu.
Tuy nhiên, nếu không được kiểm tra kỹ sẽ dễ bị lỗi SQL injection. Ví dụ đoạn code sau đâu bị
lỗi SQL injection:
string strQry = "SELECT Count(*) FROM Users WHERE Username='" + txtUser.Text +
"' AND Password ='" + txtPassword.Text + "'";
Nếu người dùng đăng nhập bình thường, ví dụ như trong hình, username là ‘Jason’ và password
là ‘Springfield’. Khi đó ứng dụng sẽ thực hiện câu truy vấn: SELECT Count(*) FROM Users
WHERE Username = ‘Jason’ AND Password = ‘Springfield’.
Tuy nhiên, nếu đăng nhập với username và Password như sau:
Lúc này, câu truy vấn sẽ được thực hiện như sau: SELECT Count(*) FROM Users WHERE
Username = ‘Blah’ OR 1 = 1 AND Password = ‘Springfield’. Chú ý rằng sau dấu – là
comment. Nghĩa là câu truy vấn thật sự là SELECT Count(*) FROM Users WHERE Username =
‘Blah’ OR 1 = 1. Như vậy là người tấn công sẽ vượt qua phần kiểm tra đăng nhập.
b. Hiển thị bảng username và password
Các website thường có ô tìm kiếm để người dùng dễ dàng tìm dữ liệu. Tuy nhiên, nếu ô tìm kiếm
này không được kiểm tra kỹ sẽ dễ tạo lỗ hổng để hacker tấn công.
Ví dụ đoạn code sau có lỗ hổng:
strSQL = “SELECT ProductID, ProductName, QuantityPerUnit, UnitPrice FROM
Products”;
if (txtFilter.Text .Length > 1) {
strSQL += “ WHERE ProductName LIKE ‘” + txt.Filter.Text + ‘”;}
Nếu giá trị của ô tìm kiếm được nhập vào là blah’ UNION Select 0, username, password 0
from users Câu lệnh truy vấn lúc đó là:
4
SELECT ProductID, ProductName, QuantityPerUnit, UnitPrice FROM Products WHERE
ProductName LIKE ‘blah’ UNION SELECT 0, username, password 0 FROM USERS –
Toán tử UNION cho phép ghép kết quả 2 câu lệnh SELECT lại, với điều kiện 2 câu lệnh này
phải có cùng số cột.
Kết quả: Username và password bị hiển thị ra.
c. Update table
Chuỗi tấn công:
5
blah’; UPDATE jb-customers SET jb-email = ‘’ WHERE email
=’;
Câu lệnh SQL truy vấn lúc đó là:
SELECT jb-email, jb-passwd, ib-login_id, jb-last_name FROM members WHERE jb-
email = ‘blah’; UPDATE jb-customers SET jb-email = ‘’ WHERE
email =’;
d. Thêm record
Chuỗi tấn công:
blah’; INSERT INTO jb-customers (‘jb-email’,’jb-passwd’,’jb-login_id’,’jb-
last_name’) VALUES (‘’,’hello’,’jason’,’jason
springfield’);
Câu lệnh SQL truy vấn lúc đó là:
SELECT jb-email, jb-passwd, ib-login_id, jb-last_name FROM members WHERE jb-
email = ‘blah’; INSERT INTO jb-customers (‘jb-email’,’jb-passwd’,’jb-
login_id’,’jb-last_name’) VALUES
(‘’,’hello’,’jason’,’jason springfield’);
6
e. Xác định tên bảng
Chuỗi tấn công:
blah’ AND 1 = (SELECT COUNT(*) FROM mytable);
Câu lệnh SQL truy vấn lúc đó là:
SELECT jb-email, jb-passwd, ib-login_id, jb-last_name FROM members WHERE jb-
email = ‘blah’ AND 1 = (SELECT COUNT(*) FROM mytable);
f. Xóa bảng
Chuỗi tấn công:
blah’; DROP TABLE CreditCard;
7
Câu lệnh SQL truy vấn lúc đó là:
SELECT jb-email, jb-passwd, ib-login_id, jb-last_name FROM members WHERE jb-
email = ‘blah’; DROP TABLE CreditCard;
II. Mô hình triển khai
Bao gồm 3 bước thực hiện:
• Bước 1: Xác định trang web có lỗi SQL injection không?
• Bước 2: Từ tỗi tìm được, chọn loại tấn công phù hợp.
• Bước 3: Triển khai tấn công.
1. Tìm lỗi SQL injection:
Bước 1: Kiểm tra xem ứng dụng web có kết nối đến server cơ sở dữ liệu để lấy thông tin không?
Bước 2: Liệt kê ra tất cả các input field, field ẩn và các post request có thể chứa giá trị dùng cho
truy vấn SQL.
Bước 3: Thử inject code vào các field trên để tạo ra lỗi.
Bước 4: Thử nhập vào một gía trị chuỗi vào các input field yêu cầu nhập số.
Bước 5: Sử dụng toán tử UNION trong các SQL injection để kết một câu truy vấn vào câu truy
vấn có sẵn.
Bước 6: Sử dụng thông tin từ các báo lỗi ở trên để phục vụ cho việc triển khai tấn công.
8
2. Các loại hình tấn công của SQL injection
a. Simple SQL injection:
UNION SQL injection: sử dụng toán tử UNION để join 2 truy vấn với nhau.
Error Based SQL injection: khai thác các lỗi cú pháp để trích xuất một số thông tin.
VD:
or 1=convert(int,(DB_NAME) sẽ lấy được thông
tên database.
b. Blind SQL injection:
Kỹ thuật này được dùng khi website bị mắc lỗi SQL injection nhưng đã bị che dấu. Blind SQL
injection chỉ khác Simple SQL injection ở chỗ thay vì người tấn công có thể thấy được một số
thông tin có ích thì họ chỉ thấy một trang báo lỗi chung.
9
Kỹ thuật này đòi hỏi người tấn công phải có nhiều kinh nghiệm.
3. Các công cụ hỗ trợ SQL injection:
• BSQLHacker: công cụ tự động hỗ trợ Blind SQL injection, Time-Base Blind SQL
injection, Deep Blind SQL injection, Error Based SQL injection.
• Marathon Tool: có khả năng gửi nhiều câu truy vấn “nặng” để thực hiện tấn công kiểu
Time-Base SQL injection.
• Ngoài ra còn có SQL Power Injector, Havij, SQL Brute, BobCat, SQLninja, SQLmap,…
III. Triển khai tấn công (không dùng tool)
1. Khảo sát sơ bộ và kiểm tra lỗi
Chọn xem một bài viết trên website. Để ý URL các bài viết, mỗi bài viết được xác định bởi một
tham số id trong URL. Chèn dấu nháy đơn vào tham số id để kiểm tra. Việc chèn dấu nháy đơn
sẽ kiểm tra việc xử lý chuỗi tham số đầu vào của ứng dụng
Khi có lỗi câu truy vấn SQL, hệ quản trị cơ sở dữ liệu sẽ xuất thông báo lỗi, ta sẽ dựa trên thông
báo này để chèn câu truy vấn cho phù hợp.
10
Như vậy đã có lỗi trong quá trình kiểm tra dữ liệu đầu vào. Dấu nháy đơn không được xử lý một
cách đúng đắn đã gây ra lỗi cú pháp trong câu truy vấn SQL.
2. Đếm số cột trong bảng
Dựa trên thông báo lỗi ở trên, ta thấy rằng phía sau vị trí chèn vẫn còn một đoạn truy vấn SQL.
Vì vậy, khi tiến hành chèn câu truy vấn tấn công, ta phải chèn thêm kí tự “ ” (comment trong
SQL) để thoát đoạn truy vấn đó.
Để có thể đếm được số cột trong bảng, ta sử dụng lệnh “ORDER BY num”, với num là vị trí của
cột trong bảng. Tham số num này là một số tùy ý nhập vào với mục đích thăm dò. Ta có thể thử
nhiều giá trị khác nhau cho đến khi tìm được số lượng cột chính xác trong bảng.
ORDER BY 1
Truy vấn thành công.
Có nhiều hơn 1 cột trong bảng.
ORDER BY 9
Lỗi truy vấn.
Không có cột thứ 9 trong bảng. Có ít hơn 9 cột trong bảng.
11
ORDER BY 8
Truy vấn thành công.
Như vậy bảng có 8 cột.
Dựa trên số lượng cột trong bảng, ta tiến hành thăm dò để xác định chính xác những cột được gọi
trong truy vấn.
3. Xác định chính xác những cột được gọi trong truy vấn
Để xác định chính xác những cột nào được gọi trong truy vấn, ta sẽ sử dụng “UNION”.
Chèn đoạn truy vấn “UNION SELECT 1,2,3,4,5,6,7,8 ”, ta sẽ xác định được chính xác những
cột được gọi. Những số tương ứng với các cột được gọi sẽ xuất hiện ở những vị trí mà giá trị
được in ra.
Tuy nhiên ở đây, sau khi truy vấn sẽ có lỗi “406 Not Acceptable”.
Lỗi này là do webserver đã được cài các mod bảo mật có nhiệm vụ lọc URL.
Ta phải tìm cách bypass các mod này để có thể tiếp tục tấn công!
Có nhiều cách để bypass các mod bảo mật, ta có thể thử lần lượt các cách hoặc cũng có thể kết
hợp các cách với nhau để đạt được hiệu quả bypass tốt nhất. Sau đây liệt kê một số cách thức
bypass các mod bảo mật của webserver.
- Thay khoảng trắng bằng + hoặc /**/.
- Thay đổi các ký tự hoa thường ngẫu nhiên trên các từ khóa. Ví dụ: UNioN, SeleCt…
- Cho nội dung truy vấn vào giữa /*![query]*/.
- Thay ký tự khoảng trắng bằng %0A (ký tự xuống dòng).
Ta thử sử dụng cách thay đổi ký tự hoa thường để bypass các mod bảo mật.
Truy vấn thành công, trên website sẽ xuất hiện các con số tương ứng với các cột được gọi trong
truy vấn.
12
4, 5, 6 chính là các cột được gọi trong truy vấn.
4. Chèn các hàm, biến để lấy thông tin hệ thống
Ta sẽ tiến hành chèn các hàm, biến của MySQL vào các vị trí tương ứng với các cột này để lấy
thông tin hệ thống.
Ở đây ta chèn 3 hàm của MySQL là VERSION(), DATABASE(), USER() để lấy các thông tin
về phiên bản MySQL, tên database và username.
Sau truy vấn ta đã lấy được các thông tin sau:
- Phiên bản MySQL: 5.1.61-LOG
- Tên database: lethanht_db
- Username: lethanht@localhost
5. Thăm dò các bảng trong cơ sở dữ liệu
Dựa trên các thông tin hệ thống đã lấy được ở bước trên ta sẽ tiến hành thăm dò, tìm các bảng
trong cơ sở dữ liệu.
“5.1.61-LOG” Đây là thông tin vô cùng quan trọng, vì nó sẽ định hướng cách thức thăm dò
của chúng ta. Ở MySQL, chỉ các phiên bản từ 5.0 trở lên sẽ có một cơ sở dữ liệu là
information_schema. Cơ sở dữ liệu này chứa tất cả thông tin về các cơ sở dữ liệu khác trong hệ
thống, các bảng, các cột, các mối quan hệ trong các cơ sở dữ liệu đó. Vì vậy, ta sẽ tìm cách truy
vấn vào cơ sở dữ liệu information_schema để lấy được tên các bảng trong cơ sở dữ liệu muốn
lấy thông tin.
Trong cơ sở dữ liệu information_schema, bảng tables sẽ chứa toàn bộ tên các bảng của các cơ sở
dữ liệu trên hệ thống. Chúng ta sẽ sử dụng câu truy vấn select, với điều kiện table_schema là tên
cơ sở dữ liệu muốn lấy.
13
Chú ý: /*!table_name*/ để bypass mod security của webserver.
Kết quả trả về là tên bảng đầu tiên khớp với điều kiện.
Để lấy toàn bộ tên bảng thay vì chỉ một bảng, ta sử dụng hàm GROUP_CONCAT() của MySQL
Kết quả là một danh sách tên các bảng được trả về
Do danh sách rất dài nên chúng ta có thể view source của site để lấy ra toàn bộ danh sách tên các
bảng trong cơ sở dữ liệu của website nha khoa lethanhtam.vn.
Để có thể view source website một cách dễ dàng hơn, chúng ta có thể sử dụng thêm addon
Firebug cho Firefox để copy đoạn text trong source.
Sau đây là tên các bảng đã lấy được từ cơ sở dữ liệu của lethanhtam.vn.
14
6. Thăm dò các cột trong bảng
Bước tiếp theo là việc thăm dò, lấy tên cột của bảng muốn lấy dữ liệu. Trong cơ sở dữ liệu
information_schema, bảng columns chứa toàn bộ tên cột của các bảng, ta cũng sử dụng câu truy
vấn select với điều kiện table_name là tên bảng muốn lấy dữ liệu.
Chú ý:
Cũng như lấy tên bảng, lấy tên cột cũng yêu cầu phải bypass mod security của webserver. Vì thế
ta phải cho tên cột vào cặp dấu /*!*/.
Ví dụ: /*!group_concat(column_name)*/, /*!table_name*/
Ở đây CHAR(101, 98, 105, 122, 95, 117, 115, 101, 114, 115) chính là bảng ebiz_users. Ta sử
dụng hàm CHAR() để mã hóa tên bảng là vì chuỗi truyền vào MySQL phải chứa dấu nháy đơn
để báo hiệu chuỗi nhưng khi qua URL nó đã bị làm sai lệch bởi các kí tự escape.
Kết quả là các cột được trả về
7. Lấy dữ liệu
Sau khi đã có tên bảng và tên cột, ta có thể chèn truy vấn select lấy dữ liệu một cách dễ dàng.
Chú ý trong hàm group_concat ta sử dụng 0x3a, là mã HEX của kí tự “:”.
Kết quả trả về là toàn bộ username và password trong bảng ebiz_users.
Tượng tự như trên, ta có thể chèn truy vấn lấy dữ liệu ở các bảng khác.
IV. Nhận xét
1. Ưu điểm:
• Lỗ hổng SQL injection là lỗ hổng thường gặp trên các website, thậm chí một số trang nổi
tiếng như www.mysql.com.
15
• Có nhiều công cụ hỗ trợ trong việc quét lỗi và tấn công.
• Kỹ thuật tấn công đa dạng.
• Có thể làm bàn đạp để thực hiện các cuộc tấn công khác.
2. Khuyết điểm:
• Yêu cầu kiến thức sâu về ngôn ngữ web, server scripting và database.
• Các loại tấn công phức tạp như Blind SQL injection đòi hỏi người tấn công phải có kinh
nghiệm nhiều.
3. Phương pháp khắc phục:
• Signature-base Detection Systems: xây dựng một cơ sở dữ liệu gồm các chuỗi input tấn
công kiểu SQL injection, khi hoạt động, các input string sẽ được so sánh với cơ sở dữ
liệu có sẵn để phát hiện tấn công.
• Theo dõi các luồng dữ liệu hệ thống bằng IPS, WAP.
• Che các lỗi hoặc sử dụng các thông báo lỗi tự tạo.
• Kiểm tra thông tin đăng nhập, nhử quản lý khoảng trắng, giới hạn độ dài chuỗi đăng
nhập.
• Password nên lưu ở dạng hash.
• Sử dụng các Type-Safe SQL Parameters.
• Sử dụng các phiên bản database mới.
• Dùng tool để quét tìm lỗi SQL injection như MS Source Code Analyzer, MS UrlScan,
dotDefender, IBM AppScan,…
16