เครื่องฆ่าเชื้อรหัส
เครื่องมือ ตรวจสอบโค้ด (code sanitizer)เป็นเครื่องมือการเขียนโปรแกรมที่ตรวจจับข้อบกพร่องในรูปแบบของพฤติกรรมที่ไม่กำหนดหรือน่าสงสัยโดยคอมไพเลอร์ โดยการ แทรกโค้ดตรวจสอบในระหว่างการทำงานเครื่องมือตรวจ สอบโค้ดได้รับการพัฒนามาหลายทศวรรษเพื่อตรวจจับข้อผิดพลาดของหน่วยความจำในภาษาการเขียนโปรแกรมที่ไม่ปลอดภัย [ 1 ]เริ่มต้นด้วยการตรวจสอบการเข้าถึงพอยเตอร์และอาร์เรย์ในยุคแรกในปี 1994 [ 2 ]และการปรับปรุงให้ปลอดภัยต่อประเภทข้อมูลในปี 2005 [ 3 ]ตามมาด้วยการขยายตัวอย่างมากไปสู่ เครื่องมือ ความปลอดภัยของหน่วยความจำ เชิงพื้นที่และเวลาที่ซับซ้อน ระหว่างปี 2009 ถึง 2019 [ 4 ] [ 5 ] [ 6 ] [ 7 ] [ 8 ] [ 9 ] [ 10 ]ณ ปี 2024 เครื่องมือตรวจสอบโค้ดที่ได้รับความนิยมมากที่สุดคือ ASan ซึ่งเดิมทีออกแบบโดยGoogleมันถูกรวมเข้ากับคอมไพเลอร์หลักส่วนใหญ่เนื่องจากมีค่าใช้จ่ายด้านหน่วยความจำและประสิทธิภาพค่อนข้างน้อย[ 1 ]
เครื่องฆ่าเชื้อที่อยู่
ASan ของ Google ซึ่งเปิดตัวในปี 2012 ใช้ ระบบ หน่วยความจำเงาในการตรวจจับข้อผิดพลาดด้านหน่วยความจำ มีให้บริการในภาษาต่างๆ ดังนี้:
- Clang (เริ่มต้นจากเวอร์ชัน 3.1 [ 11 ] )
- GCC (เริ่มต้นจากเวอร์ชัน 4.8 [ 12 ] )
- Xcode (เริ่มตั้งแต่เวอร์ชัน 7.0 [ 13 ] )
- MSVC (มีให้ใช้งานอย่างแพร่หลายตั้งแต่เวอร์ชัน 16.9 [ 14 ] )
การออกแบบดั้งเดิมของเครื่องฆ่าเชื้อทำให้เวลาในการประมวลผลเพิ่มขึ้นประมาณ 73% และการใช้หน่วยความจำเพิ่มขึ้น 240% [ 15 ]มี ASan ที่เร่งความเร็วด้วยฮาร์ดแวร์ที่เรียกว่า HWAsan ซึ่งใช้งานได้สำหรับ AArch64 และ (ในขอบเขตจำกัด) x86_64 [ 16 ]
AddressSanitizer ไม่ตรวจจับการอ่านหน่วยความจำที่ไม่ได้เริ่มต้น (แต่MemorySanitizer [ 17 ] ตรวจจับได้ ) และตรวจจับเฉพาะข้อบกพร่องการใช้งานหลังจากส่งคืนบางส่วนเท่านั้น[ 18 ]นอกจากนี้ยังไม่สามารถตรวจจับข้อบกพร่องการเสียหายของหน่วยความจำแบบสุ่มทั้งหมด หรือข้อบกพร่องการเขียนแบบสุ่มทั้งหมดเนื่องจากค่าจำนวนเต็มต่ำกว่า/สูงกว่าค่าที่กำหนด (เมื่อใช้จำนวนเต็มที่มีพฤติกรรมที่ไม่กำหนดในการคำนวณ ค่าชดเชย ที่อยู่หน่วยความจำ ) บัฟเฟอร์ที่อยู่ติดกันในโครงสร้างและคลาสไม่ได้รับการป้องกันจากค่าล้น ส่วนหนึ่งเพื่อป้องกันการทำลายความเข้ากันได้แบบย้อนหลัง[ 19 ]
KernelAddressSanitizer
KernelAddressSanitizer ( KASan ) ตรวจจับข้อผิดพลาดของหน่วยความจำแบบไดนามิกในเคอร์เนล Linux [ 20 ]การตรวจสอบเคอร์เนลต้องใช้คุณสมบัติพิเศษในคอมไพเลอร์ที่ให้ตัวเลือกบรรทัดคำสั่ง เนื่องจากเคอร์เนลไม่ได้ใช้พื้นที่แอดเดรสเดียวกันกับโปรแกรมปกติ[ 21 ] [ 22 ]-fsanitize=kernel-address
KASan ยังสามารถใช้ได้กับไดรเวอร์เคอร์เนลของ Windows ตั้งแต่ Windows 11 22H2 ขึ้นไป[ 23 ]เช่นเดียวกับ Linux การคอมไพล์ไดรเวอร์ Windows ด้วย KASAN จำเป็นต้องส่ง/fsanitize=kernel-addressตัวเลือกบรรทัดคำสั่งไปยังคอมไพเลอร์ MSVC
ผลิตภัณฑ์ฆ่าเชื้ออื่นๆ
Google ยังได้สร้างLeakSanitizer (LSan, การรั่วไหลของหน่วยความจำ ), ThreadSanitizer (TSan, การแข่งขันข้อมูลและการล็อกตาย ), MemorySanitizer (MSan, หน่วยความจำที่ไม่ได้เริ่มต้น ) และUndefinedBehaviorSanitizer ( UBSan , พฤติกรรมที่ไม่กำหนดพร้อมการควบคุมแบบละเอียด) [ 24 ]เครื่องมือเหล่านี้โดยทั่วไปมีให้ใช้งานใน Clang/LLVM และ GCC [ 25 ] [ 26 ] [ 27 ]เช่นเดียวกับ KASan มีเวอร์ชันเฉพาะเคอร์เนลของ LSan, MSan, TSan รวมถึงเครื่องมือตรวจสอบเคอร์เนลดั้งเดิมทั้งหมด เช่น KFENCE และ KCSan [ 28 ]
เครื่องมือฆ่าเชื้อเพิ่มเติม (จัดกลุ่มตามคอมไพเลอร์ภายใต้-fsanitizeหรือแฟล็กที่คล้ายกัน) ได้แก่: [ 25 ] [ 26 ] [ 27 ]
- ความสมบูรณ์ของการควบคุมการไหลของ LLVM และส่วนที่เทียบเท่าในเคอร์เนล ซึ่งตรวจสอบตารางเสมือนและการแปลงประเภทสำหรับ CFI ขอบหน้า
- MemTagSanitizer เป็นเครื่องมือคล้าย ASan ที่ใช้คุณสมบัติของ Armv8.5-A เพื่อลดภาระการทำงานให้เหลือน้อยที่สุด
- ShadowCallStack เป็นเครื่องมือ AArch64 ที่ช่วยป้องกันShadow Stack
- Scudo Hardened Allocator ซึ่งเป็นตัวจัดสรรหน่วยความจำทางเลือกที่รวม GWP-ASan ซึ่งเป็นอะนาล็อก ASan แบบความน่าจะเป็นที่มีค่าใช้จ่ายต่ำ[ 29 ]
- libFuzzer ซึ่งเป็นเครื่องมือ LLVM ที่เพิ่มการครอบคลุมโค้ดให้กับการทดสอบแบบฟัซซิ่ง[ 30 ]
การใช้งาน
ตัวตรวจสอบโค้ดจะตรวจจับพฤติกรรมที่น่าสงสัยขณะที่โปรแกรมทำงาน วิธีทั่วไปในการใช้ตัวตรวจสอบโค้ดคือการรวมเข้ากับการทดสอบแบบฟัซซิ่งซึ่งสร้างอินพุตที่น่าจะทำให้เกิดข้อผิดพลาด[ 31 ]
ผู้ใช้
นักพัฒนา ChromiumและFirefoxเป็นผู้ใช้ AddressSanitizer อย่างแข็งขัน[ 31 ] [ 32 ]เครื่องมือนี้พบข้อบกพร่องหลายร้อยรายการในเว็บเบราว์เซอร์เหล่านี้[ 33 ]พบข้อบกพร่องจำนวนหนึ่งในFFmpeg [ 34 ]และFreeType [ 35 ]เคอร์เนลLinuxได้เปิดใช้งาน AddressSanitizer สำหรับสถาปัตยกรรม x86-64ตั้งแต่ Linux เวอร์ชัน 4.0
ตัวอย่าง
ASan: การใช้ฮีปหลังจากปล่อยหน่วยความจำ
// ในการคอมไพล์: g++ -O -g -fsanitize=address heap-use-after-free.ccint main ( int argc , char ** argv ) {int * array = new int [ 100 ];ลบอาร์เรย์[] ;ส่งคืนอาร์เรย์[ argc ]; // BOOM}$ ./a.out ==5587==ข้อผิดพลาด: AddressSanitizer: heap-use-after-free บนที่อยู่ 0x61400000fe44 ที่ pc 0x47b55f bp 0x7ffc36b28200 sp 0x7ffc36b281f8 อ่านขนาด 4 ที่ 0x61400000fe44 เกลียว T0 #0 0x47b55e ใน main /home/test/example_UseAfterFree.cc:5 #1 0x7f15cfe71b14 ใน __libc_start_main (/lib64/libc.so.6+0x21b14) #2 0x47b44c ใน _start (/root/a.out+0x47b44c) 0x61400000fe44 อยู่ห่างจากจุดเริ่มต้น 4 ไบต์ ในพื้นที่ 400 ไบต์ [0x61400000fe40,0x61400000ffd0) ปลดปล่อยโดยเธรด T0 ที่นี่: #0 0x465da9 ในโอเปอเรเตอร์ delete[](void*) (/root/a.out+0x465da9) #1 0x47b529 ใน main /home/test/example_UseAfterFree.cc:4 ก่อนหน้านี้ได้จัดสรรให้กับเธรด T0 ไว้ที่นี่แล้ว: #0 0x465aa9 ในโอเปอเรเตอร์ new[](unsigned long) (/root/a.out+0x465aa9) #1 0x47b51e ใน main /home/test/example_UseAfterFree.cc:3 สรุป: AddressSanitizer: heap-use-after-free /home/test/example_UseAfterFree.cc:5 main ไบต์เงาที่อยู่รอบๆ แอดเดรสที่มีข้อผิดพลาด: [...] 0x0c287fff9fb0: ฟ้า ฟ้า ฟ้า ฟ้า ฟ้า ฟ้า ฟ้า ฟ้า ฟา ฟา ฟ้า =>0x0c287fff9fc0: fa fa fa fa fa fa fa fa[fd]fd fd fd fd fd fd fd 0x0c287fff9fd0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd [...] คำอธิบายไบต์เงา (หนึ่งไบต์เงาแทน 8 ไบต์ของแอปพลิเคชัน): ที่อยู่: 00 สามารถระบุที่อยู่ได้บางส่วน: 01 02 03 04 05 06 07 กองหลังเหลือเขตแดง: fa กองแดงขวา: เฟซบุ๊ก พื้นที่หน่วยความจำว่าง: fd โซนสีแดงด้านซ้าย: f1 กองกลางเรดโซน: f2 โซนสีแดงด้านขวา: f3 สแต็คโซนสีแดงบางส่วน: f4 สแต็กหลังจากส่งคืน: f5 การใช้งาน Stack หลังขอบเขต: f8 เขตอันตรายทั่วโลก: f9 ลำดับการเริ่มต้นทั่วโลก: f6 ถูกวางยาพิษโดยผู้ใช้: f7 ภายใน ASan: fe ==5587==การทำแท้ง
ASan: บัฟเฟอร์ฮีปล้น
// เรียกใช้: clang++ -O -g -fsanitize=address heap-buf-of.cc && ./a.outint main ( int argc , char ** argv ) {int * array = new int [ 100 ];อาร์เรย์[ 0 ] = 0 ;int res = array [ argc + 100 ]; // BOOMลบอาร์เรย์[] ;ส่งคืนres ;}==25372==ข้อผิดพลาด: AddressSanitizer: heap-buffer-overflow ที่แอดเดรส 0x61400000ffd4 ที่ pc 0x0000004ddb59 bp 0x7fffea6005a0 sp 0x7fffea600598 อ่านขนาด 4 ที่ 0x61400000ffd4 เธรด T0 #0 0x46bfee ใน main /tmp/main.cpp:4:13 0x61400000ffd4 อยู่ห่างจากบริเวณ 400 ไบต์ [0x61400000fe40,0x61400000ffd0] ไปทางขวา 4 ไบต์ จัดสรรโดยเธรด T0 ที่นี่: #0 0x4536e1 ในโอเปอเรเตอร์ delete[](void*) #1 0x46bfb9 ใน main /tmp/main.cpp:2:16
ASan: Stack-buffer-overflow
// เรียกใช้คำสั่ง: clang -O -g -fsanitize=address stack-buf-of.cc && ./a.outint main ( int argc , char ** argv ) {int stack_array [ 100 ];stack_array [ 1 ] = 0 ;return stack_array [ argc + 100 ]; // BOOM}==7405==ข้อผิดพลาด: AddressSanitizer: stack-buffer-overflow ที่แอดเดรส 0x7fff64740634 ที่ pc 0x46c103 bp 0x7fff64740470 sp 0x7fff64740468 อ่านขนาด 4 ที่ 0x7fff64740634 เกลียว T0 #0 0x46c102 ใน main /tmp/example_StackOutOfBounds.cc:5 ตำแหน่งแอดเดรส 0x7fff64740634 อยู่ในสแต็กของเธรด T0 ที่ออฟเซ็ต 436 ในเฟรม #0 0x46bfaf ใน main /tmp/example_StackOutOfBounds.cc:2 เฟรมนี้มีวัตถุ 1 ชิ้น: [32, 432) 'stack_array' <== การเข้าถึงหน่วยความจำที่ออฟเซ็ต 436 ทำให้ตัวแปรนี้ล้น
ASan: บัฟเฟอร์ล้นทั่วโลก
// RUN: clang -O -g -fsanitize=address global-buf-of.cc && ./a.out int global_array [ 100 ] = { -1 }; int main ( int argc , char ** argv ) { return global_array [ argc + 100 ]; // BOOM }==7455==ข้อผิดพลาด: AddressSanitizer: global-buffer-overflow ที่แอดเดรส 0x000000689b54 ที่ pc 0x46bfd8 bp 0x7fff515e5ba0 sp 0x7fff515e5b98 อ่านขนาด 4 ที่ 0x000000689b54 เธรด T0 #0 0x46bfd7 ใน main /tmp/example_GlobalOutOfBounds.cc:4 0x000000689b54 อยู่ห่างจากตำแหน่งเดิมไปทางขวา 4 ไบต์ ตัวแปรส่วนกลาง 'global_array' จาก 'example_GlobalOutOfBounds.cc' (0x6899c0) ขนาด 400
UBSan: nullptr-dereference
// รัน: g++ -O -g -fsanitize=null null-dereference.c && ./a.out int main ( int argc , char ** argv ) { const char * ptr = nullptr ; return * ptr ; // เกิดข้อผิดพลาด}null-dereference.c:4:10: ข้อผิดพลาดขณะรันไทม์: การโหลดพอยเตอร์ว่างของชนิด 'const char' ข้อผิดพลาดในการเข้าถึงหน่วยความจำ (core dumped)
ดูเพิ่มเติม
- อินเทล เอ็มพีเอ็กซ์
- โปรแกรมตรวจสอบแอปพลิเคชัน (AppVerif.exe) ในMicrosoft Windows SDK
- Valgrindเครื่องมือตรวจสอบข้อผิดพลาดของหน่วยความจำ
แหล่งที่มา
- Cho, Kyuwon; Kim, Jongyoon; Duy, Kha Dinh; Lim, Hajeong; Lee, Hojoon (สิงหาคม 2024). "RustSan: การปรับปรุง AddressSanitizer เพื่อการกำจัด Rust อย่างมีประสิทธิภาพ" . รายงานการประชุม USENIX Security Symposium ครั้งที่ 33 . ฟิลาเดลเฟีย, PA, สหรัฐอเมริกา: USENIX Association. หน้า3729–3746 . ISBN 978-1-939133-44-1.
- Austin, Todd M.; Breach, Scott E.; Sohi, Gurindar S. (มิถุนายน 1994). "การตรวจจับข้อผิดพลาดในการเข้าถึงพอยเตอร์และอาร์เรย์ทั้งหมดอย่างมีประสิทธิภาพ" . SIGPLAN Not . 29 (6): 290– 301.
- Necula, George C.; Condit, Jeremy; Harren, Matthew; McPeak, Scott; Weimer, Westley (พฤษภาคม 2548). "Ccured: การปรับปรุงซอฟต์แวร์เดิมให้ปลอดภัยด้วยประเภทข้อมูล" (PDF) . ACM Trans. Program. Lang. Syst . 27 (3): 477– 526.
- Nagarakatte, Santosh; Zhao, Jianzhou; Martin, Milo MK; Zdancewic, Steve (2009). "Softbound: ความปลอดภัยของหน่วยความจำเชิงพื้นที่ที่เข้ากันได้สูงและสมบูรณ์แบบสำหรับภาษา C" (PDF) . รายงานการประชุม ACM SIGPLAN ครั้งที่ 30 ว่าด้วยการออกแบบและการใช้งานภาษาโปรแกรม . หน้า245– 258.
- Serebryany, Konstantin; Bruening, Derek; Potapenko, Alexander; Vyukov, Dmitriy (2012). "AddressSanitizer: โปรแกรมตรวจสอบความถูกต้องของที่อยู่เว็บอย่างรวดเร็ว" . การประชุมทางเทคนิคประจำปี USENIX ปี 2012 . หน้า309– 318.
- Lee, Byoungyoung; Song, Chengyu; Jang, Yeongjin; Wang, Tielei (2015). "การป้องกันการใช้หน่วยความจำหลังจากถูกปล่อยด้วยตัวชี้ที่ค้างอยู่" . NDSS .
- Stepanov, Evgeniy; Serebryany, Konstantin (2015). "Memorysanitizer: ตัวตรวจจับการใช้งานหน่วยความจำที่ไม่ได้เริ่มต้นอย่างรวดเร็วใน C++" . การประชุมวิชาการนานาชาติ IEEE/ACM ว่าด้วยการสร้างโค้ดและการเพิ่มประสิทธิภาพ ปี 2015 . หน้า46– 55.
- Younan, Yves (2015). "Freesentry: การป้องกันช่องโหว่การใช้งานหลังจากปล่อยหน่วยความจำเนื่องจากพอยเตอร์ที่ค้างอยู่" . การประชุมวิชาการด้านความปลอดภัยเครือข่ายและระบบกระจายประจำปีครั้งที่ 22 .
- van der Kouwe, Erik; Nigade, Vinod; Giuffrida, Cristiano (2017). "Dangsan: การตรวจจับการใช้งานหลังจากถูกปล่อยที่ปรับขนาดได้" . รายงานการประชุม European Conference on Computer Systems ครั้งที่สิบสอง . หน้า405– 419.
- Song, Dokyung; Lettner, Julian; Rajasekaran, Prabhu; Na, Yeoul (2019). "Sok: การทำให้ข้อมูลสะอาดเพื่อความปลอดภัย" (PDF) . การประชุมวิชาการ IEEE ว่าด้วยความปลอดภัยและความเป็นส่วนตัว ปี 2019.หน้า1275–1295 .
ลิงก์ภายนอก
- กลุ่ม Google AddressSanitizer (ไม่ใช่รายชื่อผู้รับจดหมาย)
- หน้าโครงการ AddressSanitizer
- เอกสารประกอบการใช้งาน AddressSanitizer (Clang)