데이터 흐름과 신뢰 경계
55분 안팎
학습 목표
브라우저·앱·저장소의 경계를 표시합니다.
개념
그림으로 찾는 빠진 검사
로그인과 권한 검사가 있어도 입력이 어떤 경로로 들어오는지 모르면 검사가 빠진 곳을 찾기 어렵습니다. 데이터 흐름도는 사람·프로세스·저장소를 노드로, 데이터 이동을 방향 있는 화살표로 표현합니다. 신뢰 경계는 위치가 멀어지는 선이 아니라 신뢰 가정이나 권한 주체가 달라지는 지점입니다. 이번 목표는 보기 좋은 그림이 아니라 각 화살표에서 누가 무엇을 검증하는지 설명하는 것입니다.
앞 앱의 server.cjs는 HTTP 요청을 받아 어댑터를 거쳐 app.cjs의 처리 함수를 호출합니다. auth.cjs는 계정과 세션을 메모리에 보관하고 app.cjs는 자료를 Map으로 관리합니다. 외부 데이터베이스가 없는 상태에서 SQL 저장소를 그리면 실제 구현과 다른 모델이 됩니다. 향후 데이터베이스 그림은 예정 구조로 따로 표시합니다. 노드의 배치보다 현재 코드와의 대응이 먼저입니다.
노드와 경계를 분리해서 적습니다
N-browser는 사용자가 조작할 수 있는 입력 출처이며 N-app은 요청 처리 프로세스입니다. N-memory는 같은 프로세스의 자료와 세션 상태를 가리키는 논리 노드이고 N-log는 관찰 기록을 뜻합니다. B-web은 브라우저의 주장을 서버 검증으로 바꾸는 경계, B-owner는 인증된 사용자라도 타인 자료에 접근하지 못하게 하는 권한 경계입니다. 같은 프로세스 내부에도 논리 권한 경계가 존재합니다.
현재 앱과 메모리 사이를 별도의 OS 격리 경계라고 부르면 안 됩니다. 프로세스가 손상되면 그 메모리 상태에 접근할 수 있다는 가정이 남습니다. 로그 접근에는 앞 모듈의 app 계정과 auditor 계정 권한이 관계됩니다. 함수 검사만으로 Linux 파일 경계를 확인했다고 쓰지 않고 E02와 Docker 검사 결과를 별도 근거로 연결합니다. 물리 격리와 업무 인가를 한 선으로 합치지 않습니다.
로그인 흐름을 왕복으로 그립니다
F-login의 요청은 브라우저에서 앱으로 사용자명과 비밀번호를 전달합니다. B-web에서 문자열 형식과 인증 결과를 검증하고 세션 저장소에 사용자·만료 시각을 연결합니다. 응답은 쿠키 전달을 통해 브라우저로 돌아갑니다. 쿠키는 발급 수단이므로 로그인 성공 응답에 식별자가 전달되는 것과 로그에 원문을 저장하지 않는 것을 구분합니다. 서버가 토큰을 발급했다고 이후 토큰 입력을 검증 없이 신뢰하지 않습니다.
쿠키 플래그, 전달 경로, 실제 TLS는 서로 다른 관찰 대상입니다. 이 로컬 앱의 HTTP 성공은 HTTPS 인증서 검증 성공을 의미하지 않습니다. 브라우저에 잠금 아이콘이 없는 실습 상태를 서비스 배포의 보안 수준으로 확대하지 않습니다. 실제 전송 보호는 후속 검증 항목으로 남기며 이 모듈에서 외부 사이트에 요청을 보내 확인하지 않습니다.
조회와 변경을 다른 흐름으로 둡니다
F-read는 세션과 자료 ID를 받아 자료를 반환합니다. 서버는 세션 저장소에서 주체를 확인하고 자료의 owner와 비교합니다. ID는 경로 선택 입력이고 권한의 근거가 아닙니다. 타인의 ID를 알고 있어도 허용되지 않아야 합니다. 관리자 GET 예외는 현재 정책에 명시되어 있으므로 해당 예외를 B-owner의 검증 규칙에 포함합니다. 상태 404만 적지 말고 어떤 주체와 자원 조합인지 같이 씁니다.
F-change는 PATCH와 DELETE를 묶되 각 동작의 후조건을 적습니다. PATCH 성공은 소유자 자료의 제목·본문 변경이고 DELETE 성공은 자료 제거입니다. 타인 변경 거절은 응답 404와 원본 보존이 함께 필요합니다. 생성 POST에서는 owner를 본문에서 가져오지 않고 세션에서 설정합니다. 조회·변경·생성을 하나의 자료 화살표로 뭉치면 쓰기 권한과 소유자 위조 입력을 놓치기 쉽습니다.
공격 표면은 입력 목록에서 찾습니다
공격 표면은 의도하지 않은 동작을 유발할 수 있는 접점의 집합으로 정리합니다. 경로 ID, 메서드, JSON 제목·본문, 세션 쿠키, 요청 크기, 로그 기록 경로를 목록에 넣습니다. 모든 접점을 취약점이라고 부르지 않습니다. 필요한 입력 기능도 공격 표면에 포함되며 실제 결함 여부는 전제·검사·실행 결과로 판단합니다. 숨긴 버튼이나 추측하기 어려운 ID는 서버 인가를 대신하지 않습니다.
흐름표는 ID, 출발 노드, 도착 노드, 전달 데이터, 경계 ID, 검증 위치를 포함합니다. 응답 화살표에는 자료 본문 또는 오류 정보가 돌아간다는 점을 표시합니다. 로그 화살표에는 status와 request_id만 기록한다고 적고 사용자 입력이 로그로 이동할 가능성도 검토합니다. 입력에서 자료로 가는 길뿐 아니라 자료에서 화면과 증거로 나가는 길을 따라가야 유출 경로가 보입니다.
그림 리뷰와 연결 오류
동료에게 로그인·조회·변경을 차례로 손가락으로 따라가게 합니다. 각 단계의 신원 출처와 거절 지점을 설명하지 못하면 경계 설명을 보완합니다. 앞 회귀 시험의 타인 404를 F-read와 F-change에 연결하고 함수 관찰과 HTTP 관찰을 분리합니다. 모델은 보안 완료 증명서가 아니라 현재 가정을 리뷰하고 다음 검사를 고르는 도구입니다. 기능·저장 위치·권한 정책이 바뀌면 모델도 갱신합니다.
boundary 오류는 참조 ID가 경계 목록에 없다는 뜻이며 철자와 대소문자를 확인합니다. node 오류는 출발 또는 도착의 노드가 정의되지 않은 경우입니다. 키 이름을 수정한 뒤에도 위협이 연결한 flow와 boundary가 서로 일치하는지 점검합니다. ID가 존재한다는 검사와 그림이 실제 데이터 경로를 표현한다는 리뷰는 별개입니다. 경계 이름만 새로 추가해 오류를 덮지 않습니다.
실무 리뷰를 한 번 더 합니다
흐름표를 변경할 때 코드 변경과 문서 변경을 한 묶음으로 검토합니다. 자료 내보내기 기능이 생기면 앱에서 다운로드 응답으로 나가는 새 화살표와 인가 지점이 필요합니다. 단순히 기존 조회와 비슷하다는 이유로 생략하면 우회 경로를 놓칩니다. 이번 범위에는 그 기능이 없다는 사실도 모델에 적어 현재 존재하는 화살표와 미래 제안을 구별합니다. 각 화살표의 데이터 필드는 원문을 복사하지 않고 필드 이름만 씁니다.
따라하기
신뢰 주체 비교
Python 3에서 다음 코드를 실행하고 판별에 사용한 조건을 확인합니다.
claimed='demo-bob'; resolved='demo-alice'
print('claimed:', claimed)
print('trusted:', resolved)실행 결과
claimed: demo-bob trusted: demo-alice
경계 참조 점검
Python 3에서 다음 코드를 실행하고 판별에 사용한 조건을 확인합니다.
boundaries={'B-web','B-owner'}
flows=[('F-login','B-web'),('F-read','B-owner'),('F-change','B-missing')]
for name,b in flows: print(name, 'known' if b in boundaries else 'unknown')실행 결과
F-login known F-read known F-change unknown
거절 후 상태 읽기
Python 3에서 다음 코드를 실행하고 판별에 사용한 조건을 확인합니다.
before={'owner':'demo-alice','title':'synthetic'}
after=before.copy()
print('preserved:', before==after)
print('owner:', after['owner'])실행 결과
preserved: True owner: demo-alice
제출물과 실행 결과 대조
미션 ZIP의 nodes·boundaries·flows를 작성합니다. 로그인·조회·변경의 입력과 응답을 그리고 각 검증 위치를 코드에서 찾습니다.
확인 문제
실습
로그인·조회·변경 흐름표와 왕복 그림을 제출합니다. 노드 ID·방향·데이터 필드·경계 ID·검증 위치를 적고 B-web과 B-owner를 구별합니다. 메모리 저장을 별도 OS 격리로 표현하지 않습니다.
더 읽기
면접 질문
- 실습 앱에서 보호할 자산과 신뢰 경계를 설명합니다.