본문으로 건너뛰기
고급약 35분

위협 모델링 — STRIDE와 공격 트리로 테스트 대상을 뽑아내기

보안 테스트는 도구를 돌리기 전에 "무엇을 지켜야 하고 누가 어디를 노리는가"를 정하는 일에서 시작한다. 데이터 흐름도에 신뢰 경계를 그리고, STRIDE 여섯 범주로 요소별 위협을 뽑고, 공격 트리로 목표 달성 경로를 분해한 뒤, 발생 가능성과 영향으로 위험 등급을 매겨 테스트 대상 목록을 만든다. 스캐너가 알려주지 않는 우리 시스템 고유의 위협을 찾는 방법이다.

  • #위협모델링
  • #STRIDE
  • #공격트리
  • #신뢰경계
  • #위험등급

개념

도구는 "이미 알려진 것"만 찾는다

모듈 16(레슨 6)에서 SAST·DAST·SCA를 배웠다. 세 도구는 각각 코드 패턴, 실행 중 응답, 의존성 목록을 본다. 공통점이 있다. 셋 다 누군가 이미 규칙으로 정리해 둔 취약점 을 찾는다는 것이다. 그래서 도구는 "쿠폰을 두 번 적용할 수 있다", "탈퇴한 회원의 배송지가 다른 계정에서 조회된다", "관리자 승인 없이 정산 금액을 수정할 수 있다" 같은 것을 절대 찾지 못한다. 이런 것들은 우리 도메인에만 있는 규칙이 깨진 경우이고, 규칙을 아는 사람은 도구가 아니라 우리다.

위협 모델링은 그 규칙을 테스트 대상으로 바꾸는 절차다. 정의는 간단하다. 시스템을 그리고, 그 그림의 각 부분을 누가 어떻게 망칠 수 있는지 체계적으로 열거하고, 무엇부터 확인할지 정하는 것 이다. 테스터에게 이 활동은 낯설지 않다. 모듈 4의 위험 기반 테스트에서 "무엇이 잘못될 수 있는가"를 물었던 것과 구조가 같고, 다만 주체가 사용자의 실수가 아니라 의도를 가진 공격자 라는 점이 다르다.

위험 기반 테스트위협 모델링
잘못의 원인개발 실수, 사용자 오조작, 환경 변화이득을 노리는 행위자의 의도
빈도 추정과거 결함 이력·변경량공격 난이도와 공격자의 동기
"정상 입력" 가정대체로 유효무효 — 입력은 조작된다고 본다
산출물위험 기반 우선순위 테스트 계획위협 목록과 그에 대응하는 점검 케이스

1단계 — 데이터 흐름도(DFD)와 신뢰 경계

위협 모델링의 그림은 아키텍처 다이어그램이 아니다. 데이터가 어디서 와서 어디로 가고, 어디에 머무는지 를 그린 데이터 흐름도(DFD)다. 구성 요소는 네 가지뿐이다.

기호요소예
사각형외부 엔터티(External Entity)사용자, 파트너사 서버, 결제 PG
원프로세스(Process)주문 API 서버, 배치 워커, 관리자 웹
두 줄데이터 저장소(Data Store)orders 테이블, S3 버킷, Redis 세션
화살표데이터 흐름(Data Flow)HTTPS 요청, DB 쿼리, 메시지 큐 발행

여기에 하나를 더 그린다. 신뢰 경계(Trust Boundary) — 신뢰 수준이 달라지는 선이다. 위협의 대부분은 이 선을 넘는 지점에서 생긴다.

 [사용자 브라우저]                      [파트너 정산 서버]
        |                                       |
========|=========== 신뢰 경계 A ===============|==========
        |  (인터넷 → 우리 인프라)               |
        v                                       v
   ( API 게이트웨이 ) --------------------> ( 정산 배치 )
        |                 |                     |
        | JWT 검증        | 내부 호출(인증 없음) |
        v                 v                     v
   ( 주문 서비스 ) --> ( 쿠폰 서비스 )      [[ settlements ]]
        |
========|=========== 신뢰 경계 B ===============
        |  (앱 계층 → 데이터 계층)
        v
   [[ orders 테이블 ]]   [[ Redis 세션 ]]

이 그림 한 장만 그려도 질문이 저절로 나온다. "내부 호출은 인증이 없다고 했는데, 게이트웨이를 우회해 쿠폰 서비스에 직접 요청하면?" 이 질문이 곧 테스트 케이스다. 실제 현장에서 신뢰 경계를 그릴 때 가장 자주 드러나는 사실이 두 가지 있다. 하나는 아무도 정확한 그림을 갖고 있지 않다는 것 이고, 다른 하나는 "내부망이라 안전하다"는 가정이 문서화된 적 없다는 것 이다.

2단계 — STRIDE로 요소별 위협 열거

STRIDE는 마이크로소프트가 정리한 위협 분류다. 여섯 범주이고, 각 범주는 깨지는 보안 속성과 짝을 이룬다.

약자위협깨지는 속성우리 시스템에서의 예
Spoofing신원 위장인증(Authentication)만료된 JWT를 서명 검증 없이 받아들임
Tampering변조무결성(Integrity)클라이언트가 보낸 price 값을 서버가 그대로 사용
Repudiation부인부인 방지(Non-repudiation)정산 금액 수정 이력이 남지 않음
Information Disclosure정보 노출기밀성(Confidentiality)오류 응답에 SQL 쿼리와 테이블명 포함
Denial of Service서비스 거부가용성(Availability)페이지 크기 제한 없는 목록 API
Elevation of Privilege권한 상승인가(Authorization)일반 사용자가 관리자 엔드포인트 호출 성공

STRIDE의 실용적 가치는 체크리스트로 쓸 수 있다는 것 이다. DFD의 요소 종류마다 어떤 범주를 우선 보는지가 정해져 있다.

요소STRIDE
외부 엔터티OO
프로세스OOOOOO
데이터 저장소OOOO
데이터 흐름OOO

표를 그대로 읽으면 "Redis 세션(데이터 저장소)에 대해서는 T·R·I·D 네 범주를 묻는다"가 된다. 묻는 방식은 항상 같은 문장이다.

<요소>에 대해 <STRIDE 범주>가 발생한다면, 공격자는 무엇을 얻는가?
그것을 막고 있다고 믿는 통제는 무엇인가?
그 통제가 실제로 작동하는지 어떻게 확인하는가?   ← 이 줄이 테스트 케이스가 된다

세 번째 줄이 핵심이다. 위협 모델링이 문서로 끝나는 팀과 테스트로 이어지는 팀의 차이가 여기서 갈린다.

요소: Redis 세션 저장소
범주: I (정보 노출)
위협: 세션 키를 알면 다른 사용자의 세션 값을 읽을 수 있다
통제: Redis는 VPC 내부에만 노출, AUTH 설정
확인: (1) VPC 밖에서 6379 포트 접근 시도 → 차단 확인
      (2) AUTH 없이 접속 시도 → 거부 확인
      (3) 세션 키가 예측 가능한 순번인지 확인 → 난수 엔트로피 확인

3단계 — 공격 트리로 경로 분해

STRIDE가 넓게 열거하는 도구라면 공격 트리(Attack Tree)는 깊게 파는 도구다. 뿌리에 공격자의 목표를 두고, 그 목표를 이루는 하위 방법을 AND/OR로 분해한다.

목표: 다른 사용자의 주문 상세를 본다
├─ OR ─ 주문 조회 API에서 권한 검사를 우회한다
│       ├─ orderId를 남의 것으로 바꿔 호출한다            [IDOR]
│       ├─ 내 계정의 JWT에 담긴 userId를 조작한다
│       │   └─ AND ─ 서명 알고리즘을 none으로 바꿀 수 있다
│       │            + 서버가 alg 헤더를 신뢰한다
│       └─ 관리자 전용 조회 엔드포인트를 일반 계정으로 호출한다   [BFLA]
├─ OR ─ 남의 세션을 탈취한다
│       ├─ XSS로 세션 쿠키를 읽는다 (HttpOnly 미설정 시)
│       ├─ 로그아웃 후에도 토큰이 살아 있다
│       └─ 세션 고정(Session Fixation) — 로그인 시 세션 재발급 없음
└─ OR ─ 우회 경로로 데이터를 얻는다
        ├─ 주문 내역 CSV 내보내기에 권한 검사가 없다
        ├─ 검색 API의 응답에 다른 사용자 필드가 섞여 있다
        └─ 고객센터 관리자 화면이 인증 없이 열린다

공격 트리의 값은 가장 싼 경로를 드러낸다는 것 이다. JWT 서명 조작은 라이브러리가 제대로 되어 있으면 비용이 매우 높다. 반면 "CSV 내보내기에 권한 검사 누락"은 누구나 5분이면 확인한다. 공격자는 트리에서 가장 싼 가지를 고르고, 우리는 그 순서대로 테스트한다. 잎마다 비용·필요 권한·탐지 가능성을 붙이면 우선순위가 그대로 나온다.

잎 노드필요 권한난이도탐지 여부점검 우선순위
CSV 내보내기 권한 누락로그인 계정낮음로그에 안 남음1
IDOR (orderId 변경)로그인 계정낮음접근 로그 있음1
로그아웃 후 토큰 유효로그인 계정낮음안 남음2
관리자 엔드포인트 호출로그인 계정중간감사 로그 있음2
JWT alg=none없음높음안 남음3

4단계 — 위험 등급, 그리고 DREAD를 쓰지 않는 이유

위협 목록을 만들면 반드시 "그래서 뭐가 제일 급한가"라는 질문이 온다. 오래된 교재는 DREAD(Damage·Reproducibility·Exploitability·Affected users·Discoverability)를 소개하지만, 마이크로소프트도 실무에서 걷어냈고 현장에서도 잘 쓰이지 않는다. 이유는 점수가 주관적이고 사람마다 결과가 달라 재현되지 않기 때문 이다. 현재 현장에서 쓰이는 방식은 두 가지다.

  • 발생 가능성 × 영향 매트릭스 — 위협 모델링 단계처럼 아직 실제 취약점이 확인되지 않았을 때. 정성 등급(상·중·하)으로 충분하다
  • CVSS — 실제 취약점이 확인된 뒤 심각도를 표준 점수로 매길 때(모듈 23 레슨 3에서 다뤘다)

위협 모델링 단계에서는 전자를 쓴다. 주의할 점은 영향을 기술적 영향이 아니라 사업적 영향 으로 적는 것이다.

나쁜 서술: "권한 검사가 없다"              → 무엇이 문제인지 판단 불가
좋은 서술: "로그인한 누구나 전체 회원의 배송지와 연락처를
           CSV로 내려받을 수 있다 (약 42만 건, 개인정보 유출 신고 대상)"

두 번째 문장은 그 자체로 등급을 정해 준다. 이것이 이 모듈의 주제 문장 — 보안 테스트의 가치는 취약점 목록이 아니라 실제 위험의 판정에 있다 — 의 출발점이다.

언제, 얼마나 자주 하는가

위협 모델링을 전체 시스템에 대해 한 번 크게 하고 끝내면 반드시 낡는다. 현실적인 운영 방식은 두 겹이다.

주기범위참가자산출물
연 1~2회서비스 전체 DFD 갱신아키텍트·보안·QA 리드신뢰 경계 지도, 상위 위협 목록
변경 시마다바뀐 흐름만기능 담당 개발자 + QA위협 3~5개와 점검 케이스

두 번째가 실제로 효과를 낸다. 신뢰 경계를 새로 넘는 변경 — 새 외부 연동, 새 권한 역할, 새 파일 업로드, 새 웹훅 수신 — 이 생길 때만 30분짜리 세션을 여는 규칙이면 충분히 굴러간다.

실무에서 왜 필요한가

첫째, 테스트 범위를 방어할 수 있게 된다. "보안 테스트 다 했나요"라는 질문에 "OWASP Top 10 다 봤습니다"는 답이 되지 않는다. Top 10은 일반적인 목록이고 우리 도메인의 쿠폰 중복 적용은 거기에 없다. DFD와 위협 목록이 있으면 "신뢰 경계 A를 넘는 흐름 11개 중 9개를 점검했고, 남은 2개는 이번 스프린트 범위 밖"처럼 덮은 것과 안 덮은 것을 구분해서 말할 수 있다.

둘째, 개발팀과 대화가 된다. 취약점 티켓은 종종 "그건 내부망이라 괜찮다"로 닫힌다. 위협 모델의 신뢰 경계가 그려져 있으면 그 주장이 검증 가능한 문장이 된다. "내부망 가정이 맞다면, 게이트웨이를 우회해 이 서비스에 직접 도달하는 경로가 없어야 한다. 확인해 보자"로 대화가 바뀐다. 실제로 확인해 보면 우회 경로가 있는 경우가 흔하다.

셋째, 설계 단계에서 잡힌다. 위협 모델링은 코드가 없어도 할 수 있는 유일한 보안 활동이다. 스펙 리뷰에 30분짜리 STRIDE 세션을 붙이면, 구현 후에 발견하면 재설계가 필요한 문제를 설계 문서 수정으로 끝낼 수 있다. 모듈 34에서 본 제품 사이버보안 규격들도 같은 구조를 요구한다 — 자산을 식별하고, 위협을 도출하고, 통제를 정하고, 통제가 작동하는지 시험한다.

실습 과제

과제 1 — 신뢰 경계 그리기 (20분)

담당 중인 서비스(없으면 사내 위키·쇼핑몰 같은 익숙한 서비스를 가정)의 DFD를 요소 8~12개 규모로 그린다. 반드시 포함할 것.

  • 외부에서 들어오는 모든 입구(웹, 모바일 앱, 파트너 API, 웹훅, 배치 업로드, 관리자 콘솔)
  • 개인정보나 금액이 저장되는 데이터 저장소
  • 신뢰 경계 최소 2개 — 인터넷/내부, 앱 계층/데이터 계층, 자사/외주 또는 SaaS

그린 뒤 "이 경계를 넘는데 인증이 없는 흐름" 을 형광펜으로 표시한다. 보통 두세 개가 나온다.

과제 2 — STRIDE 열거와 케이스 변환 (25분)

과제 1의 요소 중 프로세스 하나와 데이터 저장소 하나 를 골라, 요소 종류별 적용 범주표에 따라 위협을 열거한다. 각 위협을 아래 표로 정리하고, 마지막 칸은 반드시 실행 가능한 절차로 쓴다.

요소범주위협 서술믿고 있는 통제확인 절차예상 등급

최소 8행을 채운다. "확인 절차"에 "검토한다", "점검한다" 같은 말이 들어가면 다시 쓴다 — 누가 봐도 같은 결과가 나오는 절차여야 한다.

과제 3 — 공격 트리와 점검 순서 (20분)

과제 2에서 등급이 가장 높게 나온 위협 하나를 목표로 삼아 공격 트리를 깊이 3단계까지 그린다. 잎마다 필요 권한·난이도·탐지 가능성을 붙이고, 가장 싼 잎 세 개 를 골라 그 순서대로 점검 케이스 번호를 매긴다. 이 세 개가 다음 스프린트에 넣을 보안 회귀 케이스가 된다.

자가 체크리스트

  • DFD의 네 요소와 신뢰 경계를 구분해 그릴 수 있다
  • STRIDE 여섯 범주와 각 범주가 깨뜨리는 보안 속성을 짝지어 말할 수 있다
  • 요소 종류(외부 엔터티·프로세스·저장소·흐름)마다 우선 적용할 STRIDE 범주를 고를 수 있다
  • 위협 서술을 "확인 절차"까지 밀어붙여 테스트 케이스로 바꿀 수 있다
  • 공격 트리를 AND/OR로 분해하고 잎에 비용을 붙여 점검 순서를 정할 수 있다
  • 위협 모델링 단계의 정성 등급과 확인된 취약점의 CVSS를 구분해 쓸 수 있다
  • DREAD를 쓰지 않는 이유를 설명할 수 있다
  • 위협 모델을 갱신해야 하는 변경(새 신뢰 경계)을 알아볼 수 있다

흔한 실수

  • 아키텍처 다이어그램을 DFD로 착각한다. 컴포넌트 배치도에는 신뢰 경계가 보이지 않는다. 데이터가 어디서 와서 어디에 머무는지를 그려야 위협이 드러난다.
  • 위협을 열거하고 끝낸다. 문서만 남고 테스트는 그대로다. 위협 한 줄마다 "확인 절차" 칸을 강제하면 이 실수가 구조적으로 막힌다.
  • "내부망이라 안전하다"를 검증 없이 통제로 적는다. 그 가정 자체가 가장 먼저 시험해야 할 대상이다. 게이트웨이 우회 경로는 생각보다 자주 존재한다.
  • DREAD 점수로 우선순위를 정한다. 사람마다 점수가 달라 재현되지 않는다. 확인 전에는 가능성×영향, 확인 후에는 CVSS를 쓴다.
  • 영향을 기술 용어로만 적는다. "권한 검사 누락"은 의사결정을 못 만든다. 몇 명의 어떤 정보가 어떻게 되는지 적어야 등급이 정해진다.
  • 모든 기능에 대해 매번 전체 모델링을 하려 한다. 지쳐서 아무도 안 하게 된다. 신뢰 경계를 새로 넘는 변경에만 30분 세션을 거는 규칙이 오래간다.

참고 자료

낯선 말 풀이

이 레슨에 나온 약어입니다. 본문에서도 처음 나올 때 점선으로 표시해 두었습니다 (제목과 링크 글자는 그대로 둡니다).

SAST — 정적 보안 분석
프로그램을 돌리지 않고 코드 자체를 읽어 위험한 부분을 찾는 검사.
DAST — 동적 보안 분석
실제로 돌아가는 서비스에 요청을 보내 보며 취약점을 찾는 검사.
SCA — 구성 요소 분석
가져다 쓴 부품 코드에 알려진 취약점이 있는지 목록과 맞춰 보는 검사.
PG — 결제 대행
쇼핑몰과 카드사 사이에서 결제를 중개해 주는 서비스.
API — 응용 프로그램 인터페이스
프로그램끼리 주고받는 창구. 사람이 화면 버튼을 누르는 대신, 프로그램이 정해진 주소로 요청을 보내 답을 받는다.
HTTPS — 암호화된 웹 전송
웹 통신을 암호로 감싼 것. 중간에서 누가 들여다봐도 내용을 못 읽는다.
DB — 데이터베이스
데이터를 넣어 두고 꺼내 쓰는 저장소. 보통 표 여러 개가 서로 연결된 형태다.
SQL — 구조화 질의 언어
저장소에 "이런 조건인 줄을 보여 달라"고 묻는 말. 영어 문장에 가까워서 읽기가 비교적 쉽다.
CSV — 쉼표로 구분된 값
표를 글자로 적어 둔 가장 단순한 형식. 줄마다 한 행, 쉼표로 칸을 나눈다.
CVSS — 공통 취약점 등급 체계
발견된 취약점이 얼마나 심각한지 0~10점으로 매기는 공통 방식.
QA — 품질보증
만든 것이 쓸 만한지 확인하고, 애초에 덜 망가지게 만드는 방법을 정하는 일. "테스트"는 그 일의 일부다.
OWASP — 오왁스프
웹과 앱 보안 자료를 공개로 만드는 비영리 단체. 취약점 목록과 점검 기준이 유명하다.

이 레슨에 나온 나머지 1개를 포함해 용어집 전체 보기