Tấn công SQL injection và Phương pháp phòng chống

Khi chúng ta truy cập CSDL và chấp nhận dữ liệu đầu vào bằng cách tạo ra các câu lệnh truy vấn, nó dễ dàng bị các kẻ gian lợi dụng tấn công SQl injection.

Đây là một kỹ thuật tấn công rất phổ biến và sự thành công của nó cũng tương đối cao.

Sql Injection được mô tả như là một trong những lỗ hổng bảo mật web nguy hiểm nhất. Khai thác Sql Injection, ngoài việc đoạt được quyền kiểm soát về mặt dữ liệu như đã nói ở trên, hacker còn có thể cài đặt backdoor trên server mà ứng dụng đang chạy, qua đó kiểm soát toàn bộ hệ thống…

CÁC KIỂU TẤN CÔNG SQL INJECTION

1. Tấn công vượt qua kiểm tra lúc đăng nhập

SQL injection xuất hiện khi các kẻ tấn công muốn làm các “thử nghiệm” trên form để lấy các thông tin về CSDL. Nó thu thập các thông tin từ các thông báo lỗi SQL . Kẻ tấn công đính vào form một trường injecting SQL, phổ biến nó thường đính vào form đăng nhập

[sourcecode language=”php”]
<form method="login.php" action="POST">
Username: <input type="text" name="username" /><br />
Password: <input type="password" name="password" /><br />
<input type="submit" value="LogIn" />
</form>
đoạn mã sử lý đăng nhập dễ bị lợi dụng:
$username = $_POST[’username’];

$password = md5($_POST[’password’]);
$sql = "SELECT *
FROM users
WHERE username = ’{$username}’ AND password = ’{$password}’";
/* database connection and query code */
if (count($results) > 0) {
// Successful login attempt
}
[/sourcecode]

Khi kẻ tấn công nhập user là :
username’ OR 1 = 1 –
và mật khẩu để trống thì cấu trúc câu lệnh SQl là:

[sourcecode language=”php”]
SELECT *
FROM users
WHERE username = ’username’ OR 1 = 1 –’ AND
password = ’d41d8cd98f00b204e9800998ecf8427e’
[/sourcecode]

điều kiện 1=1 thì luôn đúng câu lệnh SQL bỏ qua tất cả những gì sau ‘–’ vì vậy câu lệnh SQl trên sẽ trả lại tất cả các bản ghi. Bằng cách này hacker dễ dàng đăng nhập vào hệ thống với tài khoản bất kỳ khi đã biết tên tài khoản.

2. Dạng tấn công sử dụng câu lệnh SELECT

…………………

3. Các kiểu tấn công nâng cao

Đang tiếp tục cập nhật ……………………………

PHƯƠNG PHÁP PHÒNG CHỐNG TẤN CÔNG SQL INJECTION

Ngay từ khái niệm, chúng ta đã có thể biết được cách phòng chống hiệu quả Sql injection chính là việc kiểm tra kỹ càng tham số đầu vào. Những tham số mà từ đó người lập trình website sử dụng để xây dựng lên câu truy vấn tới cơ sở dữ liệu.

Công việc kiểm tra tham số đầu vào (áp dụng phòng tránh lỗi Sql injection) nên được tiến hành theo nhiều tầng:

  • Client: javascript (có thể bypass bằng các phần mềm tamper)
  • Server: PHP

1. Nếu dữ liệu kiểu INT

Khi bạn nhận dữ liệu ID trên URL thì cách tốt nhất bạn nên ép kiểu, chuyển nó về kiểu số INT, sau đó chuyển về kiểu STRING (nếu cần thiết).

Ví dụ: tôi có url như sau: webtopviet.net/login.php?id=59

[sourcecode language=”php”]
$id = isset($_GET[‘id’]) ? (string)(int)$_GET[‘id’] : false;
[/sourcecode]

Như vậy thì cho dù ta nhập vào kỳ tự gì đi nữa đều sẽ bị clear ra khỏi hết. Hoặc ta có thể dùng cách dước bằng cách dùng hàm preg_replace trong PHP để xóa đi những ký tự không phải là chữ số.

[sourcecode language=”php”]
$id = isset($_GET[‘id’]) ? $_GET[‘id’] : false;
$id = str_replace(‘/[^0-9]/’, ”, $id);
[/sourcecode]

Hoặc dùng hàm: is_numeric($var), is_int($var), is_integer($var)..

2. Dữ liệu là kiểu chuỗi:

  • Thiết lập độ dài tối đa cần thiết: length <= MAX_LENGTH
  • Lọc bỏ ký tự nguy hiểm (bao gồm các meta characters trong DBMS), lọc bỏ các từ khóa như union, select, order, information_schema, insert, drop, load_file… (sử dụng các hàm như mysql_real_escape_string(), preg_replace()…)

[sourcecode language=”php”]
$id = preg_replace("/[^0-9]/","", $_GET[‘id’]);
$query = mysql_query("SELECT * FROM table where id = "’ .$id. ‘");
[/sourcecode]

Sử dụng hàm sprintf và mysql_real_escape_string để xác định kiểu dữ liệu cho câu truy vấn.

Như bạn biết hàm sprintf gồm có hai tham số trở lên, tham số thứ nhất là chuỗi và trong đó có chứa một đoạn Regex để thay thế, tham số thứ 2 trở đi là các giá trị sẽ được thay thế tương ứng. Giá trị ráp vào sẽ được convert phù hợp rồi mới rap vào

Ví dụ:

[sourcecode language=”php”]
$webname = ‘webtopviet.com’;
$title = ‘Học lập trình PHP’;
echo sprintf(‘Website %s laf website %s’, $webname, $title);
[/sourcecode]

Kết quả in ra là: Website webtopviet.com là website Học lập trình PHP.
Nếu bạn chưa biết về hàm sprintf thì vào link này đọc nhé.

Như bạn biết hàm mysql_real_escape_string có nhiệm vụ sẽ chuyển một chuỗi thành chuỗi query an toàn, nên ta sẽ kết hợp nó để gán vào câu truy vấn. Ví dụ:

[sourcecode language=”php”]
$sql = "SELECT * FROM member WHERE username = ‘%s’ AND password = ‘%s’";
echo sprintf($sql, mysql_real_escape_string("phongma"), mysql_real_escape_string("matkhau"));
[/sourcecode]

Kết quả là: SELECT * FROM member WHERE username = ‘phongma’ AND password = ‘matkhau’.

3. Viết lại đường dẫn có thể chống SQL Injection

Vấn đề này có vẻ hơi lạ nhưng bản thân mình thấy rất đúng. Khi bạn viết lại đường dẫn dù trên hệ thống route của FW hay dù trên file .htaccess thì hãy fix chính xác đoạn mã Regular Expresition.

Ví dụ: Tôi có đường dẫn sau khi rewirte là như sau: webtopviet.com/hoc-lap-trinh-mien-phi.html thì đoạn Regex tôi sẽ viết là:

/([a-zA-Z0-9-]+)/([a-zA-Z0-9-]+)\.html/ . Thay vì như vậy thì tôi sẽ viết chính xác /([a-zA-Z0-9-]+)/([0-9])\.html/ thì sẽ tốt hơn. Và đừng quên là cũng ẩn đi đường link gốc của nó nhé.

Trên đây là cách cách tấn công cơ bản và phòng tránh, chúng ta hạn chế được chừng nào thì tốt chừng đó.

Còn đối với các kỹ thuật khác cao hơn và thế giới hacker có nhiều cao thủ cao siêu thì rất khó đối phó, đừng có nên thách thức hay gây oán thù với bất cứ ai. chúng ta nên thường xuyên backup dữ liệu. 

1 thought on “Tấn công SQL injection và Phương pháp phòng chống

  1. vũ hùng tráng Reply

    tôi muốn seo cái web của tôi lên vị trí thứ ba google

Trả lời vũ hùng tráng Hủy

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *

Website này sử dụng Akismet để hạn chế spam. Tìm hiểu bình luận của bạn được duyệt như thế nào.