ข้ามไปยังเนื้อหา
กลับไปหน้าบทความ
ความปลอดภัยเครือข่าย

Prompt Injection คืออะไร ทำไมข้อความที่ซ่อนในอีเมลถึงสั่ง LLM ได้

ทดลองกับ email assistant จำลองทีละขั้น ดูว่าคำสั่งที่ซ่อนในอีเมลยึดการทำงานของ LLM อย่างไร และ control จาก OWASP LLM01, NIST, ATLAS ที่ช่วยจำกัดความเสียหาย

ปานกลาง11 นาทีในการอ่าน

ในบทความนี้

ทีมต่าง ๆ กำลังเชื่อม large language model (LLM) เข้ากับกล่องอีเมล คลังเอกสาร และ tool ที่ลงมือทำงานได้จริง ซึ่งมีประโยชน์มาก แต่ก็เปิดช่องให้เกิดบั๊กด้าน security แบบใหม่ คือข้อความที่ควรเป็น ข้อมูล กลับถูกตีความเป็น คำสั่ง ปัญหานี้เรียกว่า prompt injection และ OWASP จัดให้อยู่อันดับหนึ่งใน Top 10 for LLM Applications 2026

โพสต์นี้เขียนแบบ lab walkthrough เราจะสร้าง email assistant จำลองขึ้นมาบนกระดาษ ส่งอีเมลให้มันหนึ่งฉบับ แล้วดูทีละขั้นว่าข้อความที่ซ่อนอยู่บรรทัดเดียวเปลี่ยนพฤติกรรมของมันได้อย่างไร จากนั้นใช้เอกสารอ้างอิงสาธารณะสามแหล่ง (OWASP, NIST และ MITRE ATLAS) มาเรียกชื่อสิ่งที่เกิดขึ้น ปิดท้ายด้วย control ที่ช่วยจำกัดความเสียหาย และเหตุผลที่ไม่มี filter ตัวเดียวที่ทำให้ปัญหานี้หายไปได้ครับ

หมายเหตุของ lab: assistant ข้างล่างเป็นระบบสมมติ ไม่ใช่ผลิตภัณฑ์จริง และเนื้อหานี้ไม่ใช่สูตรสำหรับโจมตีระบบใด จุดประสงค์คือให้เห็นกลไกชัดพอที่จะออกแบบป้องกันได้

ขั้นที่ 1: ประกอบ assistant จำลอง

assistant ของเรา ขอเรียกว่า Helper ทำงานอย่างเดียว คือเมื่อเปิดอีเมล มันจะเขียนสรุปสองบรรทัด เบื้องหลังแอป LLM แบบนี้ส่วนใหญ่ประกอบด้วยสี่ส่วนครับ

ส่วนประกอบ ใครเป็นคนเขียน ตัวอย่างใน Helper
System prompt นักพัฒนา "You summarise emails politely."
User input ผู้ใช้แอป "Summarise this one."
Retrieved data ใครก็ตามที่เขียนเนื้อหานั้น เนื้อความของอีเมลที่กำลังสรุป
Tools นักพัฒนาเปิดให้ใช้ read_inbox(), summarise(), send_email()

สามส่วนแรกเป็นข้อความทั้งหมด ก่อนเรียกโมเดล แอปจะนำทั้งสามมาต่อกันเป็นก้อนเดียวที่เรียกว่า context window แล้วโมเดลก็ทำนายคำตอบจากข้อความทั้งก้อนนั้น ถ้าโมเดลตัดสินใจว่าต้องใช้ tool แอปจะรัน tool แล้วส่งผลลัพธ์กลับเข้าไปอีกรอบ NIST อธิบายวงจรนี้สำหรับ agent ไว้ว่าเป็นซอฟต์แวร์ที่ส่ง prompt ให้โมเดลซ้ำ ๆ ประมวลผล output เช่นเลือกและเรียก function แล้วส่งผลกลับเป็นส่วนหนึ่งของ prompt ถัดไป

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

สามแหล่งที่น่าเชื่อถือต่างระดับกัน กลายเป็น token สายเดียวกันใน context window

รายงานของ NIST เรื่อง adversarial machine learning เขียนไว้ตรง ๆ ว่า ต้นเหตุของช่องโหว่หลายอย่างในแอป LLM คือข้อมูลและคำสั่งไม่ได้ถูกส่งให้ LLM ผ่านช่องทางที่แยกกัน และเปรียบว่าเป็นข้อบกพร่องแบบเดียวกับที่อยู่เบื้องหลัง SQL injection ซึ่งมีมานานหลายสิบปี ส่วน National Cyber Security Centre (NCSC) ของสหราชอาณาจักรไปไกลกว่านั้น โดยบอกว่า LLM ในปัจจุบันไม่ได้บังคับใช้ security boundary ระหว่างคำสั่งกับข้อมูลเลยครับ

ขั้นที่ 2: ส่งอีเมลให้ Helper

มีอีเมลเข้ามาจากคนนอกองค์กร ดูเหมือนข้อความเรื่องใบแจ้งหนี้ธรรมดา แต่ท้ายอีเมลมีอีกหนึ่งบรรทัดที่เป็นตัวอักษรสีขาวบนพื้นขาว เป็นคำสั่งให้ค้นกล่องอีเมลแล้วส่งผลไปยังที่อยู่ภายนอกครับ

คนอ่านไม่เห็นบรรทัดนั้น แต่โมเดลเห็น เพราะสำหรับโมเดลมันก็แค่ token อีกชุด คำอธิบาย prompt injection ของ OWASP ครอบคลุมกรณีนี้พอดี คือ input ที่ส่งผลต่อโมเดลได้นั้นไม่จำเป็นต้องให้มนุษย์อ่านออก หรือมองเห็นได้บนหน้าจอ

สิ่งที่เกิดต่อจากนี้ขึ้นกับว่า Helper ถูกสร้างมาอย่างไร

  1. ผู้ใช้กด Summarise
  2. แอปสร้าง context: system prompt + คำขอของผู้ใช้ + เนื้ออีเมล (รวมบรรทัดที่ซ่อนไว้)
  3. โมเดลอ่านทั้งหมดเป็นสายเดียว และอาจมองบรรทัดที่ซ่อนอยู่ว่าเป็นคำขอที่ควรทำตาม
  4. ถ้า Helper เรียก send_email() ได้เอง "แผน" ของโมเดลก็อาจกลายเป็นอีเมลที่ถูกส่งออกไปจริง
บรรทัดที่ซ่อนในอีเมลเปลี่ยนการเรียก tool จาก summarise เป็น send แต่ประตูอนุมัติโดยมนุษย์ที่อยู่นอกโมเดลหยุดไว้ได้

ทั้งหมดนี้ผู้โจมตีไม่ต้องแตะ Helper ไม่ต้อง login และไม่ต้องหาบั๊กหน่วยความจำ แค่ทำให้ข้อความไปอยู่ตรงหน้าโมเดลได้ก็พอครับ รูปแบบนี้ถูกอธิบายไว้ตั้งแต่ช่วงแรก ๆ บทความวิจัยปี พ.ศ. 2566 ของ Greshake และคณะแสดงว่าแอปที่ผสาน LLM เข้าไปทำให้เส้นแบ่งระหว่างข้อมูลกับคำสั่งพร่าเลือน และถูกโจมตีจากระยะไกลได้ด้วยการฝังคำสั่งไว้ในเนื้อหาที่แอปจะดึงมาอ่านภายหลัง

ขั้นที่ 3: เรียกชื่อสิ่งที่เกิดขึ้น (OWASP LLM01)

LLM01:2026 Prompt Injection ของ OWASP แบ่งปัญหาเป็นสองแบบ

  • Direct prompt injection: ผู้ใช้ หรือผู้โจมตีที่เข้าถึงได้ทางเดียวกับผู้ใช้ ป้อน input ที่เปลี่ยนพฤติกรรมของโมเดล จะตั้งใจหรือไม่ตั้งใจก็ได้
  • Indirect prompt injection: โมเดลรับเนื้อหาจากภายนอก เช่นหน้าเว็บ เอกสาร อีเมล หรือผลลัพธ์จาก tool และคำสั่งที่อยู่ในเนื้อหานั้นเปลี่ยนพฤติกรรมของมัน โดยที่ผู้ใช้ไม่ได้เป็นคนใส่และไม่เห็นคำสั่งเหล่านั้น

อีเมลของเราเป็นแบบ indirect คนที่เสียหายคือผู้ใช้ที่กด Summarise ไม่ใช่คนที่พิมพ์ครับ OWASP อธิบายว่า jailbreaking เป็นกลุ่มย่อยของ prompt injection ที่ผู้โจมตีมุ่งให้โมเดลละเมิด safety protocol ของตัวเอง และพูดตรง ๆ เรื่องการป้องกันว่า เนื่องจาก LLM ไม่ได้แยกคำสั่งกับข้อมูลในระดับสถาปัตยกรรม จึงยังไม่มีกลไกป้องกันที่เชื่อถือได้ในปัจจุบัน

บั๊กกลุ่มนี้มีบันทึกในโลกจริงด้วย CVE-2024-5184 อธิบายช่องโหว่ prompt injection ในบริการ EmailGPT ที่ทำให้ผู้ใช้ที่ประสงค์ร้ายยึด logic ของบริการได้ และบังคับให้บริการเปิดเผย system prompt ที่ hard-code ไว้ ฉบับปี 2026 ของ OWASP ก็ยก EmailGPT เป็นตัวอย่างด้วย

ขั้นที่ 4: ความเสี่ยงที่เหลือใน OWASP list แบบบรรทัดเดียว

prompt injection ไม่ค่อยสร้างความเสียหายด้วยตัวเอง มันมักเป็นก้าวแรก แล้วความเสี่ยงอื่น ๆ เป็นตัวตัดสินว่าความเสียหายจะหนักแค่ไหนครับ นี่คือฉบับปี 2026 ที่เผยแพร่ในเดือนสิงหาคม พ.ศ. 2569 (ตอนที่ผมตรวจสอบ หน้ารายการเดิมของ OWASP ยังแสดงฉบับปี 2025 อยู่ จึงอาจเห็นการเรียงลำดับทั้งสองแบบปะปนกันตามเว็บต่าง ๆ)

ID ความเสี่ยง สรุปหนึ่งบรรทัด
LLM01 Prompt Injection input (ทั้งที่พิมพ์ตรงและที่ซ่อนในข้อมูล) เปลี่ยนพฤติกรรมของโมเดล
LLM02 Sensitive Information Disclosure โมเดลหรือแอปเปิดเผยข้อมูลส่วนตัว
LLM03 Excessive Agency แอปให้ tool, permission หรือความเป็นอิสระกับโมเดลมากเกินจำเป็น
LLM04 Supply Chain จุดอ่อนในโมเดล dataset, tool และ dependency ที่ดึงเข้ามาใช้
LLM05 Data and Model Poisoning ข้อมูลที่ใช้ train, fine-tune หรือทำ embedding ถูกแก้ไขโดยเจตนาร้าย
LLM06 Unbounded Consumption ไม่จำกัดการใช้งาน จนเกิดค่าใช้จ่ายบานปลายหรือ denial of service
LLM07 Misinformation output ที่ดูมั่นใจแต่ผิด ซึ่งคนหรือระบบนำไปใช้ต่อ
LLM08 Hidden Context Exposure system prompt และ context ที่ซ่อนอยู่ถูกดึงออกมาได้ จึงห้ามเก็บความลับไว้ในนั้น
LLM09 Vector and Embedding Weaknesses ความเสี่ยงในการจัดเก็บและค้นคืน vector ของ RAG
LLM10 Improper Output Handling output ของโมเดลไปถึงระบบอื่นโดยไม่ผ่านการตรวจสอบ

สามข้อในนี้ตรงกับ assistant จำลองของเราโดยตรง

  • LLM03 Excessive Agency คือเหตุผลที่บรรทัดที่ซ่อนอยู่มีผล OWASP ระบุต้นเหตุไว้สามข้อคือ excessive functionality, excessive permissions และ excessive autonomy scenario แรกของ OWASP เองแทบจะเหมือน lab ของเรา คือ assistant ที่ต้องการแค่อ่านอีเมล แต่ใช้ tool ที่ส่งอีเมลได้ด้วย แล้วอีเมลที่ถูก inject ก็สั่งให้มันค้นกล่องอีเมลหาข้อมูลสำคัญและส่งต่อไปให้ผู้โจมตี
  • LLM10 Improper Output Handling ครอบคลุมกรณีที่ output ของโมเดลถูกส่งต่อไปยัง browser, shell หรือฐานข้อมูล ตัวอย่างของ OWASP มีทั้ง XSS จาก Markdown หรือ JavaScript ที่โมเดลสร้าง และ SQL injection จาก query ที่โมเดลสร้าง และแนะนำให้ปฏิบัติกับโมเดลเหมือนผู้ใช้คนหนึ่งตามแนวทาง zero trust
  • LLM08 Hidden Context Exposure (ฉบับปี 2025 เรียกว่า System Prompt Leakage) เตือนว่าเนื้อหาใน context ไม่ควรถือเป็นความลับ และไม่ควรพึ่ง context ที่ซ่อนไว้เพียงอย่างเดียวเป็น security boundary การเขียนใน prompt ว่า "ห้ามส่งอีเมล" เป็นแค่ความหวัง ไม่ใช่ control

ขั้นที่ 5: taxonomy ของ NIST เพื่อมองภาพกว้าง

OWASP คือรายการความเสี่ยงสำหรับคนสร้างระบบ ส่วน NIST AI 100-2 E2025, Adversarial Machine Learning: A Taxonomy and Terminology of Attacks and Mitigations (มีนาคม พ.ศ. 2568) คือคำศัพท์กลางที่ทุกคนใช้ร่วมกัน สำหรับ generative AI รายงานจัดกลุ่มการโจมตีตามสิ่งที่ผู้โจมตีต้องการทำลาย ได้แก่ availability, integrity และ privacy บวกกับหมวดที่สี่สำหรับ GenAI คือ misuse enablement ซึ่งมุ่งหลบเลี่ยงข้อจำกัดเรื่องสิ่งที่โมเดลยอมตอบ

รายงานยังอธิบาย injection สองแบบในแง่ความสามารถของผู้โจมตี

  • Direct prompting attack มาจากผู้ใช้หลัก ผ่านการ query ตามปกติ
  • Indirect prompt injection เป็นไปได้ด้วย resource control คือผู้โจมตีแก้เอกสารหรือหน้าเว็บที่โมเดลจะอ่านในภายหลัง โดยไม่ต้องคุยกับแอปเลย

ตัวอย่างในรายงานอ่านแล้วเหมือนรายการสิ่งที่ควรทดสอบในแอปของเราเอง เช่น อีเมลที่ถูก inject แล้วสั่งให้ assistant ส่งต่อเมลไปให้ผู้โจมตี prompt ที่แพร่จากกล่องเมลหนึ่งไปอีกกล่องหนึ่งแบบ worm และการใช้ฟีเจอร์อย่าง การ render รูปภาพใน Markdown เพื่อลักลอบส่งข้อมูลออก เรื่องการป้องกัน NIST ระวังคำพูดมาก โดยบอกว่า mitigation ในปัจจุบันยังป้องกันได้ไม่ครบทุกกรณี ผู้ออกแบบจึงอาจตั้งสมมติฐานไว้เลยว่า prompt injection เกิดได้ทุกครั้งที่โมเดลเห็น input ที่ไม่น่าเชื่อถือครับ

ขั้นที่ 6: MITRE ATLAS แผนที่สไตล์ ATT&CK

ถ้าใช้ MITRE ATT&CK กับ network และ endpoint อยู่แล้ว MITRE ATLAS (Adversarial Threat Landscape for AI Systems) จะดูคุ้นตาครับ มันเป็น matrix ของ tactic และ technique ที่มุ่งโจมตีระบบ AI ข้อมูลรุ่นปัจจุบัน (version 2026.09) มี 16 tactic เช่น Reconnaissance, Initial Access, Exfiltration และ Impact

lab ของเราคือ technique AML.T0051 LLM Prompt Injection ซึ่งมีสาม sub-technique คือ Direct (.000), Indirect (.001) และ Triggered (.002) ที่การกระทำของผู้ใช้หรือเหตุการณ์ในระบบไปจุดชนวน injection ซึ่งอาจถูกฝังรอไว้ในระบบของเหยื่ออยู่แล้ว ATLAS ระบุว่า indirect injection มักถูกซ่อนจากผู้ใช้ เช่นเป็นข้อความที่มองไม่เห็น และ agent ที่ถูกยึดจะได้สิทธิ์ทุกอย่างที่ระบบ AI นั้นถืออยู่

ATLAS ยังมี mitigation ที่เข้ากับประตูอนุมัติของเราได้ดี เช่น AML.M0029 Human In-the-Loop for AI Agent Actions, AML.M0030 Restrict AI Agent Tool Invocation on Untrusted Data และ AML.M0028 AI Agent Tools Permissions Configuration ซึ่งใช้หลัก least privilege กับ tool ที่ agent เรียกได้

ขั้นที่ 7: control ที่ช่วยลดความเสียหาย

LLM01:2026 ของ OWASP มี mitigation สิบเอ็ดข้อ และยอมรับตรง ๆ ว่าไม่มี control ตัวเดียวที่เพียงพอ จึงต้องใช้ซ้อนกันหลายชั้นแบบ defence in depth ผมจัดกลุ่มตามที่คิดเวลาดู assistant จำลองของเราครับ

ลดสิ่งที่โมเดลทำได้ (least privilege)

  • ให้ Helper มีแค่ tool ที่งานต้องใช้ ตัวสรุปอีเมลต้องการ read ไม่ใช่ send
  • ใช้ scope แบบอ่านอย่างเดียว และรัน action ใน context ของผู้ใช้เองด้วยสิทธิ์น้อยที่สุด ตามที่ OWASP LLM03:2026 แนะนำ
  • ใช้หลักง่าย ๆ ที่ NCSC ยกมาจากการถกเถียงสาธารณะ: เมื่อ LLM ประมวลผลข้อมูลจากฝ่ายใด สิทธิ์ของมันควรลดลงเหลือเท่ากับฝ่ายนั้น assistant ที่อ่านอีเมลจากภายนอกไม่ควรถือ tool ที่มีสิทธิ์สูง

วางประตูไว้นอกโมเดล

  • ให้มนุษย์อนุมัติ action ที่มีความเสี่ยงสูง เช่น ส่ง ลบ จ่ายเงิน หรือเปลี่ยนสิทธิ์ นี่คือประตูใน animation ข้างบน และมันได้ผลเพราะเป็นโค้ดธรรมดา ไม่ใช่ประโยคใน prompt OWASP เสริมว่าผู้อนุมัติควรเห็น action ที่จะเกิดขึ้นจริงแบบตรงตัว ไม่ใช่แค่สรุป
  • บังคับ authorisation ที่ระบบปลายทาง อย่าถามโมเดลว่า action นี้ทำได้หรือไม่
  • พิจารณาบล็อกการเรียก tool อัตโนมัติเมื่อมีข้อมูลที่ไม่น่าเชื่อถือเข้ามาใน context แล้ว (ATLAS AML.M0030)

จัดการ output เหมือน input ที่ไม่น่าเชื่อถือ

  • ตรวจ output เทียบกับรูปแบบที่คาดไว้ก่อนให้อะไรทำงานตามมัน
  • encode ให้เหมาะกับปลายทาง (HTML, SQL, shell) ใช้ parameterised query และตั้ง Content Security Policy แบบเข้มงวด ตาม OWASP LLM10:2026
  • ระวังลิงก์และรูปภาพใน output ที่ถูก render อัตโนมัติ เพราะใช้พาข้อมูลออกไปได้

แยกและติดป้ายข้อมูลให้ต่างจากคำสั่ง

  • ทำเครื่องหมายเนื้อหาที่ไม่น่าเชื่อถือให้ชัด NCSC บอกว่าแม้แต่การครอบด้วย XML tag ก็ช่วยได้ นักวิจัยของ Microsoft เรียกกลุ่มเทคนิคแบบนี้ว่า spotlighting (delimiting, datamarking และ encoding) และรายงานว่าช่วยลดอัตราการโจมตีสำเร็จจากมากกว่า 50% เหลือต่ำกว่า 2% ในการทดลองกับโมเดลตระกูล GPT
  • มองว่าสิ่งนี้ทำให้โจมตียากขึ้น ไม่ใช่ทำให้เป็นไปไม่ได้ OWASP เตือนว่าผู้โจมตีที่รู้รูปแบบการทำเครื่องหมายสามารถเลียนแบบได้

ทดสอบและเฝ้าดู

  • ทำ adversarial testing กับแอปของเราเองก่อนที่ผู้โจมตีจะทำ รวมถึงให้ผู้ทดสอบที่รู้กลไกป้องกันของเราลองโจมตีด้วย (mitigation ข้อที่สิบเอ็ดของ OWASP)
  • เก็บ log ของ input, output และการเรียก tool NCSC แนะนำให้จับตาการเรียก tool ที่ล้มเหลว ซึ่งอาจบอกว่ามีผู้โจมตีกำลังปรับแต่งการโจมตีอยู่

ทำไมไม่มี filter ตัวเดียวที่แก้ได้

หลายคนอยากเพิ่ม input filter สักตัวที่คอยจับคำว่า "ignore previous instructions" แล้วถือว่าจบ ปัญหาคือภาษามีวิธีพูดเรื่องเดียวกันได้ไม่รู้จบครับ

deny-list จับได้แค่วิธีเขียนแบบเดียว ประโยคเดียวกันที่เขียนใหม่หรือเข้ารหัสไว้ผ่านไปได้

NCSC พูดประเด็นเดียวกันว่ามีวิธีเรียบเรียงการโจมตีใหม่ได้ไม่สิ้นสุด ที่หลบ deny-list ได้ และตัวอย่างของ OWASP เองก็มีทั้ง payload splitting, payload หลายภาษา และการเข้ารหัสแบบ Base64, ROT13 หรือ emoji สำหรับ SQL injection เรามีทางแก้จริงคือ parameterised query เพราะฐานข้อมูลมีช่องทางแยกสำหรับข้อมูล แต่ LLM ไม่มีช่องทางแบบนั้น NCSC จึงบอกว่ามีโอกาสสูงที่ prompt injection จะไม่มีวันถูกแก้ได้อย่างแท้จริงในแบบเดียวกัน และมองโมเดลว่าเป็น "inherently confusable deputy" หรือผู้ช่วยที่ถูกหลอกให้สับสนได้โดยธรรมชาติ

เป้าหมายในทางปฏิบัติจึงเปลี่ยนไป แทนที่จะพยายามให้ "โมเดลไม่ทำตามข้อความที่ซ่อนอยู่เลย" ให้ตั้งเป้าว่า "ถ้ามันทำตาม ก็ไม่มีอะไรสำคัญเกิดขึ้นได้ หากไม่ผ่านการตรวจที่มันพูดหว่านล้อมไม่ได้" ใน assistant จำลองของเรา หมายความว่า Helper อาจถูกหลอกจน อยาก ส่งอีเมล แต่อีเมลก็ยังไม่ถูกส่งออกไปครับ

checklist สั้น ๆ สำหรับฟีเจอร์ LLM ของคุณ

  • ทำรายการทุกแหล่งข้อความที่ไปถึงโมเดล อะไรที่มาจากภายนอกถือว่าไม่น่าเชื่อถือ
  • ทำรายการทุก tool ที่โมเดลเรียกได้ ตัดตัวที่ฟีเจอร์ไม่จำเป็นต้องใช้ออก
  • วางการอนุมัติแบบ deterministic ไว้หน้าทุกอย่างที่ส่ง ลบ จ่ายเงิน หรือเปลี่ยนสิทธิ์
  • เก็บความลับและ logic การให้สิทธิ์ไว้นอก system prompt
  • ตรวจและ encode output ของโมเดลก่อนส่งต่อไปยังระบบอื่น
  • เก็บ log การเรียก tool และทดสอบด้วยเนื้อหาที่ถูก inject ก่อนปล่อยใช้งาน

แหล่งอ้างอิง

อ่านต่อ