ثلاثة أخطاء أمنية مشتركة يجب أن يعرفها كل مطور تفاعلي

يقول مؤلف المقال ، الذي ننشره اليوم ، إن React هي مكتبتها المفضلة لإنشاء واجهات تفاعلية. React سهل الاستخدام ومحمي بشكل جيد. ومع ذلك ، هذا لا يعني أن تطبيقات React تكون معرضة بالكامل. من السهل جدًا الوقوع في هدوء غير مبرر ، بعد أن قررت أنه لا يمكنك القلق بشأن هجمات XSS نظرًا لأن المشروع يستخدم React.

تحدث نقاط الضعف في رد الفعل غالبًا عندما يعتقد أحد المطورين أنه يستخدم آليات الحماية لهذه المكتبة ، رغم أنه في الحقيقة اتضح أن هذا ليس كذلك. لذلك ، من المهم إجراء تقييم صحيح لقدرات React ، ومعرفة المهام التي يحتاج إليها المبرمج لحلها بمفرده.



اليوم سنتحدث عن نقاط ضعف React النموذجية ، وكيفية العثور عليها أثناء مراجعة التعليمات البرمجية ، وكيفية الدفاع عنها.

المثال الأول (قصير جدًا) للبرامج النصية عبر المواقع


البرمجة النصية للمواقع المشتركة (XSS) هي ثغرة أمنية يمكن أن تؤدي إلى مشاكل خطيرة. تحدث هجمات XSS عندما يتمكن المهاجم من خداع موقع ويب وإجباره على تنفيذ شفرة JavaScript التعسفية في متصفحات مستخدميه.

يتم تنفيذ هجوم XSS المنعكس عن طريق ارتباط يحتوي على معلومات نصية ، والتي تتم معالجتها بواسطة المستعرض في شكل تعليمات برمجية. على سبيل المثال ، هذا حقل نموذج يتم فيه إدخال نص طلب خاص من جانب العميل.

هجوم XSS المخزن هو موقف يكون فيه للمهاجم حق الوصول إلى الخادم ، وعندما تنشئ الشفرة المنفذة على الخادم ما يصل إلى صفحة الويب الخاصة بالعميل. تقوم المتجهات النمطية لهذه الهجمات بتحميل التعليقات والصور على الخوادم.

استغل سامي worm ثغرة MySSpace XSS. كان واحدا من أسرع الفيروسات انتشارا في كل العصور.

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

الثغرة الأمنية رقم 1: التحكم في الحالة الأولية للصفحة ، والتي يتم استخدامها أثناء تقديم الخادم


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

<script>window.__STATE__ = ${JSON.stringify({ data })}</script> 

هذا أمر خطير لأن طريقة JSON.stringify() ، دون "التفكير" في أي شيء ، تحول أي بيانات مقدمة إليها في شكل سلسلة (طالما كانت بيانات JSON صالحة) ، وهذا هو ما سيتم عرضها على الصفحة. إذا كان { data } يحتوي على حقول يمكن لمستخدم غير موثوق به تحريرها ، مثل اسم المستخدم أو معلومات المستخدم ، فيمكن تضمين شيء مثل التالي في هذه الحقول:

 { username: "pwned", bio: "</script><script>alert('XSS Vulnerability!')</script>" } 

غالبًا ما يتم استخدام هذا النمط في التقديم من جانب الخادم لتطبيقات React التي تستخدم Redux. لقد كان حاضرًا في وثائق Redux الرسمية ، ونتيجة لذلك ، لا يزال العديد من البرامج التعليمية وقوالب نماذج التطبيقات التي يمكن العثور عليها على GitHub تستخدمها.

لا تصدق؟ ثم انظر لنفسك. ابحث في Google عن النص "تفاعل مع تطبيق مثال على تقديم جانب الخادم" وجرب هذا الهجوم على أي من نتائج البحث من الصفحة الأولى.

of تحديد نقاط الضعف أثناء مراجعة الكود


ابحث عن المكالمات إلى طريقة JSON.stringify() التي تقبل المتغيرات التي قد تحتوي على بيانات غير موثوق بها في علامة script . فيما يلي مثال تم استخدامه في وثائق Redux:

 function renderFullPage(html, preloadedState) {    return `        <!doctype html>        <html>            <head>                <title>Redux Universal Example</title>            </head>            <body>                <div id="root">${html}</div>                <script>                    window.__PRELOADED_STATE__ = ${JSON.stringify(preloadedState)}                </script>                <script src="/static/bundle.js"></script>            </body>        </html>        ` } 

وهنا جزء من التعليمات البرمجية من نموذج التطبيق الموجود على جيثب:

 function htmlTemplate( reactDom, reduxState, helmetData ) {    return `    <!DOCTYPE html>    <html>    <head>        <meta charset="utf-8">        ${ helmetData.title.toString( ) }        ${ helmetData.meta.toString( ) }        <title>React SSR</title>        <link rel="stylesheet" type="text/css" href="./styles.css" />    </head>       <body>        <div id="app">${ reactDom }</div>        <script>            window.REDUX_DATA = ${ JSON.stringify( reduxState ) }        </script>        <script src="./app.bundle.js"></script>    </body>    </html>    `;   } 

أحيانًا يكون العثور على مشكلة عدم الحصانة هذه أكثر صعوبة قليلاً. سوف تتحول التعليمة البرمجية التالية أيضًا إلى أنها غير آمنة - إذا لم context.data تنفيذ الهروب الصحيح من context.data :

 const RenderedApp = htmlData.replace('{{SSR}}', markup)    .replace('<meta-head/>', headMarkup)    .replace('{{data}}', new ArrayBuffer(JSON.stringify(context.data)).toString('base64')) 

عند القيام بالعرض من جانب الخادم ، انتبه لما يتم تقديمه بالضبط. إذا كان ما يدخله المستخدم غير محمي بشكل صحيح وعرضه في DOM ، فقد يكون ذلك خطيرًا.

▍ الحماية


أحد خيارات الحماية من مشكلة عدم الحصانة هذه هو استخدام وحدة npm serialize-javascript ، المصممة لحماية المخرجات JSON. إذا كنت تقوم بتقديم الخادم في بيئة غير Node.js ، فستحتاج إلى اختيار الحزمة المناسبة للغتك.

هنا هو الأمر لتثبيت الوحدة النمطية:

 $ npm install --save serialize-javascript 

بعد ذلك ، تحتاج إلى استيراده إلى ملف وإعادة كتابة التعليمات البرمجية التي كانت عرضة للإصابة بهجمات الفيروسات والتي كانت تتعامل مع window يلي:

 <script>window.__STATE__ = ${ serialize( data, { isJSON: true } ) }</script> 

هنا مقالة رائعة حول هذا الموضوع.

الضعف №2: روابط خبيثة


يمكن أن يكون للعلامة <a> سمة href ، والتي تحتوي على رابط إلى صفحة أخرى من الموقع ، إلى موقع آخر ، إلى مكان ما في الصفحة الحالية. قد تحتوي الروابط على برامج نصية تبدو كالتالي: javascript: stuff() . إذا لم تكن على علم بميزة HTML هذه ، فجربها الآن عن طريق نسخ الكود التالي في خط المتصفح:

 data:text/html, <a href="javascript: alert('hello from javascript!')" >click me</a> 

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

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

of تحديد نقاط الضعف أثناء مراجعة الكود


هل يمكن لمستخدمي المشروع إضافة روابط إلى الصفحات التي يمكن للمستخدمين الآخرين النقر عليها؟ إذا كان الأمر كذلك ، فحاول إضافة "رابط" إلى الصفحة كما يلي:

 javascript: alert("You are vulnerable to XSS!") 

إذا تم عرض مربع الرسالة المطابق بالنقر فوق الارتباط ، فهذا يعني أن المشروع عرضة لهجمات XSS. جرب هذا أينما يمكنك إضافة روابط. من المحتمل ألا تكون كل هذه الأماكن معرضة للخطر.

▍ الحماية


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

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

تتمثل الإستراتيجية الأخرى التي يمكنها إضافة مستوى إضافي من الحماية للمشروع في استخدام آلية فتح الروابط المخصصة في علامات تبويب المتصفح الجديدة. ومع ذلك ، لا أوصي باستخدام هذه الاستراتيجية باعتبارها "خط الدفاع" الوحيد للمشروع. فتح javascript: الروابط في علامة تبويب جديدة هي مثال على السلوك غير القياسي لعناصر الصفحة. ستعمل معظم المتصفحات على تشغيل البرنامج النصي في علامة تبويب فارغة دون الإضرار بالمستخدم ، ولكن هذا غير مضمون ، وربما يمكنك التغلب على هذا الأمر ، والذي يعتمد على المستعرض.

ضع في اعتبارك استخدام مكون UserLink الخاص ، والذي سيؤدي إلى حقيقة أن علامة <a> الضعيفة أقل احتمالًا للوصول إلى صفحات مشروعك في المستقبل. بالإضافة إلى ذلك ، يجدر إضافة بعض الاختبارات وقواعد الفحص للمشروع ، بهدف تحديد رمز يحتمل أن يكون خطيرًا ومنعه من الدخول في الإنتاج.

الروابط ليست هي الكيانات الوحيدة التي يمكن استخدامها بهذه الطريقة. لكنها على الأرجح هدف الهجوم في تطبيقات React. يمكن لأي عنصر أن يكون عرضة لهذا الهجوم إذا تمكن المهاجم من التحكم في قيمة URI الخاصة به. هناك احتمال آخر لتنفيذ هذا الهجوم ، على سبيل المثال ، هو تصميم عرض. يمكن العثور على قائمة كاملة من السمات التي قد تحتوي على URIs في هذه القائمة باستخدام الكلمة الأساسية %URI باستخدام بحث المتصفح ( Ctrl+F ).

الضعف رقم 3: سوء فهم معنى البناء بشكل خطير SetInnerHtml


أنا ممتن للغاية لرد الفعل على أن تحذير الأمان موجود مباشرة في اسم الطريقة. هذا هو الاسم بشكل dangerouslySetInnerHTML . على الرغم من هذا التحذير ، لا نزال نواجه في كثير من الأحيان حقيقة أن المطورين يتحملون المخاطر من خلال إجراء عمليات غير آمنة. ويمكن قول الشيء نفسه من eval() .

اطلع على المثال التالي الذي وجدته على الموقع من الصفحة الأولى لنتائج بحث Google:

 <script dangerouslySetInnerHTML={{ __html: `window.__PRELOADED_STATE__ = ${JSON.stringify(initialState)};`}}></script> 

هذا مثال على الضعف رقم 1 ، ولكن مع ميزة واحدة يجب أن تسترعي الانتباه إلى حقيقة أن هناك خطأ ما هنا. حيث وجدت هذا ، جرت محاولة لشرح: "نحن نستخدم بشكل خطير SetInnerHTML كوسيلة لتنظيف البيانات ومنع هجمات XSS." حسنا لا! هذا خطأ لا تفعل ذلك. لمزيد من المعلومات حول dangerouslySetInnerHTML SetInnerHTML ، اقرأ وثائق React.

مثال آخر على أن هذا يحدث فعليًا طوال الوقت هو كيف اكتشف أعضاء فريق واحد أن لديهم ثغرة أمنية عند قيامهم بإضافة علامة Markdown إلى صفحة تستخدم بشكل dangerouslySetInnerHTML SetInnerHTML. من أجل حماية أنفسهم من هذا في المستقبل ، بدأوا في استخدام قاعدة خاصة من الوبر.

of تحديد نقاط الضعف أثناء مراجعة الكود


قبل إرسال طلبات السحب أو إجراء عمليات الدمج ، من المفيد البحث في التعليمات البرمجية عن سلاسل dangerouslySetInnerHTML و eval (ابحث أيضًا عن أوامر console.log بهذه الطريقة) أو استخدام قاعدة linter المقابلة.

▍ الحماية


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

مكون الخداع ملاحظة


في عام 2015 ، اكتشف شخص ما أنه يمكنك محاكاة ساخرة للمكونات عن طريق تمرير JSON إلى تلك المكونات التي تتوقع نصًا. تمكنت من العثور على حالة واحدة فقط من رسالة خداع مكون ومناقشة طويلة سببها هذه الرسالة. ركزت المناقشة على ما هي React المسؤولة عن منع هجمات XSS. نتيجة لذلك ، أصدر مطورو React إصلاحًا يبدو أنه ساعد في إصلاح هذه الثغرة الأمنية.

قررت عدم إدراج قصة حول هذه الثغرة الأمنية في المقالة ، ولكن قد يكون هذا الموضوع ذا أهمية لمزيد من البحث.

SSR ملاحظة


خادم تقديم الضعف واسع الانتشار بسبب حقيقة أنه كان موجودا في وثائق Redux ، ونتيجة لذلك ، انتشر عبر العديد من المواد الأخرى. تم إصلاح هذه المشكلة في عام 2016. لكن حتى اليوم ، بعد ثلاث سنوات ، ما زال المرشدين المبتدئين المنتشرين في جميع أنحاء الإنترنت يعلمون ما يجب ألا تدرسه.

بالمناسبة ، إليك واجبك: ابحث عن مثال لهذه المشكلة على GitHub وأرسل طلب سحب لإصلاحه. هنا مثال .

معا يمكننا مرة واحدة وإلى الأبد التخلص من هذه الثغرة الأمنية!

أعزائي القراء! هل واجهت هجمات على مشاريع React الخاصة بك؟

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


All Articles