애플리케이션 보안

인가 모델

meellon 2026. 6. 25. 06:00

학습 목표

인가(Authorization)인증 이후 행동·리소스를 제한함을 설명할 수 있다.

RBAC(역할 기반)와 ABAC(속성 기반)의 구조·트레이드오프를 비교할 수 있다.

수평·수직 권한(IDOR, privilege escalation)을 인가 설계 관점에서 구분할 수 있다.

Policy engine(OPA 등)으로 중앙 정책을 분리하는 패턴을 설명할 수 있다.

API에서 fail closed·403 vs 401·리소스 소유 검증을 적용할 수 있다.

문제 상황

  • JWT role: admin claim만 보고 삭제 API를 열었다
    • 토큰 위조·오발급 시 전면 장애 — 서버 측 정책 없음
  • "로그인만 하면" 모든 주문 조회 API가 동작한다
    • GET /orders/12345 — 남의 orderId만 바꿔도 200 (IDOR)
  • isAdmin boolean 하나로 전 기능 통제
    • 감사·최소 권한 불가 — 퇴사자 admin 플래그 미회수
  • 마이크로서비스마다 if문 권한 복붙
    • 정책 변경 시 10곳 배포 — drift
  • "영업 시간만 허용" 같은 조건을 RBAC role에 억지로 넣었다
    • role 폭발 — admin_weekday_morning

Part 2 인증·토큰(4~7편)으로 누구는 확인했다. 이제 무엇을 할 수 있는지 — OWASP Broken Access Control의 예방 층.

본 글의 시나리오·예제는 방어·설계 학습 목적이다. 타인 데이터에 대한 무단 접근은 불법이다.

1. 인증 다음 — 인가

  인증 (Authentication) 인가 (Authorization)
질문 누구인가 이 행동·리소스 허용?
성공 identity 확립 (sub, session) policy allow
실패 HTTP 401 Unauthorized 403 Forbidden
토큰 JWT·OIDC 검증 claims 만으로 결정하지 않음

요청 처리 순서 (권장):
  1. TLS 종료
  2. 인증 — 세션·JWT 유효성 (401)
  3. 인가 — 역할·소유·정책 (403)
  4. 비즈니스 로직
  • 앞서 least privilege — 인가가 최소 권한을 코드로 강제
  • OAuth scope위임 범위 — 앱 내부 RBAC와 별개 (6~7편)

2. RBAC (Role-Based Access Control)

RBAC — 사용자에게 역할(role) 을 부여하고, 역할에 권한(permission) 을 묶는다.

개념
User user-42
Role member, support, admin
Permission orders:read, orders:refund, users:delete
Assignment user-42 → member
# code/rbac-roles.yaml (발췌)
roles:
  member:
    permissions:
      - orders:read_own
      - orders:create
  support:
    permissions:
      - orders:read_any
      - orders:refund
  admin:
    permissions:
      - users:manage
      - orders:*
패턴 설명
Flat RBAC role → permission 직접
Hierarchical adminsupportmember
Separation of duty 결제 승인 ≠ 결제 실행 role 분리
# 의사 코드 — permission check
if not user.has_permission("orders:refund"):
    raise Forbidden()

RBAC 한계

  • 속성 조건 — "본인 주문만", "같은 tenant만" → role만으로 어색
  • role 폭발 — 기능·조건 조합마다 role 추가
  • 리소스 단위order/123 소유는 RBAC ownership check 필요

3. ABAC (Attribute-Based Access Control)

ABAC주체·리소스·행동·환경 속성으로 정책을 평가한다.

속성 종류
Subject user.id, user.department, user.clearance
Resource order.owner_id, doc.classification
Action read, delete, export
Environment time, ip_country, mfa_verified
# code/abac-policy.rego (OPA v1 — 발췌)
package orders.authz

import rego.v1

default allow := false

allow if {
  input.action == "read"
  input.resource.type == "order"
  input.subject.user_id == input.resource.owner_id
}

allow if {
  input.action == "read"
  input.resource.type == "order"
  "support" in input.subject.roles
  input.subject.tenant_id == input.resource.tenant_id
}

전체 정책·opa eval용 입력 예: code/abac-policy.rego, code/abac-input.example.json

  RBAC ABAC
모델 role → permission 속성 + 정책
표현력 coarse fine-grained
복잡도 낮음 정책·테스트 필요
감사 role 변경 추적 정책 버전·decision log
  • ReBAC(Relationship-Based) — "팀 멤버", "파일 공유" 그래프 — Google Zanzibar 계열 (개념만)
  • 실무 혼합 — RBAC로 기본 역할, ABAC·ownership으로 리소스 제한

4. 리소스 소유·ACL

인증됨 ≠ 이 리소스 접근 가능 — OWASP Broken Access Control 핵심.

실패 패턴 방어
IDOR /orders/999 ID만 변경 owner_id == sub 검증
수직 상승 member가 /admin 호출 role·permission 서버 검증
수평 이동 A 사용자가 B 데이터 tenant·owner 쿼리 조건
Mass assignment role: admin body 주입 allowlist 필드
order = db.get_order(order_id)
if order.owner_id != current_user.id and not current_user.can("orders:read_any"):
    raise Forbidden()
  • JWT role claim 신뢰만 — DB·policy engine과 교차 검증
  • 목록 API — WHERE owner_id = :current_user (필터 누락 = 유출)

5. Policy engine

분산 if문 대신 정책을 데이터로 — OPA, Cedar, AWS IAM JSON, Keycloak authorization.

도구 특징
OPA (Rego) K8s admission, API sidecar, 범용
Cedar (AWS) 정형 정책 언어, 명시적 deny
IAM policy cloud 리소스 ARN·action
앱 내 RBAC 테이블 소규모 — DB roles_permissions
API Gateway / Sidecar
  → POST /v1/data/orders/authz/allow
  → input: subject, action, resource
  → allow: true | false
  • fail closed — engine 오류 시 deny (앞서 fail secure)
  • 정책 단위 테스트allow/deny fixture (CI)
  • decision log — 감사·디버그 (Observability 연계)

미들웨어 예: code/authz-middleware.example

6. 구현 패턴

패턴 설명
Centralized authz service / OPA — 단일 진실
Embedded 프레임워크 @Requires("orders:refund")
Data layer ORM scope·row-level security (PostgreSQL RLS)
BFF 프론트 메뉴 숨김 인가 — API에서 강제
GET /api/orders/12345 HTTP/1.1
Authorization: Bearer eyJ...
응답 의미
401 토큰 없음·만료·서명 실패
403 인증됐으나 정책 거부
404 존재 숨김 (owner 아닌 리소스 — 정책 선택)
  • 403 vs 404 — 정보 노출 트레이드오프 — 팀 일관 규칙
  • Admin API — 별도 prefix + 강한 MFA + IP allowlist (defense in depth)

7. 보안 체크리스트

항목 내용
순서 인증 → 인가 — 인가만으로 identity 추론 금지
JWT claims role 참고 — DB·policy 최종
CRUD create/read/update/delete permission 분리
ownership 모든 ID 기반 API owner 검증
tenant SaaS tenant_id 쿼리·정책 필수
default deny all — 명시 allow만
test IDOR·vertical 자동 테스트 (OWASP ZAP, unit)
audit deny·admin action 로그 (15편)
안티패턴  
프론트만 메뉴 숨김 API 직접 호출
isAdmin boolean permission 세분화 없음
role in JWT only 철회·변경 지연
200 on forbidden 403/404 명확

8. 정리

  • 인가 — 인증 후 행동·리소스 허용 — 401과 403 구분
  • RBAC — role·permission — 단순·운영에 강함
  • ABAC — 속성·정책 — 조건·tenant·소유 표현
  • ownership — RBAC 보완 — IDOR 방지 필수
  • Policy engine — 정책 중앙화·테스트·감사

다음에 다룰 것

  • Injection
  • SQLi, command injection, 파라미터화

해당 내용은 NIST Role-Based Access Control, OWASP Authorization Cheat Sheet, Open Policy Agent Documentation 의 내용을 기반으로 합니다.

'애플리케이션 보안' 카테고리의 다른 글

XSS와 CSRF  (0) 2026.06.27
Injection  (0) 2026.06.26
OpenID Connect  (0) 2026.06.24
OAuth 2.0  (0) 2026.06.23
JWT  (0) 2026.06.22