[PHP] SQL Injection là gì và cách phòng chống SQL Injection trong PHP

Đăng bởi: chinhnt | Lượt xem: 254 | Chuyên mục: PHP

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ập và mật khẩu.

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

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

Ví dụ: Có đường dẫn sau khi rewirte là như sau: domain.com/hoc-lap-trinh-mien-phi-tai-freetuts.html thì đoạn Regex 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 = 'vncoder.vn';
$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 vncoder.vn 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'.

3. Kết luận

Vậy là vncoder.vn đã hoàn thành hướng dẫn cơ bản cách viết code chống tấn công SQL Injection trong PHP. Hy vọng với những cách cơ bản này sẽ giúp bạn vận dụng tốt trong project của mình. Chúc bạn thành công!.

Theo: freetuts.net

4. Xem thêm

vncoder logo

Theo dõi VnCoder trên Facebook, để cập nhật những bài viết, tin tức và khoá học mới nhất!



Khóa học liên quan

Khóa học: PHP

Xây dựng Website PHP theo MVC
Số bài học:
Lượt xem: 10528
Đăng bởi: Admin
Chuyên mục: PHP

Học lập trình PHP cơ bản
Số bài học:
Lượt xem: 10364
Đăng bởi: Admin
Chuyên mục: PHP