OPEN HYPER STEP
← 목록으로 (화이트햇 보안)
SECURITY · 69 / 84
security
CHAPTER 69 / 84
읽기 약 2
FUNCTION

서비스 감지: 무엇이 실행 중인가


핵심 개념

배너 그래빙(Banner Grabbing)과 python-nmap으로 열린 포트의 서비스를 식별한다.

본문

배너 그래빙 — 서비스가 자기 정보를 흘림

PYTHON📋 코드 (36줄)
# ⚠️ 이 코드는 허가된 환경에서만 사용하세요.
import socket

def grab_banner(host: str, port: int, timeout: float = 3.0) -> str:
    """포트에 연결 후 첫 응답을 받아 서비스 추정."""
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(timeout)
    try:
        s.connect((host, port))

        # 1) 일부 서비스(SSH/SMTP)는 연결만으로 배너 전송
        try:
            data = s.recv(1024)
            if data:
                return data.decode('utf-8', errors='replace').strip()
        except socket.timeout:
            pass

        # 2) HTTP 서비스 — HEAD 요청으로 헤더 수집
        if port in (80, 8080, 8443, 443):
            s.send(b'HEAD / HTTP/1.0\r\nHost: ' + host.encode() + b'\r\n\r\n')
            data = s.recv(4096)
            return data.decode('utf-8', errors='replace').strip()

        return ''
    except (socket.timeout, ConnectionRefusedError, OSError) as e:
        return f'error: {e}'
    finally:
        s.close()

# 결과 예시
"""
SSH:    SSH-2.0-OpenSSH_8.4p1 Debian-5
SMTP:   220 mail.example.com ESMTP Postfix (Ubuntu)
HTTP:   HTTP/1.1 200 OK\r\nServer: nginx/1.18.0 (Ubuntu)\r\n...
"""

서비스 식별 패턴

PYTHON📋 코드 (23줄)
import re

SERVICE_PATTERNS = {
    'SSH':       re.compile(r'^SSH-(\d+\.\d+)-(.+?)(\s|$)'),
    'SMTP':      re.compile(r'^220.*ESMTP'),
    'HTTP':      re.compile(r'HTTP/\d\.\d (\d{3})'),
    'FTP':       re.compile(r'^220.*FTP'),
    'MySQL':     re.compile(r'\x00\x00\x00\x0a(\d+\.\d+)'),
    'Redis':     re.compile(r'-NOAUTH'),
    'Docker':    re.compile(r'docker'),
}

def identify_service(banner: str) -> dict:
    """배너에서 서비스 종류와 버전 추출."""
    for service, pattern in SERVICE_PATTERNS.items():
        m = pattern.search(banner)
        if m:
            return {
                'service': service,
                'version': m.group(1) if m.groups() else 'unknown',
                'raw_banner': banner[:200],
            }
    return {'service': 'unknown', 'raw_banner': banner[:200]}

python-nmap 활용 — 더 강력한 식별

PYTHON📋 코드 (30줄)
# pip install python-nmap
# ⚠️ 이 코드는 허가된 환경에서만 사용하세요.
import nmap

def nmap_service_scan(host: str, ports: str = '1-1024') -> dict:
    """nmap의 -sV 옵션을 Python에서 호출."""
    nm = nmap.PortScanner()
    # -sV: 서비스/버전 감지, -T4: 빠른 속도
    nm.scan(host, ports, arguments='-sV -T4')

    result = {}
    for h in nm.all_hosts():
        result[h] = {
            'state': nm[h].state(),
            'services': [],
        }
        for proto in nm[h].all_protocols():
            for port in nm[h][proto].keys():
                info = nm[h][proto][port]
                result[h]['services'].append({
                    'port': port,
                    'protocol': proto,
                    'state': info['state'],
                    'service': info.get('name', 'unknown'),
                    'product': info.get('product', ''),
                    'version': info.get('version', ''),
                })
    return result

# print(nmap_service_scan('127.0.0.1'))

실습: 열린 포트 → 서비스 식별 → 버전 확인

PYTHON📋 코드 (28줄)
# ⚠️ 이 코드는 허가된 환경에서만 사용하세요.
def fingerprint_host(host: str, ports: list[int]) -> dict:
    """포트별 서비스/버전 식별."""
    findings = []
    for port in ports:
        banner = grab_banner(host, port, 3.0)
        if banner and not banner.startswith('error'):
            service_info = identify_service(banner)
            findings.append({
                'port': port,
                **service_info,
            })
    return {'host': host, 'findings': findings}

# CVE 매핑 — 알려진 취약점이 있는 버전 확인
KNOWN_VULNS = {
    'OpenSSH_7.': ['CVE-2018-15473 (사용자 열거)'],
    'nginx/1.16.': ['CVE-2019-9511 (HTTP/2 DoS)'],
    'Apache/2.4.49': ['CVE-2021-41773 (경로 탐색)'],
}

def check_known_vulns(banner: str) -> list[str]:
    """배너에서 알려진 취약점 매칭."""
    vulns = []
    for pattern, cves in KNOWN_VULNS.items():
        if pattern in banner:
            vulns.extend(cves)
    return vulns

⚠️ 보안 관점

  • 배너 그래빙은 **수동(passive)**으로 분류되지만 일부 IDS가 감지
  • 운영 서비스는 배너에서 버전을 숨겨야 함:
    • nginx: server_tokens off;
    • Apache: ServerTokens Prod
    • SSH: DebianBanner no (sshd_config)
  • CVE 매핑은 참고용 — 실제 취약 여부는 보안 패치 적용 여부에 따라 다름

AI 프롬프트
🤖 AI에게 잘 물어보는 법 — 모델·전략별 프롬프트
Claude

무료: Sonnet 4.6 / Pro $20/mo: Opus 4.6

내 배너 그래빙 코드의
서비스 식별 정확도와 timeout 처리를 분석하고
false positive를 줄이는 패턴을 보강해줘.
ChatGPT

무료: GPT-5.5 / Plus $20/mo: GPT-5.5 Pro

배너 그래빙으로 식별 가능한 서비스 Top 20과
각각의 default 응답 패턴을
복사 가능한 정규식으로 정리해줘.
Gemini

무료: 2.5 Flash / Pro $19.99/mo: 3.1 Pro

내 호스트 핑거프린팅 결과 로그를 분석해서
CVE 매핑·취약 버전·우선순위 패치 항목을
종합 리포트로 만들어줘.
Grok

무료: Grok 4.1 / SuperGrok $30/mo

2026년 서비스 감지 트렌드 —
Nmap NSE vs Masscan + Banner-grab vs ML 기반 핑거프린팅
실무 활용도를 솔직히 알려줘.

⭐ 이것만 기억하세요
서비스 감지: 무엇이 실행 중인가 이 3가지만 확실히 잡으세요
1.배너 그래빙 + 정규식 패턴 매칭으로 서비스 종류와 버전을 80~90% 식별할 수 있다
2.python-nmap을 쓰면 nmap의 -sV(서비스 버전 감지) 결과를 Python에서 직접 활용할 수 있다
3.다음 챕터에서 ICMP/DNS/traceroute로 네트워크 응답을 분석하는 기법을 배운다


공유하기
진행도 69 / 84