Cross-Site Scripting (XSS), đây là một lỗ hổng bảo mật thường gặp trong các ứng dụng web. XSS xảy ra khi một ứng dụng web không kiểm soát được dữ liệu đầu vào từ người dùng và cho phép chúng được thực thi như là mã JavaScript trong trình duyệt của người dùng. Điều này có thể dẫn đến các vấn đề như đánh cắp thông tin người dùng, phiên làm việc, hoặc thậm chí kiểm soát toàn bộ tài khoản người dùng. Hãy cùng W3seo tìm hiểu về lỗ hổng này.
Cross Site Script Inclusive (XSSI) là gì ?
Lỗ hổng Cross Site Script Inclusive (XSSI) cho phép rò rỉ dữ liệu nhạy cảm qua ranh giới giữa các tên miền hoặc nguồn gốc. Dữ liệu nhạy cảm có thể bao gồm dữ liệu liên quan đến xác thực (trạng thái đăng nhập, cookie, mã xác thực, ID phiên, v.v.) hoặc dữ liệu cá nhân nhạy cảm hoặc cá nhân của người dùng (địa chỉ email, số điện thoại, chi tiết thẻ tín dụng, số an sinh xã hội, v.v.). XSSI là một cuộc tấn công phía máy khách tương tự như truy vấn yêu cầu chéo trang web (CSRF) nhưng có mục đích khác. Trong trường hợp CSRF sử dụng bối cảnh người dùng đã xác thực để thực hiện các hành động thay đổi trạng thái nhất định bên trong trang của nạn nhân (ví dụ: chuyển tiền vào tài khoản của kẻ tấn công, sửa đổi đặc quyền, đặt lại mật khẩu, v.v.), XSSI thay vào đó sử dụng JavaScript ở phía máy khách để làm rò rỉ dữ liệu nhạy cảm từ các phiên được xác thực.
Theo mặc định, các trang web chỉ được phép truy cập dữ liệu nếu chúng có cùng nguồn gốc. Đây là nguyên tắc bảo mật ứng dụng quan trọng và được điều chỉnh bởi chính sách cùng nguồn gốc (được định nghĩa bởi RFC 6454). Nguồn gốc được định nghĩa là sự kết hợp của lược đồ URI (HTTP hoặc HTTPS), tên máy chủ và số cổng. Tuy nhiên, chính sách này không áp dụng cho các trường hợp bao gồm thẻ HTML <script>. Ngoại lệ này là cần thiết, vì nếu không có nó, các trang web sẽ không thể sử dụng các dịch vụ của bên thứ ba, thực hiện phân tích lưu lượng truy cập hoặc sử dụng các nền tảng quảng cáo, v.v.
Khi trình duyệt mở một trang web có thẻ <script>, các tài nguyên sẽ được tìm nạp từ miền gốc chéo. Sau đó, các tài nguyên sẽ chạy trong cùng ngữ cảnh với trang web hoặc trình duyệt bao gồm, điều này có cơ hội để rò rỉ dữ liệu nhạy cảm. Trong hầu hết các trường hợp, điều này đạt được bằng cách sử dụng JavaScript, tuy nhiên, nguồn tập lệnh không nhất thiết phải là tệp JavaScript có loại text / javascript hoặc đuôi .js.
Các lỗ hổng của trình duyệt cũ hơn (IE9 / 10) cho phép rò rỉ dữ liệu qua thông báo lỗi JavaScript trong thời gian chạy, nhưng các lỗ hổng đó hiện đã được các nhà cung cấp vá lỗi và được coi là ít liên quan hơn. Bằng cách đặt thuộc tính bộ ký tự của thẻ <script>, kẻ tấn công hoặc người kiểm tra có thể thực thi mã hóa UTF-16, cho phép rò rỉ dữ liệu đối với các định dạng dữ liệu khác (ví dụ: JSON) trong một số trường hợp. Để biết thêm về các cuộc tấn công này, hãy xem Các cuộc tấn công XSSI dựa trên số nhận dạng.
Mục tiêu kiểm tra XSSI
Mục tiêu kiểm tra XSSI không chỉ dừng lại ở việc định vị dữ liệu nhạy cảm trên toàn hệ thống và đánh giá sự rò rỉ của dữ liệu nhạy cảm thông qua các kỹ thuật khác nhau mà còn bao gồm một loạt các hoạt động quan trọng khác.
Phân loại Dữ liệu Nhạy Cảm:
- Xác định và phân loại đầy đủ các loại dữ liệu nhạy cảm mà hệ thống xử lý. Điều này có thể bao gồm thông tin cá nhân, thông tin tài khoản người dùng, thông tin thanh toán, hay bất kỳ loại thông tin nào đòi hỏi sự bảo vệ đặc biệt.
Kiểm Tra Đánh Giá Rủi Ro:
- Đánh giá rủi ro của việc rò rỉ dữ liệu nhạy cảm, xác định ảnh hưởng và hậu quả mà một tình huống XSSI có thể tạo ra. Điều này giúp xác định mức độ cần thiết của các biện pháp bảo mật cụ thể.
Kiểm Tra Các Phương Tiện Truyền Thông:
- Đối với các ứng dụng web hoặc dịch vụ sử dụng nhiều loại phương tiện truyền thông như hình ảnh, video, hoặc tệp âm thanh, kiểm tra cách chúng tương tác với dữ liệu nhạy cảm và xác định xem có nguy cơ rò rỉ thông tin hay không.
Kiểm Tra Tích hợp của APIs:
- Nếu hệ thống sử dụng các API (Giao diện lập trình ứng dụng), đảm bảo rằng chúng được tích hợp một cách an toàn và không tạo ra lỗ hổng bảo mật XSSI. Kiểm tra việc trao đổi dữ liệu giữa các thành phần thông qua API.
Kiểm Tra Cơ Chế Đăng Nhập và Phiên Làm Việc:
- Tăng cường kiểm tra bảo mật đăng nhập và quản lý phiên làm việc để đảm bảo rằng thông tin nhạy cảm không bị tiết lộ thông qua các cuộc tấn công XSSI, đặc biệt là trong các kịch bản đăng nhập và đăng ký mới.
Giả Lập Cuộc Tấn Công:
- Tạo các tình huống giả định để kiểm tra sự hiệu quả của biện pháp bảo mật trước một cuộc tấn công thực tế. Điều này có thể bao gồm việc mô phỏng các cuộc tấn công XSSI để kiểm tra cách hệ thống đáp ứng và có thể phát hiện sớm các lỗ hổng tiềm ẩn.
Làm thế nào để kiểm tra XSSI
Thu thập dữ liệu bằng cách sử dụng phiên của người dùng được xác thực và chưa được xác thực
Thu thập thông tin bằng cách sử dụng phiên là một phương thức quan trọng để kiểm tra an ninh hệ thống. Quá trình này bao gồm việc xác định nơi chịu trách nhiệm gửi dữ liệu nhạy cảm, xác định các thông số cần thiết và theo dõi tất cả các phản hồi JavaScript liên quan. Khi thực hiện kiểm tra, việc tập trung đặc biệt vào dữ liệu nhạy cảm được truyền qua JSONP là quan trọng.
Để xác định các phản hồi JavaScript động và tĩnh, ta có thể tạo các yêu cầu đã xác thực và chưa xác thực, sau đó so sánh chúng. Nếu chúng có sự khác biệt, điều này chỉ ra rằng phản hồi là động; nếu không, nó là tĩnh. Việc sử dụng một công cụ như plugin proxy Veit Hailperin’s Burp có thể giúp đơn giản hóa quá trình này, giúp chúng ta tự động hóa việc tìm kiếm lỗ hổng và tiết kiệm thời gian.
Ngoài ra, đảm bảo rằng kiểm tra bao gồm cả các loại tệp khác ngoài JavaScript là quan trọng. XSSI không chỉ giới hạn ở các tệp script, mà còn có thể tận dụng các định dạng tệp khác như hình ảnh, âm thanh, và các loại tệp khác để tạo lỗ hổng an ninh trong hệ thống.
Xác định xem dữ liệu nhạy cảm có thể bị rò rỉ bằng JavaScript hay không
Người kiểm tra nên phân tích mã cho các phương tiện sau để phát hiện rò rỉ dữ liệu qua các lỗ hổng XSSI:
- Các biến toàn cục
- Tham số chức năng toàn cục
- CSV (Giá trị được phân tách bằng dấu phẩy) với hành vi trộm cắp trích dẫn
- Lỗi thời gian chạy JavaScript
- Chuỗi nguyên mẫu sử dụng this
Rò rỉ dữ liệu nhạy cảm qua các biến toàn cục
Khóa API được lưu trữ trong tệp JavaScript có URI https://victim.com/internal/api.js trên trang web của nạn nhân, Nạn nhân.com, chỉ những người dùng đã xác thực mới có thể truy cập được. Kẻ tấn công định cấu hình một trang web, attackwebsite.com và sử dụng thẻ <script> để tham chiếu đến tệp JavaScript.
Đây là nội dung của https://victim.com/internal/api.js:
<!DOCTYPE html> <html> <head> <title>Leaking data via global variables</title> </head> <body> <h1>Leaking data via global variables</h1> <script src="https://victim.com/internal/api.js"></script> <div id="result"> </div> <script> var div = document.getElementById("result"); div.innerHTML = "Your secret data <b>" + window.secret + "</b>"; </script> </body> </html>
Trong ví dụ này, một nạn nhân đã được xác thực với nạn nhân.com. Kẻ tấn công dụ nạn nhân tấn côngwebsite.com thông qua kỹ thuật xã hội, email lừa đảo, v.v. Sau đó, trình duyệt của nạn nhân tìm nạp api.js, dẫn đến việc dữ liệu nhạy cảm bị rò rỉ qua biến JavaScript chung và được hiển thị bằng innerHTML.
Rò rỉ dữ liệu nhạy cảm qua các tham số chức năng toàn cầu
Ví dụ này tương tự như ví dụ trước, ngoại trừ trong trường hợp này, attackwebsite.com sử dụng hàm JavaScript toàn cầu để trích xuất dữ liệu nhạy cảm bằng cách ghi đè lên hàm JavaScript chung của nạn nhân.
Đây là nội dung của https://victim.com/internal/api.js:
(function() { var secret = "supersecretAPIkey"; window.globalFunction(secret); })();
Trang web tấn công, attackwebsite.com, có index.html với mã sau:
<!DOCTYPE html> <html> <head> <title>Leaking data via global function parameters</title> </head> <body> <div id="result"> </div> <script> function globalFunction(param) { var div = document.getElementById("result"); div.innerHTML = "Your secret data: <b>" + param + "</b>"; } </script> <script src="https://victim.com/internal/api.js"></script> </body> </html>
Có các lỗ hổng XSSI khác có thể dẫn đến rò rỉ dữ liệu nhạy cảm thông qua chuỗi nguyên mẫu JavaScript hoặc các lệnh gọi hàm toàn cầu. Để biết thêm về các cuộc tấn công này, hãy xem Những nguy cơ không mong muốn của JavaScript động.
Rò rỉ dữ liệu nhạy cảm qua CSV
Để làm rò rỉ dữ liệu, kẻ tấn công / người kiểm tra phải có khả năng đưa mã JavaScript vào dữ liệu CSV. Mã ví dụ sau là một đoạn trích từ các cuộc tấn công XSSI dựa trên Mã nhận dạng của Takeshi Terada.
HTTP/1.1 200 OK Content-Type: text/csv Content-Disposition: attachment; filename="a.csv" Content-Length: xxxx 1,"___","aaa@a.example","03-0000-0001" 2,"foo","bbb@b.example","03-0000-0002" ... 98,"bar","yyy@example.net","03-0000-0088" 99,"___","zzz@example.com","03-0000-0099"
Trong ví dụ này, việc sử dụng các cột ___ làm điểm chèn và chèn các chuỗi JavaScript vào vị trí của chúng sẽ cho kết quả như sau.
1,"\"",$$$=function(){/*","aaa@a.example","03-0000-0001" 2,"foo","bbb@b.example","03-0000-0002" ... 98,"bar","yyy@example.net","03-0000-0088" 99,"*/}//","zzz@example.com","03-0000-0099"
Jeremiah Grossman đã viết về một lỗ hổng tương tự trong Gmail vào năm 2006 cho phép trích xuất danh bạ của người dùng trong JSON. Trong trường hợp này, dữ liệu được nhận từ Gmail và được phân tích cú pháp bởi công cụ JavaScript của trình duyệt bằng cách sử dụng phương thức khởi tạo Mảng không được tham chiếu để làm rò rỉ dữ liệu. Kẻ tấn công có thể truy cập Mảng này với dữ liệu nhạy cảm bằng cách xác định và ghi đè phương thức khởi tạo Mảng bên trong như sau:
<!DOCTYPE html> <html> <head> <title>Leaking gmail contacts via JSON </title> </head> <body> <script> function Array() { // steal data } </script> <script src="http://mail.google.com/mail/?_url_scrubbed_"></script> </body> </html>
Rò rỉ dữ liệu nhạy cảm qua JavaScript Lỗi thời gian chạy
Các trình duyệt thường đưa ra các thông báo lỗi JavaScript được chuẩn hóa. Tuy nhiên, trong trường hợp của IE9 / 10, các thông báo lỗi thời gian chạy cung cấp các chi tiết bổ sung có thể được sử dụng để làm rò rỉ dữ liệu. Ví dụ: một trang web nạn nhân.com phân phát nội dung sau tại URI http://victim.com/service/csvendpoint cho người dùng đã xác thực:
HTTP/1.1 200 OK Content-Type: text/csv Content-Disposition: attachment; filename="a.csv" Content-Length: 13 1,abc,def,ghi
Lỗ hổng này có thể bị khai thác bằng những cách sau:
<!--error handler --> <script>window.onerror = function(err) {alert(err)}</script> <!--load target CSV --> <script src="http://victim.com/service/csvendpoint"></script>
Khi trình duyệt cố gắng hiển thị nội dung CSV dưới dạng JavaScript, nó không thành công và làm rò rỉ dữ liệu nhạy cảm:
Thông báo lỗi thời gian chạy JavaScript
Rò rỉ dữ liệu nhạy cảm qua chuỗi nguyên mẫu bằng cách sử dụng this
Trong JavaScript, từ khóa this được xác định phạm vi động. Điều này có nghĩa là nếu một hàm được gọi trên một đối tượng, thì nó sẽ trỏ đến đối tượng này mặc dù hàm được gọi có thể không thuộc về chính đối tượng đó. Hành vi này có thể được sử dụng để làm rò rỉ dữ liệu. Trong ví dụ sau từ trang trình diễn của Sebastian Leike, dữ liệu nhạy cảm được lưu trữ trong Mảng. Kẻ tấn công có thể ghi đè Array.prototype.forEach bằng một chức năng do kẻ tấn công kiểm soát. Nếu một số mã gọi hàm forEach trên một cá thể mảng có chứa các giá trị nhạy cảm, thì hàm do kẻ tấn công kiểm soát sẽ được gọi với điều này trỏ đến đối tượng có chứa dữ liệu nhạy cảm.
Đây là đoạn trích của tệp JavaScript chứa dữ liệu nhạy cảm, javascript.js:
... (function() { var secret = ["578a8c7c0d8f34f5", "345a8b7c9d8e34f5"]; secret.forEach(function(element) { // do something here }); })(); ...
Dữ liệu nhạy cảm có thể bị rò rỉ với mã JavaScript sau:
... <div id="result"> </div> <script> Array.prototype.forEach = function(callback) { var resultString = "Your secret values are: <b>"; for (var i = 0, length = this.length; i < length; i++) { if (i > 0) { resultString += ", "; } resultString += this[i]; } resultString += "</b>"; var div = document.getElementById("result"); div.innerHTML = resultString; }; </script> <script src="http://victim.com/..../javascript.js"></script> ...