안녕하세요 여행자 K입니다.
이번에는 API 보안에서 가장 흔하고 치명적인 취약점 중 하나이자, OWASP API Security Top 10 2023에서 첫 번째로 꼽힌 'API01:2023 Broken Object Level Authorization (이하 BOLA)'에 대해 자세히 알아보고자 합니다. 왜 이 취약점이 그토록 위험하며, 어떻게 우리 시스템을 보호해야 하는지 알아보겠습니다.
API01:2023 Broken Object Level Authorization (BOLA)이란?
'Broken Object Level Authorization'은 말 그대로 객체 수준의 권한 부여(Authorization)가 제대로 작동하지 않아 발생하는 취약점입니다. 이는 API가 특정 리소스(객체)에 대한 요청을 처리할 때, 해당 요청을 보낸 사용자가 그 리소스에 접근하거나 조작할 수 있는 권한이 있는지 제대로 확인하지 않을 때 발생합니다.
좀 더 쉽게 설명하자면, 온라인 쇼핑몰에서 내 주문 내역을 조회할 때 GET /api/v1/orders/12345와 같은 API 요청을 보낸다고 가정해 보겠습니다. 이때 '12345'는 여러분의 주문 번호입니다. 그런데 만약 시스템이 '이 사용자가 정말로 주문 번호 12345의 주인인지'를 확인하지 않고 단순히 '12345'번 주문 내역을 반환해버린다면 어떻게 될까요? 다른 사람이 임의로 주문 번호를 '12346'이나 '12347'로 바꿔 요청해도, 다른 사람의 주문 내역을 볼 수 있게 되는 심각한 문제가 발생할 수 있습니다.
OWASP는 BOLA를 다음과 같이 설명하고 있습니다. "API는 클라이언트로부터 객체 ID를 받는 거의 모든 엔드포인트에서 발생하는 취약점입니다. 객체 수준의 권한 부여 확인이 누락되거나 효과적이지 않을 때, 공격자는 해당 객체 ID를 변경하여 리소스에 대한 무단 접근을 얻을 수 있습니다." 이러한 이유로 BOLA는 API 보안 위협 중 가장 광범위하고 심각하게 나타나며, 흔히 데이터 유출이나 무단 데이터 조작으로 이어지곤 합니다.
BOLA 취약점의 실제 예시: 소셜 미디어 프로필 접근
이해를 돕기 위해 실제 상황과 유사한 예시를 들어보겠습니다.
취약한 시나리오: 소셜 미디어 프로필 API
한 소셜 미디어 플랫폼에서 사용자가 자신의 프로필을 조회하거나 수정할 수 있는 API를 제공하고 있다고 가정하겠습니다.
API 엔드포인트: GET /api/v1/users/{user_id}/profile
정상적인 요청: 로그인한 사용자(`user_id=examuser`)가 자신의 프로필을 조회했습니다. `GET /api/v1/users/examuser/profile` 요청을 보냈고, 서버는 해당 사용자의 프로필 정보를 반환했습니다.
공격 과정:
1. 초기 상태: 공격자 A가 소셜 미디어에 가입하여 자신의 프로필 페이지를 확인했습니다. 이때 개발자 도구를 사용하여 프로필 조회 시 발생하는 API 요청을 확인했습니다. (예상 요청: GET /api/v1/users/A_user_id/profile)
2. 취약점 발견: 공격자 A는 친구인 B의 프로필 페이지를 방문하여, B의 `user_id`가 'B_user_id'임을 알게 되었습니다. 공격자 A는 자신의 프로필 조회 요청에서 `user_id`를 'B_user_id'로 변경하여 다시 요청을 보냈습니다. (공격 요청: GET /api/v1/users/B_user_id/profile)
3. 무단 접근 성공: 만약 서버가 이 요청을 받을 때, '현재 로그인한 사용자(A)가 정말 'B_user_id' 프로필을 조회할 권한이 있는가?'를 확인하지 않았다면, 서버는 B의 프로필 정보를 공격자 A에게 반환해버렸습니다. 이 경우, 공격자 A는 B의 비공개 프로필 정보(연락처, 개인 사진 등)를 열람할 수 있게 되었습니다
이처럼 BOLA 취약점은 단순히 URL의 ID 값만 바꿔보는 쉬운 시도로도 심각한 데이터 유출이나 무단 조작으로 이어질 수 있어, 모든 API 개발 과정에서 가장 우선적으로 고려되어야 하는 보안 요소입니다.
BOLA 대응 방안
BOLA는 매우 강력한 위협이지만, 효과적인 방어 방법을 통해 충분히 예방할 수 있습니다. 핵심은 모든 객체 수준의 접근에 대해 철저한 권한 확인 절차를 거치는 것입니다.
권한 확인
- API 엔드포인트에서 객체 ID(예: user_id, order_id, document_id 등)를 받아 처리할 때는 항상 해당 객체에 접근하려는 사용자가 실제 권한이 있는지를 서버 측에서 확인해야 합니다.
- 사용자의 세션 정보, 역할(Role), 권한(Permission) 등을 기반으로 접근 제어를 구현해야 합니다. '이 사용자는 자신의 데이터만 볼 수 있는가?', '이 사용자는 관리자이므로 모든 데이터를 볼 수 있는가?' 와 같은 논리를 적용해야 합니다.
모든 데이터 계층에서 검증
- 웹 애플리케이션의 컨트롤러, 서비스 계층, 데이터베이스 접근 계층 등 모든 API 데이터 흐름에서 권한 검증을 놓치지 않아야 합니다. 클라이언트 측 검증(프론트엔드에서의 접근 제한)은 우회될 수 있으므로, 반드시 서버 측에서 검증 로직을 구현해야 합니다.
예외적인 ID 사용 (UUID 등)
- 예측 가능한 순차적인 ID 대신, 예측하기 어려운 UUID(Universally Unique Identifier)와 같은 값을 사용하는 것도 공격자의 무작위 대입 시도를 어렵게 하는 데 도움이 될 수 있습니다. 하지만 이는 권한 검증을 대체할 수 있는 궁극적인 해결책은 아닙니다. 핵심은 항상 서버 측에서의 권한 확인입니다.
일관된 보안 아키텍처:
- API 게이트웨이 또는 중앙 집중식 인증/인가 시스템을 활용하여 모든 API 요청에 대해 일관된 보안 정책을 적용하는 것이 좋습니다.
API01:2023 Broken Object Level Authorization은 API 보안에서 가장 근본적이고 중요한 부분입니다. 이 취약점은 작은 실수에서 시작될 수 있지만, 그 결과는 데이터 유출과 같은 치명적인 피해로 이어질 수 있습니다. 개발 단계에서부터 권한 검증을 최우선으로 생각하고, 설계 및 구현 과정에서 빈틈없는 보안 로직을 적용하는 것이 무엇보다 중요합니다.
읽어주셔서 감사합니다.