📚 네트워크 · 패킷 분석 › 05. 네트워크 스캔 징후 분석 — 231편
이전 글: 230. Web Scan · 다음 글: 232. SSH Brute Force
Directory Scan(디렉터리·경로 탐색) 은 웹 서버에 존재하는 숨겨진 경로나 파일(관리자 페이지, 백업 파일, 설정 파일, 개발용 경로)을 찾기 위해 짧은 시간에 수많은 URL을 요청하는 정찰 행위입니다. 취약점을 폭넓게 두드리는 웹 스캔과의 차이는 230. Web Scan에서 다뤘고, 이 글은 경로 탐색이 접근 로그에 어떤 모양으로 남는가에 집중합니다.
방어자 입장에서 핵심은 "요청이 많았다"가 아니라 어떤 경로가 존재하는 것으로 응답되었는가입니다. 대부분의 요청은 404로 끝나지만, 소수의 200·301·403 응답이 공격자에게는 다음 단계의 목록이 됩니다.
| 구분 | Web Scan | Directory Scan |
|---|---|---|
| 목적 | 알려진 취약점·설정 오류 확인 | 존재하는 경로·파일 확인 |
| 요청 모양 | 파라미터에 공격 패턴 포함 | 파라미터 없이 경로만 변화 |
| 주 탐지 위치 | IDS·WAF 시그니처 | 접근 로그의 404 급증·경로 다양성 |
| 핵심 결과 | 취약 응답 여부 | 404가 아닌 응답(200·301·403) |
경로 탐색은 "요청 → 응답 코드 관찰"의 반복입니다. 방어 측에서 보면 흔적은 다음 순서로 쌓입니다.
출발지 X ── GET /경로A ──→ 웹 서버 ── 404 ──→ (없음)
출발지 X ── GET /경로B ──→ 웹 서버 ── 301 ──→ (디렉터리 존재, 끝에 / 붙여 이동)
출발지 X ── GET /경로C ──→ 웹 서버 ── 403 ──→ (존재하지만 접근 금지)
출발지 X ── GET /경로D ──→ 웹 서버 ── 200 ──→ (존재하고 열람 가능) ★
↓
방어 측 흔적: 접근 로그 404 급증 / 고유 경로 수 급증 / 짧은 요청 간격 / WAF·IDS Alert
Apache·Nginx는 디렉터리 경로를 / 없이 요청하면 보통 301로 /가 붙은 주소로 이동시킵니다. 그래서 301은 "그 디렉터리가 있다"는 신호가 될 수 있습니다. 또 403은 "없음"이 아니라 "있지만 막혀 있음" 이라는 정보를 줍니다. 일부 애플리케이션은 없는 경로에도 200과 같은 에러 페이지를 돌려주므로, 상태 코드만이 아니라 응답 크기를 함께 봐야 합니다.
| 로그 지표 | 정상 사용자 | Directory Scan 의심 |
|---|---|---|
| 404 비율 | 낮음(깨진 링크 몇 건) | 대부분이 404 |
| 고유 경로 수 | 페이지·리소스 수준 | 수백~수천 개 |
| 요청 간격 | 사람의 클릭 간격, 리소스 묶음 | 일정하고 짧은 간격 |
| Referer | 이전 페이지가 채워짐 | 비어 있음(-)이 많음 |
| 정적 리소스(CSS·JS·이미지) | 페이지와 함께 요청 | 거의 없음 |
| 메서드 | GET 위주 | GET·HEAD 반복 |
/.git/), 환경 설정 파일(/.env), 백업 확장자 같은 요청은 경로 탐색에서 자주 보입니다. 이런 요청에 200이 응답되었다면 정보 노출 사고로 봐야 합니다.웹 서버 접근 로그(Combined 형식)의 형식 예시입니다(값은 환경마다 다름).
198.51.100.23 - - [30/Sep/2026:02:14:01 +0900] "GET /admin HTTP/1.1" 301 235 "-" "Mozilla/5.0 (compatible)"
198.51.100.23 - - [30/Sep/2026:02:14:01 +0900] "GET /backup HTTP/1.1" 404 196 "-" "Mozilla/5.0 (compatible)"
198.51.100.23 - - [30/Sep/2026:02:14:01 +0900] "GET /.git/HEAD HTTP/1.1" 403 199 "-" "Mozilla/5.0 (compatible)"
198.51.100.23 - - [30/Sep/2026:02:14:02 +0900] "GET /old HTTP/1.1" 404 196 "-" "Mozilla/5.0 (compatible)"
실습 예시 — 본인 소유 실습 서버의 로그에서 출발지별 상태 코드 분포와 404가 아닌 응답을 확인하는 방어 측 명령입니다(로그 경로는 Rocky의 Apache는 /var/log/httpd/access_log, Ubuntu의 Apache는 /var/log/apache2/access.log, Nginx는 /var/log/nginx/access.log).
# 출발지별 요청 수와 404 수 (상위 10개)
awk '{t[$1]++; if($9==404) n[$1]++} END{for(i in t) print t[i], n[i]+0, i}' access.log | sort -rn | head
# 의심 출발지가 받은 404 이외 응답만 추출 (존재가 확인된 경로)
awk '$1=="198.51.100.23" && $9!=404 {print $9, $7}' access.log | sort | uniq -c | sort -rn
| 결과 | 해석 | 조치 |
|---|---|---|
| 요청 3,000건 중 404가 2,950건 | 경로 탐색 패턴 | 출발지 차단 검토 |
/admin 301 → /admin/ 200 | 관리자 경로가 외부에 열림 | 접근 제한 요청 |
/.git/HEAD 403 | 존재하지만 차단됨 | 배포 과정에서 제외 권고 |
| 민감 파일 200 | 정보 노출 | 사고로 전환, 파일 제거·노출 범위 확인 |
| 흔적 위치 | 확인 내용 |
|---|---|
| 웹 접근 로그 | 출발지별 404 비율, 고유 경로 수, 404 이외 응답 |
| WAF | 스캐너 식별·요청 빈도 차단 이벤트 |
| IDS | 스캐너 User-Agent·민감 경로 요청 규칙 Alert (293. Web Attack 탐지에서 다룸) |
| 방화벽 | 같은 출발지의 다른 포트·서버 접근 |
관제자가 확인할 질문
오탐 주의: 검색 엔진 크롤러, 사이트 링크 점검 도구, 승인된 취약점 점검은 비슷한 패턴을 만듭니다. 출발지 소유 확인(역방향 DNS 검증 등)과 점검 일정 대조를 먼저 합니다. 사이트 개편 직후에는 옛 링크 때문에 정상 사용자의 404도 늘어납니다.