تخزين التوكن في LocalStorage: الخطأ اللي يخلي أي XSS يسرق حسابك بالكامل
يا جماعة، خلونا نغيّر الزاوية اليوم.
المرة اللي فاتت تكلمنا عن منطق الأعمال.
اليوم بنفتح شيء ثاني تمامًا، شيء كل واحد يستخدمه كل يوم، بس نادرًا جدًا يوقف ويفهمه بعمق.
التخزين في المتصفح… الذاكرة العشوائية الحقيقية لتطبيقات الويب.
كثير ناس يظنون إن الأمان كله على السيرفر.
يقولون: "الـ Backend محمي، الـ Token صحيح، الـ IDOR مسكر… خلاص".
بس هم ينسون إن جزء كبير من حالة التطبيق يعيش في المتصفح نفسه، زي ما الـ RAM تعيش فيها العمليات قبل ما تموت.
الـ Cookies، الـ LocalStorage، الـ SessionStorage، الـ IndexedDB… هذي هي الذاكرة الحية للتطبيق.
وفيها أسرار كثيرة تموت لو أعدت تحميل الصفحة، وفيها أسرار ثانية تبقى أيام وأسابيع.
ليش هالنوع من "الذاكرة" خطير أكثر مما تتخيل؟
لأن المهاجم ما يحتاج يكسر السيرفر دائمًا.
أحيانًا يكفي إنه يقرأ اللي موجود في ذاكرة المتصفح في اللحظة الصح.
تخيل:
الـ Access Token محطوط في LocalStorage.
الـ Refresh Token في Cookie بدون HttpOnly.
بيانات المستخدم الحساسة مخزنة في SessionStorage عشان "تجربة أفضل".
أو حتى مفاتيح مؤقتة للتشفير متولدة في الـ Frontend ومخزنة هناك.
كل هذي الأشياء موجودة في مكان يقدر أي سكريبت شغال في نفس الصفحة يقرأه.
ولو في XSS بسيط، أو حتى Extension خبيث، أو جهاز مشترك… اللعبة تنتهي.
هذي مو ثغرة تقنية كلاسيكية.
هذي ثغرة "نسيان إن المتصفح له ذاكرة".
وش يعيش في هالذاكرة بالضبط؟
خلونا نقسمها زي ما نقسم الـ RAM:
1. Cookies
هذي أقرب شيء للـ Processes الطويلة العمر.
تقدر تكون HttpOnly (ما يقدر JavaScript يقرأها)، أو Secure، أو SameSite.
بس لو نسيت أي واحدة من هذي الخصائص، صارت مفتوحة.
2. LocalStorage
هذي الذاكرة الدائمة.
تبقى حتى لو سكرت المتصفح.
كثير مطورين يحطون فيها الـ Token عشان ما يتعبون المستخدم بإعادة تسجيل الدخول.
والنتيجة؟ أي XSS = سرقة الحساب كامل.
3. SessionStorage
هذي أقرب للـ RAM الحقيقي.
تموت لما تقفل التبويب.
بس داخل التبويب الواحد… أي سكريبت يقدر يقرأها.
4. IndexedDB
هذي الأكبر والأخطر أحيانًا.
تقدر تخزن فيها كميات كبيرة من البيانات، وفي ناس يحطون فيها ملفات أو مفاتيح أو حتى بيانات حساسة "مؤقتة".
كيف تقرأ هالذاكرة بنفسك؟ (الطريقة العملية)
ما تحتاج أدوات معقدة.
افتح أي تطبيق، اضغط F12، وروح على تبويب Application (في Chrome) أو Storage (في Firefox).
شوف:
الـ Cookies: وش فيها؟ هل الـ Token موجود؟ هل فيه HttpOnly؟
LocalStorage: هل في مفاتيح غريبة؟ هل في بيانات مستخدم؟
SessionStorage: نفس الشيء.
IndexedDB: افتحها وشوف الجداول.
بعدين جرب تسوي XSS بسيط في بيئة اختبار (مختبرك الخاص طبعًا)، وشوف إذا تقدر تقرأ هالقيم بـ document.cookie أو localStorage.getItem().
هذي الطريقة اللي أغلب الناس ما تسويها.
يفتحون Burp ويبحثون عن Injection، وينسون إن جزء كبير من الكنز موجود في المتصفح نفسه.
أمثلة حقيقية شفتها بنفسي
تطبيق بنكي يحط الـ Session Token في LocalStorage عشان "السرعة".
أي XSS = تحويل فلوس.
تطبيق توصيل يخزن عنوان المستخدم ورقم الجوال في SessionStorage.
لو فتحت نفس الحساب من جهاز ثاني في نفس الوقت، تقدر تقرأ البيانات القديمة.
نظام إدارة محتوى يحط مفتاح API مؤقت في IndexedDB.
المفتاح يصلح لساعات، والمهاجم يقدر يستخدمه وهو جالس في نفس الصفحة.
كلها حالات ما يكتشفها السكانر العادي، لأن كل طلب على حدة "صحيح".
المشكلة في المكان اللي خزنّا فيه الحالة.
الأخطاء اللي تسويها فرق التطوير كل يوم
يحطون الـ Token في LocalStorage عشان "أسهل".
ينسون خاصية HttpOnly على الـ Cookies الحساسة.
يستخدمون SessionStorage وهم فاكرين إنها آمنة 100%.
يخزنون بيانات حساسة "مؤقتة" في المتصفح عشان ما يرجعون للسيرفر كل مرة.
ما يفكرون إن المستخدم ممكن يكون فاتح أكثر من تبويب، أو يستخدم Extension، أو يكون على جهاز مشترك.
الخلاصة
السيرفر يحفظ التاريخ.
المتصفح يحفظ الحاضر.
لو كنت تختبر تطبيق ويب، وما فتحت تبويب Application في أدوات المطور، فأنت تختبر بنصف القوة.
الأمان الحقيقي مو بس "هل الـ Token صحيح على السيرفر؟".
الأمان الحقيقي هو: هل في شيء حساس عايش في ذاكرة المتصفح يقدر أي سكريبت يقرأه؟
هالمقال مو عشان نخوف أحد.
عشان نرفع المستوى.
الثغرات التقنية صارت معروفة، أما قراءة ذاكرة المتصفح لسه الملعب اللي فيه ناس قليلة تلعب فيه بتركيز.
لو جربت تفحص تطبيق وشفت شيء غريب في LocalStorage أو Cookies، اكتبه في التعليقات.
نبي نكسر هالموضوع أكثر.
خلونا نكمل المسار.

تعليقات