BUG BOUNTY · IDOR HUNTING · METHODOLOGY

منهجية صيد

الـ IDOR.

دليل شامل من اختيار البرنامج لحد إثبات الـ impact — مبني على تحليل عميق لمنهجية Arson على Starbucks Bug Bounty.

TAUGHT BY HAMADA KHAIRY · IDOR · ACCESS CONTROL · BUG BOUNTY
Hamada Khairy
THE INSTRUCTOR
// 00 — VIDEO OVERVIEW

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

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

IDOR Explanation Video
▶ VIDEO RUNTIME: COMPLETE WALKTHROUGH OPEN ON YOUTUBE ↗
// 01 — المبدأ الأول

IDOR vs Access Control

الاتنين ممكن يودوا لنفس النتيجة — بس الطريق مختلف تماماً. وخلطهم بيضيع attack vectors كاملة.

◆ ◇ ◆
IDOR — Indirect Object Reference

فشل في التحقق من الملكية

التطبيق بيأخد ID من الـ user ويرجع data من غير ما يتأكد إن الـ user ده صاحب الـ data دي.

// IDOR EXAMPLE GET /profile?userId=1337 // Backend: SELECT * FROM users WHERE id = 1337 // ❌ مش بيسأل: هل session owner = 1337؟

Failure: object-level authorization

Access Control Violation

فشل في التحقق من الصلاحية

الـ user بيوصل لـ mechanism من المفروض إن الـ role بتاعه مش مسموحله يستخدمه أصلاً.

// ACCESS CONTROL EXAMPLE GET /admin/users/all // Expected: 403 Forbidden // Vulnerable: 200 OK — كل الـ users // ❌ مش بيتحقق إن role = admin

Failure: function-level authorization

// SCRIPT — الفرق العملي0:00 – 4:00

النهارده هنتكلم عن الـ IDOR وعن الـ Access Control Violations. الموضوع ده مش بس عشان تتعلم — ده عشان تفهم ليه الـ automated scanners مش هتلاقي الـ bugs دي أبداً. إنت بتفهم الـ context اللي الـ scanner مش بيفهمه — ده الـ unfair advantage بتاعك.

لو قدرت تغير ID بتاعك لـ ID حد تاني وشفت بياناته — ده IDOR. إنت authorized تستخدم الـ mechanism — بس مش المفروض توصل لـ object حد تاني. أما لو وصلت لـ endpoint مش مسموحلك بيه أصلاً — ده Access Control Violation.

⚠️ النتيجة ممكن تكون نفسها — بس الـ root cause مختلف تماماً. لو خلطتهم هتضيع attack vectors كاملة وتفتكر إنك غطيت كل حاجة وأنت مغطيتش حاجة.

في الـ cloud-first world اللي احنا فيه، الـ attacker مش بيدور على shell — بيدور على data. الـ customer database هي الـ Crown Jewel. AWS Lambda بيديك scope محدود — بس لو وصلت للـ database، ده هو الـ devastating impact الحقيقي.

// 02 — قبل ما تبدأ

اختيار البرنامج الصح

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

◆ ◇ ◆
✦ MUST HAVE
  • Authenticated testing مسموح
  • Self-registration متاحة
  • Multiple accounts ممكن تعملها
  • Attack surface كبيرة
✦ GREAT TO HAVE
  • برنامج غير إنجليزي أقل منافسة
  • Multiple user roles
  • Payment / gift card features
  • API endpoints منفصلة
✦ RED FLAGS
  • مفيش authenticated testing
  • Self-registration ممنوعة
  • Surface ضيقة جداً
  • Static pages فقط
// SCRIPT — سر البرامج الغير إنجليزية4:00 – 5:30

Starbucks Singapore ليه؟ نفس الـ codebase تقريباً — بس بيتعمله testing أقل بكتير. والـ Singapore version لسه إنجليزي — فمعندكش language barrier.

🌏 دور على الـ Japanese، Korean، German، Singapore versions بتاعة الـ programs الكبيرة. نفس الـ bugs، تنافس أقل بكتير. الـ patch ممكن اتعمل على الـ American version من زمان وما وصلش لـ Singapore لسه.
// 03 — الأساس

حسابين — مش حساب واحد

المنهجية الصح: وثق الـ identifiers مش الـ passwords.

◆ ◇ ◆
I

HackerOne Email + Plus Notation

استخدم you+demo1@wearehacker.one و you+demo2@wearehacker.one. الاتنين بيوصلوا نفس الـ inbox — بس الـ app بيشوفهم حسابين منفصلين. الشركة هتعرف إنك researcher.

II

الـ Identifiers هم الكنز

بعد الإنشاء: Burp Suite → jwt.io → وثق الـ nameId وكل identifier. المقارنة بينهم هي اللي بتكشف الـ sequential pattern.

III

Account 1 Normal / Account 2 Incognito

Burp Suite بيشوف الـ traffic من الاتنين. ده بيخليك تقدر تقارن بين الـ requests والـ responses بسهولة.

IV

قارن — دور على الـ Pattern

A1: 8800327 — A2: 8800329. Sequential = الـ IDs predictable = الباب مفتوح. لو GUIDs — هتحتاج تلاقيهم من endpoints تانية.

// NOTES → ACCOUNTS SECTION ## Accounts ### Account 1 Email : arson+demo1@wearehacker.one nameId: 8800327 ← document this jti : a3f9c2bd... ### Account 2 Email : arson+demo2@wearehacker.one nameId: 8800329 ← Δ=2 → Sequential ✅ HIGH IDOR potential jti : b7e1d4a1...
// 04 — نظام التدوين

The Arson Note System

مش note-taking عادي — ده نظام تفكير يخليك تشوف الـ application كاملاً في رأسك.

◆ ◇ ◆
// SCRIPT — ليه النوتس مش اختياري5:30 – 8:00

لو مش بتعمل notes — إنت مش هتنجح في الـ IDOR testing. مش رأي — ده fact. الـ IDOR testing مبني على الـ context. إنت محتاج تعرف كل mechanism، إيه اللي بيتبعت في كل request، وإيه اللي بيرجع في الـ response. لو مش موثق — هتنسى وهتلف في دوايرة.

📝 الـ VS Code + Markdown. Structure ثابت على كل target: Pointers → Accounts → Mechanisms → Objects. Pointers = علامات الـ bad security culture. Mechanisms = كل CRUD موثق مع الـ auth method.
// ARSON NOTE TEMPLATE — FULL
# [TARGET] — IDOR TESTING ## Pointers ← علامات bad security culture 1. [POINTER] CSRF token not validated on GET /profile 2. [POINTER] Session cookie 'auth' missing HTTP-Only flag 3. [POINTER] JWT using HS256 (symmetric) — why not RS256? 4. [POINTER] Two auth patterns: /api/* uses JWT, core uses session ## Accounts ### A1: nameId=8800327 ### A2: nameId=8800329 ← sequential ✅ ## Mechanisms ### Personal Info READ = GET → /rewards/profile ← auth cookie UPDATE = POST → /rewards/profile ← auth cookie | ❓ email in body why? UPDATE = POST → /rewards/profile/changeEmail ← auth cookie | ❓ fuzz hidden params ### Payment Methods READ = GET → /rewards/api/card/get-payment-cards ← ACCESS TOKEN (JWT HS256) ⚠️ → Signature IS validated — test JWT attacks ### Gift Cards ⭐ HIGH PRIORITY READ = POST → /rewards/api/giftcard/search Body: {"cardNumber": "XXXX"} ⚡ cardNumber in body → IDOR CANDIDATE ← TEST FIRST ## Objects ### Gift Card: cardId, cardNumber, balance, imageUrl, autoReload, status ### User: firstName, lastName, title, birthDate, email, points, tier ### Transaction: transactionId: "cae0d1e7..." ← GUID format
// 05 — الـ Technique الأقوى

نظرية الـ Minimum Request

شيل كل حاجة غير ضرورية لحد ما تفهم إيه اللي الـ backend بيستخدمه فعلاً عشان يعرف إنت مين.

◆ ◇ ◆
// SCRIPT — The Minimum Request Theory8:00 – 14:00

أول ما بتفتح endpoint جديد في Burp Repeater، السؤال الأول مش "في IDOR ولا لأ؟" — السؤال هو: إيه أصغر request ممكن يشتغل؟

إنت بتشيل cookie بعد cookie، header بعد header، لحد ما الـ response يتعطل. الـ minimum set اللي بيشتغل — ده هو الـ authentication mechanism بتاعك.

🚨 في Starbucks، لما شيلنا الـ JWT من /rewards/profile، الـ endpoint لسه شغال. مش معناه إن في vulnerability — معناه إن الـ JWT مش بيتاستخدمش في الـ endpoint ده أصلاً. كنا بنبعت حاجة الـ backend بيتجاهلها.

ده بيعلمنا حاجة مهمة: لازم تثبت إن الـ token ده فعلاً هو اللي الـ backend بيستخدمه — مش بس إنه مش validated.

// MINIMUM REQUEST DECISION TREE
ENDPOINT returns your data

STEP 1 — Remove CSRF token

Still 200📝 POINTER: CSRF not validated

STEP 2 — Remove JWT access_token

Still 200JWT not used here → check session
401⚡ JWT IS the mechanism → analyze it

STEP 3 — Remove session cookie

302 → login✅ Session = authentication

STEP 4 — Any explicit ID in URL or body?

YES (cardNumber, userId...)🎯 Swap with A2's value
NO — only sessionFuzz for hidden params
// 06 — تحليل التوكن

فهم الـ JWT صح

الـ JWT مش magic — base64 + signature. لو الـ signature مش validated، إنت تقدر تغير أي حاجة جوا.

◆ ◇ ◆
// JWT ANATOMY + TEST eyJhbGciOiJIUzI1NiJ9. eyJuYW1lSWQiOiI4ODAwMzI3In0. oQzJxR4Fshort... ───────────────────────────── HEADER : {"alg": "HS256", "typ": "JWT"} PAYLOAD: {"nameId": "8800327", "sub": "8800327"} SIG : HMACSHA256(h+"."+p, SECRET) ─── VALIDATION TEST ────────── Remove last sig char → send Still 200?Not validated → CHANGE PAYLOAD! Got 401? → Validated → JWT attacks
⚠️ HS256 = Symmetric = سؤال مهم

ليه مش RS256؟

HS256 بيستخدم shared secret واحد. أقل شيوعاً من RS256. لو شايفه — ده pointer ممكن يكون legacy implementation.

// JWT ATTACK TREE
Signature validated?
NOChange nameId → IDOR ✅
YES + HS256Try alg:none
YES + HS256Brute force weak secret
YES + RS256Look for other vectors
// 07 — قراءة الإشارات

نظام الـ Pointers

الـ Pointer مش vulnerability — هو إشارة إن الـ team مش بيطبق best practices.

◆ ◇ ◆
إيه هو الـ Pointer؟

أي حاجة في الـ application بتقولك إن الـ security team مش على المستوى. بتدلك إنك على الطريق الصح.

"If you find misconfigurations like this, you're almost certainly going to have deeper systemic issues." — Arson
الـ Story في Starbucks
  • CSRF token موجود بس مش validated
  • Session cookie بدون HTTP-only flag
  • JWT بيستخدم HS256 مش RS256
  • اتنين auth patterns مختلفين في نفس الـ app

= فريق بيشتغل تحت ضغط + technical debt كبير

الـ Pointer إيه اللي بيعنيه الخطوة التالية الأولوية
CSRF token غير validated Developer أضافه بس ما ربطهوش تحقق من كل endpoints MEDIUM
Session cookie بدون HTTP-only قابل للسرقة بـ XSS دور على XSS → session hijack chain HIGH
JWT بيستخدم HS256 قرار غريب — legacy ممكن اختبر validation، جرب none algorithm HIGH
Auth patterns مختلفة في نفس الـ app Tech debt — كودبيسين اتلموا API endpoints ممكن تكون أقل حماية HIGH
Generic error message Dev بيخبي فرق بين not found وunauthorized قارن response time وsize → Blind IDOR MEDIUM
Sequential IDs في الـ JWT Predictable — مش GUIDs أعلى أولوية على كل endpoint CRITICAL
// 08 — رسم خريطة التطبيق

CRUD Mapping

قبل ما تهاجم حاجة، إنت لازم تفهم التطبيق كاملاً. الـ CRUD map هو طريقتك.

◆ ◇ ◆
Operation HTTP IDOR Type Impact مثال
READ GET / POST Unauthorized data access HIGH شوف profile / cards حد تاني
UPDATE POST / PUT Unauthorized modification CRITICAL غيّر email / role حد تاني
DELETE DELETE Unauthorized deletion CRITICAL امسح account حد تاني
CREATE POST Resource under other user MEDIUM أضف order لـ account حد تاني
// 09 — الـ Data Model

اكتشاف الـ Objects

كل IDOR bug بيتمحور حول object معين. كل ما عرفته أكتر، كل ما قدرت تثبت الـ impact أحسن.

◆ ◇ ◆
فين بتلاقي الـ Objects؟
  • API responses أحسن مصدر — JSON كامل وواضح
  • React DevTools component state = data model كامل
  • JS files بعض الـ apps بتخلي الـ objects في الـ JS
  • Error messages verbose errors بتكشف field names
الـ Object بيساعدك إزاي؟

لما تعرف الـ fields بتاعة الـ Gift Card — إنت عارف بالظبط إيه الـ sensitive data اللي تعرضه كـ proof of concept.

balance + cardNumber = maximum impact proof.

// GIFT CARD OBJECT — DISCOVERED VIA API POST /rewards/api/giftcard/getCardsByAccount { "cards": [{ "cardId": "gc_8a7f3b...", "cardNumber": "6350949...", ← THE IDOR KEY "balance": 25.00, "currency": "SGD", "status": "active", "autoReload": false }] } ─── IDOR TEST ──────────────────────── Take cardNumber from Account2 Send from Account1's session Returns Account2's card data? → IDOR CONFIRMED ✅
// 10 — خرائط القرار

الـ Decision Trees الكاملة

كل قرار في الـ IDOR testing ليه مساره المحدد.

◆ ◇ ◆
// MASTER IDOR HUNTING TREE
Endpoint returns data — start here

PHASE 1 — AUTH MECHANISM

Remove JWTStill 200JWT not used → check session
Remove JWT401JWT = auth mechanism → JWT branch
Remove session302Session = auth → session branch

SESSION BRANCH

ID in body/URL?
YESSwap with A2's ID
NOFuzz hidden params
Email in body?
YESTry A2's email

JWT BRANCH

Shorten signature
Still works🎯 Change ID in payload!
401Validated
HS256?alg:none or brute force

PHASE 2 — ID TYPE

Sequential int🔥 Enumerate directly
Email / UsernamePut A2's email in body
GUID / HashFind leakage in other endpoints

PHASE 3 — CONFIRMATION

Got A2's data from A1 session🏆 CONFIRMED — document & report
Generic errorCompare timing/size → Blind IDOR
403 ForbiddenValidated correctly — next endpoint
// BLIND IDOR DETECTION

الـ Blind IDOR = مش بتشوف الـ data مباشرة بس في إشارة إن الـ object موجود.

Send random invalid ID"Not found" / 404
Send valid A2 IDDifferent error OR timing⚡ Blind IDOR confirmed!
Send valid A2 IDSame error BUT different sizeBlind IDOR possible
// 11 — التطبيق العملي

لو بدأت على target النهارده

Step by step — من لحظة ما تفتح الـ program لحد ما تكتب الـ report.

◆ ◇ ◆
I

اختر الـ Target بالمعايير

Authenticated testing ✅ Self-registration ✅ Surface كبيرة ✅ Non-English bonus ✅. افتح scope وشوف كل الـ subdomains.

II

ابدأ الـ Note File

mkdir target && touch idor_notes.md. اكتب: ## Pointers → ## Accounts → ## Mechanisms → ## Objects. ثابت على كل target.

III

حسابين + Plus Notation

A1 في normal browser، A2 في incognito. Burp Suite scope = target domain فقط. Wappalyzer لتحديد الـ tech stack.

IV

افتح الـ JWTs وقارن

كل account: Burp → jwt.io → وثق كل identifier. Sequential IDs = gold. GUIDs = هتحتاج تلاقيهم من مصادر تانية.

V

Map الـ CRUD Mechanisms

Feature inventory كامل. كل section فيه READ/UPDATE/DELETE. Apply الـ minimum request theory على كل endpoint.

VI

IDOR Testing بالأولوية

أولوية: endpoints اللي فيها explicit ID في الـ body أو URL. بعت ID بتاع A2 من session بتاع A1 وشوف الـ response.

VII

Step Away بعد كل اكتشاف

جد. ابعد عن الـ computer. اتنفس. اتأكد إنك فاهم بالظبط إيه اللي بيحصل قبل ما تكتب report. التسرع = false positives محرجة.

// 12 — الملخص

Key Techniques Cheatsheet

◆ ◇ ◆
Auth Mechanism Discovery
  • Remove JWT → 200 = JWT not used here
  • Remove JWT → 401 = JWT is the mechanism
  • Remove session → 302 = Session is auth
  • Remove CSRF → 200 = Not validated POINTER
  • Check HTTP-only flag on cookies POINTER
JWT Testing
  • Shorten signature → 200 = Not validated → change payload
  • alg:none attack → remove signature entirely
  • HS256 + weak secret → hashcat brute force
  • RS256 → not worth JWT attacks alone
  • Confirm payload ID is actually used to fetch data
IDOR Vectors
  • Sequential integer in URL → enumerate directly
  • ID in request body → swap with A2's ID
  • Email as identifier in body → try A2's email
  • cardNumber / orderNumber → swap between accounts
  • Fuzz for hidden params if no visible ID
Pattern Recognition
  • API endpoints + JWT → higher IDOR chance
  • Two auth patterns in same app = tech debt = bugs
  • Generic errors → investigate Blind IDOR
  • Sequential IDs + no validation = jackpot
  • Non-English version = less competition
// BURP REPEATER CHECKLIST — لكل endpoint جديد [ ] 1. Send to Repeater [ ] 2. Remove CSRF token → still works? → POINTER logged [ ] 3. Remove JWT → 200 or 401? → note the auth mechanism [ ] 4. Remove session cookie → redirects? → confirm session = auth [ ] 5. Any ID in URL/body/JWT payload? → log in ## Mechanisms [ ] 6. Is the ID sequential? → log comparison with A2 [ ] 7. Send A2's ID from A1's session → check response [ ] 8. JWT used: shorten signature → still works? → change payload [ ] 9. Log ALL pointers before moving to next endpoint [ ] 10. Step away if you find something — breathe first
// 13 — اختبر نفسك

Quiz — منهجية مش حفظ

كل سؤال عن decision-making حقيقي.

◆ ◇ ◆
بتعمل IDOR testing على endpoint بتاع profile. لما شيلت الـ JWT access_token، الـ endpoint لسه شغال ورجع 200. إيه اللي المفروض تستنتجه؟
A. الـ JWT signature مش validated — في IDOR عن طريق JWT manipulation
B. الـ JWT مش بيتاستخدمش في الـ endpoint ده — الـ auth mechanism حاجة تانية
C. في vulnerability — ابعت report فوراً
D. الـ application كلها غير محمية
الإجابة الصح: B

لما شيل JWT ولسه الـ endpoint شغال — ده معناه إن الـ endpoint ده مش بيستخدم الـ JWT أصلاً. مش vulnerability. ده اللي حصل مع Starbucks بالظبط. الـ auth الحقيقي كان الـ session cookie — مش الـ JWT.
في الـ JWT payload عندك nameId: "8800327". Account2 عنده nameId: "8800329". اختصرت الـ signature وبعثت — لسه شغال. إيه خطوتك الجاية؟
A. ابعت report — JWT signature مش validated = vulnerability
B. جرب HS256 brute force على السيكريت
C. غير الـ nameId لـ "8800329" في الـ payload وشوف لو رجع data بتاع A2
D. الفرق 2 بس — مش كفاية للـ IDOR
الإجابة الصح: C

لما الـ signature مش validated، ده بيديك فرصة تغير أي قيمة في الـ payload. غير الـ nameId لـ ID بتاع A2 وتأكد إن الـ data اللي رجعت هي بيانات A2 فعلاً. ده هو الـ confirmation الحقيقي للـ IDOR.
بعثت cardNumber بتاع A2 من session بتاع A1. رجع: 400 Bad Request — "Invalid Starbucks card details". إيه أصح تفسير؟
A. التطبيق بيتحقق من الـ ownership وبيرجع generic error — Blind IDOR محتمل
B. الـ card number مش موجود في الـ database أصلاً
C. التطبيق محمي تماماً — move on
D. الـ JWT access token هو اللي بيمنعنا
الإجابة الصح: A

الـ generic error "Invalid card details" مش بيقولك "not found". ممكن يكون الـ card موجود بس الـ app بيرجع نفس الـ error لـ "unauthorized" و"not found" عشان ما يكشفش إن الـ object موجود. قارن response time وsize بين card حقيقي ومش حقيقي.