Tôi có nên tránh InternalHTML không?
Cheats ngăn chặn XSS thực hiện một công việc tuyệt vời để giải quyết XSS được phản ánh và lưu trữ. Cheats này giải quyết XSS dựa trên DOM (Mô hình đối tượng tài liệu) và là một phần mở rộng (và giả định hiểu) Cheats ngăn chặn XSS Show
Để hiểu XSS dựa trên DOM, người ta cần thấy sự khác biệt cơ bản giữa XSS được phản ánh và XSS được lưu trữ khi so sánh với XSS dựa trên DOM. Sự khác biệt chính là nơi cuộc tấn công được đưa vào ứng dụng XSS được phản ánh và được lưu trữ là sự cố tiêm nhiễm phía máy chủ trong khi XSS dựa trên DOM là sự cố tiêm nhiễm phía máy khách (trình duyệt) Tất cả mã này bắt nguồn từ máy chủ, nghĩa là chủ sở hữu ứng dụng có trách nhiệm đảm bảo an toàn khỏi XSS, bất kể đó là loại lỗ hổng XSS nào. Ngoài ra, các cuộc tấn công XSS luôn thực thi trong trình duyệt Sự khác biệt giữa Reflected/Stored XSS là nơi cuộc tấn công được thêm vào hoặc đưa vào ứng dụng. Với Reflected/Stored, cuộc tấn công được đưa vào ứng dụng trong quá trình xử lý yêu cầu phía máy chủ trong đó đầu vào không đáng tin cậy được thêm động vào HTML. Đối với DOM XSS, cuộc tấn công được đưa trực tiếp vào ứng dụng trong thời gian chạy ở máy khách Khi trình duyệt hiển thị HTML và bất kỳ nội dung liên quan nào khác như CSS hoặc JavaScript, trình duyệt sẽ xác định các ngữ cảnh hiển thị khác nhau cho các loại đầu vào khác nhau và tuân theo các quy tắc khác nhau cho từng ngữ cảnh. Bối cảnh kết xuất được liên kết với việc phân tích cú pháp các thẻ HTML và các thuộc tính của chúng
Đối với mục đích của bài viết này, chúng tôi đề cập đến ngữ cảnh HTML, thuộc tính HTML, URL và CSS dưới dạng ngữ cảnh con vì mỗi ngữ cảnh này có thể tiếp cận và đặt trong ngữ cảnh thực thi JavaScript Trong mã JavaScript, ngữ cảnh chính là JavaScript nhưng với các thẻ và ký tự đóng ngữ cảnh phù hợp, kẻ tấn công có thể cố gắng tấn công 4 ngữ cảnh khác bằng các phương thức JavaScript DOM tương đương Sau đây là một ví dụ về lỗ hổng xảy ra trong ngữ cảnh JavaScript và ngữ cảnh con HTML
Hãy lần lượt xem xét các ngữ cảnh con riêng lẻ của ngữ cảnh thực thi QUY TẮC #1 - Thoát HTML rồi thoát JavaScript trước khi chèn dữ liệu không đáng tin cậy vào ngữ cảnh con HTML trong ngữ cảnh thực thiCó một số phương thức và thuộc tính có thể được sử dụng để hiển thị trực tiếp nội dung HTML trong JavaScript. Các phương thức này cấu thành Ngữ cảnh con HTML trong Ngữ cảnh thực thi. Nếu các phương pháp này được cung cấp với đầu vào không đáng tin cậy thì có thể dẫn đến lỗ hổng XSS. Ví dụ Ví dụ về các phương thức HTML nguy hiểmThuộc tính
phương pháp
Hướng dẫnĐể thực hiện cập nhật động cho HTML trong DOM an toàn, chúng tôi khuyên bạn nên
QUY TẮC #2 - Thoát khỏi JavaScript trước khi chèn dữ liệu không đáng tin cậy vào văn bản con thuộc tính HTML trong ngữ cảnh thực thiVăn bản con thuộc tính HTML trong ngữ cảnh thực thi khác với các quy tắc mã hóa tiêu chuẩn. Điều này là do quy tắc mã hóa thuộc tính HTML trong bối cảnh hiển thị thuộc tính HTML là cần thiết để giảm thiểu các cuộc tấn công cố gắng thoát khỏi thuộc tính HTML hoặc cố gắng thêm các thuộc tính bổ sung có thể dẫn đến XSS Khi bạn ở trong ngữ cảnh thực thi DOM, bạn chỉ cần mã hóa JavaScript các thuộc tính HTML không thực thi mã (các thuộc tính khác với trình xử lý sự kiện, CSS và thuộc tính URL) Ví dụ: quy tắc chung là Thuộc tính HTML mã hóa dữ liệu không đáng tin cậy (dữ liệu từ cơ sở dữ liệu, yêu cầu HTTP, người dùng, hệ thống phụ trợ, v.v. ) được đặt trong Thuộc tính HTML. Đây là bước thích hợp cần thực hiện khi xuất dữ liệu trong ngữ cảnh hiển thị, tuy nhiên, việc sử dụng mã hóa Thuộc tính HTML trong ngữ cảnh thực thi sẽ phá vỡ hiển thị dữ liệu của ứng dụng Ví dụ AN TOÀN nhưng BỊ HỎNG
Vấn đề là nếu tên công ty có giá trị "Johnson & Johnson". Nội dung sẽ được hiển thị trong trường văn bản đầu vào sẽ là "Johnson & Johnson". Mã hóa thích hợp để sử dụng trong trường hợp trên sẽ chỉ là mã hóa JavaScript để không cho phép kẻ tấn công đóng dấu ngoặc đơn và mã nội tuyến hoặc thoát sang HTML và mở thẻ tập lệnh mới Ví dụ AN TOÀN và ĐÚNG CHỨC NĂNG
Điều quan trọng cần lưu ý là khi đặt thuộc tính HTML không thực thi mã, giá trị được đặt trực tiếp trong thuộc tính đối tượng của phần tử HTML, do đó không có vấn đề gì với việc đưa vào QUY TẮC #3 - Hãy cẩn thận khi chèn Dữ liệu không đáng tin cậy vào Trình xử lý sự kiện và Ngữ cảnh con mã JavaScript trong Ngữ cảnh thực thiĐặt dữ liệu động trong mã JavaScript đặc biệt nguy hiểm vì mã hóa JavaScript có ngữ nghĩa khác nhau đối với dữ liệu được mã hóa JavaScript khi so sánh với các mã hóa khác. Trong nhiều trường hợp, mã hóa JavaScript không dừng các cuộc tấn công trong ngữ cảnh thực thi. Ví dụ: một chuỗi mã hóa JavaScript sẽ thực thi ngay cả khi nó được mã hóa JavaScript Do đó, khuyến nghị chính là tránh đưa dữ liệu không đáng tin cậy vào ngữ cảnh này. Nếu bạn phải, các ví dụ sau mô tả một số cách tiếp cận hiệu quả và không hiệu quả
Phương thức 7 nguy hiểm vì nó hoàn toàn ép buộc value_string vào kiểu dữ liệu thuộc tính DOM của name_stringTrong trường hợp trên, tên thuộc tính là trình xử lý sự kiện JavaScript, vì vậy giá trị thuộc tính được chuyển đổi hoàn toàn thành mã JavaScript và được đánh giá. Trong trường hợp trên, mã hóa JavaScript không giảm thiểu đối với XSS dựa trên DOM Các phương thức JavaScript khác lấy mã dưới dạng kiểu chuỗi sẽ gặp sự cố tương tự như phác thảo ở trên ( 8, 9, Hàm mới, v.v. ). Điều này hoàn toàn trái ngược với mã hóa JavaScript trong thuộc tính trình xử lý sự kiện của thẻ HTML (trình phân tích cú pháp HTML) trong đó mã hóa JavaScript giảm nhẹ chống lại XSS 1Một cách khác để sử dụng 0 để đặt thuộc tính DOM là đặt thuộc tính trực tiếp. Đặt trực tiếp các thuộc tính trình xử lý sự kiện sẽ cho phép mã hóa JavaScript giảm thiểu XSS dựa trên DOM. Xin lưu ý, việc đặt trực tiếp dữ liệu không đáng tin cậy vào ngữ cảnh thực thi lệnh luôn là một thiết kế nguy hiểm 3 0Có những nơi khác trong JavaScript nơi mã hóa JavaScript được chấp nhận là mã thực thi hợp lệ 1hoặc 2Vì JavaScript dựa trên tiêu chuẩn quốc tế (ECMAScript), mã hóa JavaScript cho phép hỗ trợ các ký tự quốc tế trong các cấu trúc và biến lập trình bên cạnh các biểu diễn chuỗi thay thế (chuỗi thoát) Tuy nhiên, trường hợp ngược lại với mã hóa HTML. Các phần tử thẻ HTML được xác định rõ và không hỗ trợ các biểu diễn thay thế của cùng một thẻ. Vì vậy, không thể sử dụng mã hóa HTML để cho phép nhà phát triển có các biểu diễn thay thế của thẻ 1 chẳng hạnBản chất vô hiệu hóa của mã hóa HTMLNói chung, mã hóa HTML dùng để loại bỏ các thẻ HTML được đặt trong ngữ cảnh thuộc tính HTML và HTML. Ví dụ hoạt động (không có mã hóa HTML) 3Ví dụ được mã hóa thông thường (Không hoạt động – DNW) 4Ví dụ mã hóa HTML để làm nổi bật sự khác biệt cơ bản với các giá trị mã hóa JavaScript (DNW) 5Nếu mã hóa HTML tuân theo ngữ nghĩa giống như mã hóa JavaScript. Dòng trên có thể đã hoạt động để hiển thị một liên kết. Sự khác biệt này làm cho mã hóa JavaScript trở thành một vũ khí ít khả thi hơn trong cuộc chiến chống lại XSS của chúng tôi QUY TẮC #4 - Thoát khỏi JavaScript trước khi chèn dữ liệu không đáng tin cậy vào ngữ cảnh con thuộc tính CSS trong ngữ cảnh thực thiThông thường, việc thực thi JavaScript từ ngữ cảnh CSS được yêu cầu hoặc chuyển 2 sang phương thức CSS 3 hoặc gọi phương thức CSS 4 chuyển mã JavaScript để được thực thi trực tiếpTheo kinh nghiệm của tôi, việc gọi hàm 4 từ ngữ cảnh thực thi (JavaScript) đã bị tắt. Để giảm thiểu khả năng chống lại phương pháp CSS 3, hãy đảm bảo rằng bạn đang mã hóa URL dữ liệu được chuyển đến phương pháp CSS 3 6QUY TẮC #5 - Thoát URL rồi thoát JavaScript trước khi chèn dữ liệu không đáng tin cậy vào văn bản con thuộc tính URL trong ngữ cảnh thực thiLogic phân tích cú pháp URL trong cả bối cảnh thực thi và kết xuất có vẻ giống nhau. Do đó, có rất ít thay đổi trong quy tắc mã hóa cho các thuộc tính URL trong ngữ cảnh thực thi (DOM) 7Nếu bạn sử dụng các URL đủ điều kiện thì điều này sẽ phá vỡ các liên kết vì dấu hai chấm trong mã định danh giao thức ( 8 hoặc 9) sẽ được mã hóa URL để ngăn không cho các giao thức 0 và 1 được gọiQUY TẮC #6 - Điền vào DOM bằng các hàm hoặc thuộc tính JavaScript an toànCách an toàn cơ bản nhất để đưa vào DOM dữ liệu không đáng tin cậy là sử dụng thuộc tính gán an toàn 2Đây là một ví dụ về cách sử dụng an toàn 8QUY TẮC #7 - Khắc phục lỗ hổng DOM Cross-site ScriptingCách tốt nhất để khắc phục tập lệnh chéo trang dựa trên DOM là sử dụng phương thức xuất phù hợp (chìm). Ví dụ: nếu bạn muốn sử dụng đầu vào của người dùng để viết trong phần tử 3, đừng sử dụng 4, thay vào đó hãy sử dụng 5 hoặc 2. Điều này sẽ giải quyết vấn đề và đó là cách phù hợp để khắc phục lại các lỗ hổng XSS dựa trên DOMLuôn luôn là một ý tưởng tồi khi sử dụng đầu vào do người dùng kiểm soát trong các nguồn nguy hiểm như eval. 99% thời gian đó là dấu hiệu của việc thực hành lập trình kém hoặc lười biếng, vì vậy đơn giản là đừng làm điều đó thay vì cố gắng làm sạch đầu vào Cuối cùng, để khắc phục sự cố trong mã ban đầu của chúng tôi, thay vì cố gắng mã hóa đầu ra một cách chính xác, điều gây rắc rối và có thể dễ dàng sai, chúng tôi chỉ cần sử dụng 7 để viết nó trong một nội dung như thế này 9Nó làm điều tương tự nhưng lần này nó không dễ bị tấn công bởi các lỗ hổng tập lệnh chéo trang dựa trên DOM Nguyên tắc phát triển ứng dụng an toàn bằng JavaScriptXSS dựa trên DOM cực kỳ khó giảm thiểu do bề mặt tấn công lớn và thiếu tiêu chuẩn hóa trên các trình duyệt Các nguyên tắc bên dưới là một nỗ lực nhằm cung cấp các nguyên tắc cho các nhà phát triển khi phát triển các ứng dụng JavaScript dựa trên Web (Web 2. 0) để họ có thể tránh được XSS HƯỚNG DẪN #1 - Dữ liệu không đáng tin cậy chỉ nên được coi là văn bản có thể hiển thịTránh coi dữ liệu không đáng tin cậy là mã hoặc đánh dấu trong mã JavaScript HƯỚNG DẪN #2 - Luôn mã hóa JavaScript và phân định dữ liệu không đáng tin cậy dưới dạng chuỗi được trích dẫn khi vào ứng dụng khi xây dựng JavaScript theo khuôn mẫuLuôn mã hóa JavaScript và phân định dữ liệu không đáng tin cậy dưới dạng chuỗi được trích dẫn khi vào ứng dụng như minh họa trong ví dụ sau 0HƯỚNG DẪN #3 - Sử dụng tài liệu. createElement(". "), yếu tố. setAttribute(". ","giá trị"), phần tử. appendChild(. ) và tương tự để xây dựng giao diện động 8, 9, 0 và tương tự là những cách an toàn để xây dựng giao diện độngXin lưu ý, 1 chỉ an toàn cho một số thuộc tính hạn chếCác thuộc tính nguy hiểm bao gồm bất kỳ thuộc tính nào là ngữ cảnh thực thi lệnh, chẳng hạn như 2 hoặc 3Ví dụ về các thuộc tính an toàn bao gồm. _______64, _______65, _______66, _______67, _______68, _______69, _______70, _______72, _______3, _______74, _______75, _______76, _______77, _______78, _______79, _______110, _______111, _______112, _______113, _______114, _______115, _______116, _______117, _______118, HƯỚNG DẪN #4 - Tránh gửi dữ liệu không đáng tin cậy vào các phương thức hiển thị HTMLTránh phổ biến các phương pháp sau với dữ liệu không đáng tin cậy
HƯỚNG DẪN #5 - Tránh nhiều phương thức truyền dữ liệu eval() ngầm định cho nóCó rất nhiều phương pháp ngầm truyền dữ liệu 10 cho nó mà phải tránhĐảm bảo rằng mọi dữ liệu không đáng tin cậy được chuyển đến các phương thức này đều được
Đảm bảo làm theo bước 3 ở trên để đảm bảo rằng dữ liệu không đáng tin cậy không được gửi đến các phương thức nguy hiểm trong chức năng tùy chỉnh hoặc xử lý dữ liệu đó bằng cách thêm một lớp mã hóa bổ sung Sử dụng Enclosure (theo đề xuất của Gaz)Ví dụ sau minh họa việc sử dụng bao đóng để tránh mã hóa JavaScript kép 1Cách thay thế khác là sử dụng N cấp độ mã hóa Cấp độ mã hóa NNếu mã của bạn giống như sau, bạn chỉ cần tăng gấp đôi dữ liệu đầu vào mã hóa JavaScript 2 11 có lớp mã hóa JavaScript đầu tiên bị đảo ngược (khi thực thi) trong dấu nháy đơnSau đó, 12 ngầm định của 8 đảo ngược một lớp mã hóa JavaScript khác để chuyển giá trị chính xác cho 14Lý do tại sao bạn chỉ cần tăng gấp đôi mã hóa JavaScript là vì hàm 14 không tự chuyển đầu vào sang một phương thức khác được gọi ngầm hoặc rõ ràng là 12 Nếu firstName được chuyển sang một phương thức JavaScript khác được gọi ngầm hoặc rõ ràng là 10 thì 18 ở trên sẽ cần phải Một lưu ý triển khai quan trọng là nếu mã JavaScript cố gắng sử dụng dữ liệu được mã hóa kép hoặc ba trong so sánh chuỗi, giá trị có thể được hiểu là các giá trị khác nhau dựa trên số lượng 20 mà dữ liệu đã đi qua trước khi được chuyển đến so sánh if và Nếu A được mã hóa JavaScript kép thì kiểm tra if sau đây sẽ trả về false 3Điều này mang đến một điểm thiết kế thú vị. Lý tưởng nhất là cách chính xác để áp dụng mã hóa và tránh sự cố đã nêu ở trên là mã hóa phía máy chủ cho ngữ cảnh đầu ra nơi dữ liệu được đưa vào ứng dụng Sau đó, mã hóa phía máy khách (sử dụng thư viện mã hóa JavaScript chẳng hạn như nút-esapi) cho ngữ cảnh con riêng lẻ (phương thức DOM) mà dữ liệu không đáng tin cậy được chuyển đến Dưới đây là một số ví dụ về cách chúng được sử dụng 4 5Một tùy chọn là sử dụng các thuộc tính không thay đổi của ECMAScript 5 trong thư viện JavaScript. Một tùy chọn khác do Gaz (Gareth) cung cấp là sử dụng cấu trúc mã cụ thể để hạn chế khả năng thay đổi với các lần đóng ẩn danh Một ví dụ sau 6HƯỚNG DẪN #6 - Chỉ sử dụng dữ liệu không đáng tin cậy ở phía bên phải của biểu thứcChỉ sử dụng dữ liệu không đáng tin cậy ở phía bên phải của một biểu thức, đặc biệt là dữ liệu trông giống như mã và có thể được chuyển đến ứng dụng (e. g. , 21 và 10) 7Sử dụng dữ liệu người dùng không đáng tin cậy ở phía bên trái của biểu thức cho phép kẻ tấn công phá vỡ các thuộc tính bên trong và bên ngoài của đối tượng cửa sổ, trong khi sử dụng đầu vào của người dùng ở phía bên phải của biểu thức không cho phép thao tác trực tiếp HƯỚNG DẪN #7 - Khi mã hóa URL trong DOM, hãy lưu ý các vấn đề về bộ ký tựKhi mã hóa URL trong DOM, hãy lưu ý các vấn đề về bộ ký tự vì bộ ký tự trong JavaScript DOM không được xác định rõ ràng (Mike Samuel) HƯỚNG DẪN #8 - Giới hạn quyền truy cập vào các thuộc tính đối tượng khi sử dụng trình truy cập object[x]Giới hạn quyền truy cập vào các thuộc tính đối tượng khi sử dụng bộ truy cập 23 (Mike Samuel). Nói cách khác, thêm một mức độ gián tiếp giữa đầu vào không đáng tin cậy và các thuộc tính đối tượng được chỉ địnhĐây là một ví dụ về sự cố khi sử dụng các loại bản đồ 8Nhà phát triển viết mã ở trên đang cố gắng thêm các phần tử có khóa bổ sung vào đối tượng 24. Tuy nhiên, kẻ tấn công có thể sử dụng điều này để phá hoại các thuộc tính bên trong và bên ngoài của đối tượng 24Một cách tiếp cận tốt hơn sẽ là sử dụng như sau 9HƯỚNG DẪN #9 - Chạy JavaScript của bạn trong hộp cát hoặc hộp cát ECMAScript 5Chạy JavaScript của bạn trong hộp cát hoặc hộp cát ECMAScript 5 để khiến API JavaScript của bạn khó bị xâm phạm hơn (Gareth Heyes và John Stevens) Ví dụ về một số hộp cát / chất khử trùng JavaScript
HƯỚNG DẪN #10 - Không eval() JSON để chuyển đổi nó thành các đối tượng JavaScript gốcĐừng 10 JSON để chuyển đổi nó thành các đối tượng JavaScript gốc. Thay vào đó hãy sử dụng 27 và 28 (Chris Schmidt)Các vấn đề thường gặp liên quan đến việc giảm thiểu XSS dựa trên DOMbối cảnh phức tạpTrong nhiều trường hợp, bối cảnh không phải lúc nào cũng đơn giản để phân biệt 0Trong ví dụ trên, dữ liệu không đáng tin cậy bắt đầu trong ngữ cảnh URL hiển thị (thuộc tính 29 của thẻ 30) sau đó được thay đổi thành ngữ cảnh thực thi JavaScript (trình xử lý giao thức 9) chuyển dữ liệu không đáng tin cậy sang ngữ cảnh con URL thực thi ( 32 của 33)Vì dữ liệu được đưa vào bằng mã JavaScript và được chuyển đến ngữ cảnh con URL nên mã hóa phía máy chủ thích hợp sẽ như sau 1Hoặc nếu bạn đang sử dụng ECMAScript 5 với thư viện mã hóa phía máy khách JavaScript bất biến, bạn có thể thực hiện các thao tác sau 2Sự không nhất quán của thư viện mã hóaCó một số thư viện mã hóa mã nguồn mở hiện có
Some work on a block list while others ignore important characters like "<" and ">". Java Encoder là một dự án đang hoạt động cung cấp hỗ trợ mã hóa HTML, CSS và JavaScript ESAPI là một trong số ít hoạt động trên danh sách cho phép và mã hóa tất cả các ký tự không phải chữ và số. Điều quan trọng là sử dụng một thư viện mã hóa để hiểu những ký tự nào có thể được sử dụng để khai thác lỗ hổng trong ngữ cảnh tương ứng của chúng. Có rất nhiều quan niệm sai lầm liên quan đến mã hóa phù hợp được yêu cầu Mã hóa những quan niệm sai lầmNhiều tài liệu và giáo trình đào tạo bảo mật ủng hộ việc sử dụng mù quáng mã hóa HTML để giải quyết XSS Về mặt logic, đây có vẻ là lời khuyên thận trọng vì trình phân tích cú pháp JavaScript không hiểu mã hóa HTML Tuy nhiên, nếu các trang được trả về từ ứng dụng web của bạn sử dụng loại nội dung 34 hoặc phần mở rộng loại tệp là 35 thì mã hóa HTML có thể không hoạt động để giảm thiểu XSSVí dụ 3Giá trị được mã hóa HTML ở trên vẫn có thể thực thi được. Nếu điều đó vẫn chưa đủ để ghi nhớ, bạn phải nhớ rằng mã hóa sẽ bị mất khi bạn truy xuất chúng bằng thuộc tính giá trị của phần tử DOM Hãy xem trang mẫu và kịch bản 4Cuối cùng, có một vấn đề là một số phương thức trong JavaScript thường an toàn có thể không an toàn trong một số ngữ cảnh nhất định Phương pháp thường an toànMột ví dụ về thuộc tính được cho là an toàn là 5Một số bài báo hoặc hướng dẫn ủng hộ việc sử dụng nó như một giải pháp thay thế cho 37 để giảm thiểu XSS trong 37. Tuy nhiên, tùy thuộc vào thẻ mà 5 được áp dụng, mã có thể được thực thi 5Tính năng 5 ban đầu được giới thiệu bởi Internet Explorer và được chỉ định chính thức trong tiêu chuẩn HTML vào năm 2016 sau khi được tất cả các nhà cung cấp trình duyệt lớn áp dụng
Tại sao chúng ta không nên sử dụng InternalHTML?InnerHTML không cung cấp xác thực hợp lệ , do đó, bất kỳ mã HTML hợp lệ nào cũng có thể được sử dụng. Điều này có khả năng phá vỡ tài liệu JavaScript. Ngay cả HTML bị hỏng cũng có thể được sử dụng, điều này có thể gây ra các sự cố không mong muốn.
Khi nào bạn nên sử dụng InternalHTML?innerHTML hữu ích tại bất kỳ lúc nào để chèn thẻ/nội dung HTML mới dưới dạng chuỗi và có thể dễ dàng chuyển hướng đến các thành phần cụ thể trong .
Tôi nên sử dụng InternalText hay InternalHTML?innerText trả về tất cả văn bản chứa trong một phần tử và tất cả các phần tử con của nó. innerHtml trả về tất cả văn bản, bao gồm các thẻ html, được chứa bởi một phần tử .
Điều gì tốt hơn InternalHTML?Phần tử này rất mạnh và có một số mã siêu thú vị. Ghi chú. Không giống như InternalHTML, textContent có hiệu suất tốt hơn vì giá trị của nó không được phân tích cú pháp dưới dạng HTML. Vì lý do đó, sử dụng textContent cũng có thể ngăn chặn các cuộc tấn công Cross-Site Scripting (XSS). |