SQL injection là một trong những lỗ hổng (web) phổ biến nhất. Tất cả các bài tập SQL injection, được tìm thấy ở đây, sử dụng MySQL cho back-end. Việc đưa vào SQL xuất phát từ việc thiếu mã hóa / thoát đầu vào do người dùng kiểm soát khi được đưa vào các truy vấn SQL.
Tùy thuộc vào cách thông tin được thêm vào truy vấn, bạn sẽ cần những thứ khác nhau để phá vỡ cú pháp. Có ba cách khác nhau để lặp lại thông tin trong một câu lệnh SQL:
- Sử dụng dấu ngoặc kép: ‘xxx’ hoặc “xxx”
- Sử dụng back-tick `.
- Trực tiếp.
Cách thông tin được phản hồi trở lại và thậm chí cả dấu phân tách được sử dụng sẽ quyết định kỹ thuật phát hiện được sử dụng. Tuy nhiên, bạn không có thông tin này, và bạn sẽ cần cố gắng đoán nó. Bạn sẽ cần phải hình thành các giả thuyết và cố gắng xác minh chúng. Đó là lý do tại sao dành thời gian xem xét những ví dụ này là rất quan trọng.
Trong thử thách này, bạn sẽ cần bypass trang đăng nhập bằng cách sử dụng SQL injection. Truy vấn SQL trông giống như sau:
1 |
SELECT * FROM user WHERE login='[USER]' and password='[PASSWORD]'; |
Trong đó: [USER] và [PASSWORD] là các giá trị bạn đã gửi.
Logic đằng sau xác thực là:
- Nếu truy vấn trả về ít nhất một kết quả, bạn đang ở trong
- Nếu truy vấn không trả về kết quả, bạn chưa cung cấp tên người dùng và mật khẩu hợp lệ.
Mục tiêu của chúng tôi là làm cho truy vấn trả về ít nhất một kết quả. Để làm như vậy, chúng ta sẽ đưa ra một điều kiện luôn đúng: 1 = 1. Để làm điều đó, chúng tôi sẽ:
- Ngắt ra bên ngoài dấu nháy đơn để có thể đưa vào SQL bằng cách sử dụng một dấu nháy đơn.
- Thêm từ khóa OR để đảm bảo so sánh luôn đúng.
- Thêm so sánh luôn đúng: 1 = 1
- Comment truy vấn còn lại bằng cách sử dụng – (khoảng trống ở cuối quan trọng) hoặc #.
Nếu chúng ta kết hợp mọi thứ lại với nhau, chúng ta sẽ có được payload của mình.
SQL Injection 01 – 02
Tại 2 phần 01 và 02, chúng ta sẽ thử các cách sau:
1 2 3 4 5 6 7 8 |
Sử dụng dấu ': admin' or 1=1 --' admin' or '1'='1 admin' or '1'='1 -- Hoặc sử dụng dấu ": admin" or 1=1 --" admin" or "1"="1 admin" or "1"="1 -- |
SQL Injection 03
Trong bài tập này, nhà phát triển đã kiểm tra xem chỉ có một kết quả được cơ sở dữ liệu trả về. Bạn có thể bỏ qua kiểm tra này bằng cách sử dụng từ khóa LIMIT.
1 2 3 |
admin' or '1'='1 LIMIT admin' or '1'='1 LIMIT-- |
SQL Injection 04
Trong ví dụ này, thông báo lỗi loại bỏ sự bảo vệ do nhà phát triển tạo ra: NO SPACE. Thông báo lỗi này xuất hiện ngay sau khi một khoảng trống được đưa vào bên trong yêu cầu. Nó ngăn chúng tôi sử dụng phương thức ‘hoặc’ 1 ‘=’ 1 hoặc bất kỳ admin’or ‘1’=’1 nào sử dụng ký tự khoảng trắng. Tuy nhiên, quá trình lọc này dễ dàng bị bỏ qua, sử dụng tabulation (HT hoặc \t). Bạn sẽ cần sử dụng mã hóa, để sử dụng nó bên trong yêu cầu HTTP. Sử dụng cách bypass đơn giản này, bạn sẽ có thể biết cách phát hiện lỗ hổng này.
Nếu chúng ta dùng bất cứ SQL Injection nào ở trên thì sẽ bị app chuyển đổi thành space (+). Do đúng chúng ta cần thay + trong payload bằng HT (%09) trên công cụ Burp Suite:
SQL Injection 05
Trong ví dụ này, nhà phát triển chặn SPACE và tabulation. Có một cách để bỏ qua bộ lọc này. Bạn có thể:
- Bạn không cần khoảng trắng giữa các từ khóa trong nội dung của mình.
- Bạn có thể sử dụng # thay vì – (nếu cần).
- Thay OR bằng ||
Bằng cách áp dụng các thủ thuật này, bạn sẽ có thể khai thác lỗ hổng này.
1 |
admin'||1=1#' |
SQL Injection 06
Ví dụ này được xuất bản lần đầu tiên vào năm 2006 trên Blog của Chris Shiflett như một cách để bỏ qua dấu gạch ngang. Nó dựa trên cách MySQL sẽ thực hiện thoát. Nó sẽ phụ thuộc vào bộ ký tự được kết nối sử dụng. Nếu trình điều khiển cơ sở dữ liệu không biết về bộ ký tự được sử dụng, nó sẽ không thực hiện đúng việc thoát và tạo ra một tình huống có thể khai thác được. Khai thác này dựa trên việc sử dụng GBK. GBK là một bộ ký tự cho tiếng Chinese giản thể. Sử dụng thực tế là trình điều khiển cơ sở dữ liệu và cơ sở dữ liệu không “nói chuyện” với cùng một bộ ký tự, có thể tạo một dấu ngoặc kép và thoát ra khỏi cú pháp SQL để đưa vào một trọng tải.
Sử dụng chuỗi \xBF’ (URL-encoded as %bf%27), có thể nhận được một single quote sẽ không được thoát đúng cách. Do đó, có thể đưa điều kiện luôn đúng bằng %bf%27 or 1=1 -- và bỏ qua xác thực.
Lưu ý thêm, vấn đề này có thể được khắc phục bằng cách thiết lập mã hóa kết nối thành ‘GBK’ thay vì sử dụng truy vấn SQL (là nguồn gốc của vấn đề này). Đây là vấn đề xuất phát từ việc thực thi truy vấn sau:
1 |
SET CHARACTER SET 'GBK'; |
Đó là một vấn đề khá khó xảy ra đối với một ứng dụng web nhưng luôn tốt khi biết rằng nó tồn tại, đặc biệt nếu bạn chơi CTF.
Ở bài toán này cần chú ý thay đổi payload trong Burp như sau (chú ý phải đúng tuyệt đối từng ký tự):
1 |
username=admin%bf%27+or+1=1+--+&password=admin |