본문으로 건너뛰기

보안 강화 실전 고수 팁

CIS Benchmark 기반 보안 점검부터 취약점 스캐너 활용, 제로데이 대응까지 — 운영 환경에서 즉시 적용 가능한 실전 노하우를 정리합니다.


CIS Benchmark 기반 보안 점검 체크리스트

CIS(Center for Internet Security) Benchmark는 업계 표준 보안 구성 가이드입니다.

Nginx CIS Benchmark 핵심 항목

#!/bin/bash
# nginx-security-check.sh — CIS Nginx Benchmark 자동 점검

echo "=== Nginx 보안 점검 ==="

# 1. Nginx 버전 노출 확인
echo -n "[CHECK] server_tokens: "
grep -r "server_tokens" /etc/nginx/ 2>/dev/null | grep -v "#" | grep "off" \
&& echo "PASS" || echo "FAIL — server_tokens off 설정 필요"

# 2. 디렉토리 리스팅 비활성화
echo -n "[CHECK] autoindex: "
grep -r "autoindex on" /etc/nginx/ 2>/dev/null | grep -v "#" \
&& echo "FAIL — autoindex off 설정 필요" || echo "PASS"

# 3. 업로드 크기 제한
echo -n "[CHECK] client_max_body_size: "
grep -r "client_max_body_size" /etc/nginx/ 2>/dev/null | grep -v "#" \
|| echo "WARN — 기본값(1MB) 사용 중, 명시적 설정 권장"

# 4. 타임아웃 설정
echo -n "[CHECK] client_header_timeout: "
grep -r "client_header_timeout" /etc/nginx/ 2>/dev/null | grep -v "#" \
|| echo "WARN — Slowloris 방어를 위한 타임아웃 설정 권장"

# 5. Rate Limiting 설정
echo -n "[CHECK] limit_req_zone: "
grep -r "limit_req_zone" /etc/nginx/ 2>/dev/null | grep -v "#" \
&& echo "PASS" || echo "WARN — Rate Limiting 설정 권장"

# 6. 보안 헤더 확인
HEADERS=$(curl -sI https://localhost 2>/dev/null)
for header in "X-Frame-Options" "X-Content-Type-Options" "Strict-Transport-Security"; do
echo -n "[CHECK] $header: "
echo "$HEADERS" | grep -i "$header" && echo "" || echo "FAIL — 헤더 추가 필요"
done

# 7. 숨김 파일 접근 차단
echo -n "[CHECK] 숨김 파일 차단: "
grep -r "location ~ /\\\\." /etc/nginx/ 2>/dev/null | grep -v "#" \
&& echo "PASS" || echo "WARN — .env, .git 접근 차단 설정 권장"

echo ""
echo "=== 점검 완료 ==="

Apache CIS Benchmark 핵심 항목

#!/bin/bash
# apache-security-check.sh

echo "=== Apache 보안 점검 ==="

# ServerTokens 확인
echo -n "[CHECK] ServerTokens: "
apache2ctl -t -D DUMP_RUN_CFG 2>&1 | grep -i "ServerTokens" \
|| grep -ri "ServerTokens" /etc/apache2/ 2>/dev/null | grep -v "#" \
|| echo "설정 확인 필요"

# ServerSignature 확인
echo -n "[CHECK] ServerSignature: "
grep -ri "ServerSignature Off" /etc/apache2/ 2>/dev/null | grep -v "#" \
&& echo "PASS" || echo "FAIL — ServerSignature Off 설정 필요"

# 디렉토리 Options 확인
echo -n "[CHECK] Options -Indexes: "
grep -ri "Options.*-Indexes" /etc/apache2/ 2>/dev/null | grep -v "#" \
&& echo "PASS" || echo "WARN — Indexes 비활성화 권장"

# mod_security 활성화 확인
echo -n "[CHECK] ModSecurity: "
apache2ctl -M 2>/dev/null | grep security \
&& echo "" || echo "WARN — ModSecurity 미설치"

취약점 스캐너 활용

Nikto — 웹 서버 취약점 스캐너

# Nikto 설치
sudo apt install nikto

# 기본 스캔
nikto -h https://example.com

# 특정 취약점 유형만 스캔
# -Tuning 옵션: 0=정보노출, 1=파일포함, 2=기타파일, 3=XSS, 4=인젝션,
# 5=원격포함, 6=서비스거부, 7=RCE, 8=SQL, 9=파일업로드, 0=인증우회
nikto -h https://example.com -Tuning 0,3,4,8 # 정보노출+XSS+SQL만

# 출력 형식 지정
nikto -h https://example.com -Format html -o report.html
nikto -h https://example.com -Format csv -o report.csv

# 인증이 필요한 경로 스캔
nikto -h https://example.com -id admin:password

# 결과 해석:
# + OSVDB-xxx: 취약점 ID
# - : 정상 (해당 취약점 없음)
# + : 발견된 취약점 또는 주의사항

OWASP ZAP — 웹 애플리케이션 보안 테스트

# Docker로 ZAP 실행 (간단한 방법)
docker pull zaproxy/zap-stable

# 기준선(Baseline) 스캔 — 수동 없이 자동 수행
docker run -t zaproxy/zap-stable zap-baseline.py \
-t https://example.com \
-r zap-report.html

# 전체 스캔 (활성 공격 포함, 시간 많이 걸림)
docker run -t zaproxy/zap-stable zap-full-scan.py \
-t https://example.com \
-r zap-full-report.html

# API 스캔 (OpenAPI/Swagger 지원)
docker run -t zaproxy/zap-stable zap-api-scan.py \
-t https://api.example.com/openapi.json \
-f openapi \
-r zap-api-report.html

sqlmap — SQL Injection 테스트

# 특정 파라미터 SQL Injection 테스트 (허가된 환경에서만)
sqlmap -u "https://example.com/api/users?id=1" \
--level=3 --risk=2 \
--dbs # 데이터베이스 목록 추출

# POST 요청 테스트
sqlmap -u "https://example.com/login" \
--data="username=test&password=test" \
--level=5

# 쿠키 기반 인증 세션 포함
sqlmap -u "https://example.com/profile" \
--cookie="session=abc123" \
--tables

보안 헤더 일괄 설정 템플릿

운영 환경에서 즉시 적용 가능한 완전한 보안 헤더 설정:

# /etc/nginx/conf.d/security-headers.conf
# 모든 server 블록에 include하여 재사용

# 클릭재킹 방지
add_header X-Frame-Options "SAMEORIGIN" always;

# MIME 스니핑 방지
add_header X-Content-Type-Options "nosniff" always;

# XSS 보호 (구형 브라우저용, 최신은 CSP로 대체)
add_header X-XSS-Protection "1; mode=block" always;

# HSTS — HTTPS 강제 (1년, 서브도메인 포함)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

# Referrer 정보 제한
add_header Referrer-Policy "strict-origin-when-cross-origin" always;

# 권한 정책 — 불필요한 브라우저 기능 비활성화
add_header Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=()" always;

# CSP — 콘텐츠 보안 정책 (사이트에 맞게 조정 필요)
# 아래는 예시 — 실제 적용 전 report-only 모드로 테스트 권장
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.example.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' https://fonts.gstatic.com; connect-src 'self'; frame-ancestors 'self'; base-uri 'self'; form-action 'self';" always;

# 서버 정보 제거
server_tokens off;

# 서버 이름 변경 (headers-more 모듈 필요)
# more_set_headers 'Server: WebServer';

정기 보안 감사 자동화

#!/bin/bash
# /usr/local/bin/weekly-security-audit.sh
# cron: 0 2 * * 0 (매주 일요일 새벽 2시)

DATE=$(date +%Y%m%d)
REPORT_DIR="/var/reports/security"
mkdir -p "$REPORT_DIR"

echo "=== 주간 보안 감사 — $DATE ===" > "$REPORT_DIR/audit-$DATE.txt"

# 1. SSL 인증서 만료일 확인
echo "--- SSL 인증서 ---" >> "$REPORT_DIR/audit-$DATE.txt"
CERT_EXPIRY=$(echo | openssl s_client -connect example.com:443 2>/dev/null \
| openssl x509 -noout -enddate 2>/dev/null)
echo "$CERT_EXPIRY" >> "$REPORT_DIR/audit-$DATE.txt"

# 30일 이내 만료 시 알림
EXPIRY_EPOCH=$(echo "$CERT_EXPIRY" | cut -d= -f2 | xargs -I{} date -d '{}' +%s)
NOW_EPOCH=$(date +%s)
DAYS_LEFT=$(( (EXPIRY_EPOCH - NOW_EPOCH) / 86400 ))
if [ "$DAYS_LEFT" -lt 30 ]; then
echo "⚠️ SSL 인증서 $DAYS_LEFT일 후 만료!" | mail -s "SSL 만료 경고" admin@example.com
fi

# 2. fail2ban 차단 현황
echo "--- fail2ban 차단 IP ---" >> "$REPORT_DIR/audit-$DATE.txt"
fail2ban-client status 2>/dev/null >> "$REPORT_DIR/audit-$DATE.txt"

# 3. 최근 1주일 에러 로그 요약
echo "--- Nginx 에러 로그 요약 ---" >> "$REPORT_DIR/audit-$DATE.txt"
grep "$(date -d '7 days ago' '+%Y/%m/%d')" /var/log/nginx/error.log 2>/dev/null \
| grep -v "^$" | sort | uniq -c | sort -rn | head -20 \
>> "$REPORT_DIR/audit-$DATE.txt"

# 4. ModSecurity 차단 상위 규칙
echo "--- ModSecurity 주요 차단 규칙 ---" >> "$REPORT_DIR/audit-$DATE.txt"
grep "Access denied" /var/log/modsec_audit.log 2>/dev/null \
| grep -o 'id "[0-9]*"' | sort | uniq -c | sort -rn | head -10 \
>> "$REPORT_DIR/audit-$DATE.txt"

# 5. 열린 포트 확인 (예상치 못한 포트 감지)
echo "--- 열린 포트 ---" >> "$REPORT_DIR/audit-$DATE.txt"
ss -tlnp >> "$REPORT_DIR/audit-$DATE.txt"

# 6. 보안 업데이트 확인
echo "--- 보안 업데이트 대기 ---" >> "$REPORT_DIR/audit-$DATE.txt"
apt list --upgradable 2>/dev/null | grep -i security \
>> "$REPORT_DIR/audit-$DATE.txt"

echo "감사 완료: $REPORT_DIR/audit-$DATE.txt"

다층 방어(Defense in Depth) 아키텍처

클라이언트


CDN / DDoS 방어 (Cloudflare / AWS Shield)


방화벽 (iptables / UFW / AWS Security Group)


Nginx (WAF/ModSecurity, Rate Limiting, IP 차단)


애플리케이션 서버 (Spring Boot 입력 검증, 인증/인가)


데이터베이스 (최소 권한, 암호화)

각 계층의 역할:

계층방어 대상주요 도구
CDN대규모 DDoS, 글로벌 분산 공격Cloudflare, AWS CloudFront
방화벽포트 접근, 네트워크 레벨 공격iptables, UFW, AWS SG
웹서버HTTP Flood, 악성 요청, 정보 노출Nginx + ModSecurity
애플리케이션인젝션, 인증 우회, 비즈니스 로직Spring Security, Validation
데이터베이스SQL Injection, 무단 접근최소 권한, Prepared Statement

제로데이 취약점 대응 체계

# CVE 모니터링 — 자동화
# Nginx, Apache, Tomcat 신규 CVE 알림 구독

# RSS 피드 모니터링 (cron 활용)
cat > /usr/local/bin/check-cve.sh << 'EOF'
#!/bin/bash
# Nginx CVE 확인 (NVD RSS 피드)
NGINX_VERSION=$(nginx -v 2>&1 | grep -o '[0-9.]*')
echo "현재 Nginx 버전: $NGINX_VERSION"

# 최신 보안 업데이트 확인
apt-cache policy nginx 2>/dev/null | head -5

# 수동 보안 블로그 확인 링크 출력
echo "확인할 링크:"
echo " https://nginx.org/en/security_advisories.html"
echo " https://httpd.apache.org/security/vulnerabilities_24.html"
echo " https://tomcat.apache.org/security.html"
EOF
chmod +x /usr/local/bin/check-cve.sh

# 매일 아침 CVE 체크 (cron)
# 0 9 * * * /usr/local/bin/check-cve.sh | mail -s "CVE 일일 체크" admin@example.com

보안 설정 버전 관리 (Infrastructure as Code)

# Nginx 설정을 Git으로 관리
cd /etc/nginx
git init
git add .
git commit -m "initial: nginx security baseline"

# 변경 사항 추적
git diff

# 배포 스크립트와 연동
cat > /usr/local/bin/nginx-deploy.sh << 'EOF'
#!/bin/bash
# 1. 설정 검증
nginx -t || exit 1

# 2. 변경 사항 커밋
cd /etc/nginx
git add -A
git commit -m "config update: $(date +%Y%m%d-%H%M)"

# 3. 리로드
systemctl reload nginx

# 4. 헬스체크
sleep 2
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" https://localhost)
if [ "$HTTP_CODE" != "200" ]; then
echo "⚠️ 헬스체크 실패: $HTTP_CODE — 이전 설정 복원"
git stash
systemctl reload nginx
fi

echo "✅ 배포 완료"
EOF
chmod +x /usr/local/bin/nginx-deploy.sh

실전 보안 운영 체크리스트

신규 서버 배포 시 (배포 전 필수 확인)

□ server_tokens off / ServerTokens Prod 설정
□ 디렉토리 리스팅 비활성화 (autoindex off / Options -Indexes)
□ 불필요한 HTTP 메서드 차단 (TRACE, OPTIONS)
□ 보안 헤더 6종 설정 (X-Frame-Options, CSP, HSTS 등)
□ SSL/TLS 1.3 설정, 취약 암호 제거
□ Rate Limiting 설정 (API, 로그인 엔드포인트)
□ 업로드 디렉토리 스크립트 실행 차단
□ 민감 파일 접근 차단 (.env, .git, *.conf)
□ 에러 페이지 커스터마이징 (서버 정보 미포함)
□ fail2ban 설치 및 활성화
□ ModSecurity + OWASP CRS 설치 (DetectionOnly 모드 시작)
□ 방화벽 규칙 확인 (필요한 포트만 개방)
□ SSH 접근 제한 (공개키만 허용, 루트 로그인 금지)

월간 점검 항목

□ SSL 인증서 만료일 확인 (30일 이내 갱신)
□ 보안 업데이트 적용 (nginx, apache, openssl)
□ fail2ban 차단 IP 로그 검토
□ ModSecurity 오탐 규칙 조정
□ 액세스 로그 이상 트래픽 분석
□ 취약점 스캐너 실행 (Nikto 또는 ZAP)
□ 방화벽 규칙 검토 (불필요한 규칙 제거)
□ 백업 복원 테스트

보안 사고 대응 (Incident Response) 절차

# 1단계: 현황 파악 (공격 진행 중)
# 현재 연결 상태 확인
ss -tn state established | awk '{print $5}' | cut -d: -f1 | \
sort | uniq -c | sort -rn | head -20

# 비정상 프로세스 확인
ps aux | sort -k3 -rn | head -20 # CPU 높은 프로세스
netstat -tlnp # 열린 포트

# 2단계: 즉시 차단
# 공격 IP 차단 (임시)
iptables -I INPUT -s <공격_IP> -j DROP

# Nginx에서도 차단
echo "deny <공격_IP>;" >> /etc/nginx/blocklist.conf
nginx -t && nginx -s reload

# 3단계: 증거 보전
# 로그 백업 (덮어쓰기 방지)
cp /var/log/nginx/access.log /tmp/incident-$(date +%Y%m%d)-access.log
cp /var/log/nginx/error.log /tmp/incident-$(date +%Y%m%d)-error.log
cp /var/log/modsec_audit.log /tmp/incident-$(date +%Y%m%d)-modsec.log

# 4단계: 근본 원인 분석
# 어떤 URL이 공격받았는지
grep "<공격_IP>" /var/log/nginx/access.log | \
awk '{print $7}' | sort | uniq -c | sort -rn | head -20

# 5단계: 재발 방지
# 차단 규칙 영구 적용, ModSecurity 규칙 강화