มีวิธีใดที่จะวางโค้ดที่เป็นอันตรายลงในนิพจน์ทั่วไปหรือไม่


138

ฉันต้องการเพิ่มความสามารถในการค้นหานิพจน์ปกติให้กับหน้าเว็บสาธารณะของฉัน นอกจากการเข้ารหัสHTMLแล้วฉันต้องทำอะไรเพื่อป้องกันการป้อนข้อมูลของผู้ใช้ที่เป็นอันตรายหรือไม่?

การค้นหาของ Google เต็มไปด้วยผู้ที่แก้ไขปัญหาสนทนา - ใช้นิพจน์ทั่วไปเพื่อตรวจหาอินพุตที่เป็นอันตรายซึ่งฉันไม่สนใจในสถานการณ์ของฉันอินพุตของผู้ใช้เป็นนิพจน์ทั่วไป

ฉันจะใช้ห้องสมุดRegexใน. NET (C #)


4
สิ่งนี้อาจขึ้นอยู่กับว่าคุณใช้ภาษาใดและ / หรือไลบรารี regex ใด
aschepler

เนื้อหาการอ่านเพิ่มเติม: ReDoS บน OWASP , ReDoS บน Wikipedia
joeytwiddle

คำตอบ:


216

การปฏิเสธ ‐ ของ ‐ ข้อกังวลเกี่ยวกับการบริการ

ข้อกังวลที่พบบ่อยที่สุดกับ regexes คือการปฏิเสธการโจมตีบริการผ่านรูปแบบทางพยาธิวิทยาที่ไปชี้แจง - หรือแม้แต่ทวีคูณสุดยอด! - และดูเหมือนว่าจะใช้เวลาตลอดไปเพื่อแก้ปัญหา สิ่งเหล่านี้อาจปรากฏเฉพาะกับข้อมูลที่ป้อนโดยเฉพาะ แต่อย่างใดอย่างหนึ่งสามารถสร้างข้อมูลที่มันไม่สำคัญ

สิ่งเหล่านี้จะขึ้นอยู่กับว่าคอมไพเลอร์ regex ที่คุณใช้นั้นฉลาดแค่ไหนเพราะสิ่งเหล่านี้สามารถตรวจพบได้ในระหว่างการรวบรวม คอมไพเลอร์ Regex ที่ใช้การเรียกซ้ำมักจะมีตัวนับซ้ำในตัวสำหรับการตรวจสอบความก้าวหน้า

กระดาษที่ยอดเยี่ยมของ Russ Cox ในการจับคู่นิพจน์ปกติทำได้ง่ายและรวดเร็ว (แต่ช้าใน Java, Perl, PHP, Python, Ruby, ... )พูดถึงวิธีที่ NFAs ที่ทันสมัยที่สุดซึ่งทั้งหมดดูเหมือนว่าจะได้มาจากรหัสของ Henry Spencer ประสบกับการเสื่อมประสิทธิภาพอย่างรุนแรง แต่ที่ NFA สไตล์ Thompson ไม่มีปัญหาดังกล่าว

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

ด้วย DFA คุณจะใช้เวลาในการสร้างมันมากขึ้น (และจัดสรรสถานะมากขึ้น) ในขณะที่ NFA นั้นคุณใช้เวลาในการดำเนินการมากขึ้นเนื่องจากอาจมีหลายสถานะในเวลาเดียวกันและการย้อนรอยสามารถกินอาหารกลางวัน - และ CPU ของคุณ

ปฏิเสธ ‐ ของ ‐ บริการโซลูชั่น

อาจเป็นวิธีที่เหมาะสมที่สุดในการกล่าวถึงรูปแบบเหล่านี้ซึ่งอยู่บนจุดจบของการแข่งขันที่สูญเสียความร้อนของเอกภพคือการห่อพวกมันด้วยเครื่องจับเวลาที่ให้เวลาสูงสุดในการดำเนินการ โดยทั่วไปแล้วสิ่งนี้จะมากน้อยกว่าการหมดเวลาเริ่มต้นที่เซิร์ฟเวอร์ HTTP ส่วนใหญ่มีให้

มีหลายวิธีที่จะใช้สิ่งเหล่านี้ตั้งแต่รูปแบบเรียบง่ายalarm(N)ที่ระดับ C ไปจนถึงtry {}บล็อกข้อยกเว้นประเภทสัญญาณเตือนภัยที่จับได้ทุกวิธีที่จะวางไข่เธรดใหม่ที่สร้างขึ้นเป็นพิเศษด้วยข้อ จำกัด ด้านเวลาในตัว

รหัสคำบรรยายภาพ

ในภาษา regex ที่ยอมรับไฮไลต์รหัสกลไกบางอย่างสำหรับการอนุญาตหรือไม่อนุญาตเหล่านี้จากสตริงที่คุณกำลังจะรวบรวมควรจะให้ แม้ว่าคำบรรยายภาพรหัสเป็นเพียงรหัสในภาษาที่คุณใช้คุณควร จำกัด พวกเขา; พวกเขาไม่จำเป็นต้องสามารถเรียกรหัสภายนอกแม้ว่าจะทำได้คุณก็มีปัญหาที่ใหญ่กว่ามาก

ตัวอย่างเช่นใน Perl หนึ่งไม่สามารถมีคำบรรยายภาพรหัสใน regexes สร้างขึ้นจากการแก้ไขสตริง (เช่นนี้จะเป็นเพราะพวกเขาจะรวบรวมในช่วงเวลาทำงาน) เว้นแต่ว่า pragma ศัพท์ขอบเขตพิเศษuse re "eval";ในการใช้งานในขอบเขตปัจจุบัน

ด้วยวิธีนี้ไม่มีใครสามารถแอบเข้าไปในรหัสไฮไลต์เพื่อเรียกใช้โปรแกรมระบบrm -rf *เช่น เนื่องจากรหัสเสริมความปลอดภัยนั้นไวต่อความปลอดภัย Perl จึงปิดใช้งานพวกเขาตามค่าเริ่มต้นในสตริงที่สอดแทรกทั้งหมดและคุณต้องออกจากทางของคุณเพื่อเปิดใช้งานอีกครั้ง

ผู้ใช้ ‐ กำหนด \ P {roperties}

เช่น - มีประเด็นที่ละเอียดอ่อนการรักษาความปลอดภัยอีกหนึ่งที่เกี่ยวข้องกับคุณสมบัติ Unicode สไตล์ยังคง\pM, \p{Pd}, \p{Pattern_Syntax}หรือ\p{Script=Greek}- ที่อาจมีอยู่ในคอมไพเลอร์ regex บางอย่างที่สนับสนุนว่าสัญกรณ์

ปัญหาคือในบางสิ่งเหล่านี้ชุดของคุณสมบัติที่เป็นไปได้นั้นสามารถขยายได้โดยผู้ใช้ นั่นหมายความว่าคุณสามารถมีคุณสมบัติแบบกำหนดเองที่มีไฮไลต์รหัสจริงฟังก์ชั่นที่มีชื่อใน namepace โดยเฉพาะอย่างยิ่งบางอย่างเช่นหรือ\p{GoodChars} \p{Class::Good_Characters}ภาษาของคุณจัดการกับสิ่งเหล่านั้นได้อย่างไรควรดู

sandboxing

ใน Perl ช่องแซนด์บ็อกซ์ผ่านSafeโมดูลจะให้การควบคุมการมองเห็นเนมสเปซ ภาษาอื่น ๆ เสนอเทคโนโลยี sandbox ที่คล้ายกัน หากอุปกรณ์ดังกล่าวพร้อมใช้งานคุณอาจต้องการตรวจสอบอุปกรณ์เหล่านี้เนื่องจากอุปกรณ์ดังกล่าวได้รับการออกแบบมาโดยเฉพาะสำหรับการเรียกใช้โค้ดที่ไม่น่าเชื่อถือแบบ จำกัด


4
การแปลง NFA-> DFA สามารถสร้างสถานะการระเบิดแบบเลขชี้กำลังทำให้เปลี่ยนเวลา DoS เป็นพื้นที่ DoS รวมถึงต้นทุนเวลาในการสร้างจำนวนเลขชี้กำลังของสถานะ
Barry Kelly

แต่อาจเป็นไปได้ว่าเขาไม่ต้องการความสามารถในการแสดงผลปกติทั้งหมดคุณคิดอย่างไรเกี่ยวกับการ จำกัด พลังของการแสดงออกปกติอย่างที่ google ทำ: google.com/intl/th/help/faq_codesearch.html#regexp
systemsfault

1
@ Barry ค่อนข้างเหมาะสม ฉันกำลังคิดถึงกลยุทธ์ของ Russ Cox ที่ได้อธิบายไว้ในหนึ่งในเอกสารของเขาในการรวบรวมส่วนต่าง ๆ ของ NFA เป็น DFA ที่เทียบเท่า แต่ทิ้งมันไปถ้ามันใหญ่เกินไป แต่ไม่มีกระสุนเงินใน DFA แม้ว่า Thompson จะพิสูจน์ได้ว่าเทียบเท่ากับ NFA เพราะคุณต้องจ่ายค่าไพเพอร์ในบางจุดหรืออย่างอื่น เวลาที่ใช้ขอทานระบบปฏิบัติการสำหรับพื้นที่เพิ่มขึ้นและค่าใช้จ่ายในการตั้งค่าหน้าโต๊ะผู้ดูแลบางครั้งสามารถผลักดันเครื่องชั่งสมดุลต่อไปอีกทางหนึ่งและทำให้การแปลงจากเวลาหนึ่งไปสู่พื้นที่ว่างน่าดึงดูดน้อยกว่าที่ควรจะเป็น
tchrist

20

การเพิ่มคำตอบที่ยอดเยี่ยมของ tchrist: Russ Cox เดียวกับผู้ที่เขียนหน้า "การแสดงออกปกติ" ได้เปิดตัวโค้ด! re2เป็นไลบรารี C ++ ที่รับประกันรันไทม์ O (length_of_regex) และ จำกัด การใช้หน่วยความจำ มันถูกใช้ภายใน Google เพื่อให้คุณสามารถพิมพ์ regex ลงในการค้นหารหัส google - หมายความว่ามันผ่านการทดสอบการต่อสู้แล้ว


2
แน่นอนดังนั้น คุณสามารถสลับ re2 เป็นเครื่องมือ regex ของ Perl ด้วยโมดูลและมันจะใช้ re2 ถ้าเป็นไปได้และ Perl ถ้าไม่ ทำงานได้ค่อนข้างดี
tchrist

13

ใช่.

regexes สามารถนำมาใช้ในการดำเนินการโจมตี
ไม่มีวิธีแก้ปัญหาง่ายๆ


6

คุณจะต้องการอ่านเอกสารนี้:

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


1
ต่อไปนี้เป็นคำแนะนำด้านความปลอดภัยเกี่ยวกับรหัส GNU libc regcomp (3): securityreason.com/achievement_securityalert/93นาน แค่ไหน! อย่างน้อยภายใต้ linux ช่องโหว่นั้นง่ายต่อการสาธิต: grep -E ". * {10,} {10,} {10,} {10,} {10,}"
Bruce Ediger

5

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


1

วิธีที่ดีในการทดสอบ RegEx ของคุณสำหรับปัญหาด้านความปลอดภัย (อย่างน้อยสำหรับ Windows) คือเครื่องมือสร้างความสับสน SDL RegEx ที่เผยแพร่โดย Microsoft เมื่อเร็ว ๆ นี้ สิ่งนี้สามารถช่วยหลีกเลี่ยงการสร้าง RegEx ที่ไม่ดีทางพยาธิวิทยา

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.