Sie sind auf Seite 1von 4

:: EnHack.

Net ::
http://xforce.enhack.net/
PHP Underground Security - SQL Injection
http://xforce.enhack.net/viewtopic.php?f=7&t=320  

Author:  Jutoms [ 16 Feb 2009 15:19 ]


Post subject:  PHP Underground Security - SQL Injection

SQL Injection không còn xa lạ với chúng ta trong những năm trở lại đây, thậm chí nó đã
trở nên phổ biến và được rất nhiều người lợi dụng. Thế nhưng SQL Injection là gì ? Tìm lỗi,
lợi dụng, vá lỗi như thế nào thì lại là một vấn đề khác, vấn đề mà tôi sẽ đề cập trong chủ
đề này.

I. SQL Injection là gì ?
Injection nghĩa là tiêm, nhiễm và với SQL Injection ta có thể chèn (tiêm) thêm truy vấn
SQL vào câu truy vấn dựa vào lỗi của ứng dụng web.

II. Các ứng dụng của SQL Injection:


Trước khi đi tìm hiểu sâu vào việc lợi dụng (exploit) thì các bạn cần nhớ vài kí tự quan
trọng mà ta sẽ phải dùng khi thực hành.
- dấu nháy đơn ('): dấu này trong ngôn ngữ SQL dùng để "gói" chuỗi. Ta thường thêm nó
vào sau tham số kiểu số trên chuỗi truy vấn để kiểm tra có lỗi hay không. Nguyên nhân là
do không kiểm tra kiểu dữ liệu.
- dấu thăng (#) và dấu (--): các dấu này để đánh dấu chú thích, nghĩa là những kí tự
đứng sau một trong hai dấu này trên cùng một dòng sẽ được xem là chú thích được bỏ
qua khi thực hiện truy vấn.
- dấu (;): dùng để kết thúc một truy vấn và tất nhiên sau nó là bắt đầu một truy vấn
khác. Đôi khi ta dùng union để nối hai câu truy vấn.

Và sau đây là các ứng dụng lợi dụng lỗi SQL Injection:

1/ Login Bypassing – đoạt quyền Admin


Xem code PHP của file login.php
Code:
<?php
$logged = 0;
 
$nick = $_POST['nick'];
$pass = $_POST['pass'];
 
$db = mysql_connect('localhost','user','pass') or die('Error: '. mysql_error());
mysql_select_db("dbname", $link);
 
 
$query = "SELECT * FROM dbname WHERE nick ='".$nick."' AND pass ='" .$pass. "'";
$result = mysql_query($query, $db);
 
if (mysql_num_rows($result) == 0) {
echo "Denied! Your Login is Incorrect";
exit;
}
 
$logged = 1;
 
[...]
 
//EoF
?>

Ta thấy rằng nếu truy vấn không trả về bảng ghi nào tồn tại trong CSDL thì lập tức người
dùng sẽ được đưa trở về trang index.html, ngược lại sẽ đăng nhập thành công.

Lưu ý: Ở đây tôi dùng "bản ghi" (record) thay cho "kết quả" cho đúng với bản chất.

Code trên tuy đơn giản nhưng ta thấy rằng chỉ cần làm cho truy vấn có bản ghi trả về thì
ta sẽ đăng nhập thành công mà không cần biết Nick hay Pass.

Phần này đòi hỏi người đọc phải biết một tí về câu lệnh Select và điều kiện của mệnh đề
Where, kết quả của phép toán OR.

Nếu ta đăng nhập với nick và pass không khớp với một bản ghi trong CSDL thì tất nhiên
không có bản ghi nào thoả mãn để được trả về.

Nhưng giả sử ta login với thông tin sau:


$nick = xyz' OR '1' = '1
$pass = xyz' OR '1' = '1

thì câu truy vấn sẽ trở thành


"SELECT * FROM sql_inj WHERE nick ='xyz' OR '1' = '1' AND pass ='xyz' OR '1' = '1'"

xyz là một chuỗi gì đó bất kì, quan trọng là phần OR 1 = 1


Câu truy vấn kia sẽ: lựa tất cả các bản ghi nào thoả điều kiện (WHERE) nick = xyz hoặc
1=1 và pass=xyz hoặc 1=1
Mà 1 = 1 là hằng đúng nên dù (nick = xyz) là FALSE thì kết của của (nick = xyz OR 1=1)
sẽ là TRUE, tương tự với (pass=xyz hoặc 1=1) cũng sẽ là TRUE, mà (true AND true) =
true. (ta có thể xem 0 là FALSE và 1 là TRUE).

Vậy với điều kiện là một hằng đúng thì mọi bản ghi đều thoả rồi, vậy nên trong CSDL có

bao nhiêu bản ghi (tương ứng chừng ấy User) sẽ được trả về, và khi đó ...
Ngoài ra ta còn có thể làm ngắn gọn hơn vì chỉ cần nhập
 
$nick = xyz' OR '1' = '1 #
hoặc
$nick = xyz' OR '1' = '1 --

là được.

2/ Modify Database - Thay đổi dữ liệu


Cũng từ VD trên, ta có thể thay đổi password, email của admin bằng cách:
 
$nick = xyz'; UPDATE users SET email = 'email_của_mình' WHERE nick='admin';#
 
Sau đó ta chỉ việc forgot pass admin và vào check mail mình là xong. Tương tự cho cách
đổi pass admin:
 
$nick = xyz' UNION UPDATE users SET password = 'pass mới' WHERE nick='admin';#

Ngoài ra còn có rất nhiều cách để lợi dụng như nâng quyền của mình lên Admin, tìm tên
CSDL và thậm chí DROP Database.

Đối với phương thức GET thì ta cũng sử dụng tương tự bằng cách đưa tham số lên URL.
Xem bài viết viewtopic.php?f=35&t=301

III. Cách tìm lỗi:


Qua VD bạn nhận thấy đặc trưng của SQL Injection là gì ? Đó chính là sử dụng dữ liệu
được nhập vào trong câu truy vấn mà không qua kiểm tra.

IV. Cách vá lỗi:


1. Mởi php.ini và set magic_quotes_gcp thành On
Nó sẽ chèn "\" trước (') có trong:
-COOKIE
-POST
-GET

2. Sử dụng hàm addslashes() để "gói" chuỗi bằng dấu "/"


3. Sử dụng hàm htmlspecialchars(), mysql_escape_string() ... để mã hoá kí tự đặc biệt
trong câu truy vấn

4. Ép kiểu:
- Ta biết id của một đối tượng (user, category, box, product ...) luôn là kiểu số nguyên, vì
vậy ta dùng:
 
$id = (int)$_POST['id'];
hoặc
$id = (int)$_GET['id'];

hoàn tất

  All times are UTC + 7 hours


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/

[ Copyright © 2008 - Developed by EHS ]


:::::::::::::::: [ :: Entertainment and Ethical Hacking :: ] ::::::::::::::::

Das könnte Ihnen auch gefallen