Insecure Direct Object Reference
IDOR은 Insecure Direct Object Reference의 약자로 안전하지 않은 직접 객체 참조를 의미한다.
웹 애플리케이션에서는 특정 사용자의 정보나 게시글 파일 주문 내역과 같은 데이터를 구분하기 위해 각각의 객체에 식별자를 부여하는 경우가 많다.
예를 들어 사용자가 자신의 주문 내역을 확인했을 때 다음과 같은 요청이 발생한다고 가정한다.
GET /order?id=1001
여기서 1001은 서버에 저장된 특정 주문을 가리키는 식별자이다.
정상적인 서비스라면 현재 로그인한 사용자가 1001번 주문을 조회할 권한이 있는지 서버에서 확인해야 한다.
하지만 서버가 로그인 여부만 확인하고 해당 주문의 소유자가 누구인지는 확인하지 않는다면 문제가 발생한다.
사용자가 요청을 다음과 같이 변경했다고 가정한다.
GET /order?id=1002
이때 1002번 주문이 다른 사용자의 주문임에도 서버가 내용을 그대로 반환한다면 IDOR 취약점이 존재하는 것이다.
즉 IDOR의 핵심은 ID를 변경할 수 있다는 사실 자체가 아니다. 사용자가 전달한 객체 식별자를 서버가 그대로 사용하면서 그 객체에 접근할 권한이 있는지를 제대로 확인하지 않는 것이 핵심이다.
IDOR은 접근 제어 취약점의 한 종류이며 다른 사용자의 동일한 종류의 자원에 접근한다는 점에서 수평적 권한 상승과 자주 연결된다.
예를 들어 A라는 사용자가 자신의 프로필을 다음 요청을 통해 확인한다고 가정한다.
GET /profile?user_id=120
서버 내부에서는 대략 다음과 같이 user_id를 이용해 데이터를 조회할 수 있다.
SELECT name email FROM users WHERE id = 120
공격자가 user_id 값을 121로 변경한다.
GET /profile?user_id=121
서버가 현재 로그인한 사용자가 121번 사용자의 정보를 조회할 권한이 있는지 확인하지 않는다면 121번 사용자의 이름이나 이메일과 같은 정보가 반환될 수 있다.
이 과정에서 공격자가 121번 사용자의 비밀번호를 알아내거나 해당 계정으로 로그인한 것은 아니다. 자신의 정상적인 로그인 세션을 유지한 상태에서 서버에 전달하는 객체 식별자만 변경했을 뿐이다.
따라서 인증과 인가는 구분해서 이해할 필요가 있다. 인증은 요청을 보내는 사람이 누구인지 확인하는 과정이다. 로그인 과정이 대표적이다. 인가는 인증된 사용자가 특정 데이터나 기능을 사용할 권한이 있는지 확인하는 과정이다. IDOR이 존재하는 서비스는 인증에는 성공했지만 객체 단위의 인가가 제대로 이루어지지 않는 경우가 많다.
IDOR이 반드시 URL에 숫자로 나타나는 것은 아니다. 다음과 같이 파일 이름이 객체를 직접 가리킬 수도 있다.
GET /files/report_1001.pdf
공격자가 이를 다음과 같이 변경했을 때
GET /files/report_1002.pdf
다른 사용자의 문서를 내려받을 수 있다면 역시 IDOR로 볼 수 있다.
URL의 경로 자체에 객체 식별자가 들어가는 경우도 있다.
GET /api/users/153/orders
이를 다음과 같이 변경한다.
GET /api/users/154/orders
154번 사용자의 주문 정보가 반환되고 요청자가 해당 정보를 조회할 권한이 있는지 검사하지 않는다면 문제가 된다.
GET 요청에만 IDOR이 발생하는 것도 아니다.
프로필 수정 기능에서 다음과 같은 요청을 보낸다고 가정한다.
POST /profile/update
user_id=120
nickname=hello
공격자가 user_id를 다른 사용자의 값으로 변경한다.
user_id=121
nickname=changed
서버가 user_id 121의 프로필을 실제로 수정해 버린다면 단순한 정보 노출보다 더 큰 문제가 발생한다.
API에서 JSON을 사용하는 경우에도 동일하다.
POST /api/address/update
user_id 120
address Seoul
여기서 user_id 값을 다른 사용자의 ID로 변경했을 때 다른 사용자의 주소가 수정된다면 객체 수준의 권한 검사가 빠져 있는 것이다. 따라서 IDOR은 조회 기능에서만 발생하는 취약점이라고 생각하면 안 된다. 조회 수정 삭제 다운로드 등 객체를 대상으로 하는 여러 기능에서 발생할 수 있다.
IDOR을 이해할 때 자주 생기는 오해 중 하나는 연속된 숫자 ID를 사용하는 것이 취약점의 원인이라고 생각하는 것이다.
예를 들어
/user/1001
/user/1002
/user/1003
처럼 번호가 순차적으로 증가한다면 공격자가 다른 객체의 ID를 추측하기 쉬워지는 것은 사실이다.
그래서 UUID와 같이 예측하기 어려운 식별자를 사용할 수 있다.
예를 들어
/user/550e8400-e29b-41d4-a716-446655440000
처럼 긴 값을 사용하면 단순히 숫자를 하나씩 증가시키며 다른 객체를 찾는 것은 훨씬 어려워진다.
하지만 이것만으로 IDOR이 해결되는 것은 아니다. 공격자가 다른 경로를 통해 해당 UUID를 알아냈다면 여전히 그 객체에 접근을 시도할 수 있기 때문이다. 결국 서버가 해야 하는 가장 중요한 검사는 이 요청을 보낸 사용자가 이 객체에 접근할 권한이 있는가를 확인하는 것이다.
예를 들어 사용자가 1002번 주문을 요청했다고 해서 단순히 다음과 같이 조회해서는 안 된다.
SELECT FROM orders WHERE id = 1002
현재 로그인한 사용자의 식별자가 35라면 다음과 같이 주문의 소유 관계까지 확인해야 한다.
SELECT FROM orders WHERE id = 1002 AND user_id = 35
즉 1002라는 객체가 실제로 존재하는지를 확인하는 것에서 끝나는 것이 아니라 현재 사용자가 그 객체에 접근할 수 있는지도 함께 확인해야 한다.
IDOR을 테스트할 때는 두 개 이상의 테스트 계정을 사용하는 방법이 이해하기 쉽다.
User A와 User B라는 계정이 있다고 가정한다.
User A로 로그인해서 자신의 주문을 조회했더니 다음 요청이 발생했다.
GET /orders/501
그리고 User B의 주문 ID가 502라고 가정한다.
User A의 로그인 상태를 그대로 유지한 상태에서 테스트 환경에서 요청을 다음과 같이 변경한다.
GET /orders/502
서버가 403 Forbidden과 같이 접근을 거부한다면 객체 단위의 권한 검사가 적용되고 있다고 볼 수 있다.
반대로 User B의 주문 정보가 정상적으로 반환된다면 User A가 자신의 권한 범위를 벗어난 객체에 접근한 것이므로 IDOR 가능성을 확인할 수 있다.
Burp Suite를 이용하는 경우 Proxy의 HTTP history에서 이러한 요청을 확인하고 Repeater를 이용해 객체를 나타내는 파라미터를 변경하면서 응답 차이를 살펴볼 수 있다.
예를 들어
GET /my-account?id=userA
라는 요청이 있다면 테스트 환경에서 다른 테스트 계정의 식별자로 변경한다.
GET /my-account?id=userB
여기서 중요한 것은 단순히 200 OK가 반환되는지만 확인하는 것이 아니다. 응답 본문에 실제로 다른 사용자의 데이터가 포함되어 있는지 확인해야 한다. 리다이렉트나 오류 응답처럼 보이더라도 응답 안에 접근하면 안 되는 데이터가 포함되는 경우도 있기 때문이다.
IDOR의 위험성은 대상 객체에 따라 달라진다. 단순한 공개 프로필이 노출되는 것과 개인정보가 포함된 주문 내역이 노출되는 것은 영향이 다르다. 송장 의료 정보 개인 메시지 결제 정보 사내 문서와 같이 민감한 객체에 IDOR이 존재한다면 개인정보 유출로 이어질 수 있다. 더 위험한 경우는 읽기뿐 아니라 수정과 삭제까지 가능한 경우이다.
예를 들어 다음 요청에서
DELETE /api/documents/830
830을 다른 사용자의 문서 ID로 변경했을 때 실제 문서가 삭제된다면 다른 사용자의 데이터를 임의로 삭제할 수 있게 된다.
또한 일반 사용자의 객체뿐만 아니라 관리자와 연결된 객체에 접근할 수 있다면 수평적 권한 상승에서 더 높은 권한으로 이어질 가능성도 생긴다. IDOR을 방지하기 위해서는 모든 객체 접근 요청에 서버 측 인가 검사를 적용해야 한다. 클라이언트에서 버튼을 숨기거나 JavaScript를 이용해 접근을 막는 것만으로는 충분하지 않다. 공격자는 브라우저 화면을 통하지 않고 HTTP 요청 자체를 수정할 수 있기 때문이다. 객체를 조회하거나 수정하거나 삭제하기 전에 현재 로그인한 사용자가 해당 객체에 접근할 권한이 있는지를 서버에서 확인해야 한다. 가능하다면 클라이언트가 자신의 사용자 ID를 직접 전달하지 않도록 설계하는 것도 도움이 된다.
IDOR에서 가장 중요한 것은 객체의 ID를 숨기는 것이 아니라 객체에 대한 권한을 확인하는 것이다. 사용자가 어떤 객체의 ID를 알고 있다는 사실과 그 객체에 접근할 권한이 있다는 사실은 전혀 다르다.
결국 IDOR은 단순히 URL의 숫자를 바꾸는 공격이라기보다 웹 애플리케이션이 객체 단위의 인가를 제대로 수행하지 않았을 때 발생하는 접근 제어 취약점이라고 이해하는 것이 정확하다.
참고 사이트 :
Insecure Direct Object Reference Prevention - OWASP Cheat Sheet Series
Insecure Direct Object Reference Prevention Cheat Sheet Introduction Insecure Direct Object Reference (IDOR) is a vulnerability that arises when attackers can access or modify objects by manipulating identifiers used in a web application's URLs or paramete
cheatsheetseries.owasp.org
https://portswigger.net/web-security/access-control/idor?utm_source=chatgpt.com
PortSwigger — Web security tools, training and research
We enable the world to secure the web. Burp Suite, the Web Security Academy, and world-leading research from PortSwigger — the AppSec community’s home.
portswigger.net
'보안' 카테고리의 다른 글
| CSRF (0) | 2025.06.07 |
|---|---|
| SSRF (0) | 2025.05.31 |
| XSS - Stored Cross-Site Scripting (0) | 2025.05.20 |
| 손으로 배우는 해킹(Nomartic Youtube) (0) | 2025.03.11 |
| 기초 네트워크 (0) | 2025.03.11 |