تقارن سلامة الموارد الفرعية SRI المورد ببصمة تحددها الصفحة، لتمنع تشغيل نسخة تغيرت على نحو غير متوقع، ومنها ملفات جافاسكريبت الخارجية. [1]
الخلاصة السريعة
- البصمة تثبّت محتوى المورد الذي توافق عليه، ولا تجعل شفرته سليمة تلقائيًا.
- احسب البصمة للملف النهائي، وضعها في سمة
integrity. - عند اختلاف أصل المورد، يجب استيفاء CORS أيضًا.
- تعدد البصمات يوجب الانتباه إلى الخوارزمية الأقوى الموجودة بينها.
- اختبر عمدًا حالة عدم التطابق، ثم حدّث الملف وبصمته معًا عند اعتماد نسخة جديدة.
ما المشكلة التي تعالجها البصمة؟
قد يبقى عنوان المكتبة الخارجية ثابتًا بينما يغيّر تحديث أو اختراق محتواها. تثبّت SRI النسخة المتوقعة، لكن مراجعة شيفرتها وصلاحياتها وموثوقية مصدر البصمة تظل مطلوبة. [1]
أنشئ ملفًا صغيرًا وبصمته
يستخدم المثال التالي واجهة createHash في Node.js لإخراج SHA-384 بترميز Base64. احفظه باسم prepare.mjs وشغّله بالأمر node prepare.mjs. يكتب المثال الملف محليًا أولًا كي تكون البصمة محسوبة من بايتاته نفسها. [3]
import { writeFileSync, readFileSync } from 'node:fs';
import { createHash } from 'node:crypto';
writeFileSync('demo.js', "window.SRI_VERSION = 'original';\n");
const bytes = readFileSync('demo.js');
const digest = createHash('sha384').update(bytes).digest('base64');
console.log('sha384-' + digest);أنتج تشغيلنا هذه القيمة. تطابقها يتطلب النص نفسه، بما فيه نهاية السطر التي كتبها البرنامج:
sha384-vVLw6IdAjbBjgR5+Pevu18D/hsLo5N94s4GhwksYvr0ZdlGuZtFSDNam+bH5Uqkx
تتكون قيمة integrity من اسم الخوارزمية ثم شرطة ثم البصمة بترميز Base64؛ لا تستبدل بها النص السداسي الذي تعرضه بعض أدوات فحص الملفات. [4]
جرّب النجاح والفشل محليًا
ضع demo.js بجانب ملف index.html يحتوي المثال الآتي، وقدّم المجلد بخادم تطوير محلي. افتح الصفحة من عنوان الخادم، لا بالنقر على الملف. استعمل أدوات المطور لقراءة window.SRI_VERSION في وحدة التحكم.
<!doctype html>
<html lang="ar" dir="rtl">
<meta charset="utf-8">
<title>تجربة SRI</title>
<p>افتح وحدة التحكم واقرأ window.SRI_VERSION</p>
<script>window.SRI_VERSION = 'not-executed';</script>
<script src="demo.js"
integrity="sha384-vVLw6IdAjbBjgR5+Pevu18D/hsLo5N94s4GhwksYvr0ZdlGuZtFSDNam+bH5Uqkx"></script>
</html>
- في الجولة الأولى، اترك الملف كما أنشأه البرنامج. النتيجة التي نبحث عنها هي
original. - غيّر كلمة
originalداخلdemo.jsإلىchanged، واترك بصمة HTML القديمة. عطّل التخزين المؤقت من أدوات المطور وأعد تحميل الصفحة. ينبغي أن يبقى المؤشرnot-executed. - اقرأ الملف المعدّل واحسب بصمته بالأسطر الثلاثة الأخيرة من برنامج الحساب، ثم حدّث قيمة HTML. لا تعِد تشغيل السطر الذي يكتب النسخة الأصلية فوق تعديلك.
- أعد التحميل: تصبح النتيجة
changedبعد اعتماد البصمة المطابقة. هذه الخطوة توضح لماذا يجب مراجعة التعديل قبل اعتماد بصمته الجديدة.
المؤشر مجرد علامة تجريبية على تنفيذ ملفنا؛ لا تستخدمه فحصًا عامًا لأمان مكتبة حقيقية. عند فشل الجولة الأولى، افحص عنوان الطلب واستجابة الخادم قبل تفسير المشكلة على أنها اختلاف بصمة.
ماذا لو كان الملف على أصل آخر؟
أضف crossorigin="anonymous" للسكربت، واضبط سماح CORS في خادم المورد. المورد العام قد يرسل Access-Control-Allow-Origin: *. البصمة الصحيحة لا تعوض غياب السماح، والسمة لا تُنشئ رأس الخادم. [4]
ما الذي رصدناه في الاختبار؟
شغّلنا ست حالات على Microsoft Edge بإصدار 155.0.4283.45، مع خادمين محليين على منفذين مختلفين لاختبار اختلاف الأصل. أرسل خادم المورد استجابة HTTP 200 في الحالات الست، لكن ذلك لم يعن تنفيذ السكربت دائمًا.
| الحالة | قيمة المؤشر بعد التحميل |
|---|---|
| الملف الأصلي، بصمته الصحيحة، وإعداد CORS كامل | original |
| ملف معدل مع البصمة القديمة | not-executed |
| بصمة صحيحة مع غياب رأس السماح | not-executed |
| بصمة صحيحة مع غياب سمة crossorigin | not-executed |
| ملف معدل وبصمة جديدة مطابقة وإعداد CORS كامل | changed |
| SHA-384 صحيحة ومعها SHA-512 غير مطابقة | not-executed |
هذه نتائج التجربة المحددة، وليست اختبار توافق لكل المتصفحات أو أوضاع التحميل.
لماذا فشلت الحالة الأخيرة؟
يختار المتصفح أقوى خوارزمية مدعومة من القيم الصالحة. لذلك لا تنقذ SHA-384 الصحيحة قيمة SHA-512 الخاطئة. وتكفي مطابقة إحدى بصمات الخوارزمية المختارة. [4]
اجعل التحديث خطوة مراجعة
احتفظ بنسخة محددة من المكتبة، وراجع تغييرها، ثم ولّد بصمتها من الملف النهائي وانشر المرجع الجديد معه. اختبر الوظيفة التي تعتمد عليها المكتبة وحالة الحظر المقصودة. لا تعالج رسالة اختلاف البصمة بحذف integrity؛ حدّد أولًا سبب تغير المورد وهل تقبله. [1]
حدود ينبغي أن تبقى واضحة
إذا تمكن طرف من تغيير صفحة HTML والبصمة المعتمدة معًا، فقد يغير المورد ويمنحه بصمة جديدة. ولهذا تظل حماية تسليم الصفحة واتصالها مطلوبة. كذلك لا تجعل البصمة شيفرة ضعيفة خالية من العيوب، ولا تعني حماية سكربت واحد أن كل موارد الموقع مشمولة بالحماية. [1]
المصادر
- OWASP: سلامة الموارد الفرعية وحدود استخدامها
- W3C: مواصفة SRI المنشورة كتوصية في 2016
- Node.js: إنشاء التجزئة وإخراجها
- MDN: استخدام integrity وشروط CORS واختيار الخوارزمية
نتائج جدول الاختبار والمثال والرسم أُعدت لهذا المقال. أُعدّ النص بمساعدة الذكاء الاصطناعي وتُراجع حساباته وشفرته آليًا؛ لا يُنسب إلى خبير بشري مستقل.