สำหรับทุก regex 'ความชั่วร้าย' มีทางเลือกอื่นที่ไม่ใช่ความชั่วหรือปีศาจในไวยากรณ์หรือไม่?


16

เห็นได้ชัดว่าการโจมตีReDosใช้ประโยชน์จากคุณลักษณะของการแสดงออกปกติบางอย่าง (มีประโยชน์) บางอย่าง ... เป็นหลักทำให้เกิดการระเบิดของเส้นทางที่เป็นไปได้ผ่านกราฟที่กำหนดโดย NFA

เป็นไปได้หรือไม่ที่จะหลีกเลี่ยงปัญหาดังกล่าวโดยการเขียน regex ที่ 'ไม่เลว'? ถ้าไม่ใช่ (ดังนั้นไวยากรณ์จะไม่สามารถจัดการในพื้นที่ / เวลาที่ใช้งานได้จริงโดย NFA) วิธีการแยกวิเคราะห์แบบใดจะดีกว่า ทำไม?


ถ้าฉันจัดการเพื่อใช้ภาษาทางเทคนิคที่แม่นยำมันเป็นอุบัติเหตุ โปรดส่งคำตอบของคุณสำหรับผู้ที่ไม่ได้เป็นนักวิชาการ:
David Bullock

1
จริง ๆ แล้วฉันแค่พยายามหาวิธีปฏิบัติเพื่อหลีกเลี่ยงการเป็น ReDosและคำถามนี้เกิดขึ้น
David Bullock

ในการใช้ถ้อยคำใหม่คำถามของคุณ (?): ทุกภาษาปกติมีการแสดงออกปกติที่มีความยาวล้อมรอบด้วยพหุนามในจำนวนสถานะของ NFA น้อยที่สุดหรือไม่?
A.Schulz

1
@ A.Schulz ฉันไม่คิดว่าเป็นคำถาม นั่นไม่ใช่วิธีการโจมตีของ ReDos ในการโจมตี ReDos นั้น regexp จะถูกฮาร์ดโค้ดลงในซอร์สโค้ดของโปรแกรมและจัดทำโดยผู้พัฒนาซึ่งสันนิษฐานว่าน่าเชื่อถือ จากนั้นฝ่ายตรงข้ามจะได้รับการป้อนสตริงซึ่งโปรแกรมตรงกับ regexp หากฝ่ายตรงข้ามสามารถค้นหาสายป้อนข้อมูลที่ทำให้คู่แข่งขันทำงานเป็นเวลานานฝ่ายตรงข้ามชนะ ดังนั้นเราจึงกังวลเกี่ยวกับอินพุตที่ไม่เป็นปฏิปักษ์ไม่ใช่นิพจน์ทั่วไปที่ไม่เหมาะสม (ต่อ)
DW

ดังนั้นฉันคิดว่าคำถามคือแทน: ทุกภาษาปกติมีการแสดงออกปกติเช่นการจับคู่สตริงตัวละครกับการแสดงออกปกติที่ใช้เวลาO ( f ( n ) )เวลาที่f ( n )บางอย่างไม่เกินไป - ฟังก์ชันที่เติบโตอย่างรวดเร็วของn (พูดพหุนามหรืออะไรทำนองนั้น)? [อนึ่งการกำหนดสูตรใหม่นี้ชัดเจนว่าคำตอบนั้นขึ้นอยู่กับอัลกอริธึมที่ใช้สำหรับการจับคู่ ... ดังที่ฉันกล่าวถึงในคำตอบของฉัน] ขนาดของการแสดงออกปกติเป็นฟังก์ชันของขนาดของ NFA ที่น้อยที่สุด สำคัญมากที่นี่ nO(f(n))f(n)n
DW

คำตอบ:


14

มันขึ้นอยู่กับว่าคุณมีการแสดงออกปกติหรือ regexp: regexps เป็นความชั่วร้าย แต่การแสดงออกปกติเป็นเรื่องของความงามและจะไม่เปลี่ยนความชั่วร้ายกับคุณ

โดย regexp ฉันหมายถึงการแสดงออกปกติที่ทันสมัย: เช่นการแสดงออกปกติที่มีคุณสมบัติที่ทันสมัยเพิ่มเติมเช่น backreferences - เช่นการแสดงออกปกติ Perl เข้ากันได้กับ Perl นี่มีประสิทธิภาพมากกว่าการแสดงออกปกติแบบคลาสสิกจากตำราเรียนภาษา / ทฤษฎีออโตมาตาแบบปกติเนื่องจากการแสดงออกปกติแบบคลาสสิกไม่อนุญาตให้มีการอ้างอิงย้อนกลับ, lookahead, lookbehind และอื่น ๆ

สำหรับการแสดงออกปกติแบบคลาสสิกหากคุณมีการนำไปใช้ที่ดีสำหรับผู้จับคู่แล้วการแสดงออกปกติจะไม่เลวร้ายเกินไป โดยเฉพาะอย่างยิ่งอัลกอริทึมมาตรฐานสำหรับการจับคู่คือการแปลงนิพจน์ปกติเป็น NFA แล้วดำเนินการ NFA บนสตริงอินพุต สำหรับอัลกอริธึมนี้เวลาทำงานที่แย่ที่สุดในการทดสอบสตริง -character คือO ( n )เมื่อนิพจน์ทั่วไปได้รับการแก้ไข ซึ่งหมายความว่าเวลาทำงานไม่สามารถระเบิดได้เร็วเกินไป ไม่มีสตริงที่จะเพิ่มการชี้แจงในเวลาทำงาน ดังนั้นหากคุณใช้ matcher ที่ใช้อัลกอริทึมนี้จะไม่มีการแสดงออกปกติแบบคลาสสิกใด ๆ ที่จะเป็นความชั่วร้ายnO(n)

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

ในการเปรียบเทียบ regexps ที่ทันสมัยบางอย่างจะชั่วร้ายอย่างหลีกเลี่ยงไม่ หากคุณมี regexp ที่ทันสมัยการจับคู่อาจต้องใช้เวลาแทน โดยเฉพาะอย่างยิ่ง regexps ที่มีการอ้างอิงย้อนกลับสามารถรับรู้ภาษา NP-hard ดังนั้นภายใต้สมมติฐานที่เป็นไปได้มีคลาสของ regexps ชั่วร้ายที่การทดสอบสำหรับการแข่งขันต้องใช้เวลาชี้แจง ดังนั้น regexps ที่ทันสมัยบางอย่างจึงไม่สามารถหลีกเลี่ยงความชั่วร้ายได้: ไม่มีวิธีที่เป็นไปได้ในการค้นหา regexp ที่เท่ากันซึ่งจะไม่ทำให้เกิดการระเบิดแบบเลขชี้กำลังในเวลาทำงาน

(เทียบเท่าอาจมีอยู่และอาจพบได้ในทางทฤษฎี แต่ภายใต้สมมติฐานที่เป็นไปได้การหา regexp ที่เท่ากันจะใช้เวลาแบบเอกซ์โพเนนเชียลซึ่งไม่สามารถทำได้ในทางปฏิบัติหากคุณมีขั้นตอนที่เป็นระบบ จากนั้นคุณสามารถแก้ปัญหา NP-hard ในเวลาพหุนามพิสูจน์ว่า P = NP มันไม่ได้ดีอะไรมากสำหรับการมี regexp ที่เทียบเท่าหากไม่มีวิธีหามันในชีวิตของคุณ)


พื้นหลังและแหล่งที่มา:


การหาทางเลือกที่ไม่ใช่ความชั่วทำได้ง่ายขึ้นหรือไม่โดยการแบ่ง regex ออกเป็น regexes ที่เล็กกว่าหลาย ๆ ตัวและใช้ร่วมกัน?
inf3rno

1

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

Wikipedia มีการโจมตี Denial of Service 15 ประเภทและการโจมตีนี้เข้าสู่"ระดับแอพพลิเคชั่น"ในรายการดังกล่าว อีกตัวอย่างที่ค่อนข้างคล้ายกันคือการโจมตีที่เติมบันทึกของแอปพลิเคชัน

หนึ่งในการแก้ไขสำหรับการโจมตีการฉีดคือ "ล้างข้อมูล" ผู้ออกแบบแอปพลิเคชันสามารถประเมินค่าใหม่หากจำเป็นต้องรวบรวม regexps ที่ผู้ใช้อาจเป็นอันตรายจัดทำขึ้นโดยพลการ เพียงแค่ถอดการแสดงออกที่ซ้อนกันใน regexp หรือข้อ จำกัด ที่คล้ายกันอื่น ๆ อาจจะเพียงพอที่จะหลีกเลี่ยงการโจมตีนี้ แม้ว่าซอฟต์แวร์เหล่านี้จะมีซอฟต์แวร์ที่ทันสมัยจำนวนมาก แต่สามารถใช้งานได้จำนวนมากโดยไม่ต้องประเมินนิพจน์ทั่วไป บริบทเป็นเรื่องที่แอพพลิเคชั่นบางตัวไม่ต้องการความปลอดภัยเช่นนั้น

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

นี่คือตัวอย่างที่ดีของการใช้การหมดเวลาเพื่อปรับปรุงความทนทานต่อความผิดพลาดและแสดงการออกแบบ / สถาปัตยกรรม / pov ระดับสูงเพื่อลดปัญหาดังกล่าว: Fault Tolerance ในระบบที่มีปริมาณสูง, ระบบกระจาย / Netflix มันไม่มีอะไรที่เชื่อมโยงกับนิพจน์ปกติ แต่เฉพาะจุดที่นี่: ตรรกะระดับแอปพลิเคชันใด ๆ / ทั้งหมดสามารถเข้ากับเฟรมเวิร์กนี้หรืออะไรที่คล้ายกัน

บทความนี้ชี้ให้เห็นว่าbacktrackingโดยเฉพาะสามารถนำไปสู่การจับคู่ regexp ช้า Regexps มีคุณสมบัติที่แตกต่างกันมากมายและเราสามารถลองประเมินว่าอันไหนที่นำไปสู่พฤติกรรมกรณีที่เลวร้ายที่สุด

นี่คือการสำรวจทางวิทยาศาสตร์ที่ดีของหัวข้อเฉพาะที่เสนอวิธีการวิเคราะห์แบบคงที่ (s):

  • การวิเคราะห์แบบคงที่สำหรับรันไทม์เอ็กซ์โปเนนเชียลนิพจน์ปกติผ่าน Substructural Logics / Rathnayake, Thielecke

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


คำตอบนี้ดูเหมือนสับสนเกี่ยวกับบางแง่มุมของ ReDos 1. ReDoS ไม่มีส่วนเกี่ยวข้องกับการโจมตีด้วยการฉีด การโจมตีของการฉีด (เช่น XSS, การฉีด SQL, การฉีดคำสั่ง ฯลฯ ) นั้นแตกต่างกันโดยสิ้นเชิง 2. ReDos ไม่ได้เกี่ยวกับ regexps ที่เป็นอันตรายที่ส่งมาโดยฝ่ายตรงข้าม โดยทั่วไป regexp จะฮาร์ดโค้ดในโปรแกรม (จัดทำโดยผู้พัฒนา) และสตริงป้อนข้อมูลจะถูกจัดทำโดยผู้ใช้ ปัญหาไม่สามารถแก้ไขได้อย่างสมเหตุสมผลโดยการตรวจสอบความถูกต้องของอินพุตเนื่องจากโดยปกติแล้วจะไม่มีนโยบายการตรวจสอบความถูกต้องของอินพุตที่ชัดเจนพอที่จะกำจัดปัญหาได้
DW

คิดว่าคะแนนของคุณเป็นจำนวนมากทางด้านเทคนิค / การตัดผมโดยอ้างอิงจากการอ้างอิงของ ReDos & คิดถึงป่าไม้สำหรับต้นไม้ มันคล้ายกับ "การโจมตีการฉีดที่สร้างขึ้น" คำตอบชี้ให้เห็นว่ามีทางเลือกอื่นในการใช้ regexps ในโค้ด การวิเคราะห์แบบคงที่สามารถค้นหา "ความชั่วร้าย regexps" ทุกจุดของคำตอบนั้นถูกต้อง ประโยคเช่น "โดยปกติ regexp จะฮาร์ดโค้ดในโปรแกรม (จัดทำโดยผู้พัฒนา) และสตริงอินพุตถูกจัดทำโดยผู้ใช้" ไม่ตรงกับการเขียนซ้ำของ ReDos ซึ่งคลุมเครือมากขึ้นในสถานที่และอ้างถึงผู้โจมตีที่เป็นอันตราย ฯลฯ .
vzn
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.