소개
위협 모델링은 시스템이 공격받기 전에 무엇이 잘못될 수 있는지 미리 생각해보는 실용적인 방법입니다. 도구부터 시작하는 대신, 무엇을 보호해야 하는지, 데이터가 어디서 신뢰 경계를 넘나드는지, 공격자가 시스템을 어떻게 이동할 수 있는지, 그리고 어떤 통제 수단이 위험을 줄일 수 있는지를 먼저 파악합니다.
이번 실습에서는 소규모 로컬 로그인 서비스를 검사하고 security-model.json 파일에 구조화된 위협 모델을 완성합니다. 이 모델은 자유 형식의 보고서가 아닙니다. 각 단계에서 검증 스크립트로 확인할 수 있는 특정 JSON 항목을 추가하게 됩니다.
로그인 서비스 검사
이 단계에서는 모델링할 소규모 서비스를 검사합니다. 위협 모델링은 관찰 가능한 시스템 동작, 즉 애플리케이션이 무엇을 하는지, 어떤 파일을 사용하는지, 공격자에게 어떤 정보가 중요할 수 있는지에서 시작합니다.
먼저 프로젝트 디렉토리로 이동합니다:
cd /home/labex/project
준비된 파일 목록을 확인합니다:
ls -l
app.py, users.json, sessions.json, security-model.json 및 uploads 디렉토리와 같은 파일들이 보일 것입니다.
이제 데모 애플리케이션의 라우트 (route) 를 확인합니다. 라우트는 일종의 요청을 수락하는 애플리케이션 진입점입니다:
python3 app.py routes
출력 결과에는 네 가지 라우트가 표시됩니다:
/login - 사용자 이름과 비밀번호를 받아 세션 토큰을 생성합니다.
/files - 로그인한 사용자의 파일 목록을 보여줍니다.
/download - uploads 디렉토리에서 요청된 파일명을 읽어옵니다.
/admin - 관리자에게만 계정 기록을 보여줍니다.
마지막으로 현재 모델 검사기를 실행합니다. 모델이 비어 있기 때문에 각 섹션이 누락되었다는 메시지가 출력될 것입니다:
python3 model-check.py all
각 섹션에 필요한 항목이 누락되었다는 메시지가 나타날 것입니다. 이것이 이번 실습의 시작점입니다.
자산 식별
이 단계에서는 모델에 자산을 추가합니다. 위협 모델링에서 자산이란 시스템이 보호해야 하는 모든 것을 의미합니다. 이 로그인 서비스에서 중요한 자산은 파일뿐만 아니라 인증 데이터와 세션 상태도 포함됩니다.
cat 명령어를 사용하여 사용자 데이터베이스를 확인합니다:
cat users.json
이 파일에는 사용자 이름, 비밀번호, 역할이 포함되어 있습니다. 따라서 user_credentials와 admin_records는 중요한 자산입니다.
세션 파일과 uploads 디렉토리를 확인합니다:
cat sessions.json
ls -l uploads
세션 파일에는 로그인 토큰이 포함될 수 있고, uploads 디렉토리에는 사용자의 개인 콘텐츠가 포함되어 있습니다. 이는 각각 session_tokens와 private_uploads에 해당합니다.
이제 security-model.json의 assets 배열을 업데이트합니다. 아래 명령어는 파이썬의 here-document 를 사용합니다. here-document 는 PY 마커 사이의 줄들을 짧은 스크립트로 python3에 전달합니다:
python3 - <<'PY'
import json
from pathlib import Path
path = Path("security-model.json")
model = json.loads(path.read_text())
model["assets"] = [
"user_credentials",
"session_tokens",
"private_uploads",
"admin_records",
]
path.write_text(json.dumps(model, indent=2) + "\n")
PY
자산 섹션만 검사합니다:
python3 model-check.py assets
예상 결과는 다음과 같습니다:
assets: complete
신뢰 경계 매핑
이 단계에서는 신뢰 경계를 추가합니다. 신뢰 경계는 제어 수준이나 신뢰 수준이 다른 영역 간에 데이터가 이동하는 지점입니다. 신뢰할 수 없는 입력이 신뢰할 수 있는 코드, 파일 또는 권한이 필요한 기능으로 넘어갈 때 많은 공격이 발생하기 때문에 경계를 파악하는 것은 매우 유용합니다.
라우트 목록을 다시 확인합니다:
python3 app.py routes
/login, /files, /download 라우트는 사용자 측에서 입력을 받아 서버 로직으로 전달합니다. 이 소규모 모델에서는 이를 browser_to_server 경계라고 합니다.
/download 라우트는 요청에서 파일 이름을 읽어 uploads 디렉토리에 접근합니다. 이는 server_to_filesystem 경계를 생성합니다. /admin 라우트는 일반 사용자와 관리자 전용 데이터를 구분하므로 user_to_admin_area 경계를 생성합니다.
이 경계들을 모델에 추가합니다:
python3 - <<'PY'
import json
from pathlib import Path
path = Path("security-model.json")
model = json.loads(path.read_text())
model["trust_boundaries"] = [
"browser_to_server",
"server_to_filesystem",
"user_to_admin_area",
]
path.write_text(json.dumps(model, indent=2) + "\n")
PY
신뢰 경계 섹션을 검사합니다:
python3 model-check.py trust_boundaries
예상 결과는 다음과 같습니다:
trust_boundaries: complete
공격 경로 추가
이 단계에서는 공격 경로를 추가합니다. 공격 경로는 공격자가 진입점에서 자산으로 이동할 수 있는 구체적인 방법입니다. 이것이 위협 모델링의 핵심으로, 자산과 경계를 현실적인 공격자 행동과 연결하는 것입니다.
데모 자격 증명을 사용하여 로그인 시도를 해봅니다:
python3 app.py login alice wonderland
출력 결과로 세션 토큰이 나옵니다:
session-alice-demo
이 동작은 왜 비밀번호와 세션 토큰이 중요한지를 보여줍니다. 약한 비밀번호는 credential_guessing(자격 증명 추측) 을 가능하게 하고, 도난당한 토큰은 session_token_theft(세션 토큰 탈취) 를 가능하게 할 수 있습니다.
/download 라우트는 요청된 파일명을 허용하므로, 부주의한 구현은 path_traversal(경로 탐색) 공격을 허용할 수 있습니다. /admin 라우트는 관리자 기록을 보호하므로, 역할 확인이 누락되면 admin_area_abuse(관리자 영역 남용) 가 발생할 수 있습니다.
이 공격 경로들을 모델에 추가합니다:
python3 - <<'PY'
import json
from pathlib import Path
path = Path("security-model.json")
model = json.loads(path.read_text())
model["attack_paths"] = [
"credential_guessing",
"session_token_theft",
"path_traversal",
"admin_area_abuse",
]
path.write_text(json.dumps(model, indent=2) + "\n")
PY
공격 경로 섹션을 검사합니다:
python3 model-check.py attack_paths
예상 결과는 다음과 같습니다:
attack_paths: complete
완화 조치 선택
이 단계에서는 완화 조치를 추가하여 모델을 완성합니다. 완화 조치는 공격 경로의 발생 가능성이나 영향을 줄이는 통제 수단입니다. 좋은 위협 모델은 각 중요한 공격 경로를 최소한 하나 이상의 실용적인 통제 수단과 연결합니다.
소규모 로그인 서비스를 위해 다음 조합을 사용합니다:
credential_guessing은rate_limit_login으로 줄일 수 있습니다.session_token_theft는protect_session_tokens로 줄일 수 있습니다.path_traversal은validate_download_paths로 줄일 수 있습니다.admin_area_abuse는enforce_admin_authorization으로 줄일 수 있습니다.
완화 조치를 모델에 추가합니다:
python3 - <<'PY'
import json
from pathlib import Path
path = Path("security-model.json")
model = json.loads(path.read_text())
model["mitigations"] = [
"rate_limit_login",
"protect_session_tokens",
"validate_download_paths",
"enforce_admin_authorization",
]
path.write_text(json.dumps(model, indent=2) + "\n")
PY
이제 전체 모델 검사를 실행합니다:
python3 model-check.py all
모든 섹션이 완료되어야 합니다:
assets: complete
trust_boundaries: complete
attack_paths: complete
mitigations: complete
최종 구조화된 모델을 확인할 수도 있습니다:
cat security-model.json
중요한 결과는 이 모델이 동일한 소규모 서비스에 대해 보호 대상 자산, 신뢰 경계, 공격 경로 및 완화 조치를 모두 연결했다는 점입니다.
요약
소규모 로그인 서비스를 대상으로 실용적인 위협 모델링 워크플로우를 실습했습니다. 서비스를 검사하고, 자산을 식별하고, 신뢰 경계를 매핑하고, 공격 경로를 추가한 뒤, 구조화된 JSON 모델 내에서 해당 경로와 완화 조치를 연결했습니다.
이 워크플로우는 위협 모델링을 별도의 서면 보고서로 취급하는 대신, 보안적 사고를 관찰 가능한 시스템 동작과 연결하는 데 도움을 줍니다.



