ผู้ช่วย AI ของคุณปฏิบัติตามคำสั่งได้ถูกต้องประมาณ 99% แต่ช่องว่าง 1% ที่เหลือนั้นคือจุดที่ผู้โจมตีจะจู่โจม การป้อนคำสั่งที่ถูกออกแบบมาเป็นพิเศษ (crafted prompt) จะทำให้ผู้ใช้ที่ประสงค์ร้ายสามารถสั่งให้โมเดลเรียกใช้ฟังก์ชันที่ไม่ควรเข้าถึง เพื่อขโมยข้อมูลหรือดำเนินการที่มีสิทธิ์สูงได้ วิธีแก้ไขไม่ใช่การใช้ถ้อยคำที่สุภาพขึ้น แต่คือการปฏิบัติกับข้อบกพร่องนี้ในฐานะปัญหาด้านการอนุญาตสิทธิ์ (authorization issue) และการนำเครื่องมือที่อันตรายออกไปจากขอบเขตการเข้าถึงของโมเดล
ทำไม Prompt Injection ถึงไม่ใช่แค่ปัญหาเรื่องการใช้คำ
นักพัฒนามักพยายามเสริมความแข็งแกร่งให้ Agent ด้วยคำเตือนตัวพิมพ์ใหญ่ การตั้งกฎเป็นข้อๆ หรือการระบุเงื่อนไขว่า "ห้ามเรียกใช้ฟังก์ชัน admin" การป้องกันเหล่านั้นตั้งอยู่บนสมมติฐานที่ว่าโมเดลจะปฏิบัติตามประโยคที่บอกว่า "อย่าทำ X" แต่ในทางปฏิบัติ โมเดลสามารถถูกล่อลวงให้เพิกเฉยต่อคำสั่งได้ด้วยการเปลี่ยนวิธีเรียกร้อง การสวมบทบาทเป็นตัวละครอื่น หรือเพียงแค่การเพิ่มบริบทเพิ่มเติมเข้าไป ขอบเขตของภาษาเป็นสิ่งที่ต่อรองได้ แต่คำสั่งของผู้โจมตีนั้นไร้ขีดจำกัดและไม่มีต้นทุนในการทดสอบ
ช่องโหว่ที่แท้จริงอยู่ที่รายการเครื่องมือ (tool list) ที่ Agent ได้รับ เมื่อโครงสร้างคำสั่ง (prompt schema) มีฟังก์ชันที่ให้สิทธิ์ระดับ admin โมเดลก็จะมี "แผนที่" ไปสู่พลังนั้นทันที แม้ว่าในคำสั่งจะระบุว่า "อย่าใช้ฟังก์ชันนี้กับลูกค้า" แต่โมเดลก็ยังอาจถูกโน้มน้าวให้เรียกใช้มันได้ เพราะฟังก์ชันนั้นมีอยู่ในสภาพแวดล้อมการทำงาน (execution environment) ของมัน ดังนั้น ปัญหานี้จึงเป็นช่องว่างด้านการอนุญาตสิทธิ์ (authorization gap): ระบบกำลังเปิดเผยขีดความสามารถระดับสูงให้กับผู้เรียกใช้งานที่ไม่มีสิทธิ์ใช้งาน
การรักษาความปลอดภัยให้ Agent ด้วยการจำกัดการเข้าถึง
วิธีที่ง่ายที่สุดในการปิดช่องว่างนี้คือการหยุดให้โมเดลเข้าถึงเครื่องมือที่ไม่มีสิทธิ์ใช้งาน ให้คิดเสียว่ารายการเครื่องมือเปรียบเสมือน API key: หากไม่มี key นั้น การเรียกใช้งานก็ไม่สามารถเกิดขึ้นได้ ไม่มีถ้อยคำที่ชาญฉลาดใดจะสามารถเรียกใช้ฟังก์ชันที่ไม่ได้อยู่ในบริบทปัจจุบันได้
วิธีที่ผิด
Prompt: “You are an assistant. Do not use the adminDeleteUser function for regular customers.”
โมเดลยังคงเห็น adminDeleteUser ในกล่องเครื่องมือของมัน และสามารถถูกหลอกให้เรียกใช้งานได้
วิธีที่ถูก
Prompt schema for a regular customer: { “functions”: [ “searchCatalog”, “placeOrder” ] }
adminDeleteUser จะไม่ปรากฏขึ้นเลย ดังนั้นโมเดลจึงไม่มีช่องทางในการเรียกใช้งานมัน
กฎปฏิบัติ 3 ข้อสำหรับนักพัฒนา
- สร้างรายการเครื่องมือตามคำขอ (Build tool lists per request) – สร้างรายการฟังก์ชันแบบไดนามิกตามสิทธิ์ของผู้เรียกใช้งานที่ผ่านการยืนยันตัวตนแล้ว ลูกค้าจะเห็นเฉพาะฟังก์ชันที่จำเป็นต้องใช้ ส่วน admin จะเห็นชุดฟังก์ชันทั้งหมด
- Fail closed (ปิดการทำงานเมื่อเกิดข้อผิดพลาด) – หากไม่สามารถยืนยันตัวตนของผู้ใช้ได้ ให้ส่งคืนรายการว่างแทนที่จะใช้ค่าเริ่มต้นแบบ "มีเครื่องมือทั้งหมดให้ใช้งาน" วิธีนี้จะรับประกันว่าคำขอที่ไม่ได้ผ่านการยืนยันตัวตนจะไม่ได้รับอำนาจเกินความจำเป็น
- หลีกเลี่ยงการใช้สถานะร่วมกัน (Avoid shared state) – เมื่อมีการทำแคช (caching) คำจำกัดความของเครื่องมือ ห้ามเขียนข้อมูลเฉพาะของผู้ใช้ลงในอ็อบเจกต์ที่ใช้ร่วมกัน ให้ใช้การทำ copy-on-write หรือการคัดลอกแยกตามเซสชัน (per-session copies) เพื่อไม่ให้สิทธิ์ของผู้ใช้รายหนึ่งรั่วไหลไปยังคำขอของผู้ใช้อีกรายหนึ่ง
หากโครงสร้าง (schema) ที่แสดงให้ผู้ใช้ทั่วไปดูเหมือนกับที่แสดงให้ admin ดู แสดงว่าขอบเขตความปลอดภัยยังคงขึ้นอยู่กับข้อความใน prompt ซึ่ง prompt ไม่ใช่กลไกความปลอดภัยที่เชื่อถือได้
อะไรที่นำเรามาถึงจุดนี้
Prompt Injection เริ่มปรากฏขึ้นเมื่อนักพัฒนาเริ่มนำ Large Language Models (LLMs) เข้ามาใช้ในเวิร์กโฟลว์การทำงานจริงที่ต้องให้โมเดลเรียกใช้ API ภายนอก รันโค้ด หรือแก้ไขฐานข้อมูล "การใช้เหตุผล" ของโมเดลจะถูกชี้นำโดย prompt ซึ่งรวมถึงรายการเครื่องมือที่มีอยู่ด้วย โปรโตไทป์ในยุคแรกตั้งสมมติฐานว่าโมเดลจะปฏิบัติตามกฎภาษาธรรมชาติ เช่น "อย่าลบข้อมูลสำหรับผู้ที่ไม่ใช่ admin" แต่ผู้โจมตีแสดงให้เห็นอย่างรวดเร็วว่าเพียงแค่เพิ่มประโยคไม่กี่ประโยคก็สามารถข้ามกฎเหล่านั้น และสั่งให้โมเดลเรียกใช้ฟังก์ชันลบข้อมูลเดิมได้อยู่ดี
ปฏิกิริยาแรกของชุมชนนักพัฒนาคือการพยายามทำให้ภาษาใน prompt เข้มงวดขึ้น เพิ่มเงื่อนไข "ห้ามทำ X" หรือฝังตัวกรอง regex เพื่อตัดโทเคน (tokens) ที่น่าสงสัย มาตรการเหล่านั้นช่วยลดการใช้งานผิดพลาดโดยไม่ตั้งใจได้ แต่ไม่สามารถหยุดยั้งผู้โจมตีที่มีความมุ่งมั่นซึ่งสามารถเปลี่ยนวิธีเรียกร้องคำสั่งได้ง่ายๆ สาเหตุที่แท้จริง—นั่นคือการเปิดเผยฟังก์ชันระดับสูงให้กับผู้เรียกใช้งานที่ไม่น่าเชื่อถือ—จึงยังคงอยู่
ใครได้ประโยชน์ ใครเสียประโยชน์
องค์กรที่นำการกำหนดขอบเขตเครื่องมือตามคำขอ (per-request tool scoping) มาใช้ จะได้รับขอบเขตที่ชัดเจนและบังคับใช้ได้จริง Agent ของพวกเขาจะสามารถปรับใช้ในสเกลใหญ่ได้โดยไม่ต้องกังวลว่า prompt ที่ผิดเพี้ยนเพียงอันเดียวจะปลดล็อกความสามารถระดับ admin นอกจากนี้ ทีมตรวจสอบความสอดคล้อง (compliance teams) ยังพึงพอใจกับร่องรอยการตรวจสอบ (audit trail): รายการฟังก์ชันที่ส่งไปยังโมเดลคือหลักฐานที่เป็นรูปธรรมซึ่งสามารถบันทึกและตรวจสอบได้
นักพัฒนาที่พึ่งพาเพียงการป้องกันด้วย prompt (prompt-only guards) จะต้องเผชิญกับเป้าหมายที่เปลี่ยนแปลงอยู่ตลอดเวลา Agent ของพวกเขาอาจดูเหมือนทำงานได้ดีในการทดสอบ แต่อาจถูกเจาะระบบได้ในสภาพแวดล้อมจริง นำไปสู่การรั่วไหลของข้อมูล การทำธุรกรรมที่ไม่ได้รับอนุญาต หรือการละเมิดกฎระเบียบด้านความปลอดภัย ต้นทุนจากการถูกเจาะระบบนั้นสูงกว่าความพยายามในการสร้างรายการเครื่องมือแบบไดนามิกอย่างเทียบไม่ได้
ข้อโต้แย้ง: “แค่ใช้ Prompt ที่ดีขึ้นก็เพียงพอแล้ว”
มีข้อโต้แย้งว่าหากมีการทำ instruction engineering ที่เพียงพอ เช่น การใช้ layered prompts, system messages และ reinforcement learning from human feedback จะทำให้โมเดลสามารถปฏิบัติตามข้อกำหนด “do not” ได้ แต่ในความเป็นจริงแล้ว โมเดลภาษาคือ probabilistic generators ซึ่งจะคำนวณหาสิ่งที่น่าจะเป็นไปได้มากที่สุดในการเขียนต่อ ไม่ใช่การทำตามกฎความปลอดภัยที่ตายตัว แม้จะมี guardrails ที่ผ่านการ fine-tuned มาอย่างดี แต่การใช้สำนวนภาษาแบบใหม่ๆ ก็อาจเล็ดลอดไปได้ โดยเฉพาะอย่างยิ่งเมื่อผู้โจมตีสามารถทดลองซ้ำๆ ได้ไม่จำกัดโดยไม่มีต้นทุน Guardrails มีประโยชน์ในการลด noise แต่ไม่ควรเป็นปราการด่านเดียวในการป้องกัน
สิ่งที่ควรจับตามองต่อไป
- Frameworks ที่เปิดให้ใช้งาน tool scoping ในฐานะ first-class API – คาดหวังว่าจะได้เห็น library ใหม่ๆ ที่ช่วยให้คุณสามารถกำหนดความสามารถเฉพาะรายผู้ใช้ (per-user capabilities) และตัดรายการฟังก์ชันออกโดยอัตโนมัติก่อนที่จะมีการสร้าง prompt
- “function manifests” ที่เป็นมาตรฐาน – กลุ่มอุตสาหกรรมต่างๆ อาจกำหนด JSON schema ที่แยกฟังก์ชันสาธารณะและฟังก์ชันที่มีสิทธิ์พิเศษออกจากกัน ซึ่งจะช่วยให้การสร้าง manifest เฉพาะสำหรับแต่ละคำขอทำได้ง่ายขึ้น
- Runtime enforcement – บางแพลตฟอร์มกำลังทดลองใช้การประมวลผลแบบ sandboxed ที่ตรวจสอบ token ของผู้เรียกใช้งานเทียบกับฟังก์ชันที่กำลังถูกเรียกใช้ เพื่อเพิ่มการป้องกันอีกชั้นนอกเหนือจากการทำ prompt scoping
บทสรุปนั้นชัดเจน: ให้มองว่า prompt injection คือช่องโหว่ด้านการอนุญาตสิทธิ์ (authorization flaw) การนำเครื่องมือที่ไม่ได้รับอนุญาตออกจากชุดเครื่องมือของโมเดล จะช่วยกำจัดพื้นที่การโจมตี (attack surface) ที่ prompt ซึ่งใช้คำพูดอย่างชาญฉลาดพยายามจะเจาะเข้ามา Prompt สามารถช่วยชี้นำพฤติกรรมได้ แต่ไม่สามารถนำมาใช้แทนที่การควบคุมการเข้าถึง (access control) ที่เหมาะสมได้
