ป้องกัน HTML Injection ใน E-Mail — สิ่งที่ Developer ไม่ควรมองข้าม

โดย admin

3 นาที
แชร์
Blog Thumbnail

ป้องกัน HTML Injection ใน E-Mail — สิ่งที่ Developer ไม่ควรมองข้าม


ในกระบวนการพัฒนาแอปพลิเคชัน การรักษาความปลอดภัยเป็นสิ่งสำคัญที่ไม่ควรถูกมองข้าม แม้บางช่องโหว่อาจดูไม่ใหม่หรือซับซ้อน แต่ก็อาจสร้างความเสียหายร้ายแรงได้ โดยเฉพาะในแอปพลิเคชันที่มีการรับข้อมูลจากผู้ใช้งานและนำข้อมูลนั้นไปประมวลผลต่อ หนึ่งในช่องโหว่ที่พบได้บ่อยคือ HTML Injection ซึ่งอาจเกิดขึ้นเมื่อข้อมูลที่ผู้ใช้กรอกเข้าไปถูกนำไปแสดงผลในอีเมลโดยตรง หากไม่มีการตรวจสอบหรือกรองข้อมูลอย่างเหมาะสม ข้อมูลที่เป็นอันตรายอาจนำไปสู่การโจมตีที่สร้างผลกระทบต่อระบบ ความปลอดภัยของผู้ใช้ หรือทำให้เกิดการหลอกลวง (phishing) ผ่านอีเมลได้

บทความนี้จะอธิบายถึงความเสี่ยงของ HTML Injection ในอีเมล พร้อมวิธีการป้องกันที่ Developer ควรรู้และนำไปปรับใช้เพื่อปกป้องระบบและผู้ใช้งาน

HTML injection คืออะไร

HTML Injection เป็นช่องโหว่ด้านความปลอดภัยที่เกิดขึ้นเมื่อผู้โจมตีสามารถแทรกคำสั่ง HTML ที่เป็นอันตรายลงในเว็บแอปพลิเคชัน หากแอปพลิเคชันมีการรับข้อมูลจากฝั่งผู้ใช้โดยไม่มีการกรองหรือป้องกันที่เพียงพอ อาจส่งผลให้ผู้โจมตีสามารถดักจับ Session Cookies ของผู้ใช้งาน หรือปลอมแปลงตัวตน (Session Hijacking) รวมถึงการเปลี่ยนแปลงเนื้อหาบนหน้าเว็บเพื่อหลอกลวงผู้ใช้ เช่น การสร้างฟอร์มปลอมหรือเปลี่ยนเส้นทางไปยังเว็บไซต์อันตรายได้ (OWASP)

ตัวอย่างคำสั่ง

<a href=”https://www.google.com">HTML</a>

ทำไมข้อมูลที่ผู้ใช้กรอก อาจนำไปสู่ HTML Injection ในอีเมลได้

ปัญหานี้เกิดขึ้นเมื่อ Developer นำข้อมูลที่ได้รับจากผู้ใช้ เช่น ชื่อ อีเมล หรือข้อมูลอื่น ๆ ไปแสดงผลในอีเมลโดยตรง โดยไม่ทำการกรองหรือแปลงข้อมูลให้ปลอดภัย หากข้อมูลที่ผู้ใช้กรอกมีการแทรกคำสั่ง HTML หรือ JavaScript ที่เป็นอันตราย การนำข้อมูลนั้นไปแสดงในอีเมลอาจทำให้เกิด HTML Injection ซึ่งเปิดช่องทางให้ผู้ไม่หวังดีสามารถโจมตีผู้ใช้หรือระบบได้

และหากเนื้อหาภายในอีเมลถูกสร้างจาก HTML ประกอบกับการที่ Developer นำข้อมูลจากผู้ใช้มาแสดงผลโดยตรง โดยไม่มีการกรอง HTML อันตราย จะทำให้คำสั่งที่เป็นอันตรายถูก render พร้อมกับข้อมูลที่แสดงผล นี่จึงเป็นช่องโหว่ที่อาจนำไปสู่การโจมตีแบบ Email Phishing ได้ (Twilio)

ตัวอย่างสถานการณ์

บนหน้าเว็บสำหรับลงทะเบียนใช้งาน มีการรับ Input จากผู้ใช้ เช่น ชื่อผู้ใช้ อีเมล เมื่อลงทะเบียนเสร็จ ระบบจะทำการส่งอีเมลตอนรับให้กับผู้ใช้ใหม่

กรณีปกติ ผู้ใช้กรอกชื่อ และ E-mail ตามปกติ

รูปที่ 1 ผู้ใช้กรอกชื่อ และ email ตามปกติ

แต่หากมีผู้ไม่หวังดี กรอกข้อมูลที่แฝงคำสั่ง HTML อันตราย เช่น

<a href=”https://www.google.com">HTML</a>

จะเกิดอะไรขึ้น??

รูปที่ 2 ผู้ใช้กรอกข้อมูลที่แฝงคำสั่ง HTML อันตราย

เมื่อระบบส่งอีเมลต้อนรับไปให้ผู้ใช้ เนื้อหาภายในอีเมลจะแสดงลิงก์ที่สามารถคลิก ซึ่งนำไปสู่เว็บไซต์อันตรายได้

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

“แสดงว่า Application ของเราควรลดช่องใส่ Input ใช่หรือไม่?”

คำตอบคือ ไม่จำเป็น เพราะปัญหานี้ไม่ได้เกิดจากข้อมูลที่ผู้ใช้กรอกเพียงอย่างเดียว แต่เกิดจากการที่ Developer นำข้อมูลที่ได้รับจากผู้ใช้ไปประมวลผลทันทีโดยไม่มีการตรวจสอบหรือกรองข้อมูลก่อน หากมีผู้ไม่หวังดีกรอกข้อมูลที่เป็นอันตรายเข้ามา เช่น คำสั่งที่มุ่งโจมตีระบบ ข้อมูลนั้นก็สามารถสร้างความเสียหายแก่ Application ของเราได้เช่นกัน

วิธีป้องกัน HTML Injection ในอีเมล

ในบทความนี้ เราจะพูดถึงการป้องกัน HTML Injection ภายในอีเมล ในกรณีที่ Developer เขียนเนื้อหาภายในอีเมลด้วย HTML โดย Developer ควรทำการ Encode HTML สำหรับข้อมูลที่ได้รับจากผู้ใช้ก่อนที่จะนำมาแสดงผล วิธีที่นำเสนอนี้สามารถนำไปปรับใช้กับ Email provider หลายๆ เจ้า เช่น Gmail, Outlook เป็นต้น

1. ควรหลีกเลี่ยงการนำข้อมูลที่มีการรับค่า Input มาแสดงผลโดยไม่จำเป็น หรือหากจำเป็นสามารถทำได้โดย HTML encode create element

2. การ Encode HTML สามารถทำได้โดยใช้ความสามารถของ HTML นั่นเอง

<script>
function encodeHTML(text) {
            var textArea = document.createElement('textarea');
            textArea.textContent = text;
            return textArea.innerHTML;
        }
</script>

แต่สำหรับวิธีนี้อาจจะมีข้อจำกัดตรงที่ หาก Email provider ไม่รองรับการใส่ script จะไม่สามารถใช้งานได้ ผู้เขียนจึงมีอีกวิธีมานำเสนอ ตามวิธีถัดไป (zapier)

3. เปลี่ยน HTML ให้เป็น HTML Entities

สำหรับวิธีนี้จะเป็นการเปลี่ยนอักขระพิเศษใน HTML เช่น < > และ & ที่สามารถสร้างเป็น Tag ต่าง ๆ ใน HTML เป็น HTML Entities

HTML Entities จะเป็นอักขระแทนอักษรพิเศษต่าง ๆ ใน HTML เมื่อ Browser ประมวลผล จะแสดงผลเป็นข้อความธรรมดา แทนที่จะตีความเป็น Tag HTML หรือคำสั่ง ซึ่งเป็นการป้องกันไม่ให้ HTML ถูกประมวลผลในลักษณะที่ไม่ต้องการ

export function toHtmlEntity(text: string) {
  return text
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#039;');
}

ผลลัพธ์ที่ได้เมื่อกรอกคำสั่ง HTML

<a href=”https://www.google.com">new user</a>

จะถูกแปลงเป็น HTML Entity

&lt;a href=&quot;https://www.google.com&quot;&gt;new user&lt;/a&gt;

รูปที่ 4 ผู้ใช้กรอกคำสั่ง HTML ที่อันตราย

ผลลัพธ์ใน Gmail ก่อนเพิ่มการ Encode HTML

รูปที่ 5 เนื้อหาอีเมลขณะยังไม่มีการทำ Encode HTML ก่อนนำข้อมูลมาแสดงผล

หลังเพิ่มการ Encode HTML ก่อนนำข้อมูลไปแสดงผลใน HTML จะได้ผลลัพธ์ดังนี้

รูปที่ 6 เนื้อหาอีเมลหลังรทำ Encode HTML ข้อมูลก่อนนำมาแสดงผล

หมายเหตุ สำหรับ Provider ของ Gmail จะมีการ Render ที่ต่างออกไป รวมถึงมีข้อกำหนด CSS ที่อนุญาตให้กำหนดได้อย่างจำกัด หากใส่ข้อมูลที่อาจจะเป็น ลิงก์ หรือมีเครื่องหมายสัญลักษณ์พิเศษลงใน a-tag ทำให้ลิงก์นั้นจะยังสามารถคลิกได้ (Google Workspace)

ผู้เขียนเพิ่มการเติม a-tag ซ้ำอีกที หากถูกนำไปแสดงผล ผู้ใช้ก็คลิกลิงก์ได้ แต่จะอยู่ที่หน้าเว็บเดิม ไม่ได้ถูกลิงก์ไปที่อื่น

<a href=”#”>{data}</a>

เราจะมาลองทดสอบด้วยการใส่คำสั่ง HTML อื่นดูบ้างว่า ยังทำงานแบบเดิมอยู่หรือไม่

&lt;a href=&quot;https://www.google.com&quot;&gt;new user&lt;/a&gt;

รูปที่ 7เนื้อหาอีเมลหลังรทำ Encode HTML ข้อมูลก่อนนำมาแสดงผล

<body style=”background-color:red”>

รูปที่ 8 เนื้อหาอีเมลหลังรทำ Encode HTML ข้อมูลก่อนนำมาแสดงผล

<iframe src=”https://www.google.com" title=”test”></iframe>

รูปที่ 9 เนื้อหาอีเมลหลังรทำ Encode HTML ข้อมูลก่อนนำมาแสดงผล

หรือเลือกใช้ Library ในการแปลง HTML เป็น HTML Entities ได้เช่นเดียวกัน เช่น Library html entities (html-entities)

import {encode} from ‘html-entities’;
.
const username = encode(data.username);

ด้วยวิธีการ Encode HTML นี้ สามารถช่วยป้องกันการทำ HTML injection ในอีเมลได้

โดยสรุป

จะเห็นได้ว่า Developer ควรจัดเก็บข้อมูลในรูปแบบที่เหมาะสม และตรวจสอบข้อมูลที่จะนำมาแสดงผลเสมอ หากเป็นข้อมูลที่ผู้ใช้สามารถ input เข้ามาได้ นั้นก็นับว่าเป็นความเสี่ยงแล้ว

การทำ Encode HTML ก่อนส่งอีเมลเป็นอีกขั้นตอนสำคัญที่ช่วยลดความเสี่ยงในการโจมตีด้วย HTML injection สำหรับ Developer นี่คือความรับผิดชอบที่ควรทำ เพื่อปกป้องผู้ใช้งานและระบบจากภัยคุกคามที่ไม่คาดคิด

ขอบคุณที่ติดตามอ่านจนจบ แล้วพบกันใหม่ค่ะ 😊

อ้างอิง:

แชร์
กลับไปด้านบน

บทความที่เกี่ยวข้อง

อัปเดตข้อมูลด้านไซเบอร์ ทุกสัปดาห์
รับข่าวสารความรู้เชิงลึกเกี่ยวกับความปลอดภัยไซเบอร์จากดาต้าฟาร์มก่อนใคร

ฟีเจอร์นี้จะเปิดให้ใช้งานเร็ว ๆ นี้ โปรดติดตาม

ส่งสัปดาห์ละ 1 ครั้ง ไม่มีสแปม ยกเลิกการรับข่าวสารได้ทุกเมื่อ