Step 175. Level 2 종합 평가: 공격/방어 대응표 — 양면 사고의 완성

Step 175. Level 2 종합 평가: 공격/방어 대응표 — 양면 사고의 완성

Level 2 — 보안 입문과 공격 스킬 기초 | 난이도 ★★★☆☆ | 예상 소요 시간 5시간(이틀 권장)

전제: Step 96~174를 마쳤습니다. 이 챕터는 새 공격 기법을 배우지 않는 Level 2의 졸업 시험입니다.

  • 준비물: 노트(또는 빈 문서 파일), 지금까지의 실습 기록, 그리고 반나절의 시간.
  • 주의: 오늘은 "만드는" 날입니다. 여러분만의 공격/방어 대응표를 완성하고, 흐릿한 스텝을 찾아 돌아갑니다.

⚠️ 이 챕터의 실습은 내 랩·합법 플랫폼 전용입니다. 허가 없는 시스템에 적용하면 범죄입니다.

수십 개의 공격 기법을 배웠습니다. 그런데 공격만 아는 사람은 반쪽입니다 — 모든 공격에는 대응하는 방어가 있고, 모든 방어에는 우회가 있습니다. 오늘은 Level 2 전체를 "공격 × 방어 × 우회"의 한 장짜리 표로 압축합니다. 이 표가 머릿속에 자리 잡으면, 공격을 볼 때 방어가, 방어를 볼 때 우회가 자동으로 떠오르는 양면 사고가 완성됩니다.


1. 학습 목표

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

  • Level 2의 주요 공격 기법을 각각 짝이 되는 방어와 한 쌍으로 설명한다
  • 각 방어의 우회 가능성을 한 줄로 말해 "방어 ≠ 절대 안전"을 체득한다
  • 공격/방어 대응표를 직접 작성하고 계속 갱신하는 습관의 틀을 갖는다
  • Level 2 기술 목록을 "설명 가능 / 실습 가능 / 흐릿함" 3단계로 자가 채점한다
  • 흐릿한 항목만 골라 재실습하는 효율적인 복습을 한다

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

오늘의 도구 한눈에 보기

구분 내용
언어·환경 노트와 펜 + 검증용으로 파이썬(Flask)과 curl 하나
오늘의 명령어 새 명령어 없음 — 검증 실측에 curl -sI(응답 헤더 보기)만 씁니다
필요한 개념 대응 사고(공격↔방어), 심층 방어, 우회 가능성, 3단 자가 채점
오늘의 산출물 공격/방어 대응표 1장 + 자가 채점표 + 재실습 목록

2-1. 왜 "표"인가

공격 기법은 낱개로 배우면 기술 목록이 되고, 방어와 짝지으면 구조가 됩니다. SQL 인젝션을 아는 것과 "SQL 인젝션 ↔ 준비된 문장, 우회: 인코딩·필터 우회"를 아는 것은 다릅니다. 후자는 면접에서도, 실무에서도, CTF에서도 바로 작동하는 지식입니다.

표의 힘은 또 있습니다 — 빈 칸이 보인다는 것. "이 공격의 방어가 뭐였지?"라고 막히는 칸이 바로 여러분의 빈 곳입니다.

2-2. 심층 방어 — 방어는 한 겹이 아니다

심층 방어(defense in depth)는 방어를 여러 겹으로 쌓는 원칙입니다. Step 174에서 확인했듯, 체인의 각 고리마다 방어가 있을 수 있고, 앞쪽 고리일수록 끊는 비용이 쌉니다. 대응표의 "방어" 칸에 하나만 적지 말고, 앞쪽 방어와 뒤쪽 방어를 함께 적는 습관을 들이세요.

2-3. 우회 가능성 — 방어가 완벽하지 않음을 아는 것

모든 방어 칸에는 "우회 가능성" 한 줄이 따라붙습니다. 필터가 있으면 우회 페이로드가 있고, MFA가 있으면 피로 공격(MFA fatigue)과 세션 탈취가 있습니다. 방어를 우습게 보자는 것이 아닙니다 — 방어의 한계를 아는 사람만이 방어를 올바른 위치에 놓을 수 있습니다.

2-4. 자가 채점의 3단계

Step 40에서 배운 원칙을 Level 2 규모로 확장합니다. 각 기술을 세 단계로 표시합니다:

  • 설명 가능: 책 안 보고 남에게 설명할 수 있다
  • 실습 가능: 명령어를 찾아보며라도 혼자 재현할 수 있다
  • 흐릿함: 읽었는데 지금은 못 하겠다

"흐릿함"은 실패가 아니라 재실습 예약입니다.


3. 따라 하기

3-1. 대응표의 뼈대 — 먼저 함께 만드는 여덟 줄

아래 표는 Level 2 핵심 공격들의 대응표 뼈대입니다. 이것을 베껴 쓰는 것이 아니라, 이 형식으로 나머지를 직접 채우는 것이 오늘의 과제입니다.

공격 (스텝) 원리 한 줄 방어 우회 가능성
SQL 인젝션 (104, 135~137) 입력이 쿼리 문법을 바꿈 준비된 문장(prepared statement), ORM 필터 기반 방어는 인코딩·주석 우회 가능
XSS (138~139) 입력이 HTML/JS로 실행됨 출력 인코딩, CSP 헤더 필터 우회, DOM 기반 XSS
CSRF (140) 브라우저가 대신 요청 보냄 CSRF 토큰, SameSite 쿠키 토큰 누락 엔드포인트, GET 기반 상태 변경
파일 업로드 (141~142) 업로드 파일이 실행됨 확장자 화이트리스트, 업로드 폴더 실행 금지 이중 확장자, MIME 검사만 하는 경우
명령어 인젝션 (143) 입력이 쉘 명령에 붙음 쉘 호출 금지, 인자 배열 전달 필터 우회(공백 대체 ${IFS} 등)
LFI/RFI (144) 경로 입력으로 파일 읽기/포함 경로 정규화, allowlist ....//, 인코딩 우회
온라인 브루트포스 (122) 로그인 무차별 대입 레이트 리밋, 계정 잠금, MFA 스프레이(165), 분산 IP
ARP 스푸핑 (156~157) 같은 동네에서 MAC 사칭 정적 ARP, 동적 ARP 검사(DAI) 로컬 네트워크 신뢰 구조 자체의 한계

읽는 법: 네 칸의 관계를 보세요. "원리 한 줄"을 말할 수 있어야 공격을 안 것이고, "우회 가능성"을 말할 수 있어야 방어를 아는 것입니다. 이 여덟 줄이 감 잡기용입니다 — 아래 3-2에서 여러분이 나머지를 채웁니다.

3-2. 나머지 칸 채우기 — 여러분의 표

다음 항목들을 같은 네 칸 형식으로 채우세요. 막히는 칸은 비워 두지 말고 스텝 번호를 옆에 적어 두세요 — 그것이 재실습 목록이 됩니다.

  • 패스워드 스프레이·크리덴셜 스터핑 (165)
  • 오프라인 해시 크래킹 (123~124)
  • SUID·권한 상승 (106, 125~126)
  • PATH 인젝션 (108)
  • DNS 스푸핑 (159)
  • 세션·쿠키 공격 (134)
  • IDOR·접근 제어 우회 (149)
  • JWT 공격 (150)
  • 사회공학 (167)
  • OSINT 수집 (170~171)

작성 팁: 완벽한 표를 한 번에 만들려 하지 마세요. 공격 1개당 방어·우회 1쌍씩, 매일 몇 줄씩 누적하는 표가 목표입니다. 이 표는 오늘 끝나는 것이 아니라 Level 3 내내 커 가는 문서입니다.

3-3. 검증 실측 — 방어가 눈에 보이는지 확인하기

대응표가 문서에만 있으면 안 됩니다. 방어는 확인 가능해야 합니다. 3-1 표의 "XSS → CSP 헤더" 행을 손으로 검증해 봅니다.

먼저 방어 없는 서버(Step 174의 랩이 그대로 떠 있다면 그것, 아니면 아무 Flask 서버)의 헤더를 봅니다:

curl -sI http://127.0.0.1:8174/
HTTP/1.1 200 OK
Server: Werkzeug/3.1.8 Python/3.12.14
Date: Wed, 09 Sep 2026 08:04:04 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 240
Connection: close

(2026-09-09 실측.)

이제 같은 내용에 방어 헤더를 얹은 서버(step175_hardened.py)를 만들어 비교합니다:

입력 (step175_hardened.py)

from flask import Flask

app = Flask(__name__)

@app.after_request
def harden(resp):
    resp.headers["X-Content-Type-Options"] = "nosniff"
    resp.headers["X-Frame-Options"] = "DENY"
    resp.headers["Content-Security-Policy"] = "default-src 'self'"
    resp.headers["Server"] = "web"   # 서버 버전 노출 지우기
    return resp

@app.route("/")
def index():
    return "<h1>하드닝된 사이트</h1>"

if __name__ == "__main__":
    app.run(host="127.0.0.1", port=8175)
python step175_hardened.py
curl -sI http://127.0.0.1:8175/
HTTP/1.1 200 OK
Server: Werkzeug/3.1.8 Python/3.12.14
Date: Wed, 09 Sep 2026 08:04:26 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 31
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Content-Security-Policy: default-src 'self'
Server: web
Connection: close

(2026-09-09 실측.)

출력 읽는 법: 두 화면의 차이가 대응표의 실물입니다. 세 줄의 방어 헤더가 추가됐습니다 — 각각 MIME 스니핑 차단, 클릭재킹 차단, XSS 완화(CSP)에 대응합니다.

그런데 자세히 보세요 — Server: 헤더가 두 줄입니다. Werkzeug이 자기 버전을 먼저 써 버렸고, 우리의 web은 뒤에 추가된 것입니다. "헤더를 덮어썼다"와 "헤더가 사라졌다"는 다릅니다. 방어를 적용했다고 끝이 아니라, 공격자의 눈(curl)으로 다시 확인해야 비로소 방어입니다. 이 한 화면이 오늘 챕터의 축소판입니다.

예측: 실제 운영 서버에서는 Server 헤더 숨기기를 웹 서버 설정(nginx의 server_tokens off 등)에서 합니다. 프레임워크 코드에서 지우려 하면 위처럼 두 줄이 되는 경우가 많습니다 — 방어의 "층위"도 대응표에 적을 만한 정보입니다.

3-4. Level 2 기술 목록 자가 채점

노트를 펴고 Level 2의 구간별 기술을 3단계(설명 가능/실습 가능/흐릿함)로 채점합니다. 구간 목록:

구간 스텝 핵심 기술
워게임 기초 96~105 Bandit/Natas, XOR 분석, 첫 SQLi, 기법 목록화
리눅스 심화 106~110 setuid, 로그, PATH 인젝션, 링크
침투 기초 111~121 Kali, MS2, 정찰, 스캐너, Metasploit, 첫 쉘, 수동 익스플로잇
패스워드 122~124 hydra, John, hashcat
권한 상승 125~130 SUID, linPEAS, 후속 침투, 타임어택
웹 공격 131~150 Burp, SQLi, XSS, CSRF, 업로드, 웹쉘, 명령 인젝션, LFI, IDOR, JWT
실전 웹 151~155 드림핵, 독립 공략
네트워크 156~166 ARP/DNS 스푸핑, 스니핑, TLS, 방화벽, 터널링, 무선
인간·정보 167~171 사회공학, 악성코드 구조, OSINT
종합 172~174 시나리오 1·2, 보고서, 체인 공격

각 구간에 "설명 가능 / 실습 가능 / 흐릿함" 중 하나를 적으세요. 열 개 구간을 채점하는 데 30분이면 충분합니다.

3-5. 흐릿한 것만 재실습 — 진짜 복습

채점에서 "흐릿함"이 나온 구간만 골라 해당 스텝으로 돌아갑니다. 재실습의 규칙은 Step 40과 같습니다:

  • 개념이 흐릿: 그 스텝의 ‘배경 지식’을 읽고, 책을 덮고 내 말로 다시 설명해 본다
  • 손이 흐릿: ‘따라 하기’만 다시 한다. 이번엔 출력 예시를 가리고 먼저 예측한다
  • 둘 다 흐릿: 그 스텝을 처음부터 다시 한다 — 부끄러운 일이 아니라 가장 빠른 길입니다

재실습이 끝나면 대응표의 해당 칸을 다시 채웁니다. 비워 두었던 칸이 채워지는 것이 복습 완료의 증거입니다.

3-6. Level 3 미리보기 — 다음은 전문 트랙

Level 3(Step 176~)는 CTF 실전과 분야 심화입니다. 다섯 분야(Web, Pwn, Reversing, Crypto, Forensics)를 맛본 뒤 주력을 정합니다. Step 154에서 만든 약점/강점 분석이 있다면 꺼내 두세요 — 어떤 분야가 끌리는지의 첫 단서가 거기 있습니다.

지금 결정할 필요는 없습니다. 오늘의 과제는 Level 2를 닫는 것이니까요.


4. 미션과 연습문제

미션 — 나의 공격/방어 대응표 완성

3-2의 열 개 항목을 포함해, Level 2에서 배운 공격 총 18개 이상의 대응표를 완성하세요. 규칙:

  1. 네 칸(공격/원리/방어/우회 가능성)을 모두 채울 것 — 모르는 칸은 스텝 번호를 적고 재실습 후 갱신
  2. 방어 칸에는 앞쪽 방어(예방)와 뒤쪽 방어(탐지/대응)를 구분해 볼 것
  3. 표 맨 아래에 한 줄 요약: "이 표에서 내가 가장 약한 열(공격 또는 방어)은 무엇인가"

연습문제

문제 1. "완벽한 방어를 만들면 되지 않나요?"라는 질문에, 심층 방어와 우회 가능성 개념으로 답하세요.

문제 2. 3-3 실측에서 Server: 헤더가 두 줄 나왔습니다. 이것이 보여 주는 방어 적용의 교훈은 무엇인가요?

문제 3. 레이트 리밋(로그인 시도 제한)을 우회하는 공격 두 가지를 Level 2에서 배운 것으로 답하세요.

문제 4. 자가 채점에서 "흐릿함"으로 표시된 구간이 세 개 이상일 때, 권장 복습 순서는 무엇인가요? (힌트: 구간들의 의존 관계)


5. 모범 답안과 완료 기준

미션 모범 답안

3-2 항목의 참고 답 (여러분 표와 글자가 달라도 됩니다 — 네 칸이 채워졌는지가 기준):

공격 원리 한 줄 방어 우회 가능성
패스워드 스프레이 (165) 흔한 비번 1개 × 계정 다수 전 계정 레이트 리밋, MFA, 유출 비번 차단 느린 스프레이, 분산 IP
해시 크래킹 (123~124) 유출 해시를 오프라인 대입 강한 해시(bcrypt/argon2), 솔트, 긴 비번 정책 약한 해시(MD5/SHA1), 사전에 있는 비번
SUID 권한 상승 (106, 125) SUID 프로그램 오용 SUID 최소화, 파일시스템 감사, nosuid 마운트 GTFOBins 대상 정상 명령
PATH 인젝션 (108) PATH 앞쪽 가짜 명령 실행 절대경로 호출, PATH 위생 cron/스크립트의 관행적 상대경로
DNS 스푸핑 (159) 거짓 이름 해석 응답 DNSSEC, HTTPS 강제(HSTS) 내부망 신뢰, 다운그레이드 시도
세션·쿠키 공격 (134) 세션 ID 탈취·고정 HttpOnly/Secure/SameSite, 세션 회전 XSS로 탈취, 사이드채널
IDOR (149) 객체 번호 바꿔 타인 자원 접근 서버 측 접근 제어, 간접 참조 인증은 있으나 인가 누락인 엔드포인트
JWT 공격 (150) alg=none, 약한 시크릿 alg 고정, 강한 키, 만료 짧게 키 유출, 클레임 검증 누락
사회공학 (167) 인간의 신뢰·급박함 이용 교육·훈련, 확인 절차, 보고 문화 새로운 미끼, 조직 경계 공략
OSINT (170~171) 공개 정보의 조합 정보 노출 최소화, 자산 인벤토리 공개 자체는 막을 수 없음 — 노출 관리만 가능

한 줄 요약의 예: "방어 열이 약하다 — 공격은 기억나는데 짝이 되는 방어가 안 나오는 칸이 네 개였다"처럼 솔직하게. 그 한 줄이 Level 3에서의 학습 우선순위가 됩니다.

검증하는 법: ① 18개 이상, ② 우회 가능성 칸이 전부 채워졌는가(비어 있으면 그 방어를 과신하고 있다는 뜻), ③ 재실습으로 갱신된 칸에 표시가 있는가.

연습문제 해답

문제 1 해답. 완벽한 방어는 없기 때문입니다. 모든 방어에는 우회 가능성이 있고(필터는 우회 페이로드가, 잠금은 스프레이가), 하나의 방어가 뚫리는 순간이 옵니다. 그래서 방어는 여러 겹으로 쌓습니다(심층 방어) — 한 겹이 뚫려도 다음 겹이 남고, 각 겹이 공격자의 비용을 올립니다. "완벽한 한 겹"보다 "불완전한 여러 겹"이 실전의 답입니다.

문제 2 해답. 방어는 적용했다는 사실이 아니라 검증된 결과로 판단해야 한다는 것입니다. 코드에서 헤더를 "덮어썼다"고 믿었지만, 공격자의 눈(curl -sI)으로 확인하니 프레임워크가 쓴 원래 헤더가 그대로 노출돼 있었습니다. 방어는 설정이 아니라 관측으로 완성됩니다 — Step 40의 "믿지 말고 확인하라"와 같은 계명입니다.

문제 3 해답. ① 패스워드 스프레이 — 계정별 시도 횟수 제한을 피하기 위해 비밀번호 하나를 계정 여러 개에 한 번씩만 시도. ② 크리덴셜 스터핑 — 다른 사이트에서 유출된 진짜 id/비번 쌍을 대입해 "추측" 자체를 하지 않음. 둘 다 Step 165의 주제이며, 대응은 전 계정 단위 제한과 MFA, 유출 비밀번호 차단입니다.

문제 4 해답. 의존 관계의 앞쪽부터 갑니다. 예: "권한 상승(125)이 흐릿"과 "시나리오 2(174)가 흐릿"이 함께 나왔다면 174는 125를 쓰는 종합이라 앞의 125부터 재실습해야 합니다. 이 책의 구조가 입구→발판→정착→지배의 사슬이므로, 사슬의 앞 고리부터 메우는 것이 항상 빠릅니다.

완료 기준 체크리스트

  • [ ] 공격/원리/방어/우회 가능성 네 칸 형식의 대응표를 18개 이상 완성했다
  • [ ] 각 방어의 우회 가능성을 한 줄씩 적었다
  • [ ] 방어 헤더 실측으로 "방어는 관측으로 검증"을 확인했다
  • [ ] Level 2 열 개 구간을 3단계로 자가 채점했다
  • [ ] "흐릿함" 구간의 재실습 목록(스텝 번호)을 만들었다
  • [ ] 흐릿한 구간 중 최소 한 개를 실제로 재실습하고 표를 갱신했다
  • [ ] 표 맨 아래에 "나의 약한 열" 한 줄 요약을 적었다

6. 흔한 실수와 해결

벽 1. 표를 한 번에 완성하려다 지친다

증상: 18개를 한 자리에서 채우려다 중간에 손이 멈춥니다.
원인: 표는 시험이 아니라 살아있는 문서입니다.
해결: 오늘은 뼈대(3-1의 여덟 줄)와 자가 채점까지만 하고, 나머지는 재실습하면서 며칠에 걸쳐 채우세요. "계속 업데이트되는 표"가 "완벽한 표"보다 가치 있습니다.

벽 2. 방어 칸이 안 채워진다

증상: 공격은 기억나는데 방어가 떠오르지 않습니다.
원인: 정상적인 편향입니다 — 이 책은 공격 관점 책이라 방어는 공격을 뒤집어야 나옵니다.
해결: 공격의 원리 한 줄을 보고 "이 원리의 어느 고리를 끊으면 되는가"로 뒤집어 보세요. SQLi의 원리가 "입력이 쿼리 문법을 바꿈"이면, 끊는 법은 "입력과 문법을 분리(준비된 문장)"입니다. 방어는 공격의 거울입니다.

벽 3. 3-3에서 Server 헤더가 여전히 버전을 보여 준다

증상: 하드닝 코드를 넣었는데도 Server: Werkzeug/3.1.8 Python/3.12.14 줄이 남아 있습니다.
원인: 그것이 정상입니다 — Werkzeug이 자체 헤더를 먼저 쓰고, @after_request는 그 위에 다른 헤더를 추가합니다. 두 줄이 됩니다 (2026-09-09 실측).
해결: 고치려는 시도보다, 이 현상 자체가 오늘의 배움입니다. 운영 환경에서는 앞단 웹 서버(nginx 등)에서 헤더를 지웁니다. "방어를 어떤 층위에서 하느냐"도 대응표의 정보입니다.

벽 4. 자가 채점이 전부 "설명 가능"으로 나온다

증상: 너그러운 채점이 됩니다.
원인: 책을 보며 채점하면 다 아는 것 같습니다.
해결: 책을 덮고, 각 구간의 핵심 기술 하나를 소리 내어 60초 설명해 보세요. 막히면 그것은 "흐릿함"입니다. 엄격함이 이 시험의 전부입니다 — 너그러운 채점은 재실습 목록을 훔칩니다.

벽 5. 흐릿한 구간이 너무 많다

증상: 재실습 목록이 다섯 개를 넘습니다.
원인: 80개 스텝을 한 번에 다 기억하는 사람은 없습니다. 잊는 것은 기본 사양입니다.
해결: 목록을 "다음 스텝 계획표"로 이름 바꾸세요. 앞 고리부터(문제 4의 원칙) 하루 한 구간씩만. 재실습 다섯 번이면 Level 3 시작 전에 전부 메워집니다.


7. 정리

오늘의 개념

개념 한 줄 설명
공격/방어 대응표 공격·원리·방어·우회 가능성 네 칸 — Level 2의 압축 파일
양면 사고 공격을 보면 방어가, 방어를 보면 우회가 떠오르는 상태
심층 방어 불완전한 여러 겹 > 완벽한 한 겹
우회 가능성 모든 방어 칸에 붙는 꼬리표 — 한계를 아는 것이 전문가
3단 자가 채점 설명 가능 / 실습 가능 / 흐릿함 — 흐릿함은 재실습 예약
방어의 검증 설정했다 ≠ 막힌다 — 공격자의 눈(curl)으로 다시 본다

오늘의 명령어

명령 하는 일
curl -sI URL 응답 헤더만 보기 — 방어(보안 헤더)의 검증 도구

명령어보다 중요한 감각

Level 2에서 여러분은 워게임의 첫 플래그부터, 첫 쉘, 웹 공격 전 유형, 네트워크 스푸핑, 그리고 어제의 체인 공격까지 지나왔습니다. 그 긴 목록이 오늘 한 장의 표가 됐습니다. 표가 짧아 보인다고 얕게 본 것이 아닙니다 — 압축됐다는 것은 언제든 다시 펼칠 수 있다는 뜻이고, 그것이 실력입니다.

그리고 이 표의 진짜 용도를 기억하세요. 모의해킹 보고서의 "대응 방안" 장, 면접의 "이 공격을 어떻게 막겠습니까", 방어 구축의 "우선순위" — 전부 이 표의 칸들입니다. 공격자로 배운 것이 방어자의 언어로 번역되는 순간, 여러분은 이 바닥의 양쪽 문법을 다 알게 됩니다.

Level 2, 졸업을 축하합니다. 여러분은 입문자가 아니라 준비된 학습자입니다.


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