§

ข้อมูลนำเข้า

โหมด
รูปแบบ entity
ขอบเขตการเข้ารหัส
§

ผลลัพธ์

NCSA ไทยแนะนำให้ใช้ HTML entity encoding ตามแนวทางพัฒนาเว็บแอปพลิเคชันปลอดภัย เพื่อป้องกัน XSS บนหน้าเว็บภาษาไทย NECTEC และ ม.อ. ส่งเสริมมาตรฐาน SecureCoding Thailand ที่ระบุให้เข้ารหัส output ทุกจุด ส่วน BOT กำหนดแนวปฏิบัติด้านความมั่นคงปลอดภัยไอทีสำหรับเว็บฟรอนต์เอนด์ธนาคารไทย โดยเฉพาะการป้องกัน XSS ในฟอร์มที่รับอักษรไทย UTF-8 เครื่องมือนี้ทำงานในเบราว์เซอร์ทั้งหมด ไม่ส่งข้อมูลออกนอกแท็บ

วิธีการทำงานของ HTML entity encoding

HTML entity คือการอ้างอิงอักขระที่เบราว์เซอร์แยกวิเคราะห์กลับเป็นอักขระเดียว อักขระสงวน HTML ห้าตัว (<, >, &, ", ') ต้องถูกเข้ารหัสเสมอเมื่อข้อความแสดงผลเป็น HTML ส่วนที่เหลือเป็นทางเลือกขึ้นอยู่กับการเข้ารหัสเอกสาร

  1. เลือกโหมดและขอบเขต. โหมดเข้ารหัสจะประมวลผลอักขระละตัวในข้อมูลนำเข้า โหมดถอดรหัสจะสแกนหารูปแบบ entity ตัวสลับขอบเขตกำหนดว่าจะเข้ารหัสเฉพาะห้าอักขระ HTML-safe หรือรวมทุก code point ที่ไม่ใช่ ASCII ด้วย
  2. เลือกรูปแบบ entity. Named entity (&copy;) อ่านง่ายในซอร์สโค้ด การอ้างอิง decimal (&#169;) และ hex (&#xA9;) รองรับทุก Unicode code point โดยไม่ต้องมีชื่อ อีเมลไคลเอนต์รุ่นเก่าและ XML parser นิยมรูปแบบตัวเลข
  3. ประมวลผลข้อมูลนำเข้า. ในการเข้ารหัส จะอ่านแต่ละ code point และค้นหาในตารางประมาณ 200 named entity ที่พบบ่อย กรณีไม่พบจะใช้รูปแบบตัวเลขแทน ในการถอดรหัส จะสแกนด้วย regex เดียวที่จับคู่ &name;, &#NNN; และ &#xHH; ในการผ่านครั้งเดียว
  4. จับคู่กับอักขระ. การจับคู่ named จะแก้ไขผ่านตารางย้อนกลับ การจับคู่ตัวเลขจะผ่าน String.fromCodePoint ด้วยฐาน 10 หรือฐาน 16 named entity ที่ไม่รู้จักจะถูกเว้นไว้ไม่เปลี่ยนแปลงเพื่อให้ข้อมูลนำเข้าบางส่วนสามารถแปลงกลับไปกลับมาได้โดยไม่สูญเสียข้อมูล
  5. โหมดสด. เปิดโหมดสดแล้วทุกการพิมพ์จะทำการแปลงซ้ำด้วย debounce 150 มิลลิวินาที มีประโยชน์เมื่อคุณกำลังปรับแต่ง snippet และต้องการผลตอบรับทันทีก่อนวางลงในเทมเพลต

ทำไมต้องเข้ารหัส HTML entity

  • ป้องกันข้อมูลผู้ใช้ไม่ให้ทำลายเลย์เอาต์. เมื่อผู้ใช้พิมพ์ < ลงในช่องความคิดเห็น การนำข้อความนั้นไปใส่ใน HTML โดยตรงจะเขียนทับส่วนที่เหลือของหน้า การเข้ารหัสอักขระสงวนก่อนทำให้เบราว์เซอร์แสดงอักขระแทนที่จะแยกวิเคราะห์เป็นเริ่มต้น tag
  • รักษาค่า attribute ให้ถูกต้อง. การฝังสตริงที่มีเครื่องหมายคำพูดใน HTML attribute ต้องแทนที่เครื่องหมายคำพูดที่ฝังด้วย &quot; (สำหรับ attr ที่ใช้เครื่องหมายคู่) หรือ &#39; (สำหรับที่ใช้เครื่องหมายเดี่ยว) มิฉะนั้น parser จะปิด attribute เร็วเกินไปและส่วนที่เหลือของบรรทัดจะกลายเป็น markup ที่หลงเหลือ
  • ทำให้ HTML ที่ไม่ตั้งใจในข้อมูลที่จัดเก็บไม่เป็นอันตราย. บันทึก รายงานข้อผิดพลาด และการส่งออกแชทมักมีวงเล็บมุมและ ampersand จริง การเข้ารหัส entity ก่อนวางลงในหน้าเอกสารจะรักษาสำเนานั้นให้มองเห็นเป็นข้อความแทนที่จะกระตุ้น renderer หรือตัวตรวจจับลิงก์อัตโนมัติ
  • แชร์ code snippet อย่างปลอดภัย. การโพสต์ tag ตัวอย่างเช่น <script>alert(1)</script> ในบล็อก อีเมล หรือ Slack ต้องเข้ารหัสวงเล็บเพื่อให้ snippet แสดงแทนที่จะทำงาน เทคนิคเดียวกันนี้ครอบคลุม RSS feed body และฟิลด์ `description` ของ JSON-LD

การใช้งานทั่วไป

การเข้ารหัส entity ปรากฏทุกที่ที่ข้อความดิบถูกประกอบเข้ากับ HTML ระหว่างรันไทม์ — แม้เมื่อ framework มักจัดการให้คุณ เครื่องมือ manual ก็ยังมีประโยชน์ในช่วงเวลาที่ไม่ทำ

  • เทมเพลต server-rendered: Jinja2, ERB, Twig และ Handlebars escape อัตโนมัติโดยค่าเริ่มต้น แต่ raw block และตัวทำเครื่องหมาย `safe` จะปิดสิ่งนั้น — codec ช่วยให้คุณยืนยันสิ่งที่ escape จะสร้างขึ้น
  • การสร้างอีเมลและจดหมายข่าว: เครื่องยนต์เทมเพลต ESP หลายตัวไม่ auto-escape merge field ดังนั้น smart quote และเครื่องหมายลิขสิทธิ์ในชื่อที่ผู้ใช้ระบุต้องเข้ารหัสล่วงหน้า
  • เอกสารและตัวอย่างโค้ด: การวาง HTML tag ตัวอย่างลงในบล็อก Markdown หรือ snippet ของ static site ต้องเข้ารหัสวงเล็บเพื่อให้ renderer ถือว่าเป็นข้อความที่มองเห็นได้

ตัวอย่างที่ทำงานได้จริง

วาง <script>alert('hi')</script> ในข้อมูลนำเข้าโดยตั้งโหมดเป็น Encode, รูปแบบ Named, ขอบเขต Minimal ผลลัพธ์อ่านว่า &lt;script&gt;alert(&#39;hi&#39;)&lt;/script&gt; เปลี่ยนรูปแบบเป็น Numeric hex ข้อมูลนำเข้าเดิมจะสร้าง &#x3C;script&#x3E;alert(&#x27;hi&#x27;)&#x3C;/script&#x3E; พลิกโหมดเป็น Decode วางสตริงที่เข้ารหัสกลับเข้าไป แล้ว tag ต้นฉบับจะกลับมาครบถ้วน

FAQ

HTML entity คืออะไร?

HTML entity คือการอ้างอิงอักขระที่เบราว์เซอร์แทนที่กลับเป็นอักขระเดียวเมื่อแยกวิเคราะห์หน้า มีสามรูปแบบ: named (เช่น &amp; สำหรับ &), decimal numeric (&#38;) และ hex numeric (&#x26;) อักขระสงวน HTML ห้าตัว (<, >, &, ", ') ต้องถูกเข้ารหัสทุกครั้งที่ข้อความถูกนำไปไว้ใน HTML named entity ที่มีชื่ออีกประมาณ 2,225 รายการครอบคลุมสัญลักษณ์ สำเนียง และตัวอักษรกรีก แต่เป็นทางเลือกเมื่อการเข้ารหัสเอกสารเป็น UTF-8

ควรใช้ named หรือ numeric entity เมื่อใด?

ใช้ named entity เมื่อต้องการให้ซอร์สอ่านง่าย (มนุษย์ที่ตรวจสอบ &copy; ในเทมเพลตเข้าใจทันที) ใช้ numeric (decimal หรือ hex) เมื่อผู้บริโภคเป็นรุ่นเก่าหรือเข้มงวดกว่า — XML parser, อีเมลไคลเอนต์รุ่นเก่า และ feed reader บางตัวรู้จักเฉพาะ named entity HTML5 ชุดย่อยเล็กน้อย และทั้งหมดรู้จักรูปแบบตัวเลข Hex มักชนะในบริบทที่เน้นความปลอดภัยเพราะตรงกับ Unicode code-point notation ที่ใช้ในเอกสาร spec

การถอดรหัสรองรับ hex entity เช่น & หรือไม่?

ใช่ ตัวถอดรหัสใช้ regex เดียวที่จับคู่สามรูปแบบ entity ในการผ่านครั้งเดียว: &name;, &#NNN; และ &#xHH; การจับคู่ตัวเลขจะแก้ไขด้วย String.fromCodePoint ใช้ฐาน 10 หรือฐาน 16 ข้อมูลผสม (named และ numeric ในสตริงเดียวกัน) ถอดรหัสได้ถูกต้อง และชื่อที่ไม่รู้จักจะถูกเว้นไว้เป็นข้อความตามตัวอักษรเพื่อให้ข้อมูลนำเข้าบางส่วนแปลงกลับไปกลับมาได้โดยไม่สูญเสีย

ปลอดภัยที่จะใช้กับข้อมูลที่ไม่น่าเชื่อถือหรือไม่?

ตัวแปลงเองทำงานในเบราว์เซอร์เท่านั้นและไม่ส่งข้อมูลของคุณไปที่ใด ความปลอดภัยของผลลัพธ์ที่จะฝังขึ้นอยู่กับบริบท การเข้ารหัส entity จัดการบริบท HTML body และค่า attribute ซึ่งครอบคลุมกรณี OWASP Rule #1 บริบท JavaScript (inline event handler, block `<script>`), CSS และ URL แต่ละอย่างต้องการกฎการเข้ารหัสของตัวเอง — การเข้ารหัส entity เพียงอย่างเดียวไม่เพียงพอ สำหรับการป้องกันเชิงลึกฝั่งเซิร์ฟเวอร์ ให้จับคู่กับ template engine ที่รู้บริบทเช่น DOMPurify หรือ auto-escape ของ framework ของคุณ

การเข้ารหัส entity ฝั่งเบราว์เซอร์อยู่ที่ขอบเขตระหว่างข้อมูลผู้ใช้และ HTML ที่แสดงผล การแปลงในเครื่องหมายความคุณสามารถตรวจสอบสิ่งที่ framework ของคุณจะส่งออกได้ โดยไม่ต้องส่งข้อความต้นฉบับไปยังเครื่องมือของบุคคลที่สาม