
A OSINT project that explores how to dump data from React
هذه الأداة عبارة عن سكربت مستخدم سريع وغير منقّح لـ Tampermonkey يتوغل بضع مستويات في أي صفحة React ويبحث عن عبارة واحدة أو أكثر يقدمها المستخدم.
تجعل الأداة من السهل العثور على المكان الصحيح في DOM حيث يرفق React كميات كبيرة من بيانات JSON.
قد يكون العثور على هذه الأماكن يدويًا مستهلكًا للوقت جدًا، لأنه يعتمد بشكل كبير على المطوّر، وإصدار React، ومدى تعقيد الموقع المحدد، في كيفية تخزين البيانات وتمريرها.
يهدف سكربت المستخدم هذا إلى جعل هذه العملية أسهل بكثير.
فيما يلي مقطع فيديو للسكربت أثناء الاستخدام.

لمزيد من الخلفية حول كيفية عمل هذا وسببه، راجع البرنامج التعليمي حول الموضوع نفسه في مكان آخر في هذا المستودع.
انسخ سكربت المستخدم من هذا المستودع واتبع التعليمات في وثائق Tampermonkey حول كيفية تثبيت السكربت.
خلاصة الأمر أنك تختار Create a new userscript، وتحذف أي كود قالب (boilerplate) يقترحه Tampermonkey، وتلصق سكربت المستخدم، ثم تضغط حفظ. وبعدها تصبح جاهزًا.
عند التثبيت، يوفّر سكربت المستخدم قائمة سياق بزر الفأرة الأيمن تحتوي على زرّين، يجب أن يكونا مفعّلين على جميع المواقع التي تستخدم React (إذا وجدت موقعًا لا يعمل عليه، فيُرجى إخباري):
reactPropsreactFiberيمكن رؤية ذلك أدناه.

سُمّي الزران على اسم خاصيتين داخليتين يرفقهما React بعُقد HTML في DOM العادي. يستخدمهما React لتمرير البيانات داخليًا، وبناء الصفحة، والحفاظ على مزامنة حالة الصفحة مع شجرة DOM الافتراضية الخاصة به (VDOM)، والاستجابة لإجراءات المستخدم وما إلى ذلك.
ومن خلال هاتين الخاصيتين أيضًا يمكننا الوصول إلى البيانات الأولية وتفريغها بكميات كبيرة، وكذلك أطنان من البيانات التي لا تكون مكشوفة في DOM.
لاستخدام الأداة، افتح ببساطة وحدة تحكم JavaScript في أدوات المطوّرين واختر أحد الخيارين. إذا لم يمنحك أحدهما أي بيانات، فجرّب الآخر. وكما ذُكر، يبدو أن ما يعمل يعتمد بشكل كبير على الموقع المحدد.
في هذا المثال، أبحث عن بيانات حول فيديوهات SANS Institute على TikTok. وقد أدخلت إحدى العبارات - four days - الموجودة تحت أول الفيديوهات:

يتم تحويل الإدخال الذي تقدّمه لسكربت المستخدم إلى أحرف صغيرة وتجريد المسافات البيضاء قبل مقارنته بالمحتوى المرفق كخصائص على عُقد HTML، لذا فقط اكتب ما تريد.
إذا أردت، يمكنك أيضًا استخدام عبارات متعددة، فقط افصل بينها بفاصلة. إذا أردت استهداف فيديوهات متعددة في مثال TikTok، يمكن أن يكون الإدخال four days,congratulations,thank you.
يستخدم السكربت OR وليس AND كعامل بحث.
يمكنك أيضًا استخدام رمز بدل *، والذي سيفرّغ كل شيء.
لكن، تحذير بسيط بشأن ذلك:
قد يؤدي إجراء بحث بـ * إلى تعطل أدوات المطوّر لديك، ببساطة لأن ذلك قد يفرّغ عشرات الآلاف من صفوف البيانات بسهولة. لذا استخدم تلك الميزة فقط كملاذ أخير. خاصة على Facebook، ستغرق في البيانات إذا فعلت ذلك.
بشكل عام، من الأشياء المفيدة للبحث عنها بعض أسماء المستخدمين / معرّفات المستخدمين التي تعرف أنه ينبغي أن تكون موجودة - أو إذا كنت تعرف أن هناك خاصية في مكان ما بالداخل اسمها videoData فببساطة استخدمها.
عند إطلاق السكربت على TikTok (reactProps)، يتم تسجيل مجموعة من البيانات في وحدة تحكم JavaScript - وكذلك في الحافظة لديك. في الأسفل، سترى عدد مرات التطابق التي حققتها أنماط البحث (5 في هذه الحالة).

إذا أردت استكشاف بيانات JSON، فقط الصقها في محرر - يُفضَّل أن يكون محررًا يدعم JSON وإبراز بناء الجملة (syntax highlighting). فهذا يجعل مراجعتها أسهل بكثير.
لكن الميزة الرائعة حقًا - إذا كنت تخطط لبناء أدوات تعتمد على React للموقع المحدد - ليست تفريغ الحافظة. فإلى جانب تفريغ البيانات، يسجّل السكربت أيضًا كلاً من عقدة HTML التي حققت التطابق، ومسار الخاصية الدقيق الذي وُجد فيه التطابق.

تحل هذه الميزة أحد المتاعب الحقيقية عند محاولة مطابقة VDOM الخاص بـ React مع DOM العادي، الذي يمكننا - على عكس VDOM - التفاعل معه باستخدام JavaScript الخام (vanilla JavaScript).
في هذه الحالة، يخبرنا المخرَج أن البيانات التي نريدها مرفقة كخصائص، ضمن عقد أخرى، بعقدة HTML <div class="css-x6y88p-DivItemContainerV2 e19c29qe8"> كخاصية في المسار: __reactProps$xunlb5k9rwt | children | 1 | props.
امتلاك هذه المعرفة يعني أننا نعرف الآن بالضبط أي عقدة - وفي أي مسار - يمكننا جلب البيانات منها.
الرمز | هو مجرد فاصل اخترته. عند تحويل هذا إلى سكربت، استبدله بترميز النقطة (dot notation) هكذا __reactProps$xunlb5k9rwt.children[1].props - أو بترميز الأقواس المربعة هكذا ["__reactProps$xunlb5k9rwt"]["children"][1]["props"].

كما ذُكر في البرنامج التعليمي الخاص بـ React في مكان آخر في هذا المستودع، يحتوي جزء __reactProps على سلسلة من 10 أحرف يتم توليدها عشوائيًا عند كل تحميل للصفحة.
راجع البرنامج التعليمي للحصول على مثال عملي حول كيفية سحب المفتاح الذي تحتاجه من إحدى عُقد HTML.
ما يفعله السكربت فعليًا هو التوغل بضع مستويات في كل خاصية من الفئة المختارة (__reactFiber أو __reactProps) ومحاولة تحويل كل ما بداخلها إلى JSON (JSON.stringify()). إذا كانت الكائنات بداخلها تحتوي على مراجع دائرية (circular references) - وكثير منها سيفعل - فلا يمكن تحليلها كـ JSON. محاولة تحويلها ستُطلق خطأً يتم التقاطه، وستتجاهل الحلقة ذلك ببساطة وتواصل العمل.
ينظر السكربت حاليًا أيضًا إلى خصائص وسوم <div> و <article> فقط. إذا وجدت أنه يفوت شيئًا لهذا السبب، فيُرجى إخباري. هذا العمل قيد التطوير المستمر.
كما أن السكربت لا يتعمق كثيرًا في الاستدعاء الذاتي داخل الخصائص. أولاً، أنا سيئ في الاستدعاء الذاتي (recursion). ثانيًا، لست مهتمًا كثيرًا بالأشياء المتداخلة بعمق داخل الخصائص، لأن بناء أشياء فوقها يكون أكثر عرضة للكسر حتى مع تغييرات طفيفة على المنصات التي قد يستهدفها المرء. من تجربتي، ينبغي أن يكون من الممكن العثور على البيانات قريبًا من عقدة HTML.
هذا السكربت لأغراض تعليمية فقط. لا تسيء استخدامه. التزم بالسلوك الحسن. كن لطيفًا. ولا تخالف أي قوانين.