FlawDetector-LLM V1.0: การทดลองซ้ำ 1,000 ครั้ง และสิ่งที่ความแปรปรวนบอกเรา
การรายงานค่าเฉลี่ยเพียงตัวเดียวในเบนช์มาร์กโมเดลความปลอดภัย ในทางปฏิบัติคือการตลาด สิ่งที่ทีมต้องอยู่กับมันคือโค้ดชุดเดิมให้คำตอบวันศุกร์เหมือนวันจันทร์หรือไม่ สิ่งที่ V1.0 ให้เราจึงไม่ใช่ค่าเฉลี่ยที่สวย แต่เป็นแผนที่ว่าความแปรปรวนซ่อนอยู่ที่ใด
โดย ทีมวิศวกรรมความปลอดภัย FloatFactory
เอนจิน FlawDetector · งานวิจัย
ค่าเฉลี่ยตัวเดียวเปลี่ยนเบนช์มาร์กให้กลายเป็นการตลาด
เบนช์มาร์กของสแกนเนอร์ความปลอดภัยมักย่อลงเหลือสองตัวเลข คืออัตราตรวจพบและอัตราผลบวกลวง ทั้งคู่มักมาจากการรันครั้งเดียวหรือค่าเฉลี่ยของหลายครั้ง ประเด็นคือความเจ็บปวดที่ทีมเจอจริงมาจากความแปรปรวน ไม่ใช่ค่าเฉลี่ย
ถ้าข้อบกพร่องที่เป็นระดับวิกฤตในวันจันทร์หายไปในวันศุกร์ ไม่ว่าอัตราตรวจพบจะเป็น 94% หรือ 97% ทีมก็เลิกเชื่อผลลัพธ์ไปแล้ว ประสบการณ์ที่คำตัดสินเปลี่ยนทั้งที่โค้ดไม่เปลี่ยนเพียงครั้งเดียวก็เพียงพอ สิ่งแรกที่เราตัดสินใจในการออกแบบการทดลอง V1.0 จึงไม่ใช่ “จะดันค่าเฉลี่ยขึ้นอย่างไร” แต่เป็น “จะวัดอย่างไรว่าอินพุตเดียวกันให้คำตอบเดียวกัน”
การออกแบบการทดลอง: อะไรถูกทำซ้ำ 1,000 ครั้ง
หน่วยของการทำซ้ำคือคำตัดสินหนึ่งครั้งต่อหนึ่งตัวอย่าง ไม่ใช่การรันเบนช์มาร์กทั้งชุดหนึ่งรอบ เราตรึงคลังข้อมูล ตรึงพารามิเตอร์การสุ่ม แล้วป้อนอินพุตเดิมซ้ำ ๆ เพื่อวัดสัดส่วนที่คำตัดสินแตกต่างกัน คำตัดสินในที่นี้คือทูเพิลสามส่วน — มีข้อบกพร่องหรือไม่ ประเภท CWE และระดับความรุนแรง — หากส่วนใดส่วนหนึ่งต่างกันจะนับว่าไม่สอดคล้อง
| คลังข้อมูล | จำนวนตัวอย่าง | มีช่องโหว่ : ปกติ | บทบาท |
|---|---|---|---|
| ชุดที่ดัดแปลงจาก OWASP benchmark | 2,740 | 1 : 1.4 | เส้นฐานของอัตราตรวจพบและผลบวกลวง |
| รีโพที่จำลอง CVE สาธารณะ | 318 | 1 : 0 | ตรวจการเข้าถึงได้จริงในโค้ดเบสจริง |
| ชุดกลายพันธุ์สังเคราะห์ภายใน | 1,960 | 1 : 3.1 | ตรวจว่าเป็นการจำลายเซ็นหรือไม่ |
| กลุ่มควบคุมโค้ดปกติ | 5,400 | 0 : 1 | ใช้วัดอัตราผลบวกลวงโดยเฉพาะ |
ชุดสังเคราะห์คือการเขียนตัวอย่างที่มีช่องโหว่จากคลังสาธารณะขึ้นใหม่ด้วยชื่อ โครงสร้าง และเฟรมเวิร์กที่ต่างออกไป เพื่อกันไม่ให้การจำข้อมูลฝึกผ่านตัวเป็นการตรวจจับ
การทดลองซ้ำทำกับตัวอย่างที่สุ่มแบบแบ่งชั้นจำนวน 1,200 ราย โดยแต่ละรายทำซ้ำมากกว่า 1,000 ครั้ง รวมคำตัดสินกว่า 1.2 ล้านครั้ง เหตุผลของขนาดนี้ตรงไปตรงมา เมื่ออัตราความไม่สอดคล้องลดต่ำกว่า 1% การทำซ้ำ 100 ครั้งไม่สามารถแยกมันออกจากสัญญาณรบกวนในช่วงความเชื่อมั่นที่ใช้ประโยชน์ได้
ตัวเลขสรุปของ FlawDetector-LLM V1.0
94.7%
อัตราตรวจพบ
ตามชุด OWASP benchmark
3.2%
อัตราผลบวกลวง
หลังตัดซ้ำและจัดอันดับตามโอกาสถูกใช้โจมตี
99.1%
ความสม่ำเสมอของคำตัดสิน
อินพุตเดียวกัน ทำซ้ำกว่า 1,000 ครั้ง
41 วิ
มัธยฐานการสแกนทั้งรีโพ
p95 อยู่ที่ 1 นาที 58 วินาที
ตัวเลข 3.2% ไม่ใช่ค่าดิบ ผลรอบแรกจากเอนจินมีอัตราผลบวกลวง 5.8% แล้วการตัดซ้ำและการจัดอันดับตามการเข้าถึงได้จึงลดลงมาเหลือ 3.2% เราเปิดเผยทั้งสองค่าเพราะการให้เฉพาะค่าหลังการประมวลผลทำให้เปรียบเทียบไม่ได้
ความแปรปรวนอยู่ตรงไหน
ค่ารวม 99.1% ซ่อนการกระจายที่กว้างระหว่างตระกูลข้อบกพร่อง จุดที่น่าสนใจในตารางด้านล่างคืออัตราตรวจพบกับความสม่ำเสมอขยับไปด้วยกัน ตระกูลที่เราตรวจได้แย่ที่สุดก็คือตระกูลที่คำตัดสินสั่นมากที่สุด
| ตระกูลข้อบกพร่อง | อัตราตรวจพบ | ความสม่ำเสมอ | ลักษณะเด่น |
|---|---|---|---|
| Injection (CWE-89 / 78 / 94) | 97.2% | 99.6% | ตัดสินจบได้ภายในฟังก์ชันเดียว |
| การเข้ารหัสที่อ่อนแอ (CWE-327 / 330) | 96.1% | 99.4% | อิงค่าคงที่และลายเซ็นของ API |
| การข้ามการยืนยันตัวตน (CWE-287 / 862) | 93.8% | 98.2% | มิดเดิลแวร์กับแฮนด์เลอร์อยู่คนละไฟล์ |
| Path traversal และ SSRF (CWE-22 / 918) | 92.4% | 97.1% | ต้องตามฟังก์ชัน normalization ไปด้วย |
| การไหลของข้อมูลข้ามไฟล์ | 88.9% | 94.3% | ช่วงที่มีพื้นที่ปรับปรุงมากที่สุด |
รูปแบบชัดเจนมาก หลักฐานที่ต้องใช้ตัดสินอยู่ในชังก์เดียวกันหรือไม่ อธิบายเกือบทุกอย่าง ข้อบกพร่องกลุ่ม injection ประกอบสตริงคิวรีภายในฟังก์ชันเดียว โมเดลจึงเห็นหลักฐานชุดเดิมทุกครั้ง ส่วนข้อบกพร่องด้านสิทธิ์กระจายเราเตอร์ มิดเดิลแวร์ และแฮนด์เลอร์ไว้คนละไฟล์ สิ่งที่โมเดลเห็นจึงขึ้นกับว่าขอบชังก์ตกลงตรงไหน
ทำไมจึงสั่น
เราสุ่มกรณีไม่สอดคล้องราวหนึ่งหมื่นกรณีมาจำแนกสาเหตุ สามข้ออธิบายได้เกือบทั้งหมด
- ขอบของชังก์ (54%) — ตรรกะตรวจสอบกับจุดใช้งานถูกตัดแยกไปคนละชังก์ โมเดลจึงตัดสินจากครึ่งที่ตัวเองเห็น และครึ่งไหนที่เห็นก็ขยับเล็กน้อยในแต่ละรอบ
- การตัดบริบท (29%) — ในไฟล์ขนาดใหญ่ ส่วน import และการตั้งค่าด้านบนถูกตัดทิ้ง โมเดลจึงไม่รู้ว่าไลบรารีใดมีการป้องกันมาให้แล้ว ผลบวกลวงแบบ “ORM ผูกพารามิเตอร์ให้อยู่แล้วแต่ถูกมองว่าเป็น raw SQL” เกิดขึ้นตรงนี้
- ความไวต่อลำดับ (13%) — ชุดชังก์เดียวกันแต่ลำดับการนำเสนอต่างกันทำให้คำตัดสินพลิก โดยมักปรากฏเป็นระดับความรุนแรงขยับขึ้นลงหนึ่งขั้น
เราเปลี่ยนอะไรบ้าง
สามการเปลี่ยนแปลง ใช้ตามลำดับ และรันโปรโตคอลการทดลองซ้ำใหม่หลังแต่ละขั้น
- 01
Anchored chunking — จัดขอบให้ตรงกับโครงสร้างโค้ด
แทนที่จะตัดตามจำนวนโทเคนคงที่ เราใช้นิยามของฟังก์ชัน คลาส และเราต์เป็นจุดยึด แล้วบังคับให้นิยามของสัญลักษณ์ที่ถูกอ้างถึงอยู่ในชังก์เดียวกัน ขนาดชังก์กลายเป็นแบบผันแปร แต่หลักฐานไม่ถูกผ่าครึ่งอีกต่อไป ความสม่ำเสมอ 96.4% → 98.0%
- 02
Symbol-graph prepass — วาดแผนที่ก่อนอ่าน
ก่อนเรียก LLM เราให้ตัวแยกวิเคราะห์แบบสถิตสร้างกราฟการเรียกและบทสรุปการไหลของข้อมูล แล้วแนบเป็นส่วนหัวของแต่ละชังก์ โมเดลจึงรู้เสมอว่าฟังก์ชันนี้ถูกเรียกจากสามที่และสองในนั้นเป็นจุดเข้าจากภายนอก ความสม่ำเสมอ 98.0% → 98.7%
- 03
โหวตสามครั้ง — ดูดซับการสั่นที่เหลือ
เฉพาะรายการที่มีแนวโน้มความรุนแรงสูงขึ้นไป เราสลับลำดับการนำเสนอชังก์แล้วตัดสินสามครั้งและถือเสียงข้างมาก เนื่องจากจำกัดขอบเขตไว้ที่รายการเหล่านั้น เวลารวมจึงเพิ่มเพียง 9% ความสม่ำเสมอ 98.7% → 99.1%
ผลบวกลวงลดลงเป็นผลพลอยได้ เมื่อ prepass ทำให้การป้องกันที่มากับเฟรมเวิร์กมองเห็นได้ ผลบวกลวงต่อโค้ดที่ใช้ ORM เทมเพลตเอนจิน และมิดเดิลแวร์ตรวจสอบก็ลดลงอย่างเห็นได้ชัด จาก 5.8% เหลือ 4.1% ในผลรอบแรก และ 3.2% หลังการประมวลผลเพิ่มเติม
คอขวดที่เหลือ และ V1.1
ความสม่ำเสมอถูกซื้อมาด้วยเวลาแฝง การเพิ่ม prepass เปลี่ยนรูปร่างของการสแกนไป
| ขั้นตอน | สัดส่วน | เป้าหมาย V1.1 |
|---|---|---|
| Symbol-graph prepass | 27% | ลด 90% เมื่อสแกนซ้ำด้วยแคชแบบเพิ่มหน่วย |
| การอนุมานของ LLM | 61% | ลด 40% ด้วยการรวมชังก์เป็นแบตช์และการหยุดก่อนกำหนด |
| การจัดอันดับและสร้างรายงาน | 12% | ไม่เปลี่ยนแปลง |
เป้าหมายปริมาณงาน 2.4 เท่าของ V1.1 คือผลรวมของการปรับปรุงสองรายการข้างต้น
ผลของ prepass จะไม่เปลี่ยนหากไฟล์ไม่เปลี่ยน มันจึงเป็นการคำนวณที่แคชได้ แต่ V1.0 กลับทำใหม่ทุกครั้ง แคชแบบเพิ่มหน่วยจึงเป็นการปรับปรุงที่แน่นอนที่สุดใน V1.1 และยิ่งสแกนซ้ำบ่อยเท่าไรผลตอบแทนยิ่งมาก สภาพแวดล้อม CI จึงได้ประโยชน์มากที่สุด
ห้าคำถามสำหรับอ่านเบนช์มาร์กความปลอดภัย
ใช้กับตัวเลขของเราเองได้เท่ากับของคนอื่น ห้าคำถามนี้กรองการกล่าวเกินจริงออกไปได้เกือบหมด
- มีผลการทดลองซ้ำหรือไม่ ถ้ามีแค่การรันครั้งเดียว ความสามารถในการทำซ้ำของตัวเลขนั้นไม่มีใครรู้
- อัตราผลบวกลวงเป็นค่าก่อนหรือหลังการประมวลผล การเปิดเผยเฉพาะค่าหลังจัดอันดับเป็นธรรมเนียม แต่การเปรียบเทียบต้องใช้ค่าดิบ
- กลุ่มควบคุมโค้ดปกติใหญ่แค่ไหน ตัวอย่างที่มีช่องโหว่อย่างเดียววัดอัตราผลบวกลวงไม่ได้
- มีชุดกลายพันธุ์สังเคราะห์รวมอยู่ด้วยหรือไม่ ใช้คลังสาธารณะอย่างเดียวแยกการจำกับการตรวจจับจริงไม่ออก
- มีการแยกค่าตามตระกูลข้อบกพร่องหรือไม่ ค่าเฉลี่ยรวมค่าเดียวปิดบังว่าตระกูลไหนอ่อนแอ
สรุป
ผลลัพธ์ที่ใช้ประโยชน์ได้มากที่สุดจากการทดลอง V1.0 คือการวินิจฉัย ไม่ใช่สมรรถนะ ที่ใดความแปรปรวนกระจุกตัว ที่นั่นคืองานของเวอร์ชันถัดไป และการหาตำแหน่งนั้นต้องใช้ตัวเลขที่แยกย่อยแทนค่าเฉลี่ย เราใช้คำตัดสิน 1.2 ล้านครั้งไม่ใช่เพื่อให้ได้ตัวเลขสวย แต่เพื่อรู้ว่าควรเล็งไปที่ใด
ทุกรายการถูกจัดการเป็นเอกสารเกณฑ์การทดสอบภายใน และรายงานฉบับเต็มซึ่งรวมองค์ประกอบคลังข้อมูลและโปรโตคอลการทำซ้ำ สามารถขอรับได้
คำถามที่พบบ่อย
- ความสม่ำเสมอของคำตัดสิน 99.1% หมายถึงอะไรกันแน่
- หมายถึงสัดส่วนของการทำซ้ำที่อินพุตเดิมซึ่งไม่มีการเปลี่ยนโค้ดเลยให้คำตัดสินตรงกันครบทั้งสามส่วน คือมีข้อบกพร่องหรือไม่ ประเภท CWE และระดับความรุนแรง โดยทำซ้ำมากกว่า 1,000 ครั้งต่อหนึ่งตัวอย่าง หากส่วนใดต่างกันจะนับว่าไม่สอดคล้อง
- อัตราตรวจพบ 94.7% อิงคลังข้อมูลใด
- อิงชุดที่ดัดแปลงจาก OWASP benchmark จำนวน 2,740 ตัวอย่าง นอกจากนี้ยังรันรีโพที่จำลอง CVE สาธารณะและชุดกลายพันธุ์สังเคราะห์ภายในแยกต่างหาก เพื่อแยกการจำข้อมูลฝึกออกจากการตรวจจับจริง
- ทำไมความสม่ำเสมอของการไหลของข้อมูลข้ามไฟล์จึงต่ำกว่า
- เพราะหลักฐานที่ต้องใช้ตัดสินกระจายอยู่หลายไฟล์ สิ่งที่โมเดลเห็นจึงขึ้นกับตำแหน่งขอบของชังก์ Anchored chunking และ symbol-graph prepass ยกตระกูลนี้ขึ้นมาที่ 94.3% และยังเป็นเป้าหมายลำดับต้นของ V1.1
- มีการเปรียบเทียบตรง ๆ กับสแกนเนอร์อื่นหรือไม่
- การเปรียบเทียบตรงบนคลังสาธารณะไม่น่าเชื่อถือ เพราะแต่ละเครื่องมือมีนโยบายการประมวลผลก่อนและการจัดอันดับต่างกัน เราจึงเปิดเผยองค์ประกอบคลังข้อมูลและโปรโตคอลการทำซ้ำแทน เพื่อให้ทำซ้ำผลได้ในเงื่อนไขที่ตรงกัน
อ่านต่อ
บทความทั้งหมดลูปแพตช์เชิงปฏิปักษ์ตัดสินอย่างไรว่าช่องโหว่ถูกปิดผนึกจริง
ลูปแพตช์เชิงปฏิปักษ์ใช้ด่านสามชั้น — เอ็กซ์พลอยต์ต้นฉบับ การกลายพันธุ์ 12 รายการ และการถดถอย — ตัดสินว่าช่องโหว่ถูกปิดผนึกอย่างไร
ผลบวกลวงเป็นปัญหาเชิงวัฒนธรรมก่อนจะเป็นปัญหาของโมเดล
ผลบวกลวง 3.2% คือ 138 รายการต่อสัปดาห์บนโค้ด 2 ล้านบรรทัด แยกสี่สถานการณ์ที่เรียกรวมว่าผลบวกลวง แล้วใช้กฎการระงับที่มีวันหมดอายุ