Professional Documents
Culture Documents
Tuần 5 A03 Injecton SQL Injection
Tuần 5 A03 Injecton SQL Injection
Tuần 5 A03 Injecton SQL Injection
Nếu bạn là attacker bạn có thể tương tác và thay đổi truy vấn sql bằng cách thêm các ký
tự sql hoặc mã sql vào vector đầu vào của ứng dụng thì bây giờ ứng dụng đó chắc chắn
dễ bị Sql Injection
VD: Hãy tưởng tượng bạn có 1 kẻ attacker tấn công web server và có database, ứng dụng
mà web server lưu trữ có chức năng xác thực mà người dùng phải thực hiện nhập
username và password và sau khi nhập đúng sẽ được đưa vào database để xem rằng
username và password này có trong database hay không và nếu có người dùng sẽ được
cung cấp trang hồ sơ của họ và nếu không đúng nó sẽ thông báo lỗi bạn đã nhập sai
username or password
rõ ràng trong trường hợp này có 2 vector đầu vào là username field và password field
chúng được đưa vào một truy vấn trong database vì vậy chúng chắc chắn cần kiểm tra
các vector đầu vào để tìm lỗ hổng SQL INJECTION
Trong trường hợp này attacker thay vì chỉ thay tên người dùng, attacker thêm tên người
dùng quản trị viên là admin (tài khoản mà attacker muốn xâm phạm) nhưng sau đó
attacker cũng thêm một số kí tự sql sau tên người dùng admin’ - - vì thế điều này sẽ dẫn
đến tên người dùng sẽ được đưa vào truy vấn vì thế truy vấn thực hiện ở phần sau là nó
1. SELECT * FROM users : Phần này của truy vấn SQL đang cố gắng lấy tất cả các cột ( ) từ
một bảng cơ sở dữ liệu có tên "users".
2. WHERE username = 'admin'--' : Đây là điều kiện mà bạn đang cố gắng áp dụng cho truy
vấn. Bạn đang cố gắng so sánh cột "username" với giá trị 'admin', sau đó là - , đây là
3. AND password = ' ' : Trong phần này của truy vấn, bạn đang cố gắng so sánh cột
"password" với một khoảng trắng duy nhất (' ')
Nếu đầu vào này được xác thực chính xác thì database sẽ tìm đến username = admin’- -
và nó sẽ không tìm thấy nếu không có username đó.
Như thế ở đây attacker đã khai thác thành công chức năng đăng nhập của ứng dụng để
vượt qua xác thực mà không cần biết password admin vì attacker đã có thể thay đổi truy
vấn để không còn yêu cầu password
Integrity – SQLi can be used to alter data in the database (Tính toàn vẹn – SQLi có thể
được sử dụng để thay đổi dữ liệu trong cơ sở dữ liệu)
Availability – SQLi can be used to delete data in the database (Tính khả dụng – SQLi
có thể được sử dụng để xóa dữ liệu trong cơ sở dữ liệu)
Remote code execution on the operating system (Thực thi mã lệnh từ xa trên hệ điều
hành)
Error-based SQLi
Union-based SQLi
Error-Based SQLi:
Error-based SQLi là một kỹ thuật in-band SQLi buộc database (cơ sở dữ liệu) tạo ra lỗi,
cung cấp cho kẻ tấn công thông tin chỉnh sửa kỹ thuật tấn công injection của họ.
Example:
Hãy tưởng tượng bạn có ứng dụng www.ramdom.com có tham số id dễ bị tấn công . Việc
tấn công sql injection trong trường hợp này chúng ta đặt 1 trích dẫn trong trường id và đó
là kí tự tiếp theo nên điều này dễ bị tấn công sql injection trích dẫn sẽ trở thành 1 phần
của câu truy vấn và nó sẽ phá vỡ truy vấn phụ trợ và báo lỗi
Input:
www.random.com/app.php?id='
Output:
You have an error in your SQL sytax, check the manual that correspond
MySQL server version…
Và trong trường hợp này nó đã thông báo lỗi nhưng nó cho chúng ta thông tin rằng bạn
đang sử dụng mysql và đó là thông tin hữu ích và cho biết version hiện tại
Union-Based SQLi
SQL Injection dựa trên UNION (Union-Based SQLI) là một kỹ thuật SQL Injection thuộc
loại in-band, nó tận dụng toán tử SQL UNION để kết hợp kết quả của hai truy vấn thành
một tập dữ liệu kết quả duy nhất.
Trong trường hợp này nó sẽ đưa ra kết quả của truy vấn là tên người dùng và mật khẩu
Output:
carlos
afibh9cjnkuwcsfobs7h
administrator
tn8f921skp5dzoy7hxpk
Boolean-based SQLi
Time-based SQLi
Example URL:
Hãy tưởng tượng bạn có 1 trang web www.ramdom.com và có một tham số id dễ bị tấn
công bằng blind sqli và trường hợp này bạn không thể sử dụng toán tử để xuất dữ liệu
trong database
www.random.com/app.php?id=1
Khi bạn nhập id =1 nó sẽ cung cấp 1 câu truy vấn là trích xuất tittle từ bảng product nới có
id =1.
Vì bằng 1 là id hợp lệ trong bảng nên ứng dụng sẽ hiện thị tittle của các sản phẩm được
liên kết với id = 1
Backend Query:
Chúng ta muốn 1 payload sai , chúng ta có thể sử dụng 1 câu lệnh điều kiện =1 and 1=2
nên truy vấn phía sau sẽ chọn title từ bảng product trong đó id =1 và 1=2 mà id =1 là 1 id
hợp lệ nên điều này sẽ đánh giá là đúng và 1=2 chúng ta đánh giá thành sai vì 1 không
bao giờ bằng 2
Payload #1 (False):
Backend Query:
1. select title from product : Phần này chỉ định rằng bạn muốn trích xuất cột "title" từ
bảng "product".
2. where id = 1 and 1 = 2 : Điều này là mệnh đề WHERE trong câu truy vấn. Nó chỉ lấy các
hàng trong bảng "product" mà có giá trị cột "id" bằng 1 và có giá trị 1 bằng 2.
Vì "1 = 2" luôn luôn là điều kiện sai (FALSE) trong SQL, nên câu truy vấn này sẽ không trả
về bất kỳ hàng nào từ bảng "product". Nó đang kiểm tra xem liệu có bất kỳ dòng nào có
Backend Query:
1. select title from product : Phần này chỉ định rằng bạn muốn trích xuất cột "title" từ
bảng "product".
2. where id = 1 and 1 = 1 : Điều này là mệnh đề WHERE trong câu truy vấn. Nó chỉ lấy các
hàng trong bảng "product" mà có giá trị cột "id" bằng 1 và có giá trị 1 bằng 1.
Vì "1 = 1" luôn luôn là điều kiện đúng (TRUE) trong SQL, nên câu truy vấn này sẽ trả về tất
cả các hàng trong bảng "product" mà có "id" bằng 1. Nó kiểm tra xem liệu có bất kỳ dòng
nào có "id" bằng 1 và 1 bằng 1, điều này luôn đúng nên tất cả các hàng thỏa mãn điều
kiện này sẽ được trả về.
EXAMPLE 2:
Hãy tưởng tượng cùng 1 ứng dụng, ứng dụng đó có chức năng đăng nhập và do nó có
bảng users table trong database và bảng người dùng có tên người dùng và mật khẩu
hàm băm của ngườ dùng.
Tôi muốn trích xuất mật khẩu băm này cho administrator , tối làm cho nó hiển thị trên
trang web.
Việc này thực hiện bằng các đưa ra các câu hỏi đúng sai
Users Table:
Administrator / e3c33e889e0e1b62cb7f65c63b60c42bd77275d0e730432fc37b7
Payload:
SELECT Password FROM Users WHERE Username = 'Administrator' : Đây là một truy vấn SQL
được sử dụng để truy xuất mật khẩu của người dùng có tên là 'Administrator' từ
bảng "Users".
Backend Query:
Vì kí tự đầu tiên của chuỗi băm mật khẩu là e nên truy vấn ở đây là sai và mệnh đề where
đánh giá là sai và bạn sẽ không thấy title từ trang product và không có gì để trả về trang
và điều đó có nghĩa là sai và s không phải kí tựu đầu tiên.
Chúng ta thử với một payload khác
Payload:
1. www.random.com/app.php?id=1 : Đây là URL của ứng dụng web, và nó truyền một tham số
"id" với giá trị 1 vào ứng dụng. Thường, tham số "id" được sử dụng để xác định sản
phẩm hoặc tài liệu cụ thể.
2. and SUBSTRING((SELECT Password FROM Users WHERE Username = 'Administrator'), 1, 1) = 'e' : Đây là
một phần của tham số "id" trong URL. Điều này giống với một phần của một truy vấn
SQL.
xuất một phần của chuỗi. Ở đây, nó đang trích xuất ký tự đầu tiên từ mật khẩu của
người dùng.
Backend Query:
Điều này trả về đúng cho thấy e là kí tự đầu tiên của hàm băm
Nếu ký tự đầu tiên trong mật khẩu băm của quản trị viên là 'a', hãy đợi 10giây.
'; : Đây là một dấu nháy đơn được sử dụng để kết thúc chuỗi SQL và mở một tình
huống mới.
- : Đây là ký tự để đánh dấu bắt đầu của một chú thích trong SQL. Điều này có thể
được sử dụng để bỏ qua phần còn lại của câu truy vấn gốc, đặt làm chú thích, để đảm
bảo rằng câu truy vấn tiềm năng độc hại vẫn hoạt động.
Thực hiện truy cập url của ứng dụng, xem tất cả các trang mà chúng ta có thể truy cập
được như là 1 người dùng, tìm ra các tên miền phụ,các thư mục, các chứng năng của ứng
Gửi các ký tự dành riêng cho SQL như ' hoặc " và tìm kiếm lỗi hoặc sự bất thường khác
Gửi các điều kiện Boolean như OR 1=1 và OR 1=2, và tìm kiếm sự khác biệt trong phản hồi
của ứng dụng
Gửi payload được thiết kế để kích hoạt độ trễ thời gian khi được thực thi trong một truy
vấn SQL và tìm kiếm sự khác biệt trong thời gian cần thiết để trả lời
Gửi OAST payload được thiết kế để kích hoạt ngoài băng tần tương tác mạng khi được
thực thi trong một truy vấn SQL, và theo dõi mọi tương tác phát sinh
1. SELECT title, cost : Lấy giá trị từ cột "title" và "cost" của bảng "product."
3. WHERE id = 1 : Chỉ chọn các hàng trong bảng "product" mà có giá trị cột "id" bằng 1.
4. ORDER BY 1 : Sắp xếp kết quả dựa trên cột đầu tiên (cột "title" trong trường hợp này)
theo thứ tự tăng dần.
Vì có sử dụng ORDER BY 1 , kết quả sẽ được sắp xếp theo cột đầu tiên, tức là theo cột "title"
theo thứ tự tăng dần (A-Z). Các hàng trong bảng "product" mà có giá trị "id" là 1 sẽ được
lựa chọn và hiển thị với các cột "title" và "cost" tương ứng.
Tăng dần một loạt mệnh đề ORDER BY cho đến khi bạn gặp lỗi hoặc quan sát thấy một
hành vi khác trong ứng dụng.
order by 1--
order by 2--
order by 3--
order by 1-- : Sắp xếp kết quả theo cột đầu tiên trong kết quả của truy vấn.
order by 2-- : Sắp xếp kết quả theo cột thứ hai trong kết quả của truy vấn.
order by 3-- : Sắp xếp kết quả theo cột thứ ba trong kết quả của truy vấn.
Lỗi ở đây cho thấy rằng khi nói đến vị trí số 3 thì nằm ngoài phạm vi số mục trong danh
sách chọn vì thế 3 không phải là số cột ở đây vì tôi đã tăng từ 1 đến 3 nên số cột ở đây chỉ
có thể là 2
Xác định số lượng cột được yêu cầu trong SQL Injection UNION bằng
cách sử dụng NULL VALUES:
từ bảng "product" trong đó cột "id" có giá trị bằng 1. Nó chọn hai cột là "title" và
"cost" từ các hàng thỏa mãn điều kiện này.
2. UNION : UNION được sử dụng để kết hợp kết quả của các truy vấn. Nó kết hợp tất cả
các hàng độc lập từ cả hai truy vấn và loại bỏ các bản ghi trùng.
3. SELECT NULL : Phần thứ hai của truy vấn này chọn một hàng gồm một cột với giá trị
NULL.
4. - : Dấu gạch nối hai chấm là một cách để bắt đầu một comment trong SQL. Tất cả
sau dấu "--" sẽ được xem như là comment và không thực thi.
Tăng dần một loạt tải trọng UNION SELECT chỉ định một số giá trị null khác nhau cho đến
khi bạn không còn gặp lỗi nữa
Lỗi cho chúng ta biết bạn đang sử dụng toán tử kêt hợp union nhưng hai truy vấn của bạn
không có cùng số cột và vì vậy tôi biết rằng truy vấn không hề chỉ có một cột nên tôi tăng
số lượng cột lên có 2 giá trị null và thử xem có lỗi hay không nghĩa là nó có nhiều hơn 2
cột và thử cho đến khi không gặp lỗi nữa
Trong trường hợp này chúng ta chỉ có 2 cột vì các giá trị null không gây ra lỗi, số lượng
cột mà bạn có bằng số null mà bạn nhập
Tìm các cột có kiểu dữ liệu hữu ích (useful data) trong cuộc tấn công SQL injection
UNION:
• Thăm dò từng cột để kiểm tra xem nó có thể chứa dữ liệu chuỗi hay không bằng cách
gửi một chuỗi payload UNION SELECT lần lượt đặt một giá trị chuỗi vào từng cột
1. ' : Đây là một dấu nháy đơn mở, thường được sử dụng để bắt đầu một chuỗi ký tự
trong SQL. Trong trường hợp này, dấu nháy đơn đầu tiên dường như không có mục
2. UNION: UNION được sử dụng để kết hợp kết quả của các truy vấn khác nhau thành
một kết quả duy nhất.
3. SELECT 'a', NULL: Phần thứ hai của truy vấn này chọn một hàng duy nhất và gán giá trị
'a' cho cột đầu tiên và giá trị NULL cho cột thứ hai.
4. - : Dấu gạch hai chấm đánh dấu bắt đầu một comment, và tất cả sau dấu "--" sẽ
được xem xét như là một chú thích và không được thực thi.
Và nó thông báo kết quả là không tương thích với giá trị nên giá trị đầu tiên thực sự là số
nguyên
Conversion failed when converting the varchar value 'a' to data type
Tiếp theo chúng ta giữ giá trị này là null và thử ở cột thứ 2 và nếu gặp lỗi thì điều này
cũng không chấp nhận giá trị chuỗi và tiếp tục làm như vậy cho đến khi tìm giá trị cho
phép
1. UNION: UNION được sử dụng để kết hợp kết quả của các truy vấn khác nhau thành
một kết quả duy nhất.
2. : Phần thứ hai của truy vấn này chọn một hàng duy nhất và gán giá trị
SELECT NULL, 'a'
NULL cho cột đầu tiên và giá trị 'a' cho cột thứ hai.
3. - : Dấu gạch hai chấm đánh dấu bắt đầu một comment, và tất cả sau dấu "--" sẽ
được xem xét như là một chú thích và không được thực thi.
Có hai quy tắc để kết hợp tập kết quả của hai truy vấn bằng cách sử dụng UNION:
• Số lượng và thứ tự các cột phải giống nhau trong tất cả các truy vấn
• Các kiểu dữ liệu phải tương thích
Exploitation:
Chỉ ra số lượng cột mà truy vấn đang thực hiện
Vẽ hình các kiểu dữ liệu của các cột (chủ yếu quan tâm đến dữ liệu chuỗi)
Gửi điều kiện Boolean đánh giá là Đúng và ghi lại phản hồi
Viết chương trình sử dụng các câu lệnh có điều kiện để hỏi database một loạt câu hỏi
Đúng/Sai và theo dõi phản hồi
Viết chương trình sử dụng các câu lệnh có điều kiện để yêu cầu database trả lời
loạt câu hỏi TRUE/FALSE và theo dõi thời gian trả lời
Tùy thuộc vào SQL Injection, sử dụng các phương pháp khác nhau để exfil dữ liệu
https://github.com/sqlmapproject/sqlmap
Sử dụng các câu lệnh được chuẩn bị sẵn (Truy vấn được tham số hóa) thay vì nối chuỗi
một truy vấn
Additional Defenses:
String query = "SELECT * FROM products WHERE category = '"+ input + "
Statement statement = connection.createStatement();
Vì vậy việc sử dụng các câu lệnh được chuẩn bị sẵn có thể ngăn chặn các cuộc tấn công
sql injection
Việc xây dựng câu lệnh SQL được thực hiện theo hai bước:
• Ứng dụng chỉ định cấu trúc truy vấn với các phần giữ chỗ cho mỗi người dùng đầu vào
do người dùng cung cấp
• Ứng dụng chỉ định nội dung của từng phần giữ chỗ
1. custname = request.getParameter("customerName");
Dòng này trích xuất giá trị của tham số có tên "customerName" từ một yêu cầu
web. Quan trọng phải lưu ý rằng đầu vào này đến từ một nguồn bên ngoài (người
dùng hoặc khách hàng) và có thể gây rủi ro về bảo mật. Điều quan trọng là kiểm
tra và làm sạch đầu vào người dùng để ngăn chặn các cuộc tấn công SQL
injection và các loại tấn công khác.
Dòng này thiết lập một truy vấn SQL để chọn "account_balance" từ bảng
"user_data" nơi "user_name" phù hợp với tham số.
Đoạn mã này chuẩn bị một câu lệnh SQL bằng cách sử dụng một đối tượng
PreparedStatement . Sử dụng câu lệnh chuẩn bị là một thực hành tốt vì nó giúp ngăn
Dòng này gắn giá trị của custname (đầu vào người dùng) vào câu lệnh chuẩn bị,
đảm bảo rằng nó được thoát và làm sạch đúng cách. Điều này giúp bảo vệ khỏi
cuộc tấn công SQL injection.
Dòng này thực hiện câu lệnh SQL và lưu kết quả trong một đối tượng ResultSet .
Một loạt các câu lệnh được nhóm lại với nhau và được lưu trữ trong database
Not always safe from SQL injection, still need to be called in a parameterized way
Không phải lúc nào cũng an toàn trước việc tiêm SQL, vẫn cần được gọi theo cách được
tham số hóa
Là để xác định giá trị nào được ủy quyền. Mọi thứ khác được coi là trái phép
Useful for values that cannot be specified as parameter placeholders, such as the
table name.
Hữu ích cho các giá trị không thể được chỉ định làm phần giữ chỗ tham số, chẳng hạn như
tên bảng.
Additional Defenses
Ý tưởng là gây khó khăn nhất cho attacker trong việc xâm phạm tổ chức của bạn và điều
đó được thực hiện bằng cách cung cấp sự bảo vệ bổ sung
• The application should use the lowest possible level of privileges when accessing the
database
Ứng dụng nên sử dụng mức độ thấp nhất có thể của đặc quyền khi truy cập cơ sở dữ liệu
• Any unnecessary default functionality in the database should be removed or disabled
Mọi chức năng mặc định không cần thiết trong cơ sở dữ liệu nên được gỡ bỏ hoặc vô hiệu
hóa
• Ensure CIS benchmark for the database in use is applied
Đảm bảo áp dụng điểm chuẩn CIS cho cơ sở dữ liệu đang sử dụng
• All vendor-issued security patches should be applied in a timely fashion
Tất cả các bản vá bảo mật do nhà cung cấp phát hành phải được áp dụng theo cách thời
trang hợp thời
Already discussed
================================================================
Lab:
SQL INJECTION CHEAT SHEET
Lab01
Lab03
Lab04
Lab05
Lab06
Lab07
Lab08
Lab09
Lab11
Lab13
Lab15
Lab16
Lab17
Lab18
Lab02
Lab12
Lab14