Những lỗi sơ hở trong quá trình build ứng dụng
web/ phần mềm, hacker sử dụng lỗi này để lạm dụng các câu truy vấn sql bất hợp
pháp để tấn công vào web ứng dụng của chúng ta.
Sẽ hơi mơ hồ nếu như
không đi từ lý thuyết thì rất khó hiểu bởi vậy ta đi từ lý thuyết kèm ví dụ
minh họa nha.
Sql injection: Bạn học
môn hệ quản trị cơ sở dữ liệu sql server, oracle, DB2, mongo,... biết được cú
pháp, thao tác select , from, having, group by, where, inner join... thao tác
các bảng dữ liệu vớinhau
Sql injection là kỹ
thuật cho phép hacker lợi dụng chỗ sơ hở trong việc kiểm tra dữ liệu đầu vào ở
ứng dụng web và các notification của hệ quản trị CSDL trả về để inject và thi
hành các câu lệnh SQL bất hợp pháp bằng các thao tác delete, insert, update,...
chúng ta hãy để ý đến
những lỗi cơ bản thường gặp dưới đây:
1.
Không kiểm tra kí tự thoát truy vấn:
Sql injection xảy ra
khi thiếu đoạn mã kiểm tra dữ liệu đầu vào trong câu truy vấn SQL. Kết quả là
người dùng cuối có thể thực hiện 1 số truy vấn không mong muốn với CSDL:
statement = "SELECT * FROM users
WHERE name = '" + userName+ "' ;"
>>> Câu lệnh
trên truy vấn thuôc tính name từ bảng users. Tuy nhiên, nếu biến
"userName" được nhập chính xác theo 1 cách nào đó thì người dùng ác ý
có thể nhập vào giá trị của biến userName như sau:
" SELECT * FROM users
WHERE name = 'a' OR 't' = 't';"
Đoạn mã trên được sử
dụng trong 1 thủ tục xác thực thì VD trên có thể được sử dụng để bắt buộc lựa
chọn 1 tên người dùng hợp lệ bới ' t' = 't' luôn đúng. Trong khi hầu hết các
SQL server cho phép thực hiện nhiều truy vấn cùng lúc chỉ với 1 lần gọi, nhưng
1 số SQL API mysql_query của PHP lại không cho phép làm điều đó vì lý do bảo
mật. Điều này chỉ ngăn cản tin tặc tấn công bằng những câu lệnh riêng rẽ mà
không ngăn cản tin tặc tấn công bằng việc thay đổi cú pháp truy vấn.
Ở ví dụ trên cho thấy
các giá trị của biến userName sẽ gây ra việc xóa thông tin người dùng từ bảng
users cũng tương tự từ việc xóa tất cả dữ liệu từ bảng dữ liệu ( bản chất là
tiết lộ thông tin người dùng) . Minh hoạ cụ thể bằng câu truy vấn dưới đây để
hiểu rõ được bản chất hơn:
" DROP TABLE users;
SELECT * FROM data
WHERE 't' = 't'
Tổng hợp lại toàn bộ
câu truy vấn như sau:
DROP TABLE users
SELECT * FROM data
WHERE 't' = 't';
Như vậy là tin tặc lợi
dụng lỗi sơ hở cú pháp truy vấn trên để chỉ việc thay đổi thêm bớt vài lệnh
truy vần truyền vào là có thể xâm nhập được hệ thống của chúng ta 1 cách dễ
dàng.
Điều
thứ 2 liên quan tới SQL injection đó là Xử lý không đúng kiểu.
Do coder định nghĩa dữ
liệu đầu vào không rõ ràng hoặc thiếu bước kiểm tra và lọc kiểu dữ liệu đầu vào
(ví dụ kiểm tra dữ liệu nhập vào từ user là kiểu số hay chuỗi
state = "SELECT * FROM data WHERE id = "+
a_variable +" ;"
Lệnh state trên cho
chúng ta biết rằng cho người dùng nhập vào id dạng số nhưng lại không kiểm tra
kiểu nhập vào nên người dùng thay vì nhập số mà nhập vào 1 chuỗi string.
Điều
thứ 3 xảy ra là lỗi bảo mật bên trong máy chủ CSDL
Đôi khi lỗ hổng bảo
mật nằm ngay chính máy chủ CSDL, VD hàm mysql_real_escape_string()
hacker có thể thực hiện
cuộc tấn công SQL injection thành công dựa trên những ký tự unicode không thông
thường ,
lấy 1 sồ VD minh hoạ
$user ="<div> user </div>
$password = "<div> password</div>
$query = sprintf( "SELECT * FROM users
WHERE
username ='%s' AND password = '%s'")
mysql_real_escape_string($username)
mysql_real_escape_string($password)
echo $query;
Kết quả in ra sẽ
là:
SELECT * FROM users
WHERE user = ' ' AND password = ' '
Tiếp đến 1 trường hợp
nữa tại form đăng nhập, người dùng nhập tên đăng nhập mà không cần đúng mật
khẩu
<?php
$query = "SELECT * FROM users
WHERE username = '{$_POST['username']}' AND password =
'{$_POST['password']}'";
mysql_query($query);
$_POST['username'] = ' your's name';
$_POST['password'] = " OR "=";
echo $query;
?>
Câu lệnh truyền
lên server sẽ là:
SELECT * FROM users WHERE username = 'yours name' AND
password = " OR "="
4. Điều
thứ 4 xảy ra là Blind SQL injection
Lỗi SQL injection dạng
Blind SQL injection xảy ra ngay trong ứng dụng web, hậu quả của chúng
không hiển thị trực quan cho những kẻ tấn công. Nó có thể gây ra sự sai
khác khi hiển thị nội dung của 1 trang chứa lỗi bảo mật này. Hậu quả của
sự tấn công SQL injection dạng Blind SQL injection này khiến cho coder phải mất
nhiều time để phục hồi chính xác từng bit dữ liệu. Những kẻ tấn công còn sử
dụng 1 số tool tìm dò lỗi và tấn công với những thông tin đã thiết lập sẵn
Còn rất nhiều
các dạng tấn công khác xảy ra khi mà hacker sử dụng kỹ thuật SQL injection và
lỗi sơ hở trong các câu truy vấn để đột nhập lấy cắp dữ liệu
Update thêm các dạng
tấn công thường gặp với ứng dụng web
1.
Dạng
tấn công vượt qua kiểm tra lúc đăng nhập
Với dạng tấn công này,
tin tặc có thể dễ dàng vượt qua các trang đăng nhập nhờ vào lỗi khi dùng các
câu lệnh SQL thao tác trên cơ sở dữ liệu của ứng dụng web. Thông thường để cho
phép người dùng truy cập vào các trang web được bảo mật, hệ thống thường xây
dựng trang đăng nhập để yêu cầu người dùng nhập thông tin về tên đăng nhập và
mật khẩu. Sau khi người dùng nhập thông tin vào, hệ thống sẽ kiểm tra tên đăng
nhập và mật khẩu có hợp lệ hay không để quyết định cho phép hay từ chối thực
hiện tiếp. Ví dụ, trong trường hợp sử dụng ASP, người ta có thể dùng 2 trang: 1
trang HTML để hiển thị Form nhập liệu và 1 trang ASP để xử lý thông tin nhập
vào từ phía người dùng như sau:
- Trang nhập liệu:
login.htm
<form
action="ExecLogin.asp" method="post">
Username:
<input type="text" name="fUSRNAME"><br
/>
Password:
<input type="password" name="fPASSWORD"><br
/>
<input
type="submit">
</form>
- Trang xử lý nhập
liệu: execlogin.asp
<%
Dim vUsrName,
vPassword, objRS, strSQL
vUsrName =
Request.Form("fUSRNAME")
vPassword =
Request.Form("fPASSWORD")
strSQL = "SELECT
* FROM T_USERS " & _
"WHERE USR_NAME='
" & vUsrName & _
" ' and
USR_PASSWORD=' " & vPassword & " ' "
Set objRS =
Server.CreateObject("ADODB.Recordset")
objRS.Open strSQL,
"DSN=..."
If (objRS.EOF) Then
Response.Write
"Invalid login."
Else
Response.Write
"You are logged in as " & objRS("USR_NAME")
End If
Set objRS = Nothing
%>
Chỗ sơ hở trong đoạn
mã xử lý nhập liệu trên nằm ở chỗ dữ liệu nhập vào từ người dùng được dùng để
xây dựng trực tiếp câu lệnh SQL. Chính điều này cho phép tin tặc có thể điều
khiển câu truy vấn sẽ được thực hiện. Ví dụ, nếu người dùng nhập chuỗi trong
ngoặc sau vào trong cả 2 ô nhập liệu username/password của trang login.htm
là:('OR='). Lúc này, câu truy vấn sẽ được gọi thực hiện là:
SELECT * FROM T_USERS
WHERE USR_NAME =''OR''='' AND USR_PASSWORD= ''OR''=''
Câu truy vấn này là
hợp lệ và sẽ trả về tất cả các bản ghi của T_USERS và đoạn mã tiếp theo xử lí
người dùng đăng nhập bất hợp pháp này như là người dùng đăng nhập hợp lệ.
2.
Dạng
tấn công sử dụng câu lệnh SELECT
Dạng tấn công này phức
tạp hơn
Để thực hiện
được kiểu tấn công này, kẻ tấn công phải có khả năng hiểu và lợi dụng các sơ hở
trong các thông báo lỗi từ hệ thống để dò tìm các điểm yếu khởi đầu cho việc
tấn công. Ví dụ, trong các trang tìm kiếm. Các trang này cho phép người dùng
nhập vào các thông tin tìm kiếm như Họ, Tên, … Đoạn mã thường gặp là:
<%
Dim
vAuthorName, objRS, strSQL
vAuthorName = Request("fAUTHOR_NAME")
strSQL =
"SELECT * FROM T_AUTHORS WHERE AUTHOR_NAME =' " & _ vAuthorName
& " ' "
Set
objRS = Server.CreateObject("ADODB.Recordset")
objRS.Open strSQL, "DSN=..."
…
Set
objRS = Nothing %>
Tương tự như trên, tin
tặc có thể lợi dụng sơ hở trong câu truy vấn SQL để nhập vào trường tên tác giả
bằng chuỗi giá trị:
' UNION SELECT ALL
SELECT OtherField FROM OtherTable WHERE ' '=' (*)
Lúc này, ngoài câu
truy vấn đầu không thành công, chương trình sẽ thực hiện thêm lệnh tiếp theo
sau từ khóa UNION nữa. Giả sử đoạn mã nhập vào là:
' DROP TABLE T_AUTHORS
--
Câu truy vấn sẽ thực
hiện việc xóa bảng.
3.
Dạng
tấn công sử dụng câu lệnh INSERT
Ví dụ điển hình nhất ở
thao tác đăng ký thông tin người dùng, sau khi đăng ký thành công, người dùng
có thể xem thông tin của mình. Ngay lúc này SQL injection có thể được dùng khi
hệ thống không kiểm tra tính hợp lệ của thông tin nhập vào. Ví dụ, một câu lệnh
INSERT có thể có cú pháp dạng:
INSERT
INTO TableName VALUES('Value One', 'Value Two', 'Value Three')
Nếu đoạn mã xây dựng
câu lệnh SQL có dạng:
<%
strSQL =
"INSERT INTO TableName VALUES(' " & strValueOne & " ', '
" _ & strValueTwo & " ', ' " & strValueThree &
" ') "
Set
objRS = Server.CreateObject("ADODB.Recordset")
objRS.Open strSQL, "DSN=..."
…
Set
objRS = Nothing %>
Thì chắc chắn sẽ bị
lỗi SQLi, bởi vì nếu ta nhập vào trường thứ nhất ví dụ như:
' +
(SELECT TOP 1 FieldName FROM TableName) + '
Lúc này câu truy vấn
sẽ là:
INSERT
INTO TableName VALUES(' ' + (SELECT TOP 1 FieldName FROM TableName) + ' ',
'abc', 'def')
Khi đó, lúc thực hiện
lệnh xem thông tin, xem như bạn đã yêu cầu thực hiện thêm một lệnh nữa đó là:
SELECT TOP 1
FieldName FROM TableName
Trên đây là cơ bản về
kỹ thuật SQL injection, là tester chúng ta ít nhiều nên biết về kỹ thuật này để
trau dồi kinh nghiệm test cho mình J
Bài viết trên tham khảo tại wiki và 1 số trang công nghệ khác. Bạn
đọc thấy thiếu sót chỗ nào phản hồi góp ý với mình nha. Thanks for reading!
Câu hỏi thường gặp khi phỏng vấn tester
Câu hỏi thường gặp khi phỏng vấn tester