Step 101. Bandit 26~30 — git 이력에서 비밀 캐기, 그리고 완주
Level 2 — 보안 입문과 공격 스킬 기초 | 난이도 ★★★☆☆ | 예상 소요 시간 3시간
전제: Step 86~88의 Git 지식(
log,show,branch,tag)과 Step 100까지의 Bandit 경험을 사용합니다.
- 준비물: Bandit 25까지의 비밀번호 체인, SSH 접속 환경, 그리고 내 컴퓨터의 git(로컬 실험용).
- ⚠️ 이 챕터의 실습은 내 랩·합법 플랫폼 전용입니다. 허가 없는 시스템에 적용하면 범죄입니다.
- 주의: Bandit은 OverTheWire가 공식적으로 운영하는 합법 학습 플랫폼입니다 — 공격을 전제로 열어 둔 연습장이니 마음껏 공격하되, 같은 기법을 다른 시스템에 쓰면 안 됩니다. 남의 저장소를 허락 없이 캐는 것은 그것이 공개되어 있어도 침입의 시작이 될 수 있습니다.
Step 87에서 우리는 이렇게 배웠습니다 — 공개 저장소에 비밀을 올리지 마라, 지워도 과거 커밋에 남으니까. 그때는 방어의 규칙이었습니다. 오늘은 동전의 뒷면입니다: 여러분이 익힌 git log, git show, git branch -a, git tag가 그대로 "남의 실수 발굴 도구"가 됩니다. 개발자가 실수로 올린 비밀 키를 Git 이력에서 찾아내는 것은 실제 버그 바운티(취약점 신고 포상제)의 단골 기법이고, Bandit의 마지막 구간(26~30)이 바로 그 훈련장입니다. 완주 후에는 0~30 전체를 한 장의 지도로 정리하는 복기가 기다립니다.
1. 학습 목표
이 챕터를 끝내면 다음을 할 수 있습니다:
- 제한된 쉘 환경에서
more/vim경유로 파일을 읽는 우회의 개념을 설명한다 git clone으로 저장소를 통째로 가져오고, 이력·브랜치·태그에서 숨은 비밀을 찾는다- "지운 비밀은 사라지지 않는다"를 로컬 git 실험으로 직접 증명한다
git log --all -p | grep조합으로 저장소 전체 역사를 검색한다- 워게임 복기의 세 질문(기술·패턴·연결)으로 학습을 자산화한다
2. 배경 지식 — 오늘의 도구와 개념
오늘의 도구 한눈에 보기
| 구분 | 내용 |
|---|---|
| 언어·환경 | Bandit 서버(SSH, 출력 예시) + 내 컴퓨터의 git(실측 실험) |
| 오늘의 명령어 | git clone, git log --oneline --all, git show 해시, git branch -a, git show 브랜치:파일, git tag, git log --all -p | grep |
| 필요한 개념 | 제한된 쉘 우회(more→vim), git 객체와 이력, 브랜치와 태그, 비밀 유출 대응(폐기·재발급) |
| 오늘의 산출물 | treasure-lab — 비밀을 묻고 캐는 로컬 연습 저장소, 그리고 bandit-총정리.md 복기 문서 |
2-1. 제한된 쉘 — 문이 아니라 문의 부품을 본다
Bandit 26은 접속하자마자 튕기는 계정입니다. 로그인 쉘이 일반 bash가 아니라, 텍스트를 보여 주고 종료하는 특수 프로그램으로 설정되어 있기 때문입니다. 이런 환경을 제한된 쉘(restricted shell) 상황이라고 부릅니다.
우회의 실마리는 "쉘이 막혀 있어도, 그 쉘이 부른 부품의 기능은 살아 있다"는 것입니다. 출력이 터미널 창보다 길면 텍스트 표시 프로그램은 more(한 화면씩 보기) 상태로 멈추고, more 상태에서는 v 키로 편집기 vim을 띄울 수 있습니다. vim은 파일을 여는 프로그램이니, vim에 들어가는 순간 제한은 사라집니다. Step 100에서 예고한 문제의 본편입니다.
2-2. git clone — 현재 파일이 아니라 전체 역사를 가져오기
git clone은 남의 저장소를 역사채로 복제하는 명령입니다.
git clone ssh://사용자@주소:포트/경로
중요한 사실 — clone은 "현재 파일"만 가져오는 것이 아니라 .git 폴더, 즉 전체 역사를 가져옵니다. 과거의 모든 커밋, 모든 브랜치, 모든 태그가 내 컴퓨터에 복사됩니다. 이것이 발굴이 가능한 이유입니다. Bandit의 git 서버들은 레벨별로 별도 계정(bandit27-git 등)과 SSH 포트(2220)로 열려 있습니다.
2-3. 역사 캐기 3대 수법
공격자가 clone한 저장소에서 비밀을 찾는 순서는 정해져 있습니다.
- 과거 커밋:
git log --oneline→ 의심스러운 커밋을git show 해시로 열람 - 다른 브랜치:
git branch -a→ 개발용(dev) 브랜치에 진짜가 있을 수 있음 - 태그:
git tag→ 출시 표식에 끼워 넣은 메모를git show 태그명으로
셋 다 여러분이 Step 86~88에서 배운 명령입니다. 차이는 시선뿐입니다 — "내 역사 관리 도구"에서 "남의 실수 발굴 도구"로.
2-4. 복기의 기술 — 게임을 자산으로 바꾸기
워게임을 "풀고 잊는 것"과 "자산으로 만드는 것"의 차이는 복기 한 번입니다. 복기의 질문은 세 개입니다.
- 이 문제는 무엇을 요구했는가 (기술)
- 나는 왜 막혔거나 빨랐는가 (나의 패턴)
- 이 기법은 실전의 어디에 해당하는가 (연결)
세 번째 질문이 복기의 심장입니다. 기술은 연결될 때 오래 남습니다.
3. 따라 하기
3-1. Level 26 → 27: 제한된 쉘 탈출의 완성
Step 100의 3-6에서 예고한 문제의 본편입니다. 서버에 접속해 봅니다.
입력 — 정찰:
ssh bandit26@bandit.labs.overthewire.org -p 2220
출력 예시: 접속 즉시 짧은 텍스트가 보이고 연결이 끊깁니다.
절차:
- 터미널 창의 높이를 2~3줄로 극단적으로 줄입니다.
- 다시 접속 — 이번엔 텍스트가 창을 넘어
more상태(화면 하단에--More--표시)에 멈춥니다. v를 눌러 vim 진입.- vim 안에서
:e /etc/bandit_pass/bandit26입력 → 비밀번호가 열립니다.
읽는 법: 쉘이 막혀 있어도 그 쉘이 부른 부품(more)의 기능(vim 진입)으로 우회했습니다. "문이 아니라 문의 부품을 본다"는 Step 100의 교훈이 실전으로 완성된 순간입니다.
막히면: vim이 안 열리면 more 상태가 아닌 것입니다 — 창을 더 줄이세요. vim에서 갇히면 Esc → :q! → Enter.
3-2. Level 27 → 28: 첫 git 클론
입력 (서버에서, 출력 예시):
mkdir /tmp/git27 && cd /tmp/git27
git clone ssh://bandit27-git@localhost:2220/home/bandit27-git/repo
cd repo && ls
cat README
출력 예시: 클론된 저장소의 파일들 — README 안에 다음 비밀번호가 보입니다(이 레벨은 예열 단계).
읽는 법: localhost:2220은 "이 서버 안의 SSH를 통해 git 서비스에 접속"한다는 뜻입니다. 비밀번호를 물으면 현재 레벨의 것을 입력합니다.
왜 하는가: 원격 git 저장소를 clone하는 흐름 자체가 실전 기술입니다. 실제 침투에서 "개발 서버의 git이 열려 있다"는 발견은 대박 단서이고, 행동은 지금 이 순서 그대로입니다.
3-3. Level 28 → 29: 과거 커밋 파기
이번 저장소의 README는 비밀번호가 xxxxxx로 가려져 있습니다.
입력 (서버에서):
git log --oneline
git show 가장오래된커밋해시
출력 예시: 과거 커밋의 README에는 가려지기 전의 실제 비밀번호가 있습니다.
읽는 법: git show 해시는 그 커밋에서 무엇이 바뀌었는지 보여 줍니다. "비밀번호 가림" 커밋의 바로 이전이 보물 상자입니다.
왜 하는가: Step 87의 실험(지운 키를 git show로 꺼내기)이 공격 기법이 되어 돌아왔습니다. 지운 것은 사라진 것이 아니다 — 이 한 문장이 버그 바운티의 수많은 포상금을 만들어 냈습니다.
3-4. Level 29 → 30: 다른 브랜치의 진짜
입력 (서버에서):
git branch -a
git show remotes/origin/dev:README.md
출력 예시: main 외에 dev 등의 브랜치가 보이고, 그 브랜치의 README에는 진짜 비밀번호가 있습니다.
읽는 법: git branch -a는 원격 브랜치까지 전부 보여 줍니다. git show 브랜치:파일은 그 브랜치 속 파일을 체크아웃 없이 열람하는 지름길입니다. 개발용 브랜치에는 정식(main)에 못 들어간 것들 — 테스트 비밀번호, 임시 키 — 이 남아 있곤 합니다.
왜 하는가: 브랜치가 평행우주(Step 88)라는 것은, "다른 우주의 비밀도 clone 한 번이면 내 것"이라는 뜻입니다.
3-5. Level 30 → 31: 태그에 숨긴 메모
입력 (서버에서):
git tag
git show secret
출력 예시: 태그 목록에 수상한 이름(secret 등)이 있고, show로 열면 비밀번호가 적혀 있습니다.
읽는 법: 태그는 "이 지점을 표시해 두는 꼬리표"(Step 88의 부록)인데, 메모를 달 수 있습니다. 개발자가 "나중에 보려고" 태그에 비밀을 적어 두는 실수가 실제로 있습니다.
왜 하는가: log → branch → tag. 세 수법의 마지막 칸입니다. 이제 clone한 저장소에서 숨은 비밀 찾기는 완전한 절차가 되었습니다.
3-6. 내 랩에서 재현 — 비밀 묻고 캐기 (로컬 실측)
공격 기법은 "설치하는 쪽"으로도 한 번 겪어야 완성됩니다. 서버 없이 내 컴퓨터에서 세 수법 전부를 실측해 봅시다. 작업 폴더를 만들고 미니 저장소를 만듭니다.
입력 (Git Bash 또는 터미널):
mkdir treasure-lab && cd treasure-lab
git init
echo "PASSWORD=real_secret_1234" > config.txt
git add . && git commit -m "설정 추가"
sed -i 's/real_secret_1234/xxxxxx/' config.txt
git add . && git commit -m "비밀번호 가림 처리"
git checkout -b dev
echo "API_KEY=dev_only_key_9999" >> config.txt
git add . && git commit -m "개발용 키 추가"
git checkout main
git tag -a secret -m "backup: root_pw=tag_hidden_777"
(윈도우 Git Bash에는 sed가 포함되어 있습니다. 오류가 나면 config.txt를 직접 열어 real_secret_1234를 xxxxxx로 고쳐도 됩니다. git 버전에 따라 기본 브랜치가 master일 수 있습니다 — 그 경우 git checkout main 대신 git checkout master.)
이제 비밀 셋이 묻혔습니다. 현재 파일만 보면 이렇게 가려져 있습니다 (2026-09-09 실측):
$ cat config.txt
PASSWORD=xxxxxx
수법 1 — 과거 커밋. git log --oneline으로 이력을 보고, 가장 오래된 커밋을 엽니다 (2026-09-09 실측):
$ git log --oneline
b3c8011 비밀번호 가림 처리
756df69 설정 추가
$ git show 756df69
commit 756df696114cf37f86947e145ca039c898d8e26c
Author: Lab <lab@example.com>
Date: Wed Sep 9 14:26:00 2026 +0900
설정 추가
diff --git a/config.txt b/config.txt
new file mode 100644
index 0000000..abe05c1
--- /dev/null
+++ b/config.txt
@@ -0,0 +1 @@
+PASSWORD=real_secret_1234
가림 처리된 비밀번호가 첫 커밋에 그대로 살아 있습니다. 해시는 여러분 환경에서 다르게 나옵니다 — 정상입니다.
수법 2 — 다른 브랜치 (2026-09-09 실측):
$ git branch -a
dev
* main
$ git show dev:config.txt
PASSWORD=xxxxxx
API_KEY=dev_only_key_9999
수법 3 — 태그 (2026-09-09 실측):
$ git tag
secret
$ git show secret
tag secret
Tagger: Lab <lab@example.com>
backup: root_pw=tag_hidden_777
...
읽는 법: 세 수법 모두 각자의 비밀을 정확히 찾아냈습니다. 서버 없이 내 컴퓨터에서 Bandit 28~30의 핵심을 전부 재현한 것입니다.
왜 하는가: 세 수법을 "파묻는 쪽"으로 먼저 해 보면, 캐는 쪽에서 어디를 뒤져야 하는지 감이 정확해집니다. 공격자의 검색 순서는 개발자의 은닉 습관을 거꾸로 읽는 것입니다.
3-7. 전체 역사 검색 — 수법의 완성형
세 수법을 하나로 묶는 검색이 있습니다 (2026-09-09 실측):
$ git log --oneline --all
8855c3a 개발용 키 추가
b3c8011 비밀번호 가림 처리
756df69 설정 추가
$ git log --all -p | grep -i -E "pass|key|pw"
PASSWORD=xxxxxx
+API_KEY=dev_only_key_9999
-PASSWORD=real_secret_1234
+PASSWORD=xxxxxx
+PASSWORD=real_secret_1234
읽는 법: --all은 모든 브랜치의 이력을, -p는 각 커밋의 변경 내용(diff)까지 출력하라는 뜻입니다. 그 전체를 grep으로 걸러내니 묻어 둔 비밀 셋이 한 번에 다 나옵니다. -로 시작하는 줄이 "그 커밋에서 지워진 내용"입니다 — 지운 비밀이 이렇게 빼곡히 남아 있습니다.
이 한 줄이 수동 발굴의 완성형입니다. 실제 유출 점검 도구(truffleHog, gitLeaks)들도 원리는 같습니다 — 저장소 전체 이력에서 "키처럼 생긴 문자열"을 스캔하는 것을 자동화한 도구일 뿐입니다.
3-8. 복기 — 0~30을 한 장의 지도로
Bandit의 마지막 문을 열었습니다(31부터는 이 책의 범위를 넘는 심화 구간 — 여유가 되면 계속 도전하세요). 이제 복기입니다. 위키에 bandit-총정리.md를 만듭니다.
작성 가이드:
| 구간 | 핵심 기법 | 실전에서의 이름 |
|---|---|---|
| 0~5 | 숨김 파일, file, find | 기본 정찰 |
| 6~10 | 조건 검색, grep, base64 | 파일 시스템 수색 |
| 11~15 | tr, nc, openssl | 서비스 수동 대화 |
| 16~20 | nmap, diff, setuid | 권한 상승 입문 |
| 21~25 | cron 추적과 끼어들기 | 자동화 악용 |
| 26~30 | git 이력 발굴 | 비밀 노출 탐지 |
각 행에 "내가 가장 오래 막힌 레벨"과 "가장 큰 깨달음"을 한 줄씩 덧붙이세요. 그 두 줄이 이 문서의 영혼입니다.
git의 내부 구조 살짝 — 왜 지워도 남는가
.git 폴더 안에는 모든 커밋이 객체(object)로 저장됩니다. 파일을 삭제한 커밋도 이전 커밋의 객체는 그대로 남습니다 — "지우는" 행동조차 실제로는 새 커밋을 쌓는 것이니까요. 아무 브랜치·태그도 가리키지 않는 객체가 되어야 비로소 정리 대상이 되고, 그마저 git gc 같은 청소 명령이 돌기 전까지는 남아 있습니다. "Git은 잊지 않는다" — 이 구조적 사실 하나가 오늘의 모든 공격과 방어의 뿌리입니다. 그래서 유출 시 대응은 삭제가 아니라 키 폐기와 재발급입니다.
4. 미션과 연습문제
미션 — Bandit 졸업 증명 패키지
- bandit26~30을 통과하고 비밀번호 체인을 완성합니다
- 3-6의 treasure-lab을 직접 만들고, 세 수법(log / branch / tag)과 완성형 한 줄(
git log --all -p | grep)로 묻은 비밀 셋을 전부 찾아 캡처해 둡니다 bandit-총정리.md를 작성합니다 — 3-8의 기법 지도 표 + 구간별 "가장 오래 막힌 레벨"과 "가장 큰 깨달음" 각 한 줄- 내가 가진 실제 git 저장소들을 공격자 눈으로 점검합니다 —
git log --all -p | grep -i -E "pass|key|token"으로 비밀이 새어 있지 않은지 확인하고 결과를 기록합니다
연습문제
문제 1. git clone이 "현재 파일만"이 아니라 "전체 역사"를 가져온다는 것이 왜 공격자에게 유리한지 설명해 보세요.
문제 2. 개발자가 비밀번호가 든 파일을 지우고 커밋했습니다. 그런데도 비밀이 회수되는 이유를 git 객체의 관점에서 설명해 보세요.
문제 3. git show dev:config.txt는 무엇을 하는 명령이며, git checkout dev 후 파일을 여는 것과 무엇이 다른가요?
문제 4. 내 저장소에서 비밀 키가 커밋된 것을 발견했습니다. "해당 커밋을 지우면 해결"이라는 주장이 왜 틀렸는지, 올바른 대응은 무엇인지 말해 보세요.
5. 모범 답안과 완료 기준
미션 모범 답안
Bandit 26~30의 풀이 절차는 3-1~3-5의 순서 그대로입니다 — more 상태에서 vim 진입(26), README 확인(27), 과거 커밋 열람(28), dev 브랜치 열람(29), 태그 열람(30).
treasure-lab의 세 수법 검증은 3-6의 실측 출력과 같은 모양이면 정답입니다:
수법 1: git show <첫커밋> → +PASSWORD=real_secret_1234
수법 2: git show dev:config.txt → API_KEY=dev_only_key_9999
수법 3: git show secret → backup: root_pw=tag_hidden_777
완성형 한 줄의 출력에 세 비밀이 모두 섞여 나오면 됩니다 (3-7 실측 참조).
검증하는 법: ① treasure-lab에서 cat config.txt는 가려져 있는데 git show 첫커밋에는 원문이 보이는가. ② git log --all -p | grep -i pass 한 줄로 세 비밀이 전부 나오는가. ③ 내 실제 저장소 점검 결과가 기록되었는가(발견되면 폐기·재발급 계획까지). 셋이 전부 ‘예’이면 완성입니다.
연습문제 해답
문제 1 해답. clone 한 번으로 과거 커밋·모든 브랜치·태그가 통째로 내 컴퓨터에 복사되기 때문입니다. 공격자는 서버를 다시 두드릴 필요 없이, 복사본 안에서 오프라인으로 얼마든지 이력을 뒤질 수 있습니다.
문제 2 해답. 파일을 지운 커밋은 "삭제했다는 새 커밋"을 쌓을 뿐, 이전 커밋의 객체는 .git 안에 그대로 남기 때문입니다. 3-6 실측에서 현재 파일은 xxxxxx로 가려져 있지만 첫 커밋(git show 756df69)에 real_secret_1234가 그대로 있었습니다.
문제 3 해답. dev 브랜치가 가리키는 커밋 시점의 config.txt 내용을, 작업 폴더를 바꾸지 않고(체크아웃 없이) 바로 출력하는 명령입니다. checkout은 내 작업 폴더 전체를 그 브랜치 상태로 바꾸는 무거운 동작이고, 브랜치:파일 형식은 열람만 하는 가벼운 지름길입니다.
문제 4 해답. 이미 커밋된 비밀은 이력에 남고(3-6 실측), 이미 push됐다면 누가 clone했는지도 알 수 없기 때문입니다. 커밋을 지워도 clone한 사람의 복사본에는 살아 있습니다. 올바른 대응: ① 그 키를 즉시 폐기하고 새로 발급한다. ② 이력 정리는 그다음의 위생 작업이다. "노출된 비밀은 죽은 비밀로 만들어야 끝난다."
완료 기준 체크리스트
- [ ] 제한된 쉘 환경에서 more/vim 경유 우회의 개념을 설명할 수 있다
- [ ] git 저장소를 clone하고 이력·브랜치·태그에서 숨은 정보를 찾을 수 있다
- [ ] treasure-lab에서 세 수법으로 묻은 비밀 셋을 전부 찾았다
- [ ]
git log --all -p | grep완성형 한 줄을 쓸 수 있다 - [ ] "지운 것은 남는다"를 명령으로 증명하고, 대응(폐기·재발급)을 말할 수 있다
- [ ] 31개 레벨의 기법을 지도 한 장(
bandit-총정리.md)으로 정리했다 - [ ] 내 실제 저장소를 공격자 시선으로 점검했다
6. 흔한 실수와 해결
벽 1. git clone이 권한 오류를 뱉는다
증상: clone이 거부되거나 비밀번호를 무한 반복해 묻습니다 (서버에서, 출력 예시).
Permission denied, please try again.
원인: 비밀번호 오타이거나, 포트(:2220) 누락, 또는 /tmp가 아닌 쓸 수 없는 폴더에서 클론 중입니다.
해결: /tmp/작업폴더를 만들고 그 안에서 클론하세요. 주소의 포트 표기(ssh://...@localhost:2220/...)를 한 글자씩 확인합니다.
벽 2. git log가 한 줄뿐이다
증상: 과거 커밋이 안 보입니다.
원인: 기본 git log는 현재 브랜치만 보여 줍니다. 다른 브랜치의 역사는 안 나옵니다.
해결: git log --oneline --all(모든 브랜치) 또는 git branch -a로 목록을 본 뒤 git show 브랜치명:파일. 3-7 실측에서 --all을 붙이자 dev의 커밋("개발용 키 추가")이 나타난 것을 보세요.
벽 3. more에서 v가 안 먹힌다
증상: Level 26에서 vim으로 못 갑니다.
원인: more 상태 진입 실패 — 창이 여전히 큽니다. --More-- 표시가 없으면 아직 more가 아닙니다.
해결: 터미널 높이를 정말로 2~3줄까지 줄이세요. 마우스로 창 테두리를 끌어 극단적으로. vim에 들어간 뒤 갇히면 Esc → :q! → Enter로 나옵니다.
벽 4. 태그/브랜치가 비어 보인다
증상: git tag가 아무것도 안 보여 줍니다.
원인: 클론한 디렉터리 안에 있지 않거나(그 안에서 쳐야 함), 저장소가 아닌 곳에서 치고 있습니다.
해결: cd repo 확인. git tag -l, git branch -a를 저장소 안에서 다시 치세요. 3-6 실측처럼 저장소 안이면 secret 태그가 보여야 합니다.
벽 5. git checkout main에서 오류가 난다
증상 (로컬 실험에서):
error: pathspec 'main' did not match any file(s) known to git
원인: git 버전·설정에 따라 기본 브랜치가 main이 아니라 master로 만들어진 경우입니다.
해결: git branch로 현재 브랜치 이름을 확인하고 그 이름을 쓰세요. 본질은 브랜치 이름이 아니라 "원래 브랜치로 돌아가는 것"입니다.
7. 정리
오늘의 개념
| 개념 | 한 줄 설명 |
|---|---|
| 제한된 쉘 | 로그인 쉘이 특수 프로그램으로 고정된 환경 — 부품(more→vim)으로 우회 |
| git clone | 현재 파일이 아니라 전체 역사(.git)를 복제 |
| git 객체 | 커밋의 저장 단위 — 삭제 커밋도 이전 객체를 지우지 않음 |
| 역사 캐기 3수법 | 과거 커밋(log→show) / 다른 브랜치(branch→show 브랜치:파일) / 태그(tag→show) |
| 비밀 유출 대응 | 삭제가 아니라 폐기·재발급 — "노출된 비밀은 죽은 비밀로" |
| 복기의 세 질문 | 기술(무엇) · 패턴(왜 막혔나) · 연결(실전의 어디) |
오늘의 명령어
| 명령어 | 하는 일 |
|---|---|
git clone ssh://계정@주소:포트/경로 |
원격 저장소를 역사채로 복제 |
git log --oneline / --all |
이력 한 줄씩 / 모든 브랜치 포함 |
git show 해시 |
그 커밋의 변경 내용 열람 |
git show 브랜치:파일 |
그 브랜치 속 파일을 체크아웃 없이 열람 |
git branch -a / git tag |
브랜치 목록 / 태그 목록 |
git log --all -p | grep -i -E "pass|key|pw" |
전체 역사에서 비밀 패턴 검색(완성형) |
명령어보다 중요한 감각
남의 저장소를 만나면 검색 순서가 몸에 배야 합니다 — ① git log --oneline --all로 이력 전체를 훑고, ② git branch -a와 git tag로 평행우주와 꼬리표를 확인하고, ③ 의심스러운 곳을 git show로 열고, ④ 마지막으로 git log --all -p | grep 완성형으로 빠진 것이 없는지 털어 봅니다. 이 순서는 개발자의 은닉 습관(지우기→다른 브랜치→태그 메모)을 거꾸로 읽는 것입니다.
그리고 방어자로서의 감각 — 여러분은 이제 이 공격의 시행자이자 방어자입니다. 내 저장소에 비밀이 들어갔다면 "커밋 지우기"로는 부족하고 키 폐기·재발급이 필요하다는 것을, 오늘 공격자의 눈으로 직접 확인했습니다. 31개의 문을 지나온 지금, 여러분은 "리눅스 서버에서 기회를 찾는 법"의 전체 윤곽을 가졌습니다. 파일 → 조건 → 네트워크 → 권한 → 자동화 → 이력. 이 윤곽이 앞으로 배울 더 깊은 기술들이 꽂힐 자리입니다. 첫 워게임 졸업을 축하합니다.
전부 체크되면 Step 101 완료입니다. 사이드바의 체크박스를 눌러 진도를 저장하세요.