BẢO MẬT WEBSITE
CÁC CHỦ ĐỀ
BÀI MỚI NHẤT
MỚI CẬP NHẬT

kỹ thuật tấn công SQL Injection và cách phòng chống trong php

Ơ bài trước chúng ta đã được tìm hiểu cách phòng chống CSRF, vậy thì trong bài này ta sẽ tìm hiểu thêm một kỹ thuật khác cũng rất hay sử dụng để tấn công vào những website của những tay nghề thiếu kinh nghiệm lập trình, đó là kỹ thuật tấn công SQL Injection.

test php

banquyen png
Bài viết này được đăng tại freetuts.net, không được copy dưới mọi hình thức.

1. SQL Injection là gì?

SQL Injection là một kỹ thuật lợi dụng những lỗ hổng về câu truy vấn lấy dữ liệu của những website không an toàn trên web, đâ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. Tuy nhiên vào những năm trở lại đây thì xuất hiện nhiều Framwork nên nó giảm hẳn, vì các FW đã hỗ trợ rất tốt việc chống lại hack SQL Injection này.

Chắc hẳn các bạn đã biết mô hình hoạt động của website rồi nhỉ? Khi một request được gửi từ client thì ngôn ngữ SERVER như PHP sẽ lấy các thông tin từ request đó. Nhưng bản thân nó không hề phát hiện ra những thông tin đó có chứa những câu SQL độc, vì thế công việc này ta phải đổ trách nhiệm tới kinh nghiệm của lập trình viên.

Ví dụ: Giả sử tôi có một trang đăng nhập với hai thông tin là tên đăng nhậpmật khẩu.

Bài viết này được đăng tại [free tuts .net]

Đăng nhập tấn công sql injection

Và đoạn code xử lý tấn công sql injection của tôi có dạng như sau:

$username = $_POST['username'];
$password = $_POST['password'];

$sql = "select count(*) from user where username = '$username' AND password = '$password'";
Trường hợp 1: Bây giờ tôi nhập username = thehalfheartpassword = matkhau thì câu truy vấn sẽ là:

select count(*) from user where username = 'thehalfheart AND password = 'matkhau'

Trường hợp 2: Bây giờ tôi nhập username = somenamepassword = something' OR '1. Như vậy câu sql sẽ là:

SELECT * FROM cms_user WHERE user_username = 'thehalfheart' AND user_password = 'something' OR '1'

Chạy câu truy vấn này lên thì kết quả nó trả về là danh sách user nên nếu code cùi cùi thì login được luôn.

Trên đây là một ví dụ điển hình thôi, chứ thực tế thì hacker còn rất nhiều mưu mẹo khác. Tuy nhiên chung quy lại với kỹ thuật tấn công SQL Injection ta vẫn có thể không chế được nó.

2. Phòng chống SQL Injection

Với kinh nghiệm của mình thì thật sự chưa phân tích sâu vào kỹ thuật này, tuy nhiên mình cũng biết chút ít kinh nghiệm để có thể chống lại kỹ thuật này.

2.1. Nhận 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: domain.com/detail.php?id=12

$id = isset($_GET['id']) ? (string)(int)$_GET['id'] : false;
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ố.

$id = isset($_GET['id']) ? $_GET['id'] : false;
$id = str_replace('/[^0-9]/', '', $id);
Rất đơn giản, tuy nhiên mình khuyến khích nên dùng ép kiểu trong PHP, vì nó đơn giản.

2.2 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 Expression (Tham khảo Regular Expression căn bản).

Ví dụ: Tôi có đường dẫn sau khi rewirte là như sau: domain.com/hoc-lap-trinh-mien-phi-tai-freetuts.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é.

2.3 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ụ:

$webname = 'freetuts.net';
$title = 'học lập trình miễn phí';
echo sprintf('Website %s laf website %s', $webname, $title);
Kết quả in ra là: Website freetuts.net là website học lập trình miễn phí.

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ụ:

$sql = "SELECT * FROM member WHERE username = '%s' AND password = '%s'";
echo sprintf($sql, mysql_real_escape_string("thehalfheart"), mysql_real_escape_string("matkhau"));
Kết quả là: SELECT * FROM member WHERE username = 'thehalfheart' AND password = 'matkhau'.

 

Đang Cập Nhật Thêm ...

 

3. Lời kết

Thật sự thì kỹ thuật này rất nhiều và dài, kiến thức của mình chỉ mang tầm căn bản nên mình chỉ share được căn bản. Nếu bạn muốn nâng cao thì có thể đọc thêm tài liệu trên mạng, chủ yếu là tiếng anh. Tuy nhiên thật sự khi đi làm bạn nên sử dụng Framwork, vì FW đa hỗ trợ rất tốt những kiểu tấn công website thông dụng hiện nay rồi, bản thân chúng ta không thể nào tìm hiểu sâu được.

Cùng chuyên mục:

Hàm key_exists() trong PHP

Hàm key_exists() trong PHP

Cách sử dụng key_exists() trong PHP

Hàm mysqli_fetch_row() trong PHP

Hàm mysqli_fetch_row() trong PHP

Cách sử dụng mysqli_fetch_row() trong PHP

Hàm end() trong PHP

Hàm end() trong PHP

Cách sử dụng end() trong PHP

Hàm mysqli_field_count() trong PHP

Hàm mysqli_field_count() trong PHP

Cách sử dụng mysqli_field_count() trong PHP

Hàm count() trong PHP

Hàm count() trong PHP

Cách sử dụng count() trong PHP

Hàm mysqli_field_seek() trong PHP

Hàm mysqli_field_seek() trong PHP

Cách sử dụng mysqli_field_seek() trong PHP

Hàm compact() trong PHP

Hàm compact() trong PHP

Cách sử dụng compact() trong PHP

Hàm mysqli_field_tell() trong PHP

Hàm mysqli_field_tell() trong PHP

Cách sử dụng mysqli_field_tell() trong PHP

Hàm array_values() trong PHP

Hàm array_values() trong PHP

Cách sử dụng array_values() trong PHP

Hàm mysqli_free_result() trong PHP

Hàm mysqli_free_result() trong PHP

Cách sử dụng mysqli_free_result() trong PHP

Hàm array_unshift() trong PHP

Hàm array_unshift() trong PHP

Cách sử dụng array_unshift() trong PHP

Hàm mysqli_get_charset() trong PHP

Hàm mysqli_get_charset() trong PHP

Cách sử dụng mysqli_get_charset() trong PHP

Hàm array_shift() trong PHP

Hàm array_shift() trong PHP

Cách sử dụng array_shift() trong PHP

Hàm mysqli_get_client_stats() trong PHP

Hàm mysqli_get_client_stats() trong PHP

Cách sử dụng mysqli_get_client_stats() trong PHP

Hàm array_unique() trong PHP

Hàm array_unique() trong PHP

Cách sử dụng array_unique() trong PHP

Hàm mysqli_get_client_version() trong PHP

Hàm mysqli_get_client_version() trong PHP

Cách sử dụng mysqli_get_client_version() trong PHP

Hàm array_uintesect() trong PHP

Hàm array_uintesect() trong PHP

Cách sử dụng array_uintesect() trong PHP

Hàm mysqli_get_connection_stats() trong PHP

Hàm mysqli_get_connection_stats() trong PHP

Cách sử dụng mysqli_get_connection_stats() trong PHP

Hàm array_sum() trong PHP

Hàm array_sum() trong PHP

Cách sử dụng array_sum() trong PHP

Hàm mysqli_get_host_info() trong PHP

Hàm mysqli_get_host_info() trong PHP

Cách sử dụng mysqli_get_host_info() trong PHP

Top