📚 네트워크 · 패킷 분석 › 03. Wireshark 패킷 분석 — 145편
이전 글: 144. DNS 악용 유형 — 터널링·DGA·비정상 질의 탐지 · 다음 글: 146. 비정상 TCP Traffic 분석
웹 접근 로그 한 줄에서 가장 먼저 눈에 들어오는 값은 메서드(GET, POST 등)와 상태코드(200, 404 등)입니다. 이 두 값은 "클라이언트가 무엇을 하려 했고, 서버가 어떻게 반응했는가"를 요약합니다.
관제에서는 개별 요청보다 패턴이 중요합니다.
404가 수백 건 → 존재하지 않는 경로를 대량으로 탐색401/403 반복 뒤 200 한 건 → 대입 시도 후 성공 가능성500 증가 → 입력값 처리 오류를 유발하는 시도이번 글은 메서드·상태코드의 의미를 정리하고, 접근 로그에서 이런 패턴을 집계로 찾는 방법을 다룹니다. 메시지 구조는 04. HTTP 요청·응답 구조를 참고하세요.

그림 1. 같은 요청이라도 응답 코드에 따라 '시도'와 '성공'이 갈립니다
| 메서드 | 의미 | 일반 웹사이트에서의 빈도 | 관제 포인트 |
|---|---|---|---|
| GET | 리소스 조회 | 매우 높음 | 쿼리 스트링에 공격 문자열이 담기는 경우 많음 |
| POST | 데이터 전송(로그인, 글쓰기, 업로드) | 높음 | 본문이 로그에 없음. 로그인·업로드 경로 집중 확인 |
| HEAD | 헤더만 조회 | 낮음 | 모니터링·링크 점검 도구, 탐색 도구가 사용 |
| PUT | 리소스 생성·교체 | API 외에는 드묾 | 일반 웹서버에서 허용되면 파일 업로드 위험 |
| DELETE | 리소스 삭제 | API 외에는 드묾 | 허용 여부 확인 필요 |
| PATCH | 부분 수정 | API 위주 | |
| OPTIONS | 허용 메서드 조회, CORS 사전 요청 | 브라우저 CORS 환경에서 흔함 | 대량이면 서버 설정 탐색 |
| TRACE | 요청을 그대로 되돌려 받음 | 거의 없음 | 대부분 비활성화 권장 대상 |
| CONNECT | 프록시 터널 요청 | 프록시 서버에서만 | 일반 웹서버로 들어오면 프록시 악용 탐색 |
| 분류 | 의미 | 대표 코드 |
|---|---|---|
| 1xx | 정보 | 101 Switching Protocols (WebSocket 전환) |
| 2xx | 성공 | 200 OK, 201 Created, 204 No Content, 206 Partial Content |
| 3xx | 리다이렉트 | 301 Moved Permanently, 302 Found, 304 Not Modified |
| 4xx | 클라이언트 오류 | 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found, 405 Method Not Allowed, 413 Content Too Large, 429 Too Many Requests |
| 5xx | 서버 오류 | 500 Internal Server Error, 502 Bad Gateway, 503 Service Unavailable, 504 Gateway Timeout |
그 밖에 nginx는 표준이 아닌 499(응답 전에 클라이언트가 연결을 끊음)를 로그에 남깁니다. 실제로 전송되는 상태코드가 아니라 nginx가 기록용으로 쓰는 값입니다.
| 코드 | 의미 | 관제에서의 해석 |
|---|---|---|
| 401 Unauthorized | 인증이 필요하거나 인증 실패 | 계정 정보 대입 시도의 흔적일 수 있음 |
| 403 Forbidden | 인증과 상관없이 접근 권한 없음 | 차단된 경로·IP 접근, WAF 차단 응답으로 쓰이기도 함 |
단, 많은 웹 애플리케이션은 로그인 실패에도 200(실패 메시지 페이지)이나 302(로그인 페이지로 이동)를 반환합니다. 상태코드만으로 로그인 성공·실패를 판단하면 안 되고, 응답 크기·이동 위치를 함께 봅니다.
같은 경로에 대한 요청도 서버 처리 결과에 따라 상태코드가 갈립니다.
[요청] METHOD /path
↓
허용된 메서드인가? ── 아니오 → 405 Method Not Allowed
↓ 예
경로(리소스)가 존재하는가? ── 아니오 → 404 Not Found
↓ 예
접근 권한이 있는가? ── 인증 필요 → 401 / 권한 없음 → 403
↓ 예
애플리케이션 처리 중 오류? ── 예 → 500 (앞단 프록시가 백엔드 연결 실패 시 502/504)
↓ 아니오
200 / 201 / 204 / 3xx
탐지 관점에서 보면 공격자의 시도는 대부분 4xx로 끝납니다. 관제가 주의해야 할 것은 4xx 사이에 섞인 2xx 한 건, 그리고 특정 입력 뒤 늘어나는 5xx입니다.
실습 환경: 본인 소유 Linux VM (Rocky Linux 또는 Ubuntu). 인터페이스 이름은 ens33을 예시로 사용합니다. 이전 글에서 설치한 nginx를 사용합니다(로그: /var/log/nginx/access.log, Rocky·Ubuntu 공통).
curl -s -o /dev/null -w "%{http_code} GET\n" http://127.0.0.1/
curl -s -o /dev/null -w "%{http_code} HEAD\n" -I http://127.0.0.1/
curl -s -o /dev/null -w "%{http_code} OPTIONS\n" -X OPTIONS http://127.0.0.1/
curl -s -o /dev/null -w "%{http_code} TRACE\n" -X TRACE http://127.0.0.1/
curl -s -o /dev/null -w "%{http_code} DELETE\n" -X DELETE http://127.0.0.1/
for p in admin backup.zip test.php .env; do
curl -s -o /dev/null -w "%{http_code} /$p\n" "http://127.0.0.1/$p"
done
📷 [실습 화면 삽입] 메서드별 상태코드(200/405 등)와 404 요청 결과가 출력된 화면
nginx·Apache의 combined 형식에서 공백 기준 필드는 $1 클라이언트 IP, $6 메서드(앞에 " 포함), $7 경로, $9 상태코드, $10 응답 크기입니다(요청줄에 공백이 없는 경우 기준).
LOG=/var/log/nginx/access.log # Apache: Rocky) /var/log/httpd/access_log, Ubuntu) /var/log/apache2/access.log
# 상태코드 분포
sudo awk '{print $9}' $LOG | sort | uniq -c | sort -rn
# 메서드 분포
sudo awk '{print $6}' $LOG | tr -d '"' | sort | uniq -c | sort -rn
# 404를 가장 많이 받은 IP
sudo awk '$9==404 {print $1}' $LOG | sort | uniq -c | sort -rn | head
# 5xx가 발생한 요청 경로
sudo awk '$9 ~ /^5/ {print $9, $7}' $LOG | sort | uniq -c | sort -rn | head
📷 [실습 화면 삽입] 상태코드 분포와 IP별 404 집계 결과 화면
형식 예시(값은 환경마다 다름):
200 GET
200 HEAD
405 OPTIONS
405 TRACE
405 DELETE
404 /admin
404 /backup.zip
404 /test.php
404 /.env
$ sudo awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn
12 200
4 404
3 405
| 결과 | 의미 |
|---|---|
GET·HEAD 200 | 정적 페이지 정상 제공 |
OPTIONS·TRACE·DELETE 405 | nginx 정적 페이지 설정에서는 해당 메서드 미허용 (서버·설정에 따라 결과가 다를 수 있음) |
탐색 경로 404 | 존재하지 않는 경로 요청이 로그에 누적됨 |
| 패턴 | 정상일 수 있는 경우 | 의심해야 하는 경우 |
|---|---|---|
| 한 IP의 404 급증 | 사이트 개편 후 깨진 링크, 검색 엔진 수집 | admin, .env, backup, .git 등 민감 경로를 짧은 시간에 연속 요청 |
| 404 사이의 200 | 실제 존재하는 페이지 | 탐색 중 민감 경로에서 200 → 노출 여부 즉시 확인 |
| 로그인 경로 401/403 또는 동일 응답 크기 반복 | 사용자의 비밀번호 오입력 몇 회 | 한 IP 또는 여러 IP에서 수십~수백 회 반복 후 응답 크기가 달라진 요청 발생 |
| 5xx 증가 | 배포 직후 오류, 백엔드 장애 | 쿼리 스트링에 ', ", --, < 등이 포함된 요청 직후에만 500 발생 |
| PUT·DELETE·TRACE·CONNECT | REST API 서버, 승인된 점검 | 정적 웹사이트에 비정상 메서드 요청 (특히 PUT 성공 201/204) |
| 429 증가 | 요청 제한 정책의 정상 동작 | 한 IP가 제한을 계속 초과 → 자동화 도구 |
| 200인데 응답 크기가 평소와 크게 다름 | 콘텐츠 변경 | 같은 경로에서 특정 요청만 응답이 비정상적으로 큼 (데이터 과다 노출 가능성) |
시간대별 추이를 보면 급증 여부가 명확해집니다.
# 분 단위 404 건수 (combined 형식의 [dd/Mon/yyyy:HH:MM 부분 사용)
sudo awk '$9==404 {print substr($4,2,17)}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head
| 로그·장비 | 메서드·상태코드 관련 흔적 |
|---|---|
| 웹 서버 접근 로그 | 모든 요청의 메서드·상태코드·크기 |
| 웹 서버 에러 로그 | 404 원인(파일 없음), 권한 오류, 백엔드 연결 실패 |
| WAF | 차단 시 자체 응답 코드(403 등)와 탐지 룰 이름 |
| SIEM 상관분석 | "N분 내 404 M건 이상" 같은 임계치 룰 (07. 네트워크 보안관제 통합 분석 시리즈에서 다룸) |
방어 설정 예 (정상 운영 범위 확인 후 적용):
TraceEnable Off 로 TRACE 비활성화location 블록에서 제한 (예: limit_except GET POST { deny all; } — GET을 허용하면 HEAD도 함께 허용되며, 거부된 메서드는 403으로 응답)한계와 오탐 주의