تطوير البرمجيات
هجمات التوقيت في PHP: مثال عملي - لماذا "hash_equals()" مهم
هل تريد مثالًا واقعيًا لهجوم التوقيت على رموز واجهة برمجة التطبيقات في Wordpress/Laravel/PHP؟ نحن نغطيها هنا، بما في ذلك النصائح وأفضل الممارسات ضد هجمات التوقيت.
يعتمد العديد من المطورين على المقارنة البسيطة باستخدام === أو == عند التحقق من مفاتيح واجهة برمجة التطبيقات أو الرموز أو السلاسل السرية الأخرى. للوهلة الأولى، يبدو ذلك معقولاً - ولكن هناك مشكلة: يمكن استغلال فروق التوقيت في المقارنة من قبل المهاجمين.
تصف هذه المقالة مثالًا واقعيًا لكيفية عمل هجوم التوقيت من الناحية النظرية.
السيناريو الحقيقي (مثال مبسط)
تخيل أن إحدى الخدمات المصغرة الداخلية تقبل الطلبات برمز معلمة استعلام ومقارنتها برمز واجهة برمجة تطبيقات GitHub المخزنة في البيئة.
كود غير آمن (مثال مبسط):
$ المتوقع = getenv('GITHUB_API_TOKEN')؛$provided = $_GET ['token'] ؟ ''؛إذا ($ provided = === $ متوقع) { } PHP
سأشرح سبب إشكالية ذلك في القسم التالي.
كيف يعمل هجوم التوقيت؟
إذا كان تنفيذ مقارنة الرمز المميز يقارن حرفًا بحرف ويجهض على الفور عند أول خطأ، فإن الطلب الذي يحتوي على الحرف الأول الصحيح يستغرق وقتًا أطول قليلاً في المتوسط.
وبالتالي فإن الحرف الأول الصحيح يؤدي في المتوسط إلى وقت معالجة أطول قليلاً من الحرف الأول غير الصحيح. الأمر نفسه ينطبق على الحرف الثاني وهكذا.
ويستفيد المهاجم من ذلك من خلال اختبار جميع الأحرف الممكنة لكل موضع، وقياس أزمنة الاستجابة في كثير من الأحيان وتحليلها إحصائيًا. من المحتمل أن يكون الحرف الذي لديه أكبر متوسط/زمن أطول بشكل متناسب هو الصحيح. بهذه الطريقة، يتم إعادة بناء الرمز المميز خطوة بخطوة.
لماذا تعتبر hash_equals() الخيار الصحيح
يوفر PHP دالة مقارنة سلاسل في وقت ثابت مع hash_equals(). فهي تضمن أن وقت تنفيذ المقارنة لا يعتمد على البادئات المشتركة - طالما أن كلا السلسلتين بنفس الطول.
بديل آمن (لـ Laravel وPHP وWordpress):
$ المتوقع = getenv('GITHUB_API_TOKEN')؛ $provided = $_GET ['token'] ؟ ''؛إذا كانت (hash_equals($ متوقع، $ provided)) { } PHP
ملاحظة: تكون hash_equals() "مستقلة زمنيًا" فقط إذا كانت الأطوال متساوية. من الممارسة الجيدة تصميم الرموز بحيث يكون الطول ثابتًا (مثل HMACs، أو معرّفات UUID ذات الطول الثابت أو سلاسل Base64 عشوائية ذات طول ثابت).
هل تعلم؟ يتم إنشاء UUID-V4 فقط بشكل عشوائي تمامًا، ولذلك غالبًا ما يتم استخدامه لرموز الأمان. ولأنه لا يحتوي على أي معلومات متعلقة بالوقت أو الجهاز، فإنه يوفر مستوى عالٍ من عدم القدرة على التنبؤ، وبالتالي يحمي من الهجمات القائمة على الأنماط أو التنبؤات. هذا هو بالضبط السبب في أن UUID-V4 هو الخيار المفضل عندما يتعلق الأمر بالمعرّفات الآمنة التي يصعب تخمينها.
تدابير دفاعية إضافية - أكثر من مجرد hash_equals()
- طول الرمز المميز الثابت
استخدم رموزًا ذات طول ثابت، مثل UUID-V4. إذا قام أحد المهاجمين بتخمين الطول، فهذا أقل فائدة طالما أن الرموز نفسها آمنة.
- تحديد المعدل
الحد من الطلبات لكل عنوان IP أو لكل حساب. تتطلب هجمات التوقيت العديد من القياسات؛ الحد من المعدل يزيد بشكل كبير من الجهد والتكاليف بالنسبة للمهاجم.
- التسجيل والمراقبة
التعرّف على الأنماط غير الاعتيادية (العديد من محاولات الرمز المميز، والتباين المنتظم لمعلمات معينة) والتفاعل تلقائياً.
- الملح / HMAC / التوقيعات
استخدم الرموز الموقّعة (HMAC مع مفتاح سري) أو رموز OAuth بدلاً من مقارنة المفاتيح الثابتة الخام بشكل علني.
- TLS/HTTPS
يحمي التشفير قنوات الاتصال - على الرغم من أنه لا يمنع هجمات التوقيت على الأجزاء الداخلية للخادم، إلا أنه مطلب أساسي.
- تناوب الرموز المميزة
العمر القصير للرموز المميزة يقلل من فائدة الرمز المميز المخترق.
الخاتمة
لا تعد هجمات التوقيت مشكلة نظرية بحتة - فقد تم التحقيق فيها عملياً ويمكن أن يكون لها عواقب وخيمة، خاصة بالنسبة لنقاط النهاية التي يمكن الوصول إليها للجمهور. الخبر السار: بالنسبة لمطوري PHP/لارافيل/ووردبريس فإن الإجراء المضاد الأول بسيط للغاية:
- استبدل المقارنات المباشرة للسلاسل الحساسة بـ
hash_equals().
- التأكد من ثبات أطوال الرموز الرمزية والحد من المعدل والتسجيل وإدارة آمنة للرموز الرمزية.