Concerns & Security กับเรื่อง HTML จาก Clients

Tae Keerati Jearjindarat
2 min readFeb 28, 2021

วันนี้มีเรื่องที่อยากจดบันทึกเอาไว้ว่าควรระวังอีกเรื่องหนึ่งซึ่งเกี่ยวข้องกับความปลอดภัยของระบบ และ เป็น concern ในการพัฒนาซอฟต์แวร์นั่นคือเรื่อง HTML Sanitization ครับ

Background

เรื่องมีอยู่ว่าวันหนึ่งผมได้ Requirement ให้พัฒนาระบบเดิมที่ต้องรับ input ที่เป็น HTML จาก wysiwyg หรือก็คือพวก Component HTML Editor อย่างเช่น CKEditor นั่นเอง

หลาย ๆ ครั้งเราอาจจะเชื่อใน Library ที่เราใช้หรือ Framework ที่เราเลือกอย่างเช่น React ว่ามันปลอดภัย แต่จริงๆ แล้วมันไม่ใช่ครับ เนื่องจากมันเป็นสิ่งที่อยู่กับ Client และสามารถ bypass มาจาก Client ได้ตลอดเวลา เช่น อาจจะแกะ API ที่เราใช้ส่ง Request เพื่อส่งข้อมูลแปลกๆ มา Server โดยตรง เพื่อหลังจากนั้น Server จะได้นำ Script เหล่านั้นไปใช้เพื่อโจมตีระบบ และทำให้เกิดปัญหาได้

ถึงแม้ว่าเราจะแบ่ง Role และ Permission ตั้งแต่การออกแบบ Software แล้ว แต่เราไม่สามารถ Trusted ผู้ใช้ระดับสูงในระบบได้อยู่ดี เพราะอาจเกิด Human Error ทำให้คนใช้ระบบโดนแฮคจากกรณีอื่น ๆ ได้ เราจึงจำเป็นต้องป้องกันในระบบเราให้ดีครับ

โดยปกติการ Render HTML ใน React จากข้อมูลประเภท String เราจะใช้ property ที่ชื่อ dangerouslySetInnerHTML ซึ่งมันจะทำนำค่า String ที่เราใส่ไป render บน DOM Element ให้

function MyComponent() {
return <div dangerouslySetInnerHTML={“<div>Hello</div>”} />;
}

ความอันตรายก็คือหาก Script ที่ Inject ลงไปเป็น Script ที่ขโมย Cookie ของผู้ใช้ หรือ ขโมยข้อมูลต่าง ๆ จะทำให้ระบบเรามีช่องโหว่ได้และสามารถแฮคได้นั่นเอง

HTML Sanitization

ในการออกแบบระบบสมัยที่ยังไม่มี Markdown ให้เป็นทางเลือก สุดท้ายเราก็จำเป็นต้องเก็บ HTML ลง Database และนำมาเรียกใช้ภายหลังอยู่ดี ทำให้ระบบเราย่อมมีความเสี่ยงเรื่องนี้อยู่ แต่เราสามารถป้องกันได้โดยศึกษาเรื่อง HTML Sanitization ครับ ซึ่งเป็น process สำหรับกาจัดการ HTML ให้มีความปลอดภัย โดยใช้หลักการ Whitelist และ Blacklist มาช่วย หลักการง่ายมากครับ เนื่องจาก HTML มีลักษณะเป็น XML อยู่แล้ว และมี tag อยู่ 2 ประเภท คือ

  1. Opening or Closing Tag เช่น <div>Text to see</div>
  2. Empty Tag เช่น <img />

โดยเราสามารถเขียนโปรแกรมมาเช็ค Tag ที่จะต้อง render ได้เลยซึ่งเราสามารถ whitelist tag ที่อนุญาตให้ใช้งานได้ และใส่ Blacklist กับ tag ที่อันตรายหรือไม่ต้องการใช้ได้เลย เช่น tag script เป็นต้น

นอกจากเราต้องจัดการ tag แล้ว ยังมีกรณีอื่นอีก เช่น กรณี input ใส่สามารถ tag แปลกๆ ได้หรือใส่ได้ แต่ไม่ครบ จะทำให้เราไม่สามารถ Render HTML ได้เพราะ Syntax ผิดพลาด

แต่โชคดีที่เรามีโปรเจคที่ชื่อว่า OWASP ที่คอยอัพเดทข่าวสาร มี document แนวทางและเครื่องมือให้เราใช้หรือทำตาม เพื่อป้องกัน Application ของเราให้ปลอดภัยจากกรณีเหล่านี้นั่นเอง ซึ่ OWASP มีโปรเจคสำหรับภาษา Java ที่สามารถจัดการเรื่องนี้ได้โดยที่เราไม่ต้องเก็บ edge case ต่าง ๆ และสามารถใช้ได้เลย ที่ Github ส่วนภาษาอื่น ๆ คิดว่ามี Library สำหรับจัดการอยู่แล้ว แต่หากภาษานั้นไม่มีก็สามารถพัฒนาเป็นหนึ่ง Component ในระบบไปโดยแนะนำให้อิง OWASP เป็นแนวทางครับ

วิธีใช้สำหรับภาษา Java ก็คือนำไปใส่ในไฟล์ pom (หรือ package resolver ของภาษานั้น) และ import ตัว package ไปใช้ในโค้ดของเรา

ตัวอย่างเช่น

PolicyFactory s = new HtmlPolicyBuilder()
.allowElements("div", "a")
.allowAttributes("href")
.onElements("a")
.toFactory();
String input = "<div><a href="medium.com">LINK</a><script>alert("Hi");</script></div>";String output = s.santinize(input);
// output = "<div><a href="medium.com">LINK</a></div>";

เป็นการอนุญาตให้ใช้ได้แค่ tag div และ tag a ในระบบของเรา HTML โดย filter tag div ที่เราไม่ต้องการออกไปนั่นเอง และผลลัพธ์จะได้ String กลับมา โดยไม่มี tag อันตรายอย่าง script หลุดมาทำให้เราสามารถส่งไปให้ Client ทำการ Render ได้อย่างปลอดภัย

ส่วนรายละเอียดอื่น ๆ ขอข้ามไปครับเพราะมีเยอะ และส่วนตัวคิดว่า Documents ของ Project เขียนไว้ค่อนข้างดี มีรายละเอียดพร้อมตัวอย่างให้เราดู สามารถศึกษาด้วยตัวเองได้ไม่ยากครับ

สรุป

เป็นเนื้อหาที่ดูไม่ยาก เพราะแค่เช็คและแปลง HTML ก่อนไป Render ให้ผู้ใช้ในระบบเราแค่นั้น แต่ก็อยากแนะนำให้ตรวจดูระบบของเราว่ามีช่องโหว่นี้หรือไม่ หากมีช่องโหว่ก็ควรจะรีบแก้ไข เพราะเกี่ยวข้องกับความปลอดภัยของระบบเรานั่นเองครับ แต่หากใครกำลังออกแบบระบบใหม่ที่จำเป็นต้องใช้การส่งข้อความไปหา User ในระบบหรือพวก Annoucement System เราอาจจะใช้ Markdown แทนก็ได้ครับ แต่ความสามารถบางอย่างอาจจะทำได้ไม่เหมือนใช้ wysiwyg แต่จากที่ยกตัวอย่างไปเป็นระบบเก่าทำให้ต้องคิดเรื่อง backward compatibility ด้วยทำให้ยังคงใช้ HTML เหมือนเดิมและทำในส่วนการป้องกันเพิ่มเติมครับ

ขอบคุณทาง depa และ คณะเทคโนโลยีสารสนเทศ มจธ.
ที่มอบทุนการศึกษาเพชรพระจอมเกล้าเพื่อพัฒนาเทคโนโลยีและนวัตกรรมดิจิทัล และทำให้ได้ความรู้เพิ่มสำหรับใช้ทำงานจริงครับ

เรื่องต่อไปจะเป็นเรื่องอะไร ติดตามกันต่อไป ขอบคุณที่อ่านจนจบครับ 🙏

--

--

Tae Keerati Jearjindarat

Hi, I'm Tae, Associate Engineering Manager at LINEMAN Wongnai. Thanks for following <3