شرح حقن القوالب من جانب الخادم (Server-Side Template Injection - SSTI)

Safely LocK
0



المقدمة:

محركات القوالب (Template Engines) هي نوع من البرمجيات المستخدمة لتحديد مظهر صفحة الويب. غالبًا ما يتجاهل المطورون الهجمات التي تستهدف هذه المحركات، والتي تُعرف بـ Server-Side Template Injections (SSTIs)، على الرغم من أن هذه الهجمات يمكن أن تؤدي إلى عواقب وخيمة مثل تنفيذ الأكواد عن بُعد. لقد أصبحت هذه الهجمات أكثر شيوعًا في السنوات الأخيرة، مع وجود حالات تم اكتشافها في تطبيقات شركات مثل Uber وShopify .



آلية العمل:

لفهم كيفية حدوث حقن القوالب (Template Injections)، يجب أولًا فهم كيفية عمل محركات القوالب. ببساطة، تقوم هذه المحركات بدمج بيانات التطبيق  مثل اسم المستخدم من قاعدة البيانات  مع قوالب الويب المكتوبة بلغات مثل Jinja، لإنشاء صفحات ويب ديناميكية. هذه العملية تسمح للمطورين بتحديد كيفية ظهور الصفحات مع الحفاظ على فصل منطق الخادم (مثل معالجة البيانات) عن تصميم الواجهة الأمامية (مثل تنسيق HTML).


ما هو محرك القوالب (Template Engine) ؟:

  •     تخيل أن لديك تطبيق ويب يستخدم محرك قوالب مثل Jinja2 (المستخدم في لغة Python). ببساطة، يأخذ محرك القوالب البيانات من الخادم ويقوم بإدراجها في صفحة HTML بطريقة منظمة. هذا يساعد المطورين على فصل منطق الخادم (Back-end) عن تصميم الصفحة (Front-end).


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



كيف يعمل ؟:

  •     تخيل أن لديك موقع ويب يعرض قائمة من المنتجات. بدلًا من كتابة HTML ثابت لكل منتج، يمكنك استخدام محرك قوالب لإنشاء قالب واحد قابل لإعادة الاستخدام، وسيقوم الخادم تلقائيًا بملئه بالبيانات من قاعدة بيانات أو مصدر آخر.




لماذا نستخدم محركات القوالب ؟:

تحسن محركات القوالب كفاءة عرض صفحات الويب من خلال السماح للمطورين بإعادة استخدام القوالب مع عرض بيانات مختلفة بشكل ديناميكي.



أهم فوائد محركات القوالب:

  •  ✅ إعادة الاستخدام: يمكن للمطورين استخدام نفس القالب لإنشاء صفحات متعددة بمحتوى مختلف.

  • ✅ التنسيق الموحد: يضمن الاتساق عبر صفحات متعددة (مثل قوائم المنتجات أو ملفات المستخدمين).
  • ✅ فصل المهام: يتم فصل كود HTML عن منطق الأعمال، مما يسهل التعديل والصيانة.
  •  ✅ الكفاءة: يقلل من التكرار ويسرع عملية التطوير.




مثال على Jinja في Python:

ما هو Jinja ؟:

Jinja هي لغة قوالب لـ Python تُستخدم لإنشاء صفحات HTML ديناميكية. تسمح بفصل منطق الخادم عن العرض الأمامي.






النتيجة بعد تنفيذ الكود:







📌 النقاط الرئيسية:

  •      ✅ `{{ list_title }}` و `{{ list_description }}`: هذه تعبيرات تُستخدم لإدراج قيم ديناميكية في HTML.
  •      ✅ `{% for item in item_list %}`: هذه عبارة تكرار (Loop) تقوم بالمرور على قائمة من العناصر.
  •      ✅ `{% if not loop.last %},{% endif %}`: تضمن إضافة فاصلة بين العناصر، باستثناء العنصر الأخير.




قواعد تركيب Jinja:

  • `{{ }}` (التعبيرات): تُستخدم للمتغيرات أو الدوال التي تُرجع قيمًا.
  • `{% %}` (العبارات): تُستخدم لبنيات التحكم (التكرارات، الشروط، إلخ).




حقن القوالب (Template Injection):

  •     تحدث ثغرات حقن القوالب عندما يتم إدخال بيانات المستخدم في القوالب دون تعقيم مناسب، مما يسمح للمهاجمين بحقن وتنفيذ أكواد ضارة. على سبيل المثال، النهج الآمن (مثل الكود الأول) يقوم بتمرير بيانات المستخدم كمتغيرات إلى قالب Jinja2 باستخدام "render ()" مع متغيرات محددة (`list_title`, `list_description`, `item_list`). هذا يمنع الحقن لأن المدخلات تُعامل كبيانات عادية وليست أكواد قابلة للتنفيذ.


  ولكن الخطر يظهر عندما يقوم المطورون بدمج مدخلات المستخدم مباشرة في سلسلة القالب، كما في "Template("<html><h1>The user’s name is: " + user_input + "</h1></html>")" ، هنا، لا يستطيع محرك القوالب (Jinja2) التمييز بين مدخلات المستخدم ومنطق القالب ، على سبيل المثال:

  •     إدخال غير ضار مثل Vickie يعرض <h1>The user’s name is: Vickie</h1>.
  •     ولكن إدخال مثل {{1+1}} يتم تنفيذه ككود Python، مما يؤدي إلى "<h1>The user’s name is: 2</h1>".
  •     والأسوأ، إدخال مثل "{{‘Vickie’.upper()}}" يعرض <h1>The user’s name is: VICKIE</h1>، مما يظهر كيف يمكن للمهاجمين تنفيذ تعبيرات Python عشوائية.



الخلاصة الرئيسية:
الدمج المباشر يخلط بين البيانات والأكواد، مما يسمح للمهاجمين بحقن وتنفيذ أوامر ضارة. اعتمادًا على صلاحيات النظام، يمكن أن يؤدي هذا إلى استغلال خطير مثل قراءة ملفات حساسة أو تصعيد الصلاحيات. للبقاء في أمان، قم دائمًا بتمرير مدخلات المستخدم كمتغيرات إلى `render()`، ولا تقم أبدًا بدمجها مباشرة في القالب.



مثال على الكود الآمن







لماذا هذا الكود آمن؟:

  •     يتم تمرير مدخلات المستخدم كبيانات وليس كأكواد: يتم تمرير القيم من `user_input` (مثل `title`, `description`, `list`) إلى `render()` كمتغيرات. Jinja2 يعاملها كبيانات عادية للعرض وليس كمنطق قالب قابل للتنفيذ.

  •     لا يوجد دمج مباشر: على عكس المثال الخطير (`Template("… " + user_input + "…")`)، هذا الكود لا يدمج مدخلات المستخدم مباشرة في سلسلة القالب. القالب (`example.jinja`) محدد مسبقًا ومنفصل عن المدخلات.




ماذا لو كانت مدخلات المستخدم ضارة ؟:

  •     إذا كانت `user_input.title = "{{1+1}}"`، سيكون الناتج `<h1>{{1+1}}</h1>` (نص حرفي)، وليس `<h1>2</h1>`. Jinja2 يقوم بتهريبها ما لم يتم تعطيل ذلك.

  •     إذا كانت `user_input.title = "<script>alert('hack')</script>"`، سيتم عرضها كـ `<h1>&lt;script&gt;alert('hack')&lt;/script&gt;</h1>` (يتم تهريب HTML افتراضيًا)، مما يمنع تنفيذ السكريبت في المتصفح.



النقاط الرئيسية :

  •  التصميم الآمن: بتمرير مدخلات المستخدم كمتغيرات إلى `render()`، يعرف محرك القوالب أنها بيانات وليست تعليمات، مما يمنع مخاطر الحقن.
  •  الفصل: منطق القالب (في `example.jinja`) معزول عن مدخلات المستخدم، على عكس الدمج المباشر.
  •   التهريب الافتراضي: Jinja2 يقوم تلقائيًا بتهريب الأحرف الخاصة (مثل `<`, `>`) ما لم يتم تعطيل ذلك، مما يضيف طبقة إضافية من الأمان.



مثال على الكود الضعيف:
 





ما الذي يحدث هنا ؟:

  •   `from jinja2 import Template`: يستورد فئة `Template` من Jinja2، وهي مكتبة لإنشاء قوالب ديناميكية في Python.

  •  `tmpl = Template("…")`: ينشئ قالبًا عن طريق دمج سلسلة HTML ثابتة (`<html><h1>The user’s name is: `) مع `user_input` (متغير يُفترض أنه يحتوي على بيانات من المستخدم) وإغلاقها بـ `</h1></html>`. العامل `+` يقوم بدمج هذه العناصر مباشرة في سلسلة القالب.

  •  print(tmpl.render()): يقوم بعرض القالب وطباعة HTML الناتج. بما أنه لم يتم تمرير أي متغيرات إلى `render()`، فإن Jinja2 يعالج أي شيء تم تضمينه في سلسلة القالب.




لماذا هذا الكود خطير ؟:

  •     الدمج المباشر: يتم دمج `user_input` مباشرة في سلسلة القالب باستخدام `+`. Jinja2 لا يستطيع التمييز بين مدخلات المستخدم ومنطق القالب، لذا يقوم بتفسير أي شيء داخل `{{ }}` ككود Python قابل للتنفيذ.

  •     لا يوجد فصل: على عكس تمرير المدخلات كمتغيرات (مثل `render(name=user_input)`)، هنا تصبح المدخلات جزءًا من القالب نفسه. إذا قدم المستخدم `{{1+1}}`، فإن Jinja2 ينفذها بدلًا من معاملتها كنص عادي.

  •     تنفيذ أكواد عشوائية: يمكن للمهاجمين حقن تعبيرات Python مثل `{{‘secret’.upper()}}` أو أسوأ (مثل الوصول إلى وظائف النظام إذا كان مسموحًا)، مما قد يؤدي إلى:
  •     كشف البيانات الحساسة.
  •      اختراق النظام، اعتمادًا على صلاحيات التطبيق.



النقاط الرئيسية:

  • الثغرة: دمج `user_input` مباشرة في سلسلة القالب يفتح الباب أمام حقن القوالب، حيث يمكن تنفيذ مدخلات المستخدم كأكواد.

  •  خطر التنفيذ: أي شيء داخل `{{ }}` من المستخدم (مثل `{{1+1}}`, `{{‘text’.upper()}}`) يتم تنفيذه كـ Python، وليس فقط عرضه كنص.

  • الإصلاح: قم بتمرير مدخلات المستخدم كمتغيرات إلى `render()`، مع الحفاظ على فصل منطق القالب عن البيانات.

  • التأثير الواقعي: إذا تم تشغيل هذا على خادم ويب، يمكن للمهاجمين تصميم مدخلات للتلاعب بالتطبيق، سرقة البيانات، أو تصعيد الصلاحيات



نصيحة أمنية أخيرة:

لمنع مخاطر SSTI، قم بتمرير مدخلات المستخدم كمتغيرات، وتجنب السماح للمحتوى الذي يتحكم فيه المستخدم بأن يصبح جزءًا من منطق القالب، وتأكد من التهريب والتحقق المناسب، واستخدم العزل (Sandboxing) عندما يكون ذلك ممكنًا.



حسابنا على Linkedin

إرسال تعليق

0تعليقات

إرسال تعليق (0)

#buttons=(موافق!) #days=(20)

يستخدم موقعنا ملفات تعريف الارتباط لتحسين تجربتك. تاكد الان
Ok, Go it!