Trong bài viết này, chúng tôi sẽ giải thích kịch bản chéo trang (cross-site scripting) là gì, mô tả các loại lỗ hổng kịch bản chéo trang khác nhau cũng như cách tìm và ngăn chặn kịch bản chéo trang.
Kịch bản chéo trang (XSS) là gì?
Kịch bản chéo trang (Cross-site scripting – XSS) là một lỗ hổng bảo mật web cho phép kẻ tấn công giả trang thành người dùng, thực hiện bất kỳ hành động nào mà người dùng có thể thực hiện và truy cập vào bất kỳ dữ liệu nào của người dùng. Nếu người dùng nạn nhân có quyền truy cập đặc quyền trong ứng dụng, thì kẻ tấn công có thể có toàn quyền kiểm soát tất cả các chức năng và dữ liệu của ứng dụng.
XSS hoạt động như thế nào?
Kịch bản chéo trang hoạt động bằng cách đưa vào một trang web dễ bị tổn thương các lệnh JavaScript độc hại cho người dùng. Khi mã độc thực thi bên trong trình duyệt của nạn nhân, kẻ tấn công hoàn toàn có thể tấn công ứng dụng.
Các loại tấn công XSS là gì?
Có ba loại tấn công XSS chính. Đó là:
- Reflected XSS, trong đó tập lệnh độc hại xuất phát từ yêu cầu HTTP hiện tại.
- Stored XSS, tập lệnh độc hại xuất phát từ cơ sở dữ liệu của trang web.
- DOM-based XSS, trong đó lỗ hổng tồn tại trong mã phía máy khách thay vì mã phía máy chủ.
Reflected cross-site scripting
Reflected XSS là tấn công đơn giản nhất của kịch bản chéo trang (cross-site scripting). Nó phát sinh khi một ứng dụng nhận dữ liệu trong yêu cầu HTTP và dữ liệu đó trong phản hồi ngay lập tức theo cách không an toàn.
Dưới đây là một ví dụ đơn giản về lỗ hổng reflected XSS:
https://insecure-website.com/status?message=All+is+well. <p>Status: All is well.</p>
Ứng dụng không thực hiện bất kỳ xử lý dữ liệu nào khác, vì vậy kẻ tấn công có thể dễ dàng tạo ra một cuộc tấn công như thế này:
https://insecure-website.com/status?message=<script>/*+Bad+stuff+here...+*/</script> <p>Status: <script>/* Bad stuff here... */</script></p>
Nếu người dùng truy cập URL được tạo bởi kẻ tấn công, thì tập lệnh của kẻ tấn công sẽ thực thi trong trình duyệt của người dùng, trong bối cảnh phiên của người dùng đó với ứng dụng. Tại thời điểm đó, tập lệnh có thể thực hiện bất kỳ hành động nào và truy xuất bất kỳ dữ liệu nào mà người dùng có quyền truy cập.
Stored cross-site scripting
Stored XSS (còn được gọi là persistent XSS hoặc second-order XSS) phát sinh khi một ứng dụng nhận dữ liệu từ một nguồn không đáng tin cậy và dữ liệu đó bao gồm các phản hồi HTTP sau đó theo cách không an toàn.
Dữ liệu trong câu hỏi có thể được gửi đến ứng dụng thông qua các yêu cầu HTTP; ví dụ: nhận xét về bài đăng trên blog, biệt danh người dùng trong phòng trò chuyện hoặc chi tiết liên hệ về đơn đặt hàng của khách hàng. Trong các trường hợp khác, dữ liệu có thể đến từ các nguồn không đáng tin cậy khác; ví dụ: ứng dụng webmail hiển thị các tin nhắn nhận được qua SMTP, ứng dụng tiếp thị hiển thị các bài đăng trên phương tiện truyền thông xã hội hoặc ứng dụng giám sát mạng hiển thị dữ liệu gói từ lưu lượng mạng.
Dưới đây là một ví dụ đơn giản về lỗ hổng XSS được lưu trữ. Ứng dụng bảng tin cho phép người dùng gửi tin nhắn, được hiển thị cho người dùng khác:
<p>Hello, this is my message!</p>
Ứng dụng không thực hiện bất kỳ xử lý dữ liệu nào khác, vì vậy kẻ tấn công có thể dễ dàng gửi tin nhắn tấn công người dùng khác:
<p><script>/* Bad stuff here... */</script></p>
Kịch bản chéo trang dựa trên DOM
XSS dựa trên DOM (còn được gọi là DOM XSS ) phát sinh khi một ứng dụng chứa một số JavaScript phía máy khách xử lý dữ liệu từ một nguồn không tin cậy theo cách không an toàn, thường là bằng cách ghi dữ liệu trở lại DOM.
Trong ví dụ sau, một ứng dụng sử dụng một số JavaScript để đọc giá trị từ trường đầu vào và ghi giá trị đó vào một phần tử trong HTML:
var search = document.getElementById('search').value; var results = document.getElementById('results'); results.innerHTML = 'You searched for: ' + search;
Nếu kẻ tấn công có thể kiểm soát giá trị của trường đầu vào, chúng có thể dễ dàng xây dựng một giá trị độc hại khiến tập lệnh của chính chúng thực thi:
You searched for: <img src=1 onerror='/* Bad stuff here... */'>
Trong trường hợp điển hình, trường đầu vào sẽ được điền từ một phần của yêu cầu HTTP, chẳng hạn như tham số chuỗi truy vấn URL, cho phép kẻ tấn công thực hiện một cuộc tấn công bằng URL độc hại, giống như reflected XSS.
XSS có thể được sử dụng để làm gì?
Kẻ tấn công khai thác lỗ hổng kịch bản chéo trang (cross-site scripting) thường có thể:
- Mạo danh hoặc giả trang là người dùng nạn nhân.
- Thực hiện bất kỳ hành động mà người dùng có thể thực hiện.
- Đọc bất kỳ dữ liệu mà người dùng có thể truy cập.
- Nắm bắt thông tin đăng nhập của người dùng.
- Thực hiện sai lệch ảo của trang web.
- Tiêm trojan vào trang web.
Tác động của lỗ hổng XSS
Tác động thực sự của một cuộc tấn công XSS thường phụ thuộc vào bản chất của ứng dụng, chức năng và dữ liệu của nó và trạng thái của người dùng bị xâm nhập. Ví dụ:
- Trong một ứng dụng brochurware, nơi tất cả người dùng là ẩn danh và tất cả thông tin là công khai, tác động thường sẽ rất nhỏ.
- Trong một ứng dụng chứa dữ liệu nhạy cảm, chẳng hạn như giao dịch ngân hàng, email hoặc hồ sơ chăm sóc sức khỏe, tác động thường sẽ nghiêm trọng.
- Nếu người dùng bị xâm nhập có các đặc quyền nâng cao trong ứng dụng, thì tác động nói chung sẽ rất nghiêm trọng, cho phép kẻ tấn công kiểm soát hoàn toàn ứng dụng dễ bị tổn thương và thỏa hiệp tất cả người dùng và dữ liệu của họ.
Cách tìm và kiểm tra lỗ hổng XSS
Phần lớn các lỗ hổng XSS có thể được tìm thấy nhanh chóng và đáng tin cậy bằng cách sử dụng trình quét lỗ hổng web có sẵn trên internet.
Kiểm tra thủ công cho reflected và stored XSS thường bao gồm gửi một số đầu vào duy nhất đơn giản (chẳng hạn như một chuỗi ký tự chữ và số ngắn) vào mọi điểm nhập trong ứng dụng; xác định mọi vị trí nơi đầu vào đã gửi được trả về trong phản hồi HTTP; và kiểm tra từng vị trí riêng lẻ để xác định xem liệu đầu vào được chế tạo phù hợp có thể được sử dụng để thực thi JavaScript tùy ý hay không.
Kiểm tra thủ công XSS DOM phát sinh từ các tham số URL bao gồm một quy trình tương tự: đặt một số đầu vào duy nhất đơn giản vào tham số, sử dụng các công cụ dành cho nhà phát triển của trình duyệt để tìm kiếm DOM cho đầu vào này và kiểm tra từng vị trí để xác định xem có thể khai thác được không.
Cách ngăn chặn các cuộc tấn công XSS
Ngăn chặn kịch bản chéo trang là chuyện nhỏ trong một số trường hợp nhưng có thể khó hơn nhiều tùy thuộc vào độ phức tạp của ứng dụng và cách nó xử lý dữ liệu do người dùng kiểm soát.
Nói chung, việc ngăn chặn hiệu quả các lỗ hổng XSS có thể liên quan đến sự kết hợp của các biện pháp sau:
- Lọc đầu vào khi đến. Tại thời điểm nhận được đầu vào của người dùng, hãy lọc càng nhiều càng tốt dựa trên những gì được mong đợi hoặc đầu vào hợp lệ.
- Mã hóa dữ liệu trên đầu ra. Tại thời điểm mà dữ liệu do người dùng kiểm soát là đầu ra trong các phản hồi HTTP, hãy mã hóa đầu ra để ngăn không cho nó bị hiểu là nội dung hoạt động. Tùy thuộc vào bối cảnh đầu ra, điều này có thể yêu cầu áp dụng kết hợp mã hóa HTML, URL, JavaScript và CSS.
- Sử dụng các tiêu đề phản ứng thích hợp. Để ngăn ngừa XSS trong phản ứng HTTP mà không nhằm mục đích chứa bất kỳ HTML hoặc JavaScript, bạn có thể sử dụng Content-Type và X-Content-Type-Tùy chọn tiêu đề để đảm bảo rằng các trình duyệt giải thích các câu trả lời theo cách bạn dự định.
- Chính sách bảo mật nội dung. Là tuyến phòng thủ cuối cùng, bạn có thể sử dụng Chính sách bảo mật nội dung (CSP) để giảm mức độ nghiêm trọng của bất kỳ lỗ hổng XSS nào vẫn xảy ra.
Các câu hỏi thường gặp về kịch bản chéo trang
Các lỗ hổng XSS phổ biến như thế nào? Các lỗ hổng XSS rất phổ biến và XSS có lẽ là lỗ hổng bảo mật web xảy ra thường xuyên nhất.
Các cuộc tấn công XSS phổ biến như thế nào? Rất khó để có được dữ liệu đáng tin cậy về các cuộc tấn công XSS trong thế giới thực, nhưng có lẽ nó ít được khai thác hơn các lỗ hổng khác.
Sự khác biệt giữa XSS và CSRF là gì? XSS liên quan đến việc khiến một trang web trả lại JavaScript độc hại, trong khi CSRF liên quan đến việc khiến người dùng nạn nhân thực hiện các hành động mà họ không có ý định thực hiện.
Sự khác biệt giữa XSS và injection SQL là gì? XSS là một lỗ hổng phía máy khách nhắm vào người dùng ứng dụng khác, trong khi SQL SQL là lỗ hổng phía máy chủ nhắm vào cơ sở dữ liệu của ứng dụng.
Làm cách nào để ngăn XSS trong PHP? Lọc các đầu vào của bạn với danh sách trắng các ký tự được phép và sử dụng gợi ý loại hoặc truyền kiểu. Thoát các kết quả đầu ra của bạn với htmlentity và ENT_QUOTES cho các bối cảnh HTML hoặc JavaScript Unicode thoát cho các bối cảnh JavaScript.
Làm cách nào để ngăn XSS trong Java? Lọc các đầu vào của bạn với danh sách trắng các ký tự được phép và sử dụng thư viện như Google Guava để mã hóa HTML đầu ra của bạn cho các bối cảnh HTML hoặc sử dụng mã JavaScript Unicode cho bối cảnh JavaScr