متوفر أيضًا بلغات أخرى: English · Español · Português · Français
X-Frame-Options: ماذا تفعل هذه الترويسة حقًّا اليوم
الصق ترويستك والإطارات المحيطة بالصفحة، وانظر أي خطوة من خطوات المعيار هي الفاصلة.
ما هي X-Frame-Options؟
X-Frame-Options ترويسة استجابة تخبر المتصفح هل يجوز عرض صفحتك داخل إطار يملكه شخص آخر. وُجدت لصدّ هجوم سرقة النقر: إذ يضمّن المهاجم صفحتك الحقيقية، ويجعلها غير مرئية، ثم يدفع الضحية إلى النقر على زر لا تراه. وقيمتان فقط لهما معنى: DENY ترفض التأطير كله، وSAMEORIGIN تسمح به من أصلك أنت وحده.
الترويسة أقدم من المسار الذي يُنتج معايير الويب عادةً. فقد أطلقتها المتصفحات نحو عام 2009، وكُتب الوصف الذي يستشهد به الجميع، أي RFC 7034، بعد ذلك بأربع سنوات لتوثيق ما كان قد بُني بالفعل. وتلك الوثيقة مصنَّفة إعلامية، وتقول ذلك عن نفسها في سطورها الأولى: إنها ليست مواصفة على مسار معايير الإنترنت.
أي أن الوثيقة التي تحيل إليها أكثر الصفحات لم تعد هي التي تحكم السلوك. فمعيار HTML هو الذي يحمل الآن نموذج المعالجة، ويصرّح بأن تعريفه يَجُبّ تعريف تلك الوثيقة. والقواعد التي يوردها أقصر، والخوارزمية أدقّ، وهو يحسم مسائل عدة تركتها الوثيقة الأصلية مفتوحة صراحةً.
طريقة الاستخدام
- أدخِل ترويستك. واحدة في كل سطر إن كانت الاستجابة ترسل أكثر من واحدة. فالقيمة المفصولة بالفواصل وعدة ترويسات منفصلة متكافئتان معياريًّا، ومن ثم يعطي الشكلان الإجابة نفسها هنا.
- صِف الإطارات المحيطة بالصفحة. أعطِ أصل المستند الذي يرسل الترويسة، ثم الأصول التي تؤطّره، من الأقرب إلى الأبعد وصولًا إلى لسان المتصفح. وهذا أهم مما يبدو: فالفحص يصعد السلسلة كاملة.
- أضِف سياسة Content-Security-Policy إن كنت ترسلها. إذا حملت سياسة مُنفَّذة توجيه frame-ancestors، جرى تجاهل X-Frame-Options تمامًا. وأشِّر على خانة Report-Only لترى الفارق، وهو أكبر مما يتوقعه معظم الناس.
الحالات التي لا يدوّنها أي جدول
السلوك اللافت يظهر حين تحمل الاستجابة أكثر من قيمة، وهو أمر شائع عمليًّا لأن وسيطًا أو إطار عمل يضيف ترويسة كان التطبيق قد ضبطها أصلًا. وينشر المعيار جدول إجابات محلولة لهذه الحالات بالذات، والنتائج ليست ما قد تخمّنه. فـ SAMEORIGIN إلى جانب قيمة فاسدة تحجب الصفحة. وقيمتان فاسدتان تسمحان بها. والقاعدة مقصودة: فالترويسة التي تحمل قيمة ذات معنى وأخرى مضطربة تبدو كإعداد خاطئ لشيء كان يحاول أن يعمل، فتُحجب عن عمد، بينما الترويسة غير المقروءة بالكامل تُعامَل كأنها لم تُرسَل قط.
وتكفي فاصلة في النهاية لتفجير ذلك. فالفصل بالفواصل يحوّل SAMEORIGIN, إلى قيمتين، الثانية فارغة، وتُحتسب قيمةً ثانية مغايرة، فتُحجب الصفحة. وإرسال SAMEORIGIN في ترويسة وX-Frame-Options فارغة في أخرى يفعل الشيء نفسه، وللسبب نفسه تمامًا.
وALLOWALL هي الناجية الأغرب. فهي لا ترد في RFC 7034 على الإطلاق — ولم تكن يومًا جزءًا من قواعد الترويسة الموثَّقة — ومع ذلك يسمّيها المعيار، لغرض واحد لا غير هو أن تلتقطها قاعدة تعدد القيم. وهي وحدها لا تفعل شيئًا البتة، والصفحة التي ترسل ALLOWALL فقط قابلة للتضمين كصفحة لا ترسل ترويسة أصلًا.
وALLOW-FROM هي التي ما زال الناس ينسخونها من الشروح. فهي في قواعد الوثيقة الأصلية، ويقول معيار HTML بأوضح عبارة إنها لا ينبغي أن تُنفَّذ. والصفحة التي تعتمد عليها للسماح لشريك بعينه إنما تسمح للجميع، في صمت، لأن القيمة التي لا تقبلها القواعد تُعامَل كأن لا ترويسة هناك.
السؤال الذي تركته الوثيقة الأصلية مفتوحًا
تبدو SAMEORIGIN قاطعة الدلالة وليست كذلك. تخيّل صفحة تؤطّرها أداة شريك، وتلك الأداة مؤطَّرة بدورها بموقعك أنت في المستوى الأعلى. فهل الأصل الذي تجري مقارنته هو أصل الصفحة المؤطِّرة مباشرةً، أم أصل مستند المستوى الأعلى في اللسان، أم أصول كل المستندات بينهما؟ تقرّ RFC 7034 بالقراءات الثلاث في نصها هي، إذ تلاحظ أن المعايير قد لا تُقيَّم بإجماع، ثم تعدّد كل احتمال.
ويحسم معيار HTML الأمر: يصعد الفحص سلسلة السوابق كاملة، ويكفي مستند واحد من أصل مختلف في أي موضع منها لحجب الصفحة. فالمثال أعلاه مرفوض إذن، وإن كانت صفحة المستوى الأعلى صفحتك. وهذه أشدّ القراءات الثلاث، وهي التي تنفّذها الأداة أعلاه — ولهذا يبدو المثال الافتراضي كأنه ينبغي أن يُسمح به وهو ليس كذلك.
والقاعدة الأخرى الجديرة بالمعرفة أن توجيه CSP باسم frame-ancestors لا يكتفي بأن تكون له الأولوية، بل يُخرج X-Frame-Options من الحساب كليًّا. إذ تبحث الخوارزمية عن التوجيه قبل أن تنظر في قيمة الترويسة أصلًا، فالصفحة التي ترسل DENY مع أي سياسة تتضمن frame-ancestors تحكمها السياسة وحدها. غير أن هذا لا يسري إلا على سياسة مُنفَّذة. أما ترويسة Content-Security-Policy-Report-Only فتُتخطّى، لأن الخوارزمية لا تنظر إلا في السياسات التي صفتها التنفيذ — ومن ثم فنقل frame-ancestors إلى وضع الإبلاغ فقط أثناء الاختبار يعيد زمام الأمر، بلا إشعار، إلى ترويسة ربما كففت عن التفكير فيها.
ما لا تستطيع هذه الأداة إخبارك به
هي تخبرك بما يجب أن يفعله متصفح مطابق للمعيار، لا بما يفعله متصفح بعينه. والتمييز حقيقي: فسبب إقرار الوثيقة الأصلية بوجود التباس هو أن التنفيذات كانت مختلفة، وقد يحمل متصفح سلوكًا قديمًا سنوات. ولم يُقَس شيء هنا في مواجهة متصفح حقيقي، وملحق دعم المتصفحات في وثيقة من عام 2013 ليس دليلًا على حال اليوم.
وهي لا ترى الصفحة التي تسأل عنها. فالأصول أنت من يوردها، ولا تصحّ الإجابة إلا بقدر صحة السلسلة التي وصفتها — والسلسلة هي الجزء السهل الخطأ فيه، إذ قد تؤطّر صفحتك جهة لم تضعها أنت هناك. وإن أردت الجواب الحقيقي لصفحة حقيقية، فأدوات المطوّر في المتصفح تخبرك متى رُفض إطار ولماذا.
وأخيرًا، X-Frame-Options هي النصف الأقدم من ثنائي. فكل ما تعبّر عنه بها يمكن التعبير عنه بتوجيه CSP باسم frame-ancestors، وهو يغطي فوق ذلك ما تعجز الترويسة عنه: السماح لأصل بعينه، أو لعدة أصول، أو المطابقة على المخطط. وتظل الترويسة جديرة بالإرسال للعملاء القدامى، ويتعايش الاثنان بلا مشكلة، لكن أي نشر جديد ينبغي أن تقوده السياسة لا الترويسة.
لماذا هي مجانية؟
تنفيذ خوارزمية من مواصفة قياسية حسابٌ على بضع سلاسل نصية، ويجري داخل متصفحك. لا خادم في المسار، فلا شيء يستوجب فاتورة ولا حساب يلزم إنشاؤه.
لا يُرفع أي شيء. فالترويسة والأصول التي تكتبها لا تغادر التبويب.