Step 114. 정찰 2: 취약점 스캐너와 결과 읽기 — 스캐너는 후보 생성기다

Step 114. 정찰 2: 취약점 스캐너와 결과 읽기 — 스캐너는 후보 생성기다

Level 2 — 보안 입문과 공격 스킬 기초 | 난이도 ★★★☆☆ | 예상 소요 시간 3시간

전제: Step 113에서 대상의 서비스 인벤토리(포트·서비스·버전 표)를 만들었다. nmap의 기본 옵션(-sV, --script)을 쓸 수 있다. 리눅스 터미널(WSL 포함)이 준비되어 있다.

  • 준비물: 리눅스 터미널과 nmap. 오늘의 스캔 대상은 127.0.0.1(내 컴퓨터 자신)과, 랩이 있다면 Metasploitable2(이하 MS2)뿐입니다.
  • 주의: ⚠️ 이 챕터의 실습은 내 랩·합법 플랫폼 전용입니다. 허가 없는 시스템에 적용하면 범죄입니다. 이 챕터의 모든 실측은 WSL 리눅스(Nmap 7.94SVN)에서 127.0.0.1만을 대상으로 수행했습니다. MS2 대상 출력과 상용 스캐너 화면은 "출력 예시"로 표기합니다.

Step 113에서 우리는 대상의 "지도"를 그렸습니다 — 어떤 포트에, 어떤 서비스가, 몇 번 버전으로 돌고 있는지. 오늘은 그 지도 위에 "여기가 뚫릴 후보"라는 표시를 자동으로 얹어 주는 도구, 취약점 스캐너(vulnerability scanner)를 다룹니다. 스캐너는 편리하지만 거짓말도 합니다. 그래서 오늘의 진짜 목표는 스캐너를 "돌리는 법"이 아니라, 스캐너의 말을 비판적으로 읽는 법입니다.


1. 학습 목표

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

  • nmap의 vuln 스크립트 카테고리로 취약점 후보를 자동 수집한다
  • 스캐너 출력에서 CVE 번호를 추출해 목록으로 정리한다
  • 오탐(false positive)이 생기는 이유를 설명하고, 스캔 결과를 버전 정보와 교차 검증한다
  • 스캐너를 "결론"이 아니라 "후보 생성기"로 대하는 작업 절차를 따른다
  • 스캔이 느릴 때 포트와 스크립트 범위를 좁혀 시간을 관리한다

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

오늘의 도구 한눈에 보기

구분 내용
언어·환경 리눅스 터미널(WSL 또는 랩 VM), nmap 7.94의 NSE 스크립트
오늘의 명령 nmap --script vuln, --script "http-vuln-*"(범위 좁히기), grep CVE 결과파일, --script-help
필요한 개념 CVE 번호, 오탐(false positive)과 미탐(false negative), Step 113의 서비스 인벤토리
오늘의 산출물 취약점 후보 목록 + 각 후보의 신뢰도 판단(높음/검증 필요)

2-1. 취약점 스캐너가 하는 일

취약점 스캐너는 정찰의 마지막 공정입니다. 서비스와 버전을 파악한 뒤, "이 버전에는 이런 알려진 취약점이 있다"를 데이터베이스와 대조해 후보를 뽑아 줍니다. 대표적으로 세 부류가 있습니다.

  • nmap NSE vuln 카테고리: 우리가 아는 nmap에 내장된 취약점 검사 스크립트들입니다. 오늘 실측 환경(WSL의 nmap 7.94SVN)에는 이름에 vuln이 들어간 스크립트가 50개 내장되어 있었습니다.
  • Nessus / OpenVAS 같은 전용 스캐너: 수만 개의 검사 항목을 가진 상용·오픈소스 스캐너입니다. 웹 화면에서 예쁜 리포트를 뽑아 주는 대신 설치와 라이선스가 무겁습니다. 오늘은 화면 예시로만 봅니다.
  • vulners 같은 외부 API 연계 스크립트: 발견한 버전을 외부 취약점 DB에 질의합니다. 인터넷이 필요하다는 약점이 있습니다 — 오늘 실측에서 이 약점이 그대로 드러납니다.

2-2. 오탐과 미탐 — 스캐너의 두 가지 거짓말

스캐너의 판단은 대부분 "버전 번호 대조"입니다. 여기서 두 종류의 오류가 납니다.

  • 오탐(false positive, 없는데 있다고 함): 배포판(우분투 등)은 취약점을 고칠 때 버전 번호를 올리지 않고 패치만 뒤로 포팅(backport)하는 경우가 많습니다. 스캐너는 버전만 보고 "취약"이라고 하지만 실제로는 이미 고쳐져 있습니다. 반대로, 설정이 달라서 공격 조건이 성립하지 않는 경우도 있습니다.
  • 미탐(false negative, 있는데 못 찾음): 스캐너의 DB에 없는 신종 취약점, 비표준 포트에 숨은 서비스, 배너를 숨긴 서비스는 잡히지 않습니다. "스캐너가 깨끗하다고 했다"가 "안전하다"를 뜻하지는 않습니다.

그래서 스캐너의 출력은 결론이 아니라 후보 목록입니다. 실제로 뚫리는지는 다음 단계(수동 검증, 익스플로잇)에서 확인해야 하고, 그 확인이 Step 117에서 시작됩니다.

2-3. 결과를 읽는 절차

실무 정찰에서 스캐너 결과를 처리하는 순서는 정해져 있습니다.

  1. 스캔을 돌리고 결과를 -oN 파일로 남긴다
  2. 출력에서 CVE 번호만 추출해 목록화한다 (grep)
  3. Step 113의 인벤토리(서비스·버전)와 교차 대조한다 — 스캐너가 말한 버전이 내가 직접 확인한 버전과 같은가?
  4. 각 후보에 신뢰도를 붙인다 — "높음(버전 일치 + 공격 조건 성립)" 또는 "검증 필요(버전만 근거)"
  5. 검증 우선순위를 정해 다음 단계로 넘긴다

3. 따라 하기

3-1. 준비 — 연습용 서비스와 내장 스크립트 확인

Step 81 때처럼, 텅 빈 컴퓨터를 스캔하면 배울 것이 없으니 연습용 웹 서버를 하나 엽니다.

입력 (터미널 1)

mkdir -p /tmp/steplab && cd /tmp/steplab
echo "<h1>hello plain world</h1>" > index.html
python3 -m http.server 8000

이 창은 실습 내내 닫지 마세요. 다른 터미널에서 오늘의 주인공인 vuln 스크립트가 몇 개나 있는지 세어 봅니다.

입력 (터미널 2)

ls /usr/share/nmap/scripts/ | grep -c vuln

출력 (2026-09-09 실측):

50

읽는 법: 이 nmap에는 vuln 카테고리급 스크립트가 50개 있습니다. HTTP용(http-vuln-*), SMB용(smb-vuln-*), SMTP용(smtp-vuln-*) 등 서비스별로 나뉘어 있습니다. 이 50개를 전부 한 번에 돌리는 것이 --script vuln입니다 — 그리고 그것이 왜 문제인지 곧 몸으로 배웁니다.

: 도구의 규모를 아는 것이 시간 관리의 출발점입니다. "50개를 대상 서비스 전부에" 돌리는 일은 생각보다 무겁습니다.

3-2. 범위를 좁힌 취약점 스캔

감각을 잡기 위해 HTTP 서비스 전용 취약점 스크립트(http-vuln-*)만 골라 8000번 포트에 돌려 봅니다.

입력

nmap --script "http-vuln-*" -sV -p 8000 127.0.0.1

출력 (2026-09-09 실측):

Starting Nmap 7.94SVN ( https://nmap.org ) at 2026-09-09 15:12 KST
Nmap scan report for localhost (127.0.0.1)
Host is up (0.00014s latency).

PORT     STATE SERVICE VERSION
8000/tcp open  http    SimpleHTTPServer 0.6 (Python 3.12.3)
|_http-server-header: SimpleHTTP/0.6 Python/3.12.3

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 6.30 seconds

읽는 법: 20개가 넘는 http-vuln-* 스크립트가 전부 돌았는데(6.30초), 스크립트가 추가로 보고한 취약점은 하나도 없습니다. |_http-server-header 줄은 취약점 보고가 아니라 배너 재확인입니다 — 이 스크립트는 version 카테고리라서 -sV를 켰을 때 자동으로 따라옵니다(스크립트 파일의 categories = {"version"}을 실측으로 확인했습니다). 파이썬의 간이 서버는 스캐너가 아는 CVE와 매칭되는 것이 없는 깨끗한 대상입니다.

: "스캐너가 아무 말도 안 하는 것"도 정상적인 결과라는 감각을 먼저 잡습니다. 그래야 다음 단계의 "말이 많은 결과"가 얼마나 이례적인지 대비가 됩니다.

3-3. vuln 카테고리 전체 — 그리고 시간 폭탄

이제 카테고리 전체를 돌려 봅니다. 단, 먼저 예측해 보세요. 8000번 포트 하나에 50개 스크립트를 돌리면 얼마나 걸릴까요?

입력

time nmap --script "vuln and not vulners" -p 8000 127.0.0.1 -oN /tmp/steplab/vuln_all.txt

출력 (2026-09-09 실측 — 200초 제한을 걸고 실행했다가 시간 초과로 중단):

real    3m20.003s   ← 200초가 지나 timeout이 스캔을 강제 종료

스캔은 끝나지 않았고, 결과 파일도 비어 있었습니다(nmap은 스캔이 끝나야 파일을 씁니다). 무엇이 시간을 잡아먹었을까요? 용의자를 --script-help로 신문해 봅니다.

입력

nmap --script-help http-slowloris-check

출력 (2026-09-09 실측, 일부):

http-slowloris-check
Categories: vuln safe
  Tests a web server for vulnerability to the Slowloris DoS attack without
  actually launching a DoS attack.
  ...
  The script opens two connections to the server, each without the final CRLF.
  After 10 seconds, second connection sends additional header. Both connections
  then wait for server timeout.

읽는 법: 이 스크립트는 "서버가 불완전한 연결을 얼마나 오래 붙들고 있는가"를 재는 검사라서, 설계상 서버의 타임아웃이 끝날 때까지 기다립니다. 검사 자체가 시간을 먹는 구조인 것입니다. 이런 스크립트가 섞여 있어서 vuln 카테고리 전체 실행은 포트 하나에도 몇 분씩 걸릴 수 있습니다.

: 실무에서 "스캔이 안 끝난다"는 하루 일정을 날리는 사고입니다. 과제 가이드가 "vuln 스크립트는 30분 이상 걸릴 수 있다 — -p로 포트를 좁혀라"라고 경고한 이유가 이것입니다. 범인을 알았으니, 느린 스크립트를 빼고 다시 돌려 봅시다.

3-4. 느린 스크립트를 제외하고 완주하기

입력

time nmap --script "vuln and not vulners and not http-slowloris-*" -sV -p 8000 127.0.0.1 -oN /tmp/steplab/vuln_fast.txt

출력 (2026-09-09 실측):

PORT     STATE SERVICE VERSION
8000/tcp open  http    SimpleHTTPServer 0.6 (Python 3.12.3)
|_http-csrf: Couldn't find any CSRF vulnerabilities.
|_http-dombased-xss: Couldn't find any DOM based XSS.
|_http-stored-xss: Couldn't find any stored XSS vulnerabilities.
|_http-server-header: SimpleHTTP/0.6 Python/3.12.3

Nmap done: 1 IP address (1 host up) scanned in 79.29 seconds

읽는 법: 79초 만에 완주했고, 이번에는 스크립트 세 개가 "못 찾았다(Couldn’t find any)"고 정중하게 보고했습니다. 이 출력의 독법이 중요합니다 — "Couldn’t find any XSS"는 "XSS가 없다"가 아니라 "이 스크립트의 검사 방법으로는 발견하지 못했다"입니다. 미탐의 가능성이 문장 속에 그대로 적혀 있습니다.

: 스캐너의 부정 결과는 부정의 증명이 아닙니다. 이 한 줄의 어조를 읽는 것이 오늘 배우는 비판적 독해의 절반입니다.

3-5. 외부 API 스크립트의 함정 — vulners

vuln 카테고리에는 발견한 버전을 외부 취약점 DB(vulners.com)에 질의하는 vulners 스크립트도 있습니다. 폐쇄된 랩에서 돌리면 어떻게 될까요?

입력

nmap --script vulners -sV -p 8000 127.0.0.1

출력 (2026-09-09 실측):

PORT     STATE SERVICE VERSION
8000/tcp open  http    SimpleHTTPServer 0.6 (Python 3.12.3)
|_http-server-header: SimpleHTTP/0.6 Python/3.12.3

Nmap done: 1 IP address (1 host up) scanned in 6.70 seconds

읽는 법: 아무 보고도 없습니다. 에러 메시지조차 없습니다. 외부 DB에 닿지 못하자 조용히 포기한 것입니다. "출력 없음"이 "취약점 없음"이 아니라 "검사 불능"일 수 있다는 좋은 실례입니다.

: 스캐너가 조용할 때는 "깨끗하다"와 "못 했다"를 반드시 구분해야 합니다. 오늘 실측처럼 네트워크가 막힌 환경에서는 후자가 정답입니다.

3-6. 결과에서 CVE 추출하기 — MS2 대상 (출력 예시)

랩의 MS2(Metasploitable2)를 대상으로 같은 스캔을 돌리면 결과가 어떻게 달라지는지 봅시다. MS2는 일부러 취약하게 만든 연습용 가상머신이라, 아래와 같은 출력이 나오는 것이 정상입니다 (이 환경에는 MS2가 없으므로 출력 예시로 표기합니다).

입력 (랩에서, MS2의 IP가 192.168.56.101이라고 가정)

nmap --script vuln -sV 192.168.56.101 -oN ms2_vuln.txt

출력 예시 (발췌):

21/tcp   open  ftp     vsftpd 2.3.4
|_smtp-vuln-cve2010-4344: ...
| sslv2-drown:
|   ciphers: ...
| vulners:
|   cpe:/a:vsftpd:vsftpd:2.3.4:
|       CVE-2011-2523  10.0    https://vulners.com/cve/CVE-2011-2523
...
|_ssl-ccs-injection: VULNERABLE: ...

입력 — 결과 파일에서 CVE 번호만 뽑아 목록화:

grep -oE 'CVE-[0-9]{4}-[0-9]+' ms2_vuln.txt | sort -u

출력 예시:

CVE-2004-2687
CVE-2011-2523
CVE-2015-3306
...

읽는 법: MS2처럼 낡은 시스템은 결과가 수십 개 나오는 게 정상입니다(과제 가이드의 경고와 일치). grep -oE ... | sort -u는 스캔 결과를 "CVE 후보 목록"으로 압축하는 실무 기법입니다. 우리 환경의 연습 서버 결과 파일에서는 이 명령이 0건을 반환했습니다(2026-09-09 실측) — 깨끗한 대상과 취약한 대상의 대비를 기억하세요.

: 스캐너 원본 출력은 보고서에 못 씁니다. CVE 목록으로 요약하는 이 단계가 있어야 다음 단계(Step 115에서 각 CVE를 NVD에서 읽기)로 넘어갈 수 있습니다.

3-7. 교차 검증 — 스캐너의 말을 믿을까

마지막 공정은 스캐너의 주장을 내가 직접 모은 정보와 대조하는 것입니다. 절차는 이렇습니다 (랩 기준).

  1. 스캐너가 "vsftpd 2.3.4에 CVE-2011-2523"이라고 했다면, Step 113에서 -sV로 직접 확인한 버전이 정말 2.3.4인지 대조합니다 — 배너 조작으로 속였을 수도 있습니다.
  2. 각 후보에 신뢰도를 붙입니다. 예: "CVE-2011-2523 — 버전 일치, 공개 익스플로잇 존재 → 신뢰도 높음", "CVE-2004-2687 — 버전 근거만 있음 → 검증 필요".
  3. 이 목록이 Step 116~117에서 실제 익스플로잇을 고르는 재료가 됩니다.

: "스캐너가 취약하다고 한 것 중 실제로 뚫리는 것은?"이라는 의심 목록을 만드는 일이 오늘의 완료 기준이자, 침투 테스트 전체의 품질을 좌우하는 습관입니다.


4. 미션과 연습문제

미션 — 취약점 후보 목록과 신뢰도 판단

  1. 3-1의 연습 서버를 켠 채로, nmap --script "vuln and not vulners and not http-slowloris-*" -sV -p 8000 127.0.0.1 -oN vuln_fast.txt를 실행하고 소요 시간을 기록합니다.
  2. 결과 파일에서 "못 찾았다(Couldn’t find)"고 보고한 스크립트가 몇 개인지 세어 봅니다.
  3. 랩에 MS2가 있다면 nmap --script vuln -sV <MS2_IP> -oN ms2_vuln.txt를 실행하고(시간이 걸립니다 — -p로 좁혀도 됩니다), grep -oE 'CVE-[0-9]{4}-[0-9]+' ms2_vuln.txt | sort -u로 CVE 후보 목록을 만듭니다.
  4. 목록에서 흥미로운 CVE 3개를 골라 각각 "스캐너가 제시한 근거(버전? 응답 시험?)"와 "Step 113 인벤토리와의 일치 여부"를 표로 정리합니다.
  5. 각 후보에 신뢰도(높음/검증 필요)를 붙이고, 그 판단 근거를 한 줄씩 적습니다.

연습문제

문제 1. 오탐(false positive)이 생기는 대표적 이유 두 가지를 말해 보세요.

문제 2. 스캔 결과에 Couldn't find any stored XSS vulnerabilities라고 적혀 있을 때, 이 문장이 보장하는 것과 보장하지 않는 것을 구분해 설명해 보세요.

문제 3. --script vuln 전체 실행이 포트 하나에서도 몇 분씩 걸릴 수 있는 이유를, 오늘 확인한 스크립트 하나를 근거로 설명해 보세요.

문제 4. 스캐너가 조용할 때(보고가 하나도 없을 때) 가능한 해석 두 가지와, 둘을 구별하기 위해 확인할 것을 말해 보세요.


5. 모범 답안과 완료 기준

미션 모범 답안

1~2번은 실측으로 바로 확인됩니다. 2026-09-09 실측 환경에서는 스캔이 79.29초 걸렸고, "Couldn’t find" 보고는 세 개(CSRF, DOM XSS, 저장형 XSS)였습니다. 여러분의 환경에서는 열린 서비스에 따라 수가 달라질 수 있습니다.

3번의 CVE 추출 명령은 출력 예시에서 확인한 대로입니다:

grep -oE 'CVE-[0-9]{4}-[0-9]+' ms2_vuln.txt | sort -u

4~5번의 표는 이런 모양이면 충분합니다 (MS2 기준 예시):

CVE 스캐너의 근거 인벤토리와 일치? 신뢰도 근거 한 줄
CVE-2011-2523 vsftpd 2.3.4 버전 매칭 일치(21번 포트에서 -sV로 확인) 높음 버전 일치 + 공개 익스플로잇 다수
CVE-2004-2687 distccd 버전 추정 확인 필요 검증 필요 배너에 버전이 없어 추정일 뿐
CVE-2015-3306 mod_copy 모듈 존재 가정 확인 필요 검증 필요 실제 모듈 로드 여부 미확인

검증하는 법: ① 결과 파일에 스캔 일시와 명령 전문이 적혀 있는가(-oN의 자동 기록). ② CVE 목록이 sort -u로 중복 없이 정리됐는가. ③ 신뢰도 판단에 "버전 일치 여부"가 근거로 들어갔는가 — 근거 없이 전부 "높음"이면 다시 하세요.

연습문제 해답

문제 1 해답. 첫째, 배포판의 백포트 패치 — 취약점은 고쳐졌지만 버전 번호가 그대로라 스캐너가 "취약"으로 분류합니다. 둘째, 공격 조건 불성립 — 취약한 버전이 맞지만 해당 기능(모듈/설정)이 꺼져 있어 실제로는 공격이 안 통하는 경우입니다.

문제 2 해답. 보장하는 것: "이 스크립트의 검사 방법(시그니처·시험 페이로드)으로는 발견이 없었다"는 사실입니다. 보장하지 않는 것: XSS가 실제로 없다는 것입니다. 다른 입력 경로, 다른 페이로드, 인증 뒤의 페이지는 이 검사 밖입니다. 부정 결과는 부정의 증명이 아닙니다.

문제 3 해답. http-slowloris-check 같은 스크립트는 "서버가 불완전한 연결을 얼마나 오래 붙드는가"를 재야 하므로 설계상 서버 타임아웃까지 기다립니다(--script-help 실측: "Both connections then wait for server timeout"). 이런 스크립트가 카테고리에 섞여 있어 전체 실행이 수 분으로 늘어납니다 — 2026-09-09 실측에서도 200초 제한에 걸려 중단됐고, 제외하자 79초에 끝났습니다.

문제 4 해답. 해석 하나는 "정말 깨끗하다", 다른 하나는 "검사가 동작하지 않았다"입니다. 오늘 vulners 스크립트가 외부 DB에 못 닿아 조용히 끝난 것(6.70초 무출력, 실측)이 후자의 예입니다. 구별법: 스캔이 정상 완료됐는지(시간, Nmap done 줄), 스크립트가 실제로 실행됐는지(--script-trace 또는 스크립트별 도움말의 필요 조건), 외부 자원이 필요한 스크립트인지를 확인합니다.

완료 기준 체크리스트

  • [ ] --script vuln--script "http-vuln-*"의 차이(범위와 시간)를 설명할 수 있다
  • [ ] 스캔이 느릴 때 스크립트 선택식(and not ...)으로 범위를 좁힐 수 있다
  • [ ] 결과 파일에서 CVE 번호를 추출해 중복 없는 목록을 만들었다
  • [ ] 오탐과 미탐을 구분해 설명할 수 있다
  • [ ] "Couldn’t find" 문장의 의미를 정확히 해석할 수 있다
  • [ ] 스캐너 결과를 Step 113 인벤토리와 교차 검증하는 절차를 말할 수 있다
  • [ ] 미션: 후보 3개의 신뢰도 판단 표를 완성했다

6. 흔한 실수와 해결

벽 1. vuln 스캔이 영원히 안 끝나요

증상 (2026-09-09 실측): --script "vuln and not vulners"로 포트 하나를 검사했는데 200초가 지나도 완료되지 않아 timeout이 강제 종료했고, -oN 결과 파일은 비어 있었습니다.

원인: http-slowloris-check처럼 검사 자체가 서버 타임아웃을 기다리는 스크립트가 카테고리에 섞여 있습니다. nmap은 스캔이 끝나야 파일을 쓰므로, 중단하면 기록도 날아갑니다.
해결: 느린 스크립트를 선택식으로 빼세요 — --script "vuln and not vulners and not http-slowloris-*"(실측 79초 완주). 실무에서는 포트 범위(-p)도 함께 좁힙니다.

벽 2. vulners 스크립트가 아무 말도 안 해요

증상 (2026-09-09 실측): --script vulners -sV를 실행했는데 6.70초 만에 조용히 끝나고 취약점 보고가 한 줄도 없습니다.

원인: 이 스크립트는 외부 API(vulners.com)에 버전을 질의합니다. 인터넷이 막힌 랩이나 폐쇄망에서는 검사 자체가 불능이고, 에러 없이 조용히 넘어갑니다.
해결: "조용함 = 깨끗함"으로 오독하지 마세요. 외부 자원이 필요한 스크립트인지 --script-help로 확인하고, 막힌 환경이면 다른 검사 수단(NVD 오프라인 DB, searchsploit — Step 115)으로 대체합니다.

벽 3. 스캐너가 수십 개를 쏟아내서 어디부터 볼지 모르겠어요

증상 (출력 예시, MS2 대상): CVE가 수십 개 나옵니다.

원인: MS2는 일부러 취약하게 만든 시스템이라 정상입니다. 문제는 스캔이 아니라 우선순위 부재입니다.
해결: ① grep -oE 'CVE-[0-9]{4}-[0-9]+' 파일 | sort -u로 목록화하고, ② Step 113 인벤토리와 버전을 대조하고, ③ "공개 익스플로잇이 있는가"로 정렬합니다. 세 장의 필터를 거치면 검증할 후보는 손에 꼽힙니다.

벽 4. 버전이 스캐너와 인벤토리에서 다르게 보여요

증상: -sVvsftpd 2.3.4라고 했는데, 다른 스크립트는 다른 버전을 근거로 삼았습니다.

원인: 스크립트마다 버전을 추정하는 경로(배너, 응답 패턴, 휴리스틱)가 다릅니다. 배너는 관리자가 바꿀 수도 있습니다.
해결: 직접 확인한 값(-sV 배너)을 기준으로 삼고, 스캐너 측 추정은 "근거 약함"으로 표시해 신뢰도를 낮추세요. 교차 검증이 존재하는 이유입니다.

벽 5. 스캐너 리포트를 그대로 보고서에 붙여요

증상: Nessus/nmap 출력 원문을 결과 보고서에 통째로 첨부합니다.

원인: 스캐너 출력은 "후보"이지 "결론"이 아닙니다. 오탐이 그대로 보고되면 엉뚱한 패치를 시키게 됩니다.
해결: 후보 목록 → 교차 검증 → 신뢰도 표기 → 수동 검증 순으로 가공한 뒤 보고하세요. 오늘 미션의 표가 그 가공 형식입니다.


7. 정리

오늘의 개념

개념 한 줄 설명
취약점 스캐너 버전·응답을 DB와 대조해 취약점 "후보"를 자동으로 뽑는 도구
오탐(false positive) 없는데 있다고 함 — 백포트 패치, 조건 불성립이 주원인
미탐(false negative) 있는데 못 찾음 — DB 밖의 취약점, 숨은 서비스
부정 결과의 독법 "Couldn’t find"는 "없다"가 아니라 "이 방법으로는 못 찾았다"
교차 검증 스캐너의 주장을 직접 모은 인벤토리와 대조하는 필수 공정
후보 생성기 스캐너의 올바른 자리 — 결론은 사람의 검증이 내린다

오늘의 명령어

명령 하는 일
ls /usr/share/nmap/scripts/ | grep -c vuln 내장 vuln 스크립트 개수 확인 (실측 50개)
nmap --script "http-vuln-*" -sV -p 포트 대상 HTTP 취약점 스크립트만 골라 스캔
nmap --script "vuln and not vulners and not http-slowloris-*" ... 느린 스크립트를 빼고 카테고리 스캔
grep -oE 'CVE-[0-9]{4}-[0-9]+' 결과파일 | sort -u 스캔 결과를 CVE 후보 목록으로 압축
nmap --script-help 스크립트명 스크립트의 동작·소요 시간·필요 조건 확인
nmap ... -oN 파일 명령 전문이 적힌 재현 가능한 스캔 기록

명령어보다 중요한 감각

취약점 스캐너는 부지런하지만 생각이 없는 조수입니다. 버전 번호만 보고 후보를 수십 개 쏟아 내고, 못 찾으면 "없다"가 아니라 "못 찾았다"고만 말하며, 외부 DB가 막히면 에러도 없이 조용해집니다. 이 조수를 쓰는 실력은 실행 명령이 아니라 독법에 있습니다 — "이 보고의 근거가 무엇인가, 내가 직접 확인한 것과 일치하는가"를 묻는 습관입니다.

오늘 실측이 보여 준 대비를 기억하세요. 깨끗한 연습 서버에서는 20개 스크립트가 6초 만에 아무 말 없이 끝났고, 느린 스크립트 하나가 전체 스캔을 200초 넘게 붙잡았습니다. 그리고 스캐너가 뽑아 준 CVE 번호는 끝이 아니라 시작입니다. 그 번호 하나를 NVD와 Exploit-DB에서 읽어 내는 독서가 정찰의 완성이고, 그 독서법은 이어지는 Step 115의 주제입니다.


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