1. Nội dung

  • Giới Thiệu
  • SQL Injection
  • SQL Injection Blind
  • Cách Phòng Chống
  • Các Bài Viết Liên

2. Giới thiệu

  • 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, v.v. 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 như SQL Server, MySQL, Oracle, DB2, Sysbase...
  • SQL Injection chia làm 2 loại chính:
  • SQL Injection
  • SQL Injection (Blind)
  • Trong các bài viết về Series Web Application Security sẽ sử dụng DVWA để có thể thấy rõ được cách thức tấn công và lỗ hổng. Trong DVWA có 4 cấp độ Security – được lưu trữ trong cookie : security
  • imposible – với cấp độ này thì kẻ tấn công không thể nào tấn công được hệ thống
  • high – khi thiết lập ở cấp độ này vẫn có thể tấn công vào hệ thống nhưng rất khó
  • medium – mức độ security trung bình
  • low – mức độ thấp nhất có thể hack một cách dễ dàng để có thể hiểu về các lỗ hổng. Các bài viết sẽ đề cập tới level low và level imposible.

3. SQL Injection

Định nghĩa

  • Kiểu tấn công nguy hiểm khi tiêm thêm dữ liệu đầu vào để liệt kê ra các dữ liệu không mong muốn đổ ra cho người dùng nhìn thấy.
  • Database:
- mysql> select * from users; 
+---------+------------+-----------+---------+----------------------------------+------------------------------------------------+---------------------+--------------+ 
| user_id | first_name | last_name | user | password | avatar | last_login | failed_login | 
+---------+------------+-----------+---------+----------------------------------+------------------------------------------------+---------------------+--------------+ 
| 1 | admin | admin | admin | 7c6a180b36896a0a8c02787eeafb0e4c | http://webtest1.com/hackable/users/admin.jpg | 2016-12-29 08:19:09 | 0 | 
| 2 | Gordon | Brown | gordonb | e99a18c428cb38d5f260853678922e03 | http://webtest1.com/hackable/users/gordonb.jpg | 2016-12-29 07:22:43 | 0 | 
| 3 | Hack | Me | 1337 | 8d3533d75ae2c3966d7e0d4fcc69216b | http://webtest1.com/hackable/users/1337.jpg | 2016-12-29 07:22:43 | 0 | 
| 4 | Pablo | Picasso | pablo | 0d107d09f5bbe40cade3de5c71e9e9b7 | http://webtest1.com/hackable/users/pablo.jpg | 2016-12-29 07:22:43 | 0 | 
| 5 | Bob | Smith | smithy | 5f4dcc3b5aa765d61d8327deb882cf99 | http://webtest1.com/hackable/users/smithy.jpg | 2016-12-29 07:22:43 | 0 | 
+---------+------------+-----------+---------+----------------------------------+------------------------------------------------+---------------------+--------------+
 5 rows in set (0.00 sec)

Xem Xét Lỗ Hổng

  • Trang web có chức năng hiển thị: -
  • Client nhập vào số ID và hiển thị ra các thông tin về người dùng như ID, First Name, Surname
  • Một client bình thường thì sẽ không có vấn đề gì. Client sẽ chỉ nhập đúng những ID yêu cầu.
  • Với level security low thì code kiểm tra ID như sau:
$query = "SELECT first_name, last_name FROM users WHERE user_id = '$id';"; 
$result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' ); // Get results 
$num = mysql_numrows( $result );
$i = 0;
while( $i < $num ) { 
  // Get values 
  $first = mysql_result( $result, $i, "first_name" ); 
  $last = mysql_result( $result, $i, "last_name" ); 
  
  // Feedback for end user 
  $html .= "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>"; 
  
  // Increase loop count 
  $i++;
}
  • Một Hacker ác ý có thể nhập một số chuỗi [10000′ OR ‘1’ = ‘1]  như vậy câu Query trên nếu cộng thêm $id thì sẽ thành như sau
$id="10000' OR '1'='1"; 
↓ 
SELECT first_name, last_name FROM users WHERE user_id = '$id'; 
↓ 
SELECT first_name, last_name FROM users WHERE user_id = '10000' OR '1'='1';
  • Như vậy với câu SQL trên thì sau khi được thực hiện sẽ lấy ra hết cả first_name, last_name từ trong table users.
  • Kết quả:
  • Nếu thay đổi sang level cao hơn của DVWA: Level = high thì bên server:
// Check database 
$query = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;"; 
$result = mysql_query( $query ) or die( '<pre>Something went wrong.</pre>' );

  • Với level như trên thì khi nhập [10000′ OR ‘1’ = ‘1] -> câu query sẽ thành:
SELECT first_name, last_name FROM users WHERE user_id = '10000' OR '1'='1' LIMIT 1;
  • Như vậy cho dù lấy được dữ liệu ra nhưng không phải toàn bộ những dữ liệu của bảng users.
  • Lúc này thử thay đổi đầu vào khi lợi dụng một số comment out của MYSQL:
  • Dữ liệu nhập: [1000′ OR 1=1; — ‘] Query sẽ thành:
SELECT first_name, last_name FROM users WHERE user_id = '1000' OR 1=1; -- ' LIMIT 1;
  • Vì sau dấu: [–] mọi thứ sẽ trở thành comment của đoạn query nên nó không có ý nghĩa. Và với đoạn mã trên làm cho lỗ hổng SQL Injection vẫn có thể lợi dụng được.

4. SQL Injection Blind

Định nghĩa

  • Định nghĩa bời Wikipedia: Blind SQL (Structured Query Language) injection is a type of SQL Injection attack that asks the database true or false questions and determines the answer based on the applications response. This attack is often used when the web application is configured to show generic error messages, but has not mitigated the code that is vulnerable to SQL injection. When an attacker exploits SQL injection, sometimes the web application displays error messages from the database complaining that the SQL Query's syntax is incorrect. Blind SQL injection is nearly identical to normal SQL Injection, the only difference being the way the data is retrieved from the database. When the database does not output data to the web page, an attacker is forced to steal data by asking the database a series of true or false questions. This makes exploiting the SQL Injection vulnerability more difficult, but not impossible. .

  • Đây là một kiểu tấn công hết sức kỳ công. Cũng dựa trên lỗ hổng về SQL và để mò mẫm dữ liệu. Có một số Web Application chỉ đưa ra thông báo lỗi và kẻ tấn công dựa vào đó hỏi database những câu hỏi kiểu dạng Đúng, Sai để có thể tìm được dữ liệu của DataBase. Vì câu hỏi Đúng Sai cần rất nhiều mới biết được câu trả lời nên kiểu tấn công này rất kỳ công, khó nhưng vẫn có thể xảy ra.

Xem xét lỗ hổng

  • Trang web hiển thị: DVWA: SQL Injection (Blind) – security level: low

  • Trong ví dụ trên thì hệ thống Web Application cung cấp một chức năng kiểm tra userID có tồn tại hay không. Nếu có dữ liệu thì trả về message: ‘User ID exists in the database‘ ngược lại trả về: ‘User ID is MISSING from the database‘

  • Để kiểm tra chức năng trên có thể khai thác lỗ hổng SQL Injection Blind không thì thử nhập với chuỗi sau: [1000′ OR 1 = 1 — ] và dự đoán kết quả sẽ như sau:

  • Như vậy dù nhập dữ liệu UserID ko có trong Database thì câu trả lời vẫn là có. Như vậy chức năng trên có thể lợi dụng để kiểm tra SQL Injection Blind.

  • Câu hỏi để hỏi database trong SQL Injection Blind thường là [{true query} AND {check query}]. Ví dụ như câu hỏi SQL ở trên, đã có UserID=1 rồi nên có hỏi database như sau:

[1′ AND (SELECT user_id FROM users where user_id<10 LIMIT 1)>0 — ] 
hoặc
[1′ AND (SELECT user_id FROM users where user_id>=10 LIMIT 1)>0 –]

Với câu hỏi database như trên. Nếu cái nào trả về true thì có thể đoán được là user_id

  • Như kết quả từ cách thử trên thì đoán được user_id của bảng users chỉ có giá trị nhỏ hơn 10. Nhưng ở đây Hacker làm sao biết được có những bảng nào với trường nào? Chả lẽ chịu thua? Một cách thức khác dựa vào đây có thể đoán được cấu trúc database, table, column. Ví dụ
1' AND ascii(lower(substring((SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES where TABLE_NAME>'u' LIMIT 1), 1,1)))>116
1' AND ascii(lower(substring((SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES where TABLE_NAME>'u' LIMIT 1), 1,1)))<118
1' AND ascii(lower(substring((SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES where TABLE_NAME>'u' LIMIT 1), 1,1)))=116
  • Với câu hỏi trên với database ta có thể biết được có 1 table có tên bắt đầu bằng chữ ‘u’, để kiểm tra có table tên usser, có column tên usser_id hay không? thì hacker sẽ tốn khá nhiều time để thử.
  • Nhưng sau khi thử xong và có thể dựa vào câu hỏi đúng sai có thể tìm được account, password, các thông tin muốn trộm cắp… một cách dễ dàng – chỉ tội mất time

5. Cách Phòng chống

  • Nguyên Nhân Bị mắc lỗi SQL Injection
  • Do lỗi developer tạo SQL Query bằng cách cộng chuỗi thông thường.
  • Do việc thông báo lỗi đúng sai khi query một query.
$query = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
  • SQL Injection Blind
  • Do việc không xử lý input đầu vào từ bên client ở trên server side.
  • Cách phòng chống
  • Dùng SQL_PlaceHolder thay vì cộng chuỗi thông thường:
  • Không đưa ra thông báo lỗi liên quan đến database khi thực hiện query sai
  • Không bao giờ tin tưởng input của client.
$data = $db->prepare( 'SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;' );
$data->bindParam( ':id', $id, PDO::PARAM_INT ); $data->execute();
  • Một trang web đang hoạt động bị gặp SQL – Innjection: Chú ý nội dung chỉ để tham khảo.*** Trang web đó đã fixed nên đừng cố thử***


6. Các Bài Viết Liên Quan Tới Series