
웹서버 취약점 - SSL 보안 설정 및 점검 가이드
#Web server Security SSL Confguration guide
웹서버 취약점 개선을 위해 점검하는 항목들을 정리합니다. 새로운 프로토콜과 암호화 방법은 지속적으로 업그레이드가 필요합니다. 현재 안전한 것도 시간이 지나면 보안에 취약하므로 정기적인 검사와 개선을 해야 합니다.
1. 프로토콜 관리
- 허용: TLS 1.2, TLS 1.3
- 차단: SSLv2, SSLv3, TLS 1.0, TLS 1.1 (이미 폐기, 취약점 존재)
- 설정 예시 (Apache):
-
SSLProtocol -all +TLSv1.3 +TLSv1.2 -
apache
2. 암호군(Cipher Suite) 최적화
- 허용:
- ECDHE-ECDSA-AES128/256-GCM-SHA256/384
- ECDHE-RSA-AES128/256-GCM-SHA256/384
- ECDHE-ECDSA/ RSA-CHACHA20-POLY1305
- 차단:
- CBC 기반 암호군 (패딩 오라클 취약점)
- 3DES, IDEA, SEED, CAMELLIA, ARIA 등 비표준/취약 암호군
- RSA 키 교환 (PFS 미지원)
- 설정 예시 (Nginx):
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:\ ECDHE-RSA-AES128-GCM-SHA256:\ ECDHE-ECDSA-AES256-GCM-SHA384:\ ECDHE-RSA-AES256-GCM-SHA384:\ ECDHE-ECDSA-CHACHA20-POLY1305:\ ECDHE-RSA-CHACHA20-POLY1305; ssl_prefer_server_ciphers on;
3. 키 교환 및 커브 설정
- ECDHE 우선 → Perfect Forward Secrecy(PFS) 보장
- 커브: X25519 → secp384r1 → prime256v1 순서
- DHE 사용 시: 2048비트 이상 dhparam.pem 직접 생성
# DH params (DHE 사용 시)
ssl_dhparam /etc/ssl/dhparam.pem;
4. 세션 관리
# Session tickets
ssl_session_tickets off;
ssl_session_timeout 10m;
- SSLSessionTickets off : 기본적으로 off 권장 (키 재사용 위험)
- ssl_session_timeout 10m : 10분~1시간 권장
5. 인증서 검증
- OCSP Stapling: 서버가 인증서 유효성 검증 응답을 클라이언트에 전달
-
nginx
ssl_stapling on; ssl_stapling_verify on; resolver 1.1.1.1 1.0.0.1 valid=300s; resolver_timeout 5s;
6. 보안 헤더
- HSTS (Strict-Transport-Security): HTTPS 강제, 다운그레이드 공격 방지
-
nginx
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; - 기타 헤더:
- X-Content-Type-Options: nosniff
- X-Frame-Options: SAMEORIGIN
- Content-Security-Policy (필요 시)
7. 최신 프로토콜 지원
- HTTP/2 활성화: 성능 개선 (멀티플렉싱, 헤더 압축)
- HTTP/3/QUIC: 모바일 및 불안정 네트워크 환경에서 성능 향상
8. 점검 방법
- Online Tools : 온라인 검사
SSL Labs Server Test [https://www.ssllabs.com/ssltest]
CryptCheck [https://cryptcheck.fr/]
CypherCraft [https://www.cyphercraft.io/]
Hardenize [https://www.hardenize.com/]
ImmuniWeb [https://www.immuniweb.com/ssl/]
Observatory by Mozilla [https://observatory.mozilla.org/]
SSL Configuration Generator [https://ssl-config.mozilla.org/]
- Offline Tools : CLI 도구
O-Saft - OWASP SSL advanced forensic tool [https://wiki.owasp.org/index.php/O-Saft]
CipherScan [https://github.com/mozilla/cipherscan]
CryptoLyzer [https://gitlab.com/coroner/cryptolyzer]
SSLScan - Fast SSL Scanner [https://github.com/rbsec/sslscan]
SSLyze [https://github.com/nabla-c0d3/sslyze]
testssl.sh - Testing any TLS/SSL encryption [https://testssl.sh/]
tls-scan [https://github.com/prbinu/tls-scan]
- CLI 도구 사용 예시
- nmap --script ssl-enum-ciphers -p 443 example.com
- openssl s_client -connect example.com:443 -tls1_3
- testssl.sh https://example.com
- 브라우저 개발자 도구: Security 탭에서 현재 연결 프로토콜/암호군 확인
📌 체크리스트 요약
- [ ] TLS 1.2/1.3만 허용
- [ ] CBC/3DES/IDEA 등 취약 암호군 제거
- [ ] ECDHE + AES-GCM/CHACHA20만 유지
- [ ] X25519 커브 우선
- [ ] Session Tickets off (또는 키 로테이션)
- [ ] OCSP Stapling on
- [ ] HSTS 헤더 추가 (preload 고려)
- [ ] HTTP/2/3 활성화
- [ ] SSL Labs 등으로 정기 점검
(보안 설정이 양호한 웹서버 검사 결과)
root@# nmap --script ssl-enum-ciphers -p 443 www.example.com
Starting Nmap 7.80 ( https://nmap.org ) at 2026-01-07 11:30 KST
Nmap scan report for www.example.com (2xx.1xx.2x.x4)
Host is up (0.045s latency).
PORT STATE SERVICE
443/tcp open https
| ssl-enum-ciphers:
| TLSv1.2:
| ciphers:
| TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (secp256r1) - A
| TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (secp256r1) - A
| TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (secp256r1) - A
| compressors:
| NULL
| cipher preference: client
|_ least strength: A
Nmap done: 1 IP address (1 host up) scanned in 4.18 seconds
(보안 설정이 취약한 웹서버 검사 결과)
# nmap --script ssl-enum-ciphers -p 443 http://www.example.com
Starting Nmap 7.80 ( https://nmap.org ) at 2026-01-07 13:50 KST
Nmap scan report for http://www.example.com (104.18.27.120)
Host is up (0.0035s latency).
Other addresses for http://www.example.com (not scanned): 104.18.26.120 2606:4700::6812:1a78 2606:4700::6812:1b78
PORT STATE SERVICE
443/tcp open https
| ssl-enum-ciphers:
| TLSv1.0:
| ciphers:
| TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (ecdh_x25519) - A
| TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (ecdh_x25519) - A
| TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_SEED_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_ARIA_256_CBC_SHA384 (rsa 2048) - A
| TLS_RSA_WITH_CAMELLIA_256_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_ARIA_128_CBC_SHA256 (rsa 2048) - A
| TLS_RSA_WITH_CAMELLIA_128_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_IDEA_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
| compressors:
| NULL
| cipher preference: server
| warnings:
| 64-bit block cipher 3DES vulnerable to SWEET32 attack
| 64-bit block cipher IDEA vulnerable to SWEET32 attack
| TLSv1.1:
| ciphers:
| TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (ecdh_x25519) - A
| TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (ecdh_x25519) - A
| TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
| compressors:
| NULL
| cipher preference: server
| TLSv1.2:
| ciphers:
| TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (ecdh_x25519) - A
| TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (ecdh_x25519) - A
| TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (ecdh_x25519) - A
| TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (ecdh_x25519) - A
| TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (ecdh_x25519) - A
| TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (ecdh_x25519) - A
| TLS_RSA_WITH_AES_128_GCM_SHA256 (rsa 2048) - A
| TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
| TLS_RSA_WITH_SEED_CBC_SHA (rsa 2048) - A
| TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (ecdh_x25519) - A
| TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 (ecdh_x25519) - A
| TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA (ecdh_x25519) - C
| TLS_RSA_WITH_AES_256_GCM_SHA384 (rsa 2048) - A
| TLS_RSA_WITH_AES_256_CCM_8 (rsa 2048) - A
| TLS_RSA_WITH_AES_256_CCM (rsa 2048) - A
| TLS_RSA_WITH_ARIA_256_GCM_SHA384 (rsa 2048) - A
| TLS_RSA_WITH_AES_128_CCM_8 (rsa 2048) - A
| TLS_RSA_WITH_AES_128_CCM (rsa 2048) - A
| TLS_RSA_WITH_ARIA_128_GCM_SHA256 (rsa 2048) - A
| TLS_RSA_WITH_AES_256_CBC_SHA256 (rsa 2048) - A
| TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 (rsa 2048) - A
| TLS_RSA_WITH_AES_128_CBC_SHA256 (rsa 2048) - A
| compressors:
| NULL
| cipher preference: server
| warnings:
| 64-bit block cipher 3DES vulnerable to SWEET32 attack
|_ least strength: C
Nmap done: 1 IP address (1 host up) scanned in 3.22 seconds
SSL 보안 설정 유의 사항
| 기존 문제점 | 개선점 |
| SSLv3, TLS 1.0/1.1 허용 | TLS 1.2/1.3만 허용 |
| 3DES, IDEA, CBC 암호군 허용 | AES-GCM/CHACHA20만 허용 |
| RSA 키 교환 사용 | ECDHE 기반으로 PFS 보장 |
| ARIA, CAMELLIA, SEED 등 과다 암호군 | 표준 강력 암호군만 유지 |
| TLS 1.3 미지원 | TLS 1.3 활성화 |
- TLS 1.2에서는 SSLCipherSuite/ssl_ciphers 설정이 반드시 필요합니다.
- TLS 1.2와 TLS 1.3만 허용. (1.3 : 최신브라우저 지원)
Apache, Nginx 모두 TLS 1.3을 지원하는 경우 서버가 기본적으로 안전한 TLS 1.3 암호군을 허용합니다 - TLS 1.2에서는 SSLCipherSuite/ssl_ciphers 설정이 반드시 필요합니다. (약한 암호군 제거 목적)
- .SSLv3, TLS 1.0, TLS 1.1 완전히 차단.
- RSA 키 교환 사용 차단 : RSA 키 교환은 Perfect Forward Secrecy(PFS)를 제공하지 않음 → 세션 키가 장기적으로 노출될 위험.
- 암호군 과다 허용 : ARIA, CAMELLIA, SEED 등 비표준/호환성 낮은 암호군 등 차단
- ECDHE 기반 + AES-GCM/CHACHA20만 허용.
- 3DES (SWEET32 취약점), IDEA, CBC 모드 등 암호군 차단.
- DHE, RSA 키 교환, CBC, 3DES, IDEA, CAMELLIA, SEED 제거.
SSL 설정 예시
#TLS 1.3 활성화:
SSLProtocol -all +TLSv1.3 +TLSv1.2
#암호군 최적화 (TLS 1.2)
SSLOpenSSLConfCmd TLS13Ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
SSLHonorCipherOrder on
Apache 최적화 예시
# 프로토콜: TLS 1.3만 허용 (호환성 필요 시 TLS 1.2 추가)
SSLProtocol -all +TLSv1.3 +TLSv1.2
# 커브: X25519 우선, secp384r1/prime256v1 보조
SSLOpenSSLConfCmd Curves X25519:secp384r1:prime256v1
# TLS 1.3 암호군 (OpenSSL 기본 안전 스위트)
SSLOpenSSLConfCmd TLS13Ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
# TLS 1.2 암호군 (DHE 제거, ECDHE만 유지)
SSLCipherSuite \
ECDHE-ECDSA-AES128-GCM-SHA256:\
ECDHE-RSA-AES128-GCM-SHA256:\
ECDHE-ECDSA-AES256-GCM-SHA384:\
ECDHE-RSA-AES256-GCM-SHA384:\
ECDHE-ECDSA-CHACHA20-POLY1305:\
ECDHE-RSA-CHACHA20-POLY1305
# 서버 사이퍼 우선
SSLHonorCipherOrder on
# 세션 티켓 비활성화
SSLSessionTickets off
# OCSP Stapling
SSLUseStapling on
SSLStaplingCache "shmcb:/var/run/ocsp_stapling(128000)"
# HSTS (preload 고려)
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
# HTTP/2 활성화
Protocols h2 http/1.1
Nginx 최적화 예시 예시
server {
listen 443 ssl http2; # HTTP/2 활성화
# listen 443 quic reuseport; # HTTP/3 (옵션)
# 프로토콜
ssl_protocols TLSv1.3 TLSv1.2;
# 커브
ssl_ecdh_curve X25519:secp384r1:prime256v1;
# TLS 1.3 암호군
ssl_ciphers TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256;
# TLS 1.2 암호군 (DHE 제거)
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:\
ECDHE-RSA-AES128-GCM-SHA256:\
ECDHE-ECDSA-AES256-GCM-SHA384:\
ECDHE-RSA-AES256-GCM-SHA384:\
ECDHE-ECDSA-CHACHA20-POLY1305:\
ECDHE-RSA-CHACHA20-POLY1305;
# 서버 사이퍼 우선
ssl_prefer_server_ciphers on;
# 세션 티켓 비활성화
ssl_session_tickets off;
ssl_session_timeout 10m;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 1.1.1.1 1.0.0.1 valid=300s;
resolver_timeout 5s;
# HSTS
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
}
SSL 설정 항목 설명
- HTTP/2/3 지원 → 최신 프로토콜로 성능 개선.
- Early Data 비활성화 → 보안 강화.
- DH 파라미터 지정 → 안전한 DHE 키 교환.
- OCSP Stapling → 인증서 검증 성능 및 신뢰성 향상.
- HSTS → HTTPS 강제, 다운그레이드 공격 방지.
1. listen 443 ssl http2;
- 443 포트에서 SSL/TLS 활성화 + HTTP/2 지원
- HTTPS 기본 포트(443)에서 TLS 암호화된 연결을 받고, HTTP/2 프로토콜을 사용하도록 설정.
- HTTP/2는 멀티플렉싱, 헤더 압축 등 성능 개선 기능 제공.
2. listen 443 quic reuseport; (옵션)
- HTTP/3/QUIC 지원
- QUIC은 UDP 기반의 최신 프로토콜로, 모바일 환경과 불안정한 네트워크에서 성능 향상.
- reuseport는 여러 워커 프로세스가 동일 포트를 효율적으로 공유하도록 함.
3. ssl_early_data off;
- TLS 1.3 Early Data(0-RTT) 비활성화
- Early Data는 성능 향상(빠른 재연결)을 제공하지만, 재전송 공격 위험이 있어 보안상 끄는 것이 권장됨.
4. ssl_dhparam /etc/ssl/dhparam.pem;
- DHE(Diffie-Hellman Ephemeral) 키 교환 시 사용할 파라미터 파일 지정
- 최소 2048비트 이상 강력한 DH 파라미터를 직접 생성해 적용해야 안전.
5. ssl_stapling on;
- OCSP Stapling 활성화
- 서버가 인증서 유효성 검증(OCSP 응답)을 미리 가져와 클라이언트에 전달.
- 클라이언트가 직접 CA 서버에 요청하지 않아도 되므로 성능과 신뢰성 향상.
6. ssl_stapling_verify on;
- OCSP 응답 검증 활성화
- 서버가 가져온 OCSP 응답이 유효한지 확인.
- 잘못된 응답이나 위조된 응답을 방지.
7. resolver 1.1.1.1 1.0.0.1 valid=300s;
- DNS Resolver 지정
- OCSP Stapling 등 외부 요청 시 사용할 DNS 서버를 지정 (Cloudflare DNS).
- valid=300s → 캐시 유효 시간 300초.
8. resolver_timeout 5s;
- DNS 응답 대기 시간
- DNS 서버 응답을 기다리는 최대 시간 5초로 설정.
9. add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
- HSTS(HTTP Strict Transport Security) 헤더 추가
- 브라우저가 해당 도메인에 대해 항상 HTTPS로만 접속하도록 강제.
- max-age=31536000 → 1년 동안 HTTPS 강제.
- includeSubDomains → 모든 서브도메인에도 적용.
- preload → 브라우저 벤더의 HSTS preload 리스트에 등록 가능.
- always → 모든 응답에 헤더 추가.
🔒 SSL/TLS 보안 설정 항목별 분석
| 보안 항목 | 문제점 | 권장사항 |
| HSTS (Strict-Transport-Security) | - 브라우저가 HTTP로 접속 시 다운그레이드 공격 가능 - 중간자 공격(MITM) 위험 증가 - 사용자가 HTTPS를 강제하지 않음 |
- max-age 최소 6개월 이상 - includeSubDomains로 전체 도메인 적용 - preload 등록 시 브라우저 기본 내장 |
| Protocols (TLSv1.3 only, 필요 시 1.2 추가) | - TLS 1.0/1.1 허용 시 취약점(POODLE, BEAST 등) 노출 - 구형 프로토콜로 인한 보안 약화 |
- TLS 1.3만 허용 시 가장 안전 - 레거시 클라이언트 필요 시 TLS 1.2 병행 |
| Ciphers (ECDHE + AES-GCM/CHACHA20) | - 취약한 CBC, RC4, 3DES 등 사용 가능 - 암호화 강도 낮아짐 |
- GCM/CHACHA20만 허용 - ECDHE 기반으로 PFS(Perfect Forward Secrecy) 보장 |
| Curves (X25519 first) | - 기본 커브 선택 시 성능/보안 최적화 부족 - 일부 클라이언트에서 낮은 보안 커브 사용 |
- X25519 우선 배치 - secp384r1, prime256v1 보조로 호환성 확보 |
| Order (서버 사이퍼 우선 on) | - 클라이언트가 약한 암호군 선택 가능 - 일관된 보안 정책 유지 불가 |
- 서버 우선 설정으로 강한 암호군 강제 |
| Tickets (off 또는 키 로테이션 자동화) | - 세션 티켓 키 고정 시 장기 노출 위험 - 재사용 공격 가능 |
- 티켓 off로 안전성 확보 - 필요 시 키 로테이션 자동화 필수 |
| DH params (2048-bit 이상) | - 기본 DH 파라미터가 약하거나 짧을 경우 취약 - DHE 사용 시 안전성 저하 |
- 최소 2048-bit 이상 dhparam 파일 생성 - 가능하면 ECDHE만 사용 |
| Stapling (OCSP on + resolver 설정) | - 클라이언트가 직접 OCSP 서버에 요청 → 느린 인증서 검증 - 일부 브라우저에서 인증서 신뢰 문제 |
- 서버에서 OCSP stapling 제공 - DNS resolver 지정으로 안정성 확보 |
| HSTS (preload 고려) | - 사용자가 첫 접속 시 HTTPS 강제되지 않음 - 피싱/다운그레이드 위험 |
- preload 등록으로 브라우저 자체에서 HTTPS 강제 |
| ALPN (HTTP/2/3 활성화) | - HTTP/1.1만 사용 시 성능 저하 - 멀티플렉싱, 헤더 압축 등 최신 기능 미사용 |
- HTTP/2 기본 활성화 - HTTP/3(QUIC) 지원 시 모바일/네트워크 성능 개선 |
'InfraPlatform' 카테고리의 다른 글
| WSL2에서 VHDX 디스크 마운트하는 방법 (0) | 2026.01.20 |
|---|---|
| Windows 10/11 - WSL 2 업그레이드 (0) | 2026.01.19 |
| Windows WSL에 Ollama/CUDA 커스텀 경로 설치 가이드(Ubuntu 22.04) (1) | 2026.01.06 |
| (꿀팁) 리눅스 시스템 시간 동기화 하기 (Chrony,NTP ) (36) | 2026.01.05 |
| (꿀팁) Red Hat 계열 리눅스 시간 관리 방법 (1) | 2026.01.02 |
| 리눅스에서 숫자 계정 생성 정책 허용 (useradd --badname 활용) (11) | 2025.11.29 |
| 디자인 과학 연구 방법론(Design Science Research Methodology, DSRM) (0) | 2025.10.29 |