تخط إلى المحتوى
English

CSRF (Cross-Site Request Forgery)

كيف يجعل موقع خبيث متصفحك يرسل طلبا موثوقا يغير حالة إلى موقع آخر أنت مسجل دخوله وكيف يوقفه الرمز و SameSite

المسار
أمن الويب
الوقت المتوقع
25 د
المستوى
متوسط
تقدمك في المسار0%

قبل هذا الدرس

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

ما هي الثغرة؟

لنقل أن لوحة تحكم تغير بريدك الاحتياطي بهذا الطلب:

الطلب الحقيقي
POST /settings HTTP/1.1
Host: panel.example
Cookie: session=abc123

email=me@example.com

المهاجم يبني صفحة تجعل متصفحك أنت يرسل نفس الطلب إلى panel.example:

attacker.html
<form action="https://panel.example/settings" method="POST">
  <input type="hidden" name="email" value="attacker@evil.example">
</form>
<script>document.forms[0].submit();</script>

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

ليش تصير؟

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

كيف تنحمى منها

  • رمز CSRF الخادم يضع قيمة عشوائية فريدة لكل جلسة في صفحاته ويطلبها مع كل طلب يغير حالة والمهاجم على موقع آخر لا يقدر قراءة هذي القيمة (سياسة المصدر الواحد تمنعه) فلا يقدر إرفاقها
  • كوكيات SameSite قيمة SameSite=Lax تخبر المتصفح أن لا يرفق الكوكي مع معظم طلبات المواقع الأخرى و SameSite=Strict يمنعه عنها كلها
  • أبق تغييرات الحالة بعيدة عن GET طلب GET يجب أن يقرأ فقط فإذا غير شيئا فرابط أو صورة بسيطة تقدر تشغله و SameSite=Lax ما زال يسمح بالكوكي عند التنقل العلوي بطلب GET
safe.js
app.post('/settings', (req, res) => {
  if (!req.session.user) return res.status(401).end();
  if (req.body.csrf !== req.session.csrfToken) return res.status(403).end();
  db.setRecoveryEmail(req.session.user, req.body.email);
  res.end('updated');
});
// Set-Cookie: session=...; SameSite=Lax; HttpOnly; Secure

XSS و CSRF قريبان لكن متعاكسان XSS يشغل شيفرة المهاجم على الموقع فيقدر يقرأ الرمز ويهزم دفاعات CSRF و CSRF لا يشغل شيفرة على الموقع بل يجعل المتصفح يرسل طلبا فقط أصلح XSS أولا فالرمز لا يحمي صفحة يقدر المهاجم يبرمجها

سؤال مراجعةموقع يطلب رمز CSRF على POST /transfer لكن GET /transfer?to=... أيضا يحول أموالا ولا يفحص أي رمز هل الموقع آمن من CSRF؟

اللابات

  • طلب يأتي من موقع آخر

    سهللاب في المتصفح

    اصنع صفحة مهاجم ترسل طلبا مزورا يغير بريد الزعيم الاحتياطي إلى بريدك وسلمها له

  • رمز على الباب الأمامي فقط

    متوسطلاب في المتصفح

    غير بريد الزعيم الاحتياطي إلى بريدك رغم وجود الرمز على طلب POST

  • ثغرة في الملاذ الأخير

    صعبلاب في المتصفح

    غير بريد الزعيم الاحتياطي إلى بريدك رغم حماية SameSite=Lax