إعادة حجب الخدمة

هجوم حجب الخدمة باستخدام التعبيرات النمطية ( ReDoS ) [ 1 ] هو هجوم يعتمد على تعقيد الخوارزمية ، ويؤدي إلى حجب الخدمة من خلال تقديم تعبير نمطي (regex) و/أو مُدخلات تستغرق وقتًا طويلاً للتقييم. يستغل هذا الهجوم حقيقة أن العديد من تطبيقات التعبيرات النمطية [ 2 ] تتميز بتعقيد فائق الخطية في أسوأ الحالات ؛ ففي بعض أزواج التعبيرات النمطية والمُدخلات، قد يزداد الوقت المستغرق بشكل متعدد الحدود أو أُسّي بالنسبة لحجم المُدخلات. وبالتالي، يستطيع المهاجم إجبار البرنامج على قضاء وقت طويل من خلال تقديم تعبير نمطي مُصمم خصيصًا و/أو مُدخلات. عندها سيتباطأ البرنامج أو يتوقف عن الاستجابة. [ 3 ] [ 4 ]

وصف

يمكن إجراء مطابقة التعبيرات النمطية ("regex") عن طريق بناء آلة حالة محدودة . يمكن تحويل التعبيرات النمطية بسهولة إلى آلات حالة غير حتمية (NFAs)، حيث قد يكون لكل حالة ورمز إدخال عدة حالات تالية محتملة. بعد بناء الآلة، توجد عدة احتمالات:

  • قد يقوم المحرك بتحويلها إلى آلة حالة محدودة حتمية (DFA) وتشغيل المدخلات من خلال النتيجة؛
  • قد يُجرّب المحرك جميع المسارات الممكنة واحدًا تلو الآخر حتى يتم العثور على تطابق أو حتى يتم تجربة جميع المسارات وفشلها (" التراجع "). [ 5 ] [ 6 ]
  • قد ينظر المحرك في جميع المسارات الممكنة عبر الآلة غير الحتمية بالتوازي؛
  • قد يقوم المحرك بتحويل الآلة غير الحتمية إلى آلة حتمية بشكل كسول ( أي أثناء المباراة).

من بين الخوارزميات المذكورة أعلاه، تُعدّ الخوارزميتان الأوليان إشكاليتين. تكمن إشكالية الأولى في أن الآلة الحتمية قد تحتوي على ما يصل إلى2م{\displaystyle 2^{m}}الولايات التيم{\displaystyle m}يمثل عدد الحالات في الأوتوماتون غير الحتمي؛ وبالتالي، قد يستغرق التحويل من الأوتوماتون غير الحتمي إلى الأوتوماتون الحتمي وقتًا أُسّيًا . أما الحالة الثانية فهي إشكالية لأن الأوتوماتون غير الحتمي قد يحتوي على عدد أُسّي من المسارات ذات الطولن{\displaystyle n}بحيث يكون المرور عبر مدخل بطولن{\displaystyle n}سيستغرق الأمر أيضًا وقتًا أُسّيًا. [ 7 ] ومع ذلك، فإن الخوارزميتين الأخيرتين لا تُظهران سلوكًا مرضيًا.

لاحظ أنه بالنسبة للتعبيرات النمطية غير المرضية، فإن الخوارزميات الإشكالية عادة ما تكون سريعة، ومن الناحية العملية، يمكن توقع أن تقوم " بتجميع " التعبير النمطي فييا(م){\displaystyle O(m)}الوقت ومطابقتهيا(ن){\displaystyle O(n)}بدلاً من ذلك، يتم استخدام محاكاة NFA والحساب الكسول لـ DFA.يا(م2ن){\displaystyle O(m\cdot 2^{n})}تعقيد أسوأ الحالات. [ أ ] يحدث هجوم حجب الخدمة باستخدام التعبيرات النمطية عندما يتم تطبيق هذه التوقعات على تعبير نمطي مقدم من المستخدم، وتؤدي التعبيرات النمطية الخبيثة المقدمة من المستخدم إلى حدوث تعقيد أسوأ الحالات لمطابق التعبيرات النمطية.

على الرغم من إمكانية كتابة خوارزميات التعبيرات النمطية بكفاءة، إلا أن معظم محركات التعبيرات النمطية الموجودة حاليًا تُضيف إلى لغات التعبيرات النمطية بنياتٍ إضافية لا يمكن حلها دائمًا بكفاءة. هذه الأنماط المُوسّعة تُجبر تطبيق التعبيرات النمطية في معظم لغات البرمجة على استخدام التراجع.

أمثلة

التراجع الأسي

تحدث أخطر أنواع المشاكل مع مطابقة التعبيرات النمطية المتراجعة، حيث يكون وقت تشغيل بعض الأنماط أسيًا بالنسبة لطول سلسلة الإدخال. [ 8 ] بالنسبة لسلاسل منن{\displaystyle n}عدد الأحرف، ووقت التشغيل هويا(2ن){\displaystyle O(2^{n})}يحدث هذا عندما يكون للتعبير النمطي ثلاث خصائص:

  • يطبق التعبير النمطي التكرار ( +, *) على تعبير فرعي؛
  • يمكن أن يتطابق التعبير الفرعي مع نفس المدخلات بطرق متعددة، أو يمكن أن يتطابق التعبير الفرعي مع سلسلة إدخال تمثل بادئة لتطابق محتمل أطول؛
  • وبعد التعبير الفرعي المتكرر، يوجد تعبير يطابق شيئًا لا يطابقه التعبير الفرعي.

يمكن شرح الشرط الثاني بشكل أفضل من خلال مثالين:

  • في (a|a)+$، يتم تطبيق التكرار على التعبير الفرعي a|a، والذي يمكن أن يتطابق aبطريقتين على كل جانب من جوانب التناوب.
  • في (a+)*$، يتم تطبيق التكرار على التعبير الفرعي a+، والذي يمكن أن يطابق aأو aa، إلخ.

في كلا المثالين، استخدمنا $مطابقة نهاية السلسلة، محققين بذلك الشرط الثالث، ولكن من الممكن أيضًا استخدام حرف آخر لهذا الغرض. على سبيل المثال، (a|aa)*cيمتلك نفس البنية الإشكالية.

ستُظهر جميع التعبيرات النمطية الثلاثة المذكورة أعلاه زمن تشغيل أُسّيًا عند تطبيقها على سلاسل نصية من الشكل التالي:أ...أx{\displaystyle a...ax}على سبيل المثال، عند محاولة مطابقتها aaaaaaaaaaaaaaaaaaaaaaaaxباستخدام محرك تعبيرات التراجع، سيستغرق الأمر وقتًا طويلاً لإكماله، وسيتضاعف وقت التشغيل تقريبًا لكل عنصر إضافي aقبل النقطة x.

من الممكن أيضًا وجود عملية تراجع تستغرق وقتًا متعدد الحدوديا(نx){\displaystyle O(n^{x})}بدلاً من التوزيع الأسي. قد يُسبب هذا مشاكل أيضًا مع المدخلات الطويلة جدًا، على الرغم من قلة الاهتمام بهذه المشكلة لأن المدخلات الخبيثة يجب أن تكون أطول بكثير لإحداث تأثير ملحوظ. مثال على هذا النمط هو " a*b?a*c"، عندما تكون المدخلات عبارة عن سلسلة طويلة بشكل تعسفي من " a".

تعابير نمطية ضعيفة في المستودعات الإلكترونية

تم العثور على ما يُسمى بتعبيرات نمطية "خبيثة" أو ضعيفة في مستودعات التعبيرات النمطية على الإنترنت. تجدر الإشارة إلى أنه يكفي العثور على تعبير فرعي ضعيف لمهاجمة التعبير النمطي الكامل.

  1. RegExLib، المعرّف = 1757 (التحقق من صحة البريد الإلكتروني) – انظر الجزء الأحمر^([a-zA-Z0-9])(([\-.]|[_]+)?([a-zA-Z0-9]+))*(@){1}[a-z0-9]+[.]{1}(([a-z]{2,3})|([a-z]{2,3}[.]{1}[a-z]{2,3}))$
  2. مستودع تعابير التحقق من صحة OWASP ، اسم فئة Java - انظر الجزء الأحمر^(([a-z])+.)+[A-Z]([a-z])+$

هذان المثالان عرضة أيضًا للمدخلات aaaaaaaaaaaaaaaaaaaaaaaa!.

الهجمات

إذا تأثر التعبير النمطي نفسه بمدخلات المستخدم، كما هو الحال في خدمة ويب تسمح للعملاء بإدخال نمط بحث، فبإمكان المهاجم حقن تعبير نمطي خبيث لاستنزاف موارد الخادم. لذا، في معظم الحالات، يمكن تجنب هجمات حجب الخدمة باستخدام التعبيرات النمطية عن طريق منع المستخدم من تنفيذ أنماط عشوائية على الخادم. في هذه الحالة، تُعد تطبيقات الويب وقواعد البيانات من أكثر التطبيقات عرضةً للخطر. بدلاً من ذلك، قد تتسبب صفحة خبيثة في توقف متصفح المستخدم أو استهلاكه كميات هائلة من الذاكرة.

مع ذلك، إذا وُجد تعبير نمطي ضعيف على جانب الخادم، فقد يتمكن المهاجم من إدخال بيانات تُفعّل أسوأ سلوكياته. في هذه الحالة، قد تكون برامج فحص البريد الإلكتروني وأنظمة كشف التسلل عرضةً للاختراق أيضًا.

في حالة تطبيقات الويب، قد يستخدم المبرمج نفس التعبير النمطي للتحقق من صحة المدخلات على كلٍ من جانب العميل وجانب الخادم في النظام. يمكن للمهاجم فحص كود العميل، بحثًا عن تعبيرات نمطية خبيثة، وإرسال مدخلات مُصممة خصيصًا مباشرةً إلى خادم الويب لتعطيله. [ 9 ]

التخفيف

يمكن التخفيف من هجمات ReDoS دون إجراء تغييرات على محرك التعبيرات النمطية، وذلك ببساطة عن طريق تحديد حد زمني لتنفيذ التعبيرات النمطية عند استخدام مدخلات غير موثوقة. [ 10 ]

يمكن تجنب هجمات ReDoS تمامًا باستخدام تطبيق تعبيرات نمطية غير قابلة للاختراق. بعد أن تعطل جدار حماية تطبيقات الويب (WAF) الخاص بشركة CloudFlare نتيجة لهجوم ReDoS من نوع PCRE في عام 2019، أعادت الشركة كتابة جدار الحماية الخاص بها لاستخدام مكتبة Rust regex غير التراجعية، باستخدام خوارزمية مشابهة لخوارزمية RE2 . [ 11 ] [ 12 ]

يمكن اكتشاف التعبيرات النمطية المعرضة للثغرات برمجيًا باستخدام أداة فحص الأخطاء (linter ). [ 13 ] تتراوح الطرق من التحليل الثابت البحت [ 14 ] [ 15 ] إلى اختبار التشويش (fuzzing) . [ 16 ] في معظم الحالات، يمكن إعادة كتابة التعبيرات النمطية الإشكالية كأنماط "غير ضارة". على سبيل المثال، (.*a)+يمكن إعادة كتابة التعبير النمطي إلى التعبير النمطي ([^a]*a)+. كما يمكن استخدام المطابقة التملكية والتجميع الذري ، اللذين يعطلان التراجع لأجزاء من التعبير، [ 17 ] لـ"معالجة" الأجزاء المعرضة للثغرات. [ 18 ] [ 19 ]

التنفيذ الخطي الزمني (الأوتوماتا المحدودة)

بينما تفتقر بعض مكتبات التعبيرات النمطية إلى آليات دفاع مدمجة ضد هجمات حجب الخدمة المُعاد تنفيذها (ReDoS)، مثل مكتبة C++ القياسية<regex> ، ومكتبة C POSIX <regex.h>[ 20 ] ، ومكتبة Boostboost.regex (التي تستخدم التراجع، مما يؤدي إلى زمن تنفيذ أُسّي)، فإن مكتبات تعبيرات نمطية أخرى مُصممة خصيصًا لمنع هجمات حجب الخدمة المُعاد تنفيذها. ويتم ذلك باستخدام آلات الحالة المحدودة الحتمية، التي تعمل بزمن خطي يتناسب مع حجم المُدخلات.

استخدام مكتبة RE2 من جوجل للغة C++ : [ 21 ]

استيراد < re2 / re2 . h > ; استيراد std ;باستخدام std :: string_view ؛ باستخدام re2 :: RE2 ؛constexpr string_view TEXT = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!" ; constexpr string_view PATTERN = "^(a+)+$" ;int main ( int argc , char * argv []) { bool isMatch = RE2 :: FullMatch ( TEXT , PATTERN ); std :: println ( "نتيجة المطابقة: {}" , isMatch ); }

استخدام regexالحزمة لـ Rust : [ 22 ]

استخدم التعبير النمطي :: التعبير النمطي ;نص ثابت : & str = "aaaaaaaaaaaaaaaaaaaaaaaaa!" ; نمط ثابت : & str = r"^(a+)+$" ;fn main () { // تُرجع الدالة Regex::new() قيمة Result<Regex, Error> ويجب فك تغليفها match Regex :: new ( PATTERN ) { Ok ( re ) => { let is_match : bool = re . is_match ( TEXT ); println! ( "نتيجة المطابقة: {}" , is_match ); } Err ( err ) => { eprintln! ( "فشل فك تغليف التعبير النمطي: {}" , err ); } } }

مهلة مطابقة التعبير النمطي

يمكن استخدام مهلات زمنية لإلغاء مهام التعبير النمطي إذا استغرقت وقتًا طويلاً.

تُعدّ خاصية المهلة الزمنية جزءًا لا يتجزأ من مكتبة .NET القياسية ، حيث يدعم الصنف System.Text.RegularExpressions.Regexخاصيةً معينة MatchTimeout. [ 23 ] فيما يلي مثال بلغة C# :

namespace Wikipedia.Examples ;باستخدام System ؛ باستخدام System.Text.RegularExpressions ؛public class Example { private const string Text = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!" ; private const string Pattern = @"^(a+)+$" ;static void Main ( string [] args ) { try { Regex re = new ( Pattern , RegexOptions.None , TimeSpan.FromMilliseconds ( 100 ) ) ; bool isMatch = re.IsMatch ( Text ) ; Console.WriteLine ( $ "نتيجة المطابقة: { isMatch}" ); } catch ( RegexMatchTimeoutException ex ) { Console.WriteLine ( $ " انتهت مهلة عملية التعبير النمطي! { ex.Message } " ) ; } } }

التعبيرات النمطية في وقت الترجمة

التعابير النمطية في وقت الترجمة هي تعابير نمطية تنقل عملية التحليل والتحقق إلى وقت الترجمة ، مما يلغي الحمل الزائد في وقت التشغيل . مع ذلك، لا تكون التعابير النمطية في وقت الترجمة مفيدة إلا إذا أمكن تحديد النمط في وقت الترجمة.

توفر مكتبة التعبيرات النمطية في وقت الترجمة للغة C++ ( ctre ) من تطوير هانا دوسيكوفا، ctre::match<>دالة تقوم بتحليل التعبيرات النمطية أثناء الترجمة. [ 24 ] إذا تسبب نمط ما أثناء الترجمة في تجاوز constexprحد خطوات التقييم، فسيفشل التجميع. وقد تم اقتراحها لإضافتها إلى مكتبة C++ القياسية ، ولكنها لم تُدرج فيها حتى الآن. [ 25 ]

استيراد < ctre.hpp > ؛ استيراد std ؛باستخدام std :: string_view ؛constexpr string_view TEXT = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaa!" ;int main ( int argc , char * argv []) { // ctre::match<> هو نوع ctre::regex_results<> // تتم عملية المطابقة في وقت الترجمة عند وضع علامة constexpr constexpr bool isMatch = ctre :: match < "^(a+)+$" > ( TEXT ); std :: println ( "نتيجة المطابقة: {}" , isMatch ); }

توفر لغة البرمجة Dstd.regex.ctRegex خاصية التعبير النمطي في وقت الترجمة. [ 26 ]

في لغة Rust، يمكن إنجاز التعبيرات النمطية في وقت الترجمة بواسطة بعض المكتبات الخارجية، مثل lazy_regex و ctreg و regex-automata ، والتي توفر وحدات ماكرو متنوعة للتحقق من صحة التعبيرات النمطية في وقت الترجمة. [ 27 ]

في لغة C#، توجد System.Text.RegularExpressions.GeneratedRegexAttributeخاصية تقوم بإنشاء تطبيق للتعبير النمطي من خلال توليد المصدر في partialطريقة ما. [ 28 ]

namespace Wikipedia.Examples ;باستخدام System ؛ باستخدام System.Text.RegularExpressions ؛public partial class Example { [GeneratedRegex(@"^(a+)+$")] private static partial Regex Pattern ();private const string Text = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaa!" ;static void Main ( string [] args ) { // يتم تنفيذ منطق IsMatch() أثناء التشغيل bool isMatch = Pattern (). IsMatch ( Text ); Console . WriteLine ( $"نتيجة المطابقة: {isMatch}" ); } }

انظر أيضاً

مراجع

  1. يمكن للحساب الكسول للآلة الحتمية أن يصل عادةً إلى سرعة الآلات الحتمية مع الحفاظ على سلوك أسوأ الحالات مشابهًا لمحاكاة الآلة غير الحتمية. ومع ذلك، فإن تنفيذه أكثر تعقيدًا بكثير وقد يستهلك ذاكرة أكبر.
  1. OWASP (2010-02-10). "هجوم حجب الخدمة باستخدام التعبيرات النمطية" . تم الاطلاع عليه بتاريخ 2010-04-16 .
  2. ديفيس، جيمس؛ لويس، مايكل؛ كوجلان، كريستي؛ سيرفانت، فرانسيسكو؛ لي، دونغيون (2019). "لماذا لا تُعدّ التعابير النمطية لغة مشتركة؟ دراسة تجريبية حول إعادة استخدام التعابير النمطية وقابليتها للنقل" (ملف PDF) . المؤتمر الأوروبي المشترك لهندسة البرمجيات وندوة أسس هندسة البرمجيات التابعة لجمعية ACM : 443-454 .
  3. شركة ريفرستار للبرمجيات (18 يناير 2010). "نشرة أمنية: تحذير بشأن استخدام التعابير النمطية" . مؤرشفة من الأصل بتاريخ 15 يوليو 2011. تم الاطلاع عليها بتاريخ 16 أبريل 2010 .
  4. ريستيك، إيفان (15 مارس 2010). دليل ModSecurity . لندن، المملكة المتحدة: Feisty Duck Ltd.، ص 173. ISBN  978-1-907117-02-2أُرشف من المصدر الأصلي بتاريخ 2016-08-08 . تم الاطلاع عليه بتاريخ 2010-04-16 .
  5. كروسبي ووالاش، أمن يوزنكس (2003). "هجوم حجب الخدمة باستخدام التعبيرات النمطية" . مؤرشف من الأصل بتاريخ 1 مارس 2005. تم الاطلاع عليه بتاريخ 13 يناير 2010 .
  6. برايان سوليفان (2010-05-03). "هجمات حجب الخدمة باستخدام التعبيرات النمطية وآليات الدفاع ضدها" . تم الاطلاع عليه بتاريخ 2010-05-06 .
  7. كيراج، ج.؛ راثناياكي، أ.؛ ثيليكي، هـ. (2013). "التحليل الثابت لهجمات حجب الخدمة باستخدام التعابير النمطية". أمن الشبكات والأنظمة . مدريد، إسبانيا: سبرينغر. ص 135-148 . arXiv : 1301.0849 . doi : 10.1007/978-3-642-38631-2_11 . 
  8. جيم مانيكو وأدار وايدمان (7 ديسمبر 2009). "بودكاست OWASP رقم 56 (ReDoS)" . تم الاطلاع عليه بتاريخ 2 أبريل 2010 .
  9. بارلاس، إيفي؛ دو، شين؛ ديفيس، جيمس (2022). "استغلال تنقية المدخلات لهجمات حجب الخدمة باستخدام التعبيرات النمطية" (ملف PDF) . المؤتمر الدولي المشترك بين ACM وIEEE لهندسة البرمجيات : 1-14 . arXiv : 2303.01996 .
  10. "التراجع في التعبيرات النمطية في .NET - .NET" . learn.microsoft.com . 11 أغسطس 2023. عند استخدام System.Text.RegularExpressions لمعالجة مدخلات غير موثوقة، يجب تحديد مهلة زمنية. إذ يمكن لمستخدم خبيث إدخال بيانات إلى RegularExpressions، مما يتسبب في هجوم حجب الخدمة. تُمرر واجهات برمجة تطبيقات إطار عمل ASP.NET Core التي تستخدم RegularExpressions مهلة زمنية.
  11. "جعل جدار حماية تطبيقات الويب أسرع بنسبة 40%" . مدونة كلاود فلير . 1 يوليو 2020.
  12. كوكس، روس (2007). "مطابقة التعبيرات النمطية يمكن أن تكون بسيطة وسريعة" . تم الاسترجاع في 20 أبريل 2011 . يصف خوارزمية RE2
  13. انظر على سبيل المثال: شميدت، مايكل (30 مارس 2023). "RunDevelopment/scslre" . جيت هاب .، تسويوساتو، كيتسون. "إعادة فحص المقدمة" .، وديفيس، جيمس. "vuln-regex-detector/src/detect/README.md" . جيت هاب .
  14. هـ. ثيليكي، أ. راثناياكي (2013). " التحليل الثابت لهجمات الحرمان من الخدمة باستخدام التعبيرات النمطية (ReDoS). مؤرشف بتاريخ 3 أغسطس 2014 في أرشيف الإنترنت ". تم الاطلاع عليه بتاريخ 30 مايو 2013.
  15. ^ ب. فان دير ميروي، إن وايدمان (2017). " تحليل Regex الثابت ". تم الاسترجاع 2017/08/12.
  16. "الاختبار باستخدام التحليل الثابت | إعادة الفحص" . makenowjust-labs.github.io .
  17. "الفئات الأساسية: التعابير النمطية: المحددات الكمية: الفروق بين المحددات الكمية الجشعة، والمترددة، والملكية" . دروس جافا . أوراكل . مؤرشف من الأصل في 7 أكتوبر 2020. تم الاطلاع عليه في 23 ديسمبر 2016 .
  18. "compose-regexp.js، "المطابقة الذرية"" . GitHub . 2 يناير 2024."tc39/proposal-regexp-atomic-operators" . اللجنة الفنية 39 التابعة لـ Ecma. 31 ديسمبر 2023.
  19. "منع هجمات حجب الخدمة باستخدام التعبيرات النمطية (ReDoS)" . www.regular-expressions.info .
  20. "regex(3) - صفحة دليل لينكس" . man7.org . 28 يونيو 2025.
  21. "Github - google/re2" . github.com . 1 يوليو 2025.
  22. "regex - Rust" . docs.rs. تم الاطلاع عليه بتاريخ 15 سبتمبر 2025 .
  23. "خاصية Regex.MatchTimeout (System.Text.RegularExpressions) Microsoft Learn" . learn.microsoft.com . تم الاطلاع عليه بتاريخ 15 سبتمبر 2025 .
  24. ^ هانا دوسيكوفا (8 مايو 2026). "تجميع التعبيرات العادية للوقت v3" . جيثب.كوم . هانا دوسيكوفا.
  25. ^ هانا دوسيكوفا. “تجميع التعبيرات العادية للوقت” (PDF) . open-std.org . مجموعة العمل 21 . تم الاسترجاع في 9 يوليو 2026 .
  26. لغة D (9 يوليو 2026). "std.regex" . dlang.org . لغة D.
  27. كانوب (11 فبراير 2026). "Crate lazy_regex" . docs.rs . docs.rs.
  28. مايكروسوفت ليرن. "فئة GeneratedRegexAttribute" . learn.microsoft.com . مايكروسوفت ليرن . تم الاطلاع عليه في 9 يوليو 2026 .