Đăng chéo này dưới dạng tài liệu tham khảo tổng hợp từ phiên bản beta Tài liệu SO đang ngoại tuyến.
Vấn đề
Kịch bản chéo trang là việc thực thi mã từ xa ngoài ý muốn của máy khách web. Bất kỳ ứng dụng web nào cũng có thể tự hiển thị với XSS nếu nó nhận đầu vào từ người dùng và xuất trực tiếp trên trang web. Nếu đầu vào bao gồm HTML hoặc JavaScript, mã từ xa có thể được thực thi khi nội dung này được hiển thị bởi máy khách web.
Ví dụ: nếu bên thứ 3 chứa tệp JavaScript:
// http://example.com/runme.js
document.write("I'm running");
Và một ứng dụng PHP trực tiếp xuất ra một chuỗi được truyền vào nó:
<?php
echo '<div>' . $_GET['input'] . '</div>';
Nếu tham số GET không được kiểm tra chứa <script src="http://example.com/runme.js"></script>
thì đầu ra của tập lệnh PHP sẽ là:
<div><script src="http://example.com/runme.js"></script></div>
JavaScript của bên thứ 3 sẽ chạy và người dùng sẽ thấy "Tôi đang chạy" trên trang web.
Giải pháp
Theo nguyên tắc chung, không bao giờ tin tưởng đầu vào đến từ khách hàng. Mọi giá trị GET, POST và cookie đều có thể là bất cứ thứ gì, và do đó nên được xác nhận. Khi xuất bất kỳ giá trị nào trong số này, hãy thoát chúng để chúng không bị đánh giá theo cách không mong muốn.
Hãy nhớ rằng ngay cả trong các ứng dụng đơn giản nhất, dữ liệu có thể được di chuyển xung quanh và sẽ khó theo dõi tất cả các nguồn. Vì vậy, đó là một thực hành tốt nhất để luôn luôn thoát đầu ra.
PHP cung cấp một vài cách để thoát đầu ra tùy thuộc vào ngữ cảnh.
Chức năng lọc
Các hàm lọc của PHP cho phép dữ liệu đầu vào của tập lệnh php được vệ sinh hoặc xác nhận theo nhiều cách . Chúng rất hữu ích khi lưu hoặc xuất dữ liệu đầu vào của khách hàng.
Mã hóa HTML
htmlspecialchars
sẽ chuyển đổi bất kỳ "ký tự đặc biệt HTML" nào thành mã hóa HTML, nghĩa là chúng sẽ không được xử lý như HTML tiêu chuẩn. Để sửa ví dụ trước của chúng tôi bằng phương pháp này:
<?php
echo '<div>' . htmlspecialchars($_GET['input']) . '</div>';
// or
echo '<div>' . filter_input(INPUT_GET, 'input', FILTER_SANITIZE_SPECIAL_CHARS) . '</div>';
Sẽ xuất:
<div><script src="http://example.com/runme.js"></script></div>
Mọi thứ bên trong <div>
thẻ sẽ không được trình duyệt hiểu là thẻ JavaScript mà thay vào đó là một nút văn bản đơn giản. Người dùng sẽ thấy an toàn:
<script src="http://example.com/runme.js"></script>
Mã hóa URL
Khi xuất ra một URL được tạo động, PHP cung cấp urlencode
chức năng để xuất các URL hợp lệ một cách an toàn. Vì vậy, ví dụ, nếu người dùng có thể nhập dữ liệu trở thành một phần của tham số GET khác:
<?php
$input = urlencode($_GET['input']);
// or
$input = filter_input(INPUT_GET, 'input', FILTER_SANITIZE_URL);
echo '<a href="http://example.com/page?input="' . $input . '">Link</a>';
Bất kỳ đầu vào độc hại sẽ được chuyển đổi thành một tham số URL được mã hóa.
Sử dụng các thư viện bên ngoài chuyên biệt hoặc danh sách OWASP AntiSamy
Đôi khi bạn sẽ muốn gửi HTML hoặc các loại đầu vào mã khác. Bạn sẽ cần duy trì một danh sách các từ được ủy quyền (danh sách trắng) và không được ủy quyền (danh sách đen).
Bạn có thể tải xuống các danh sách tiêu chuẩn có sẵn tại trang web OWASP AntiSamy . Mỗi danh sách phù hợp với một loại tương tác cụ thể (ebay api, tinyMCE, v.v ...). Và nó là nguồn mở.
Có các thư viện hiện có để lọc HTML và ngăn chặn các cuộc tấn công XSS cho trường hợp chung và thực hiện ít nhất cũng như các danh sách AntiSamy với việc sử dụng rất dễ dàng. Ví dụ: bạn có Bộ lọc HTML