Step 85. 프로젝트 — HTTP vs HTTPS 비교 보고서
Level 1 — 프로그래밍과 컴퓨터 내부 | 난이도 ★★★☆☆ | 예상 소요 시간 3시간
전제: Step 83~84의 캡처·필터·프로토콜 분석을 마쳤다. curl과 파이썬 간이 서버를 다룰 수 있다.
- 준비물: Wireshark(또는 tshark), 터미널 2개, 웹 브라우저, 문서 작성 도구.
- 주의: ⚠️ 이 챕터의 실습은 내 랩·합법 플랫폼 전용입니다. 허가 없는 시스템에 적용하면 범죄입니다. 평문 실험은 전부 내 컴퓨터 안(
127.0.0.1)에서, HTTPS 실험은 공개 사이트에 대한 정상 접속만으로 이뤄집니다. 이 챕터의 패킷 출력은 2026-09-09에 WSL 리눅스(TShark 4.2.2, curl 8.5.0)에서 실측했고, 브라우저·GUI 화면 설명은 "화면 예시"입니다.
주소창의 자물쇠 — HTTPS입니다. 그런데 자물쇠가 있고 없고가 실제 전선 위에서 어떤 차이를 만드는지 직접 본 사람은 거의 없습니다. 이번 프로젝트의 목표는 단 하나입니다. 같은 내용을 HTTP(평문)로 한 번, HTTPS(암호문)로 한 번 보내고, 캡처로 둘을 나란히 찍어 비교 보고서를 쓴다. 직접 눈으로 확인하면 "HTTPS가 안전하다"는 말이 교과서 문구가 아니라 여러분이 스스로 증명한 사실이 됩니다.
1. 학습 목표
이 챕터를 끝내면 다음을 할 수 있습니다:
- 로컬에 평문 웹 서버를 열고, 요청/응답이 패킷에 글자 그대로 실리는 것을 캡처로 증명한다
- 평문 POST 본문(비밀번호 포함)이 노출되는 장면을 재현하고 기록한다
- TLS 핸드셰이크와 Application Data를 구분하고, 암호문만 보임을 확인한다
- 암호화가 가려 주는 것과 가려 주지 못하는 것(메타데이터)을 대조표로 정리한다
- 스크린샷(또는 캡처 인용)에 해석을 붙인 비교 보고서 한 부를 완성한다
2. 배경 지식 — 오늘의 도구와 개념
오늘의 도구 한눈에 보기
| 구분 | 내용 |
|---|---|
| 언어·환경 | 리눅스 터미널 + Wireshark(또는 tshark) + 브라우저 |
| 오늘의 명령·기능 | python3 -m http.server 8000(평문 서버), curl(요청 발생), Follow TCP/HTTP Stream(대화 복원), tshark -Y tls |
| 필요한 개념 | 평문/암호문, TLS 핸드셰이크, 인증서, 메타데이터, Step 83~84의 캡처 기술 |
| 오늘의 산출물 | 《HTTP vs HTTPS 비교 분석 보고서》 1부 (캡처 증거 4건 + 대조표 + 결론) |
2-1. 평문(plain text)이란
평문은 "암호화되지 않은, 있는 그대로의 글자"입니다. HTTP로 비밀번호 mypw123을 내면, 네트워크 위를 지나는 패킷 안에 mypw123이라는 글자가 그대로 실립니다. 같은 구간의 패킷을 볼 수 있는 사람 — 같은 공용 와이파이의 다른 사용자, 회선을 관리하는 사업자 등 — 은 도구만 있으면 읽을 수 있습니다. 오늘 그것을 직접 읽어 봅니다.
2-2. HTTPS와 TLS 한눈에 보기
HTTPS는 "HTTP를 TLS(Transport Layer Security)라는 암호화 통로 안에 넣은 것"입니다. 통로를 만드는 과정이 TLS 핸드셰이크입니다.
- 클라이언트가 "암호화해서 말하고 싶다"고 인사합니다 (Client Hello).
- 서버가 인증서를 내밉니다 — "이 서버가 진짜 그 서버라는 신분증"입니다.
- 둘이 이번 통신에서만 쓸 일회용 암호화 열쇠를 합의합니다.
- 이후의 모든 HTTP 내용은 그 열쇠로 암호화되어 오갑니다 (Application Data).
암호화된 뒤의 패킷을 열어 봐도 나오는 것은 의미 없는 바이트 나열, 즉 암호문(cipher text)입니다.
2-3. 보고서를 쓰는 이유
실무 보안에서 관찰은 절반이고, 나머지 절반은 문서화입니다. 침해 사고 보고서, 진단 결과 보고서 — 전부 "내가 본 것을 남이 재현할 수 있게 적는 기술"입니다. 형식은 단순합니다.
[보고서 뼈대]
1. 실험 목적
2. 실험 환경 (날짜, 운영체제, 도구 버전)
3. 실험 절차
4. 관찰 결과 (캡처 증거 + 해석)
5. 결론 — 암호화가 가려 준 것과 가려 주지 못한 것
3. 따라 하기
3-1. 내 컴퓨터 안에 평문 웹 서버 열기
입력 (터미널 1)
mkdir -p http-lab && cd http-lab
echo "<h1>hello plain world</h1>" > index.html
python3 -m http.server 8000
출력 (화면 예시):
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
읽는 법: "8000번 포트에서 HTTP 서비스 중"이라는 뜻입니다. 이 창은 실험 내내 닫지 마세요. 요즘 인터넷의 웬만한 사이트는 전부 HTTPS라, 평문을 관찰하려면 이렇게 직접 만들어야 합니다.
3-2. 평문 트래픽 캡처 — 글자가 그대로 보인다
입력
# 터미널 2 (캡처)
tshark -i lo -a duration:6 -w plain.pcap
# 캡처가 도는 사이 터미널 3에서
curl -s http://127.0.0.1:8000/ > /dev/null
curl -s -X POST http://127.0.0.1:8000/login -d "username=hacker&password=mypw123" > /dev/null
읽는 법: 127.0.0.1 트래픽은 랜카드를 거치지 않으므로 반드시 루프백(lo, 윈도우는 Npcap Loopback Adapter)에서 캡처합니다. 간이 서버는 POST를 처리하지 못해 501 오류를 냅니다 — 하지만 패킷은 이미 전선에 나갔다는 점이 중요합니다.
3-3. 평문 로그인 — 비밀번호가 훤히 보이는 순간
캡처 파일에서 POST 대화를 통째로 복원해 봅니다.
입력
tshark -r plain.pcap -Y http
tshark -r plain.pcap -q -z follow,tcp,ascii,1
출력 (2026-09-09 실측, 스트림 복원 일부):
POST /login HTTP/1.1
Host: 127.0.0.1:8000
User-Agent: curl/8.5.0
Accept: */*
Content-Length: 32
Content-Type: application/x-www-form-urlencoded
username=hacker&password=mypw123
HTTP/1.0 501 Unsupported method ('POST')
Server: SimpleHTTP/0.6 Python/3.12.3
...
읽는 법: 맨 아래 줄을 보세요. username=hacker&password=mypw123이 평문 그대로 실려 있습니다. 서버가 거절(501)했든 말든, 패킷을 본 사람은 이미 비밀번호를 알았습니다. GUI에서는 POST 패킷 우클릭 → Follow → HTTP Stream으로 같은 창이 뜹니다 (화면 예시). 이것이 증거 1 — 평문 대화 복원 화면입니다.
왜: 방금 실험에서 "비밀번호를 아는 사람"은 서버가 아니라 패킷을 본 사람 전원입니다. 공용 와이파이에서 평문 HTTP 로그인을 하면 정확히 이 일이 벌어집니다.
3-4. HTTPS 트래픽 캡처 — 보이는 것과 보이지 않는 것
이제 암호문 쪽입니다. 공개 사이트에 정상 접속하며 캡처합니다.
입력
tshark -i eth0 -f "tcp port 443" -a duration:10 -w tls.pcap
# 다른 터미널에서
curl -s https://example.com -o /dev/null
출력 (2026-09-09 실측):
4 0.016170231 192.168.39.82 → 172.66.147.243 TLSv1 583 Client Hello (SNI=example.com)
6 0.032460886 172.66.147.243 → 192.168.39.82 TLSv1.3 3750 Server Hello, Change Cipher Spec
7 0.032461144 172.66.147.243 → 192.168.39.82 TLSv1.3 372 Application Data
10 0.035322790 192.168.39.82 → 172.66.147.243 TLSv1.3 146 Change Cipher Spec, Application Data
11 0.035690588 192.168.39.82 → 172.66.147.243 TLSv1.3 152 Application Data
14 0.048524337 172.66.147.243 → 192.168.39.82 TLSv1.3 619 Application Data, Application Data
...
읽는 법: Client Hello로 인사하고 Server Hello가 답한 뒤, 그 다음부터는 전부 Application Data — 암호화된 내용입니다. 그리고 주의 깊게 볼 것이 있습니다. 목록에 Certificate라는 줄이 없습니다. 최신 TLS 1.3에서는 서버의 인증서조차 암호화되어 Application Data 안으로 들어갑니다 (실측 환경의 협상 결과가 TLS 1.3이었습니다). 옛 TLS 1.2 환경에서는 인증서가 평문으로 지나가는 것이 목록에 보입니다.
Application Data 패킷의 내용을 열면 (2026-09-09 실측, 16진 덤프 일부):
0ed0 7e ae 32 45 54 c9 5b 9f 53 1c 24 fc c6 2f 00 33 ~.2ET.[.S.$../.3
0ee0 71 5d 76 25 15 64 6d 78 b2 06 59 82 33 c9 d8 c5 q]v%.dmx..Y.3...
0ef0 65 b8 b5 a5 57 9d 3d d0 77 8b 9b fa 66 79 93 b1 e...W.=.w...fy..
읽는 법: 무작위 바이트 나열뿐입니다. 여기에 페이지 내용이 들어 있지만, 읽을 수 없습니다. 3-3과 정확히 대조됩니다. 이것이 증거 2 — 암호문 덤프 화면입니다.
3-5. 그런데도 보이는 것 — SNI와 메타데이터
암호문 시대에도 새어 나가는 것이 있습니다. Client Hello를 펼쳐 봅시다.
입력
tshark -r tls.pcap -Y "tls.handshake.type == 1" -V | grep -A2 "Server Name"
출력 (2026-09-09 실측):
Server Name Indication extension
Server Name Type: host_name (0)
Server Name: example.com
읽는 법: 내용은 전부 암호화됐는데, "어디에 접속했는가"(SNI, 서버 이름 표시)는 평문으로 보입니다. 여기에 목적지 IP 주소, 통신 시각, 패킷 크기(위 목록의 583, 3750, 372… 숫자들)까지 더하면, 감시자는 내용 없이도 꽤 많은 것을 압니다. 이것이 증거 3 — "그래도 보이는 것" 화면입니다.
왜: TLS는 내용은 완벽하게 가리지만, "누가 누구와, 언제, 얼마나 통신했는가"(메타데이터)는 가리지 못합니다. Step 84의 행위 분석이 암호화 시대에도 통하는 이유입니다.
3-6. 인증서 구경 — 자물쇠의 정체
입력: 브라우저 주소창의 자물쇠 아이콘 → "연결이 안전함" → "인증서" 메뉴를 클릭합니다.
화면 예시: 인증서 창이 열리며 발급 대상(누구에게), 발급자(누가 보증), 유효 기간이 보입니다.
읽는 법: 인증서는 공인 성적표 같은 것입니다. CA(Certificate Authority, 인증 기관)라는 공신력 있는 기관이 "이 도메인의 주인이 이 공개키의 주인임을 보증한다"고 서명해 둔 문서이고, 브라우저는 이 서명을 검증한 뒤에야 자물쇠를 보여 줍니다. 암호화만으로는 "상대가 진짜 은행이 아니라 사칭범이면?"이라는 구멍이 남는데, 인증서가 그 구멍을 메웁니다. 이것이 증거 4 — 인증서 정보 창입니다.
3-7. 보고서 조립 — 대조표와 해석 붙이기
문서 도구를 열고 2-3의 뼈대에 맞춰 작성합니다. 핵심은 이 대조표입니다 (오늘 실측으로 검증됨):
| 항목 | HTTP (평문) | HTTPS (암호문) |
|---|---|---|
| 요청 줄 (GET / …) | 보임 | 안 보임 |
| 헤더 (User-Agent 등) | 보임 | 안 보임 |
| 본문 (비밀번호 포함) | 보임 | 안 보임 |
| 접속한 서버 이름 (SNI) | 보임 | 보임 |
| 목적지 IP 주소 | 보임 | 보임 |
| 통신 시각과 크기 | 보임 | 보임 |
| 중간에서 내용 바꿔치기 | 가능 | 불가능 (무결성 검사) |
읽는 법: 세로로 읽으면 각 프로토콜의 노출 범위이고, 가로로 읽으면 암호화가 항목별로 한 일입니다. "보임"이 남는 세 행이 3-5의 결론 — 메타데이터는 남는다 — 과 정확히 연결됩니다.
왜: 표는 "내가 본 것"을 "독자가 한눈에 비교할 수 있는 형태"로 바꾸는 장치입니다. 보안 보고서에서 표 하나는 문장 열 줄의 일을 합니다. 각 증거(캡처 인용 또는 스크린샷) 아래에는 반드시 해석 두세 줄을 붙이세요 — 그림은 증거이고, 해석이 주장입니다.
4. 미션과 연습문제
미션 — 《HTTP vs HTTPS 비교 분석 보고서》 완성
- 실험 목적·환경(날짜, OS, 도구 버전)·절차를 2-3 뼈대로 적습니다.
- 증거 4건을 붙입니다: ① 평문 대화 복원(Follow Stream) ② 평문 POST 본문의 비밀번호 ③ HTTPS Application Data 암호문 ④ 인증서 창. GUI가 없으면 tshark 출력 인용으로 대체합니다.
- 각 증거마다 해석 2~3줄을 붙입니다 ("이 화면에서 봐야 할 것은 X이며, 이것은 Y를 의미한다").
- 3-7의 대조표를 채우고, "중간에서 바꿔치기" 행까지 포함시킵니다.
- 결론: TLS가 가려 준 것 2가지 + 가려 주지 못한 것 1가지를 한 문장씩으로 씁니다. 파일명
step85_http_vs_https로 저장합니다.
연습문제
문제 1. 평문 HTTP의 위험을 "엽서"에, HTTPS를 "봉인된 편지"에 비유할 때, 이 비유가 정확히 설명하는 것과 놓치는 것(메타데이터)은 무엇인가요?
문제 2. 서버가 POST를 거절(501)했는데도 비밀번호가 새었다고 말하는 이유는 무엇인가요?
문제 3. TLS 1.3 캡처 목록에 Certificate 줄이 없는 이유는 무엇이며, 이것이 감시자 입장에서 무엇을 어렵게 하나요?
문제 4. HTTPS 통신에서 감시자가 알 수 있는 것을 세 가지 들어 보세요.
5. 모범 답안과 완료 기준
미션 모범 답안
결론 문장의 예 (오늘 실측에 근거):
- 가려 준 것 1: 요청 줄, 헤더, 본문 — POST 본문의 비밀번호가 평문(pcap의 follow 스트림)에서는
그대로 읽혔으나, TLS에서는 Application Data의 무작위 바이트로만 보였다.
- 가려 준 것 2: 응답 내용 — 서버가 보낸 HTML이 TLS 쪽에서는 어느 패킷에서도 복원되지 않았다.
- 가려 주지 못한 것: 접속 사실 그 자체 — Client Hello의 SNI(서버 이름)와 목적지 IP,
통신 시각·크기(메타데이터)는 평문으로 남았다.
실험 환경 기록의 예: "2026-09-09, WSL 우분투, TShark 4.2.2, curl 8.5.0, 대상 127.0.0.1:8000(평문) 및 example.com(HTTPS, TLS 1.3 협상됨)."
검증하는 법: ① 증거 4건이 전부 붙었고 각각 해석이 있는가. ② 대조표의 마지막 두 행(IP/시각·크기)이 "보임/보임"인가. ③ 결론이 "내용은 가리지만 메타데이터는 못 가린다"를 명시하는가. ④ 혼자 읽어도 재현 가능한 절차(명령 전문)가 적혔는가.
연습문제 해답
문제 1 해답. 비유가 설명하는 것: 엽서(HTTP)는 지나가는 길의 누구든 내용을 읽을 수 있고, 봉인된 편지(HTTPS)는 내용을 읽을 수 없다는 점. 놓치는 것: 봉인된 편지라도 봉투 겉면 — 보낸 사람, 받는 사람, 보낸 시각, 편지의 두께 — 는 보입니다. 실제로 Client Hello의 SNI와 IP 주소, 시각, 크기가 평문으로 남습니다.
문제 2 해답. 패킷은 요청을 보내는 순간 이미 전선 위를 지나갔기 때문입니다. 서버의 응답(501 거절)은 그 다음 일이고, 지나간 패킷을 본 사람은 본문의 password=mypw123을 이미 읽었습니다. "서버가 처리했는가"와 "내용이 노출됐는가"는 별개의 문제입니다 (2026-09-09 실측으로 확인).
문제 3 해답. TLS 1.3에서는 인증서가 핸드셰이크의 암호화 구간 안으로 들어가 Application Data로 전송되기 때문입니다 (옛 TLS 1.2에서는 평문으로 지나갔습니다). 감시자 입장에서는 "이 서버의 인증서 내용"까지 엿볼 수 없게 되어, 상대방 확인의 단서가 SNI와 IP 주소로 줄어듭니다.
문제 4 해답. ① 접속한 서버의 이름(Client Hello의 SNI)과 목적지 IP 주소, ② 통신의 시각과 지속 시간, ③ 오간 데이터의 크기와 리듬. 내용은 모르더라도 "누가 누구와, 언제, 얼마나"는 알 수 있습니다.
완료 기준 체크리스트
- [ ] 파이썬 간이 서버를 열고 루프백에서 평문 HTTP를 캡처할 수 있다
- [ ] 평문 POST 본문에서 비밀번호가 보이는 것을 증명할 수 있다
- [ ] TLS 핸드셰이크(Client Hello/Server Hello)와 Application Data를 구분할 수 있다
- [ ] SNI와 메타데이터가 암호화 밖에 남는다는 것을 설명할 수 있다
- [ ] 인증서의 역할(사칭 방지)을 설명할 수 있다
- [ ] 증거와 해석이 붙은 비교 보고서 1부를 완성해 저장했다
6. 흔한 실수와 해결
벽 1. loopback에서 아무것도 안 잡혀요
증상: 127.0.0.1 실험인데 패킷이 0개입니다.
원인: 일반 네트워크 카드를 캡처하고 있습니다. 127.0.0.1 트래픽은 카드를 거치지 않고 운영체제 안에서만 돕니다.
해결: 루프백 전용 인터페이스(리눅스 lo, 윈도우 Npcap Loopback Adapter)를 고르세요. 윈도우에 목록이 없다면 Wireshark를 Npcap 포함으로 재설치해야 합니다.
벽 2. http 필터인데 안 보여요
증상: curl은 성공했는데 http 필터가 조용합니다.
원인: 8000번 같은 비표준 포트를 http 필터가 못 알아보는 경우가 있습니다.
해결: 필터를 tcp.port == 8000으로 바꿔 보세요. 잡히면 포트 인식 문제이며, 그 상태에서 Follow → TCP Stream으로 내용을 확인할 수 있습니다. 실측의 필드 추출에서도 -Y http가 8000번 포트를 HTTP로 올바르게 인식했지만, 환경에 따라 다를 수 있습니다.
벽 3. HTTPS인데 Client Hello도 안 잡혀요
증상: tls 필터가 텅 빕니다.
원인: 브라우저가 이미 열어 둔 연결을 재사용(핸드셰이크는 이미 끝남)하거나 캐시만으로 페이지를 그렸을 수 있습니다.
해결: 브라우저를 완전히 닫았다가 다시 열어 접속하세요. 그래도 안 되면 필터를 tcp.port == 443으로 넓혀 확인합니다. curl로 새 접속을 만드는 것(3-4)이 가장 확실합니다.
벽 4. Application Data가 어떤 건지 못 찾겠어요
증상: 온통 TCP 패킷뿐이라 TLS 레코드를 못 고르겠습니다.
원인: Wireshark가 해당 연결을 TLS로 해석하지 못한 것이거나, 필터가 걸린 채입니다.
해결: Server Hello가 있는 연결부터 찾으세요. 그 바로 뒤의 같은 주소 쌍 패킷들이 Application Data입니다. 패킷 우클릭 → Decode As로 TLS를 지정해 줄 수도 있습니다.
벽 5. 보고서가 "스크린샷 나열"이 돼 버려요
증상: 그림만 있고 무엇을 봐야 하는지 모르겠는 문서.
원인: 해석이 빠졌습니다. 그림은 증거이고 주장은 글입니다.
해결: 각 증거 아래 "이 화면에서 봐야 할 것은 X, 이것은 Y를 의미한다" 두 줄 공식을 쓰세요. 나쁜 예 "(스크린샷) 끝" / 좋은 예 "POST 본문에 비밀번호가 평문으로 보인다 — 같은 구간의 패킷을 열람 가능한 누구든 이 값을 읽을 수 있다."
7. 정리
오늘의 개념
| 개념 | 한 줄 설명 |
|---|---|
| 평문(plain text) | 암호화되지 않은 그대로의 글자 — 패킷에 글자 그대로 실림 |
| 암호문(cipher text) | 열쇠 없이는 의미 없는 바이트 나열 |
| TLS 핸드셰이크 | 인사(Client/Server Hello) → 인증서 → 열쇠 합의 → 이후 전부 암호문 |
| 인증서 | "상대가 진짜인가"를 CA가 보증하는 신분증 — 사칭 방지 |
| SNI | Client Hello 속 접속 대상 이름 — TLS 1.3에서도 평문으로 남음 |
| 메타데이터 | 누가·누구와·언제·얼마나 — 암호화가 가리지 못하는 것 |
| TLS 1.3 | 인증서까지 암호화 구간 안으로 — 캡처 목록에 Certificate 줄이 없음 |
오늘의 명령어
| 명령 | 하는 일 |
|---|---|
python3 -m http.server 8000 |
연습용 평문 웹 서버 |
curl -X POST 주소 -d "..." |
평문 본문 전송 실험 |
tshark -i lo -a duration:6 -w plain.pcap |
루프백 평문 캡처 |
tshark -r 파일 -q -z follow,tcp,ascii,1 |
대화 통째 복원 — 평문 증명 |
tshark -i eth0 -f "tcp port 443" |
HTTPS만 캡처 |
tshark -r tls.pcap -Y "tls.handshake.type == 1" -V |
Client Hello 상세 — SNI 확인 |
명령어보다 중요한 감각
"HTTPS가 안전하다"를 오늘부터는 이렇게 말할 수 있습니다. "내가 127.0.0.1에서 보낸 비밀번호가 패킷에 그대로 읽혔고, 같은 실험이 TLS에서는 무작위 바이트만 남겼다 — 그래서 안전하다"라고요. 보안 전문가의 첫 자격은 "들었다"가 아니라 "확인했다"로 말하는 습관입니다.
동시에 오늘의 대조표가 말해 주는 경계도 기억하세요. 자물쇠는 내용을 지키지만 여러분이 어디에 접속했는지까지 숨겨 주지는 않습니다. 그리고 관찰을 해석 붙인 문서로 남기는 일 — 침투 테스트 업계에 "기술이 절반, 보고서가 절반"이라는 말이 있는 이유가 오늘의 마지막 배움입니다.
전부 체크되면 Step 85 완료입니다. 사이드바의 체크박스를 눌러 진도를 저장하세요.