XSS là gì, và làm sao hiển thị nội dung Markdown do người dùng nhập mà không bị XSS?
Gợi ý trả lời
Người phỏng vấn muốn biết bạn có hiểu XSS là chuyện nội dung không tin cậy được trình duyệt chạy như mã, và bạn có biết nó lọt vào từ những chỗ nào, không chỉ thuộc lòng tên.
XSS (cross-site scripting) xảy ra khi dữ liệu của người dùng được đưa vào trang theo cách trình duyệt hiểu là HTML hoặc mã thay vì là chữ. Khi đó kẻ tấn công chạy được mã trong trang của bạn, với quyền của người đang xem: đọc cookie, gọi API thay họ, đổi nội dung trang.
Với Markdown, rủi ro chính đến từ ba chỗ:
- HTML thô. Markdown cho phép viết HTML nên các thư viện chuyển nó sang đầu ra nguyên văn, kể cả thẻ như
<img onerror=...>. Thẻ<script>chèn quainnerHTMLkhông chạy, nhưng nhiều cách khác vẫn chạy. - Liên kết và ảnh có giao thức nguy hiểm.
[xem](javascript:...)chạy mã khi bấm. - Bộ lọc cấu hình sai. Danh sách cho phép quá rộng, hoặc lọc bằng regex tự viết, rất dễ bị lách.
Có hai hướng xử lý đáng nhắc tới. Hướng một là chuyển Markdown sang HTML rồi lọc bằng thư viện sanitize chuyên dụng theo danh sách cho phép (DOMPurify, sanitize-html), chỉ giữ những thẻ và thuộc tính cần. Hướng hai là không tạo ra chuỗi HTML: phân tích Markdown thành các khối có kiểu rồi dựng bằng framework như React, nơi chữ được đặt làm nội dung phần tử nên tự được thoát ký tự. Với hướng hai, bạn vẫn phải tự kiểm tra địa chỉ của liên kết và ảnh, chỉ nhận http, https và đường dẫn trong site.
Ý quan trọng để nêu: đừng dùng dangerouslySetInnerHTML (hoặc innerHTML) cho nội dung chưa được lọc, và mọi đường đưa nội dung ra trang, kể cả ô xem trước trong trang quản trị, phải đi qua cùng một bộ xử lý an toàn.
Điểm cộng: nhắc tới Content Security Policy như lớp bảo vệ thứ hai, hạn chế nơi mã được phép chạy, và nhắc rằng một điều kiện an toàn thì nên có test, ví dụ test cho các địa chỉ javascript: và data:.