Step 173. 시나리오 1 복기와 침투 보고서 — 기록을 문서로 엮는 기술

Step 173. 시나리오 1 복기와 침투 보고서 — 기록을 문서로 엮는 기술

Level 2 — 보안 입문과 공격 스킬 기초 | 난이도 ★★★☆☆ | 예상 소요 시간 3시간

전제: Step 172(종합 시나리오 1)의 타임라인과 증거, Step 128(MS2 보고서)의 6단 구조를 안다.

  • 준비물: Step 172의 타임라인과 증거 파일들, 마크다운 에디터, 파이썬 3(구조 검증기용).
  • ⚠️ 이 챕터의 실습은 내 랩·합법 플랫폼 전용입니다. 허가 없는 시스템에 적용하면 범죄입니다.
  • 성격 안내: 오늘은 [프로젝트] 챕터입니다. 새로운 공격이 없습니다 — 어제의 공격을 남이 재현할 수 있는 문서로 만드는 날입니다.

침투는 끝났지만 일은 끝나지 않았습니다. 실무 침투 테스트의 산출물은 쉘이 아니라 보고서이고, 보고서는 두 명의 독자를 위해 씁니다 — 임원("얼마나 위험한가, 뭘 해야 하나")과 엔지니어("어디를 어떻게 고치나"). 오늘은 두 갈래 일을 합니다. 먼저 복기 — 시나리오 1의 전 과정을 기억이 아니라 기록으로 재구성하고, 놓친 단서를 분석합니다. 그다음 보고서 — 복기의 결과를 두 독자가 각자 읽을 수 있는 문서로 엮습니다. 막혔던 지점과 돌파 과정까지 쓰는 것이 오늘의 규칙입니다 — 실패가 보고서의 가치를 높입니다.


1. 학습 목표

이 챕터를 끝내면 다음을 할 수 있습니다:

  • 타임라인 기록에서 공격 경로를 재구성한다
  • 놓친 단서 분석(왜 늦게 봤는가)으로 다음 판의 개선점을 뽑는다
  • 경영진 요약(비기술)과 기술 상세(재현 가능)의 톤을 구분해 쓴다
  • 발견사항을 위험도·재현 단계·증거·수정 방안의 네 칸으로 기술한다
  • 보고서 구조를 자동 검증하는 작은 도구를 만든다

2. 배경 지식 — 오늘의 도구와 개념

오늘의 도구 한눈에 보기

구분 내용
언어·환경 마크다운, 파이썬 3 (구조 검증기)
오늘의 재료 Step 172의 타임라인, 증거 출력, server.log 인용
필요한 개념 복기(debrief), 놓친 단서 분석, 재현 가능성, 위험도 서술, 두 독자
오늘의 산출물 시나리오1-침투보고서.md 1부 + report_check.py 구조 검증기

2-1. 복기 — 기억이 아니라 기록으로

복기(debrief)는 끝난 판을 다시 펼쳐 보는 일입니다. 바둑의 복기처럼, 목적은 결과 확인이 아니라 판단의 검토입니다 — "여기서 왜 이 가설을 먼저 검증했는가", "이 단서는 왜 늦게 봤는가".

복기의 원료는 기억이 아니라 기록입니다. 기억은 이기고 난 판을 미화합니다 — 실제로는 40분을 헤맨 구간이 기억에서는 5분으로 줄어듭니다. Step 172에서 시각을 적어 둔 이유가 오늘 드러납니다: 타임라인의 시각 간격이 "어디서 시간을 썼나"의 정직한 답입니다.

2-2. 놓친 단서 분석 — 다음 판을 위한 유산

복기에서 가장 값진 산출물은 "놓친 단서" 목록입니다. 서식은 세 칸입니다.

단서: (나중에 보니 결정적이었던 것 — 예: 배너에 버전이 있었다)
처음 본 시각 vs 활용한 시각: (예: 0:05에 봄 → 0:41에 활용)
늦은 이유: (예: 배너를 읽지 않고 포트 번호만 보고 지나침)
다음 판의 규칙: (예: 열린 포트마다 배너 전체를 소리 내어 읽는다)

"늦은 이유"가 "다음 판의 규칙"으로 변하는 순간, 실수가 자산이 됩니다.

2-3. 두 독자, 두 문체

보고서의 첫 장(요약)과 본문(기술 상세)은 언어가 다릅니다.

✗ 요약에 쓰면 안 되는 문장: "9000/tcp에서 인증 없는 명령 실행 확인"
○ 요약의 문장: "외부에서 아무 인증 없이 서버의 명령을 실행할 수 있었으며,
   이 서버는 최고 권한으로 동작 중이었습니다."

반대로 기술 상세의 기준은 재현 가능성입니다 — "제3자가 이 글만 보고 똑같이 재현할 수 있는가". 명령, 출력, 증거가 그 재료입니다. Step 128에서 배운 "증거 없는 주장은 쓰지 않는다"가 여기서도 그대로 적용됩니다.

2-4. 위험도는 근거 있는 서술이 먼저

발견사항에는 위험도를 매깁니다. 실무에는 CVSS라는 표준 점수 체계가 있지만, 입문 단계에서는 정확한 계산보다 근거 있는 서술이 우선입니다 — "인증 없이 원격에서 최고 권한의 명령 실행이 가능하므로 High/Critical 급"처럼, 등급 뒤에 이유가 붙는 형태입니다. Step 128의 심각도 기준(치명=원격 즉시 제어, 높음=권한 상승 직결, 중간=정보 노출)을 그대로 씁니다.


3. 따라 하기

3-1. 복기 — 타임라인 재구성

Step 172의 타임라인을 펴고, 각 줄을 "단계"로 묶습니다. 틀:

# 시나리오 1 복기 (작성일: ____)

### 단계별 재구성
| 시각 | 단계 | 한 일 | 결과 | 소요 |
|------|------|-------|------|------|
| 16:52 | 정찰 | nmap -sV | open + 배너 획득 | 1분 |
| 16:53 | 가설 | "인증 없는 명령 실행" | 수립 | 즉시 |
| 16:53 | 검증 | nc로 id 실행 | uid=0(root) 확인 | 1분 |

### 시간 분석
가장 오래 쓴 구간: ____
그 이유와 다음 판의 대책: ____

### 놓친 단서 (2-2의 세 칸 서식으로 최소 2개)
1. 단서: ____ / 지연: ____ / 이유: ____ / 규칙: ____
2. 단서: ____ / 지연: ____ / 이유: ____ / 규칙: ____

읽는 법: "소요" 칸은 시각 간격으로 채웁니다 — 기억이 아니라 기록에서. 가장 오래 쓴 구간이 곧 여러분의 성장 포인트이고, 그 구간의 분석이 보고서의 "돌파 과정" 절의 재료입니다.

3-2. 보고서 뼈대 — Step 128 구조의 재활용

Step 128의 6단 구조를 시나리오 1 버전으로 가져오되, 복기 절이 추가됩니다.

# 시나리오 1 침투 테스트 보고서
작성일: ____ | 작성자: ____ | 대상: (랩 환경 표기)

### 1. 요약
(비기술 3문장 — 무엇이 가능했고, 얼마나 위험하고, 어디서부터 고치나)

### 2. 범위와 정찰
(대상, 기간, 방법 + 스캔 결과 인용 — 증거: evidence/01-scan.txt)

### 3. 침투 경로
#### 경로 1: (서비스명) [위험도]
- 취약 원인: ____
- 공격 방법: (명령 순서 그대로 — 재현 가능하게)
- 획득 권한: ____ (증거의 id 출력)
- 방어 방법: ____

### 4. 증거
(출력 인용 또는 evidence/ 파일 참조 — 스크린샷에는 id/whoami 포함)

### 5. 권고 사항
(위험도 순 — 각 항목의 근거는 3절의 발견)

### 6. 타임라인과 복기
(3-1의 재구성 표 + 놓친 단서와 다음 판의 규칙)

읽는 법: 1~5절은 Step 128에서 연습한 그대로이고, 6절이 오늘의 추가분입니다. "막혔던 지점과 돌파 과정"은 3절의 각 경로 안에 한 문장으로도 넣고, 6절에 구조화해 넣습니다.

3-3. 발견사항 상세 — 네 칸의 반복

경로 하나당 "취약 원인 → 공격 방법 → 획득 권한 → 방어 방법"을 채웁니다. Step 172 미니 체인으로 채운 예시 (실측 기반):

### 경로 1: 인증 없는 명령 실행 서비스 [치명]
- 취약 원인: 9000/tcp 서비스가 인증 없이 명령을 받아 실행.
  서비스가 root 권한으로 동작 중이어서 피해가 최고 권한에 직결.
- 공격 방법:
  1. nmap -p 9000 -sV 127.0.0.1 → 배너 "MiniVulnService 1.0" 획득
  2. printf "id\n" | nc 127.0.0.1 9000 → 명령 실행 확인
- 획득 권한: root (아래 증거)
- 증거:
  $ uid=0(root) gid=0(root) groups=0(root)     (2026-09-09 실측)
- 방어 방법: 서비스에 인증 추가, 서비스 계정의 권한을 최소화.

읽는 법: "공격 방법"은 명령 순서 그대로 — 독자가 따라 하면 같은 결과가 나와야 합니다. "방어 방법"은 원인과 한 쌍입니다 — 원인이 "인증 없음"이면 방어는 "인증 추가", 원인이 "root 동작"이면 방어는 "권한 최소화".

3-4. 구조 검증기 — 빠진 절을 기계가 찾게

보고서가 길어지면 절 하나가 빠져도 눈에 안 띕니다. 작은 검증기를 만듭니다.

입력: report_check.py:

# 보고서 구조 검증기 — 필수 절이 있는지 확인
import re, sys

REQUIRED = ["요약", "범위와 정찰", "침투 경로", "증거", "권고", "타임라인"]

def check(path):
    text = open(path, encoding="utf-8").read()
    headings = re.findall(r"^#{2,3}\s+(.+)$", text, re.M)
    print(f"검사 대상: {path}")
    missing = []
    for need in REQUIRED:
        ok = any(need in h for h in headings)
        print(f"  [{'x' if ok else ' '}] {need}")
        if not ok:
            missing.append(need)
    if missing:
        print("누락:", ", ".join(missing))
    else:
        print("구조 검증 통과 — 필수 6절 모두 존재")

if __name__ == "__main__":
    check(sys.argv[1] if len(sys.argv) > 1 else "report.md")

출력 (2026-09-09 실측, 뼈대가 완성된 샘플에 대해):

검사 대상: report_sample.md
  [x] 요약
  [x] 범위와 정찰
  [x] 침투 경로
  [x] 증거
  [x] 권고
  [x] 타임라인
구조 검증 통과 — 필수 6절 모두 존재

뼈대가 비어 있는 파일(절이 없는 파일)에 대해서는 (2026-09-09 실측):

검사 대상: step170_meta.py
  [ ] 요약
  [ ] 범위와 정찰
  [ ] 침투 경로
  [ ] 증거
  [ ] 권고
  [ ] 타임라인
누락: 요약, 범위와 정찰, 침투 경로, 증거, 권고, 타임라인

읽는 법: 정규표현식 ^#{2,3}\s+(.+)이 마크다운의 절 제목만 골라냅니다 (Step 48 복습). 구조 확인을 기계에 맡기면 여러분의 눈은 내용 검토에 집중할 수 있습니다 — Step 164의 자동화 감각이 문서 작업에도 그대로 통합니다.

3-5. 셀프 피드백 — 재현성 자문

완성 초고에 마지막 질문을 던집니다: "이 보고서로 누군가 내 침투를 재현할 수 있는가?"

체크 순서: ① 3절의 명령을 그대로 옮겨 치면 같은 출력이 나오는가. ② 모든 출력에 출처(증거 파일 또는 실측 표기)가 있는가. ③ 요약을 기술을 모르는 사람에게 읽어 줬을 때 위험의 크기가 전해지는가. 하나라도 ‘아니오’면 그 절로 돌아가 보강합니다. 이 자문이 보고서를 "내 일기"에서 "남의 설명서"로 바꿉니다.


4. 미션과 연습문제

미션 — 시나리오 1 침투 보고서 1부 완성

  1. 3-1의 틀로 Step 172 타임라인을 재구성하고, 시간 분석과 놓친 단서 2개를 채웁니다
  2. 3-2의 뼈대로 시나리오1-침투보고서.md를 만들어 6절을 모두 채웁니다
  3. 요약은 비기술 3문장으로, 본문의 모든 주장에는 증거(출력 인용 또는 파일 참조)가 붙어 있습니다
  4. 막혔던 지점과 돌파 과정이 최소 1건 기록돼 있습니다
  5. report_check.py로 구조 검증을 통과합니다
  6. (Step 172를 랩 없이 계획서로 했으면) 미검증 칸에 [랩 실행 후 실측으로 교체 예정] 표시를 답니다

연습문제

문제 1. 복기를 "기억"이 아니라 "기록"으로 해야 하는 이유를, 시간 분석의 예로 설명해 보세요.

문제 2. 놓친 단서 분석의 산출물이 "다음 판의 규칙"이어야 하는 이유를 설명해 보세요.

문제 3. 같은 발견을 요약절과 기술 상세절에 각각 어떻게 다르게 쓰는지, 2-3의 예를 참고해 설명해 보세요.

문제 4. "막혔던 지점과 돌파 과정을 기록하는 것이 보고서의 가치를 높인다"는 말의 뜻을, 독자 입장에서 설명해 보세요.


5. 모범 답안과 완료 기준

미션 모범 답안

놓친 단서 분석의 실측 기반 예시입니다 (Step 172 미니 체인 복기):

단서: nmap -sV가 서버의 단일 연결을 소모한다 (버전 탐지 = 접속)
처음 본 시각 vs 활용: 스캔 직후 nc 실패 → 로그 확인 후 원인 파악
늦은 이유: "스캔은 읽기만 한다"고 가정하고 서버 구조를 의심하지 않음
다음 판의 규칙: 랩 서비스는 항상 반복 수락 구조로 만들고,
  실패하면 상대 측 로그부터 연다

요약절의 예시: "본 점검에서 대상 서버는 외부의 명령을 아무 인증 없이 실행했으며, 해당 서비스가 최고 권한으로 동작해 서버 전체 장악이 가능했습니다. 원인은 인증 부재와 과다한 실행 권한 두 가지입니다. 즉시 인증 적용과 권한 최소화가 필요합니다."

검증하는 법: ① report_check.py 통과. ② 요약에 포트 번호·도구 이름이 없는가. ③ 경로마다 네 칸이 채워졌는가. ④ 놓친 단서가 "규칙"으로 끝나는가. ⑤ 미실측 표시가 정직하게 달렸는가. 전부 ‘예’이면 완성입니다.

연습문제 해답

문제 1 해답. 이긴 판의 기억은 미화됩니다 — 40분 헤맨 구간이 5분으로 줄어드는 식입니다. 기록의 시각 간격은 거짓말을 하지 않으므로, "어디서 시간을 썼나"의 정직한 답이 됩니다. 시간 분석이 정직해야 다음 판의 시간 배분이 개선됩니다.

문제 2 해답. "늦게 봤다"는 사실만 기록하면 다음 판에도 같은 지연이 반복됩니다. 규칙("열린 포트마다 배너를 읽는다")으로 바꿔야 행동이 바뀝니다. 복기의 목적은 후회가 아니라 다음 판의 체크리스트 개선이고, 규칙은 개선이 저장되는 형식입니다.

문제 3 해답. 같은 사실을 독자의 언어로 번역합니다. 기술 상세에는 "9000/tcp, 인증 없음, 명령 실행, uid=0"처럼 재현에 필요한 정밀한 사실이 들어가고, 요약에는 "외부에서 인증 없이 서버 전체 장악 가능"처럼 결정에 필요한 사업 언어가 들어갑니다. 정밀함은 본문에, 판단 재료는 요약에 — 둘을 섞으면 양쪽 독자를 모두 잃습니다.

문제 4 해답. 독자는 성공 경로만 있는 보고서에서 "저자가 운이 좋았다" 이상을 배울 수 없습니다. 막힌 지점과 돌파 과정이 있어야 독자는 같은 함정을 피해 갈 수 있고, 그 문장들이 보고서를 재사용 가능한 지식으로 만듭니다. 또한 실패의 기록은 보고서 전체의 신뢰를 올립니다 — 숨기지 않는 사람의 성공 주장은 믿을 수 있습니다.

완료 기준 체크리스트

  • [ ] 타임라인을 단계별 표로 재구성했다
  • [ ] 놓친 단서 2개를 세 칸 서식으로 분석했다
  • [ ] 요약을 비기술 3문장으로 썼다
  • [ ] 경로마다 네 칸(원인·방법·권한·방어)을 채웠다
  • [ ] 모든 주장에 증거가 붙어 있다
  • [ ] 막힌 지점과 돌파 과정이 기록돼 있다
  • [ ] report_check.py 구조 검증을 통과했다
  • [ ] 재현성 자문(3-5)의 세 질문에 ‘예’로 답했다

6. 흔한 실수와 해결

벽 1. 검증기가 FileNotFoundError로 죽는다

증상 (2026-09-09 실측, 파일명을 잘못 적은 경우):

FileNotFoundError: [Errno 2] No such file or directory: 'nofile.md'

원인: 검증기에 넘긴 파일명이 현재 디렉터리에 없습니다.
해결: ls(또는 dir)로 파일명을 확인하고 넘기세요. 익숙해지면 try/except FileNotFoundError로 감싸 친절한 안내를 띄우는 것도 좋은 보강입니다.

벽 2. 요약에 기술 용어가 자꾸 들어간다

증상: 요약에 "nc", "9000번 포트", "uid=0"이 보입니다.
원인: 쓰는 사람의 눈이 아직 공격자에게 있습니다.
해결: 테스트 — 요약만 떼서 기술을 모르는 사람에게 읽어 보세요. "그래서 뭐가 위험한데?"라는 반응이 나오면 다시 씁니다. 요약의 각 문장은 "무슨 일이 가능했나, 얼마나 위험한가, 어디서부터 고치나" 셋 중 하나에 답해야 합니다.

벽 3. 타임라인이 비어 있어 복기가 기억 의존이 된다

증상: 재구성 표를 채우다 보니 시각이 전부 추정입니다.
원인: Step 172에서 기록을 미룬 것입니다.
해결: 이번 판은 정직하게 [기록 없음 — 추정]으로 표시하고, 분석은 확실한 구간만 하세요. 그리고 다음 판의 첫 규칙으로 "명령마다 한 줄씩 즉시 기록"을 채택합니다. 빈칸을 표시하는 정직함도 복기의 산출물입니다.

벽 4. 권고 사항이 본문 발견과 안 이어진다

증상: 권고에 본문에 없는 내용("백신 도입 권고" 같은)이 섞여 있습니다.
원인: 일반론을 채워 넣은 것입니다.
해결: Step 128의 규칙 그대로 — 권고의 각 항목 뒤에 "근거: 경로 N"을 괄호로 달아 보세요. 달 근거가 없는 권고는 빼거나, 그 발견을 본문에 추가합니다. 권고의 추진력은 "우리가 이 구멍으로 직접 들어갔습니다"에서 나옵니다.

벽 5. 실패를 지우고 성공만 쓴다

증상: 막혔던 40분이 보고서 어디에도 없습니다.
원인: 실패를 부끄러워하는 마음입니다.
해결: 5절의 문장을 다시 읽으세요 — 실패의 기록은 독자의 함정 회피 문장이자, 이 보고서를 믿을 수 있게 하는 신뢰의 증거입니다. 성공만 있는 보고서는 일기이고, 실패와 돌파가 있는 보고서는 교본입니다.


7. 정리

오늘의 개념

개념 한 줄 설명
복기(debrief) 끝난 판을 기록으로 다시 펼치는 일 — 목적은 판단 검토
놓친 단서 분석 단서·지연·이유·규칙 — 실수를 다음 판의 자산으로
두 독자 임원(사업 언어의 요약)과 엔지니어(재현 가능한 상세)
재현 가능성 "이 글만 보고 똑같이 할 수 있는가" — 기술 상세의 기준
위험도 서술 등급 뒤에 이유 — 정확한 계산보다 근거가 먼저
구조 검증 빠진 절은 기계가 찾는다 — 눈은 내용 검토에

오늘의 명령어·도구

도구 하는 일
report_check.py 필수 6절의 존재를 자동 확인
re.findall(r"^#{2,3}\s+(.+)$", text, re.M) 마크다운 절 제목 추출
Step 128의 6단 구조 보고서 뼈대 — 요약~권고
Step 172 타임라인 복기와 3절 침투 경로의 원료
[랩 실행 후 실측으로 교체 예정] 미검증의 정직한 표시

명령어보다 중요한 감각

오늘로 시나리오 1의 사이클이 닫혔습니다 — 침투하고, 기록하고, 복기하고, 문서로 남겼습니다. 쉘은 세션이 끊기면 사라지지만, 보고서는 시스템을 고치는 힘으로 남습니다. 그리고 복기가 가르쳐 준 것을 잊지 마세요: 최고의 공격자는 한 번도 안 막히는 사람이 아니라, 막힌 곳을 규칙으로 바꾸는 사람입니다. 여러분의 첫 보고서가 완벽할 필요는 없습니다 — 정직하고, 재현 가능하고, 다음 판이 나아지는 문서면 충분합니다.


전부 체크되면 Step 173 완료입니다. 사이드바의 체크박스를 눌러 진도를 저장하세요.