태그 보관물: Apache

아파치 웹서버 정보 숨기기

개요

웹 취약점 스캐너(Nikto, Nessus 등)나 공격자가 서버를 탐지할 때 가장 먼저 확인하는 것이 HTTP 응답 헤더의 서버 정보입니다. 노출된 버전 정보는 해당 버전에 존재하는 CVE 취약점을 직접 타겟팅하는 데 활용됩니다.

기본 설정된 Apache로 웹서비스를 운영하면 HTTP 응답 헤더와 에러 페이지에 웹서버 정보(버전, OS, PHP 버전)가 노출됩니다. 이 정보는 공격자에게 취약점 탐색 시 활용될 수 있으므로 ServerTokensServerSignature 지시자로 불필요한 정보를 숨기는 것이 보안 운영의 기본입니다.

증상 — 기본 상태에서의 서버 정보 노출

curl로 HTTP 응답 헤더를 확인하면 Apache 버전, OS 정보, PHP 버전까지 노출되는 것을 확인할 수 있습니다.

<admin-user>@localhost:~$ curl --head <domain>
HTTP/1.1 302 Found
Date: Fri, 05 Mar 2021 02:21:54 GMT
Server: Apache/2.4.x (CentOS) OpenSSL/1.0.x PHP/7.2.x
// 웹서버/OS 버전 외에도 PHP 버전까지 노출되고 있습니다.

httpd.conf 설정

httpd.conf 또는 httpd-default.conf에 아래 두 지시자를 추가하고 Apache를 재시작합니다.

# httpd.conf 또는 httpd-default.conf에 추가
ServerTokens Prod
ServerSignature Off

# 아파치 재기동
# systemctl restart httpd

ServerTokens 옵션 상세

ServerTokens 지시자의 각 옵션별로 HTTP 응답 헤더에 포함되는 정보 범위가 다릅니다. 보안을 위해 가장 최소한의 정보만 노출하는 Prod 옵션 사용을 권장합니다.

키워드 제공 정보 예문
Prod 웹 서버 종류 Apache
Min 웹 서버 버전 Apache/2.2.3
OS 웹 서버 버전 + 운영체제 Apache/2.2.3 (CentOS)
Full 웹 서버의 모든 정보 Apache/2.2.3 (CentOS) DAV/2 PHP/5.16
ServerTokens 지시자 옵션

추가 보안 설정 — 에러 페이지 커스터마이징

ServerSignature Off로도 Apache 기본 에러 페이지에서 버전 정보가 노출될 수 있습니다. 404, 403, 500 등 에러 발생 시 기본 Apache 에러 페이지에는 서버 서명이 포함되므로, 커스텀 에러 페이지를 사용하는 것이 보안에 유리합니다.

# httpd.conf에 커스텀 에러 페이지 지정
ErrorDocument 403 /error/403.html
ErrorDocument 404 /error/404.html
ErrorDocument 500 /error/500.html

또한 Apache의 Header 지시자(mod_headers)로 보안 관련 HTTP 응답 헤더를 추가하면 XSS, 클릭재킹 등의 공격에 대한 방어가 강화됩니다. X-Content-Type-Options: nosniff는 MIME 타입 스니핑을 차단하고, X-Frame-Options: SAMEORIGIN은 iframe을 이용한 클릭재킹을 방지합니다. Strict-Transport-Security(HSTS)는 HTTPS 강제 적용을 브라우저에 알립니다.

# mod_headers 활성화 후 적용 (httpd.conf 또는 .htaccess)
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-XSS-Protection "1; mode=block"
# HTTPS 환경에서만 HSTS 적용
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"

이러한 보안 헤더 설정은 securityheaders.com 등의 도구로 점수를 측정하고 누락된 헤더를 파악하는 방법으로 체계적으로 관리할 수 있습니다.

결과 확인

Apache 재시작 후 동일하게 curl로 헤더를 확인하면 Server: Apache만 표시되어 버전 및 OS 정보가 제거된 것을 확인할 수 있습니다.

<admin-user>@localhost:~$ curl --head <domain>
HTTP/1.1 302 Found
Date: Fri, 05 Mar 2021 02:26:10 GMT
Server: Apache
// 웹서버 종류만 표시

참고

참고 문서: Apache ServerTokens 지시자 공식 문서 · Apache ServerSignature 지시자 공식 문서

WordPress 설치(Apache base)

개요

CentOS 7 환경에서 Apache(httpd) 기반으로 WordPress 설치를 진행하는 전체 절차입니다. Apache → PHP → MariaDB 순서로 설치하고 WordPress 패키지를 DocumentRoot에 배포한 후, wp-config.php에 DB 연결 정보와 Salt 값을 설정하면 브라우저에서 WordPress 설치 마법사 화면에 접근할 수 있습니다.

구성 개요

Apache, PHP, MariaDB 세 컴포넌트를 같은 서버에 설치하는 방식을 LAMP 스택(Linux + Apache + MySQL/MariaDB + PHP)이라 합니다. LAMP 스택은 WordPress의 가장 전통적인 배포 방식으로, 소규모 서비스나 내부 서버에서 간단하게 구성할 수 있습니다. Apache는 PHP 요청을 mod_php로 처리하고, MariaDB는 WordPress의 게시글, 사용자, 설정 데이터를 저장합니다. 이 가이드는 CentOS 7 기준으로 작성되었으나 Rocky Linux 8/9에서도 DNF 명령과 패키지 이름만 일부 변경하면 동일하게 적용할 수 있습니다.

설치 환경

  • OS: CentOS 7 64bit
  • Web Server: Apache 2.4 + mod_ssl
  • Language: PHP 7.2
  • Database: MariaDB 10.3

Apache 설치

mod_ssl 모듈을 포함하여 Apache를 설치합니다. HTTPS를 사용하려면 mod_ssl이 반드시 필요합니다.

# yum install httpd httpd-devel mod_ssl -y

httpd.conf에 VirtualHost 설정을 추가합니다. HTTP 요청은 HTTPS로 리다이렉트하고, SSL VirtualHost에 인증서 경로를 지정합니다. Self-signed 인증서 생성 방법은 Apache HTTPS 구성 — mod_ssl 설치 및 self-signed 인증서 생성을 참고하세요.

<VirtualHost *:80>
  RewriteEngine On
  RewriteCond %{HTTPS} !=on
  RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L]
  DocumentRoot /app/doc/wordpress
  ServerName www.<domain>
  ServerAlias www.<domain>
</VirtualHost>

<VirtualHost *:443>
  SSLEngine on
  SSLCertificateFile /etc/pki/tls/certs/ca.crt
  SSLCertificateKeyFile /etc/pki/tls/private/ca.key
  DocumentRoot /app/doc/wordpress
  ServerName www.<domain>
  ServerAlias www.<domain>
</VirtualHost>

ssl.conf에서 인증서 파일 경로를 지정합니다.

SSLCertificateFile /etc/pki/tls/certs/ca.crt
SSLCertificateKeyFile /etc/pki/tls/private/ca.key

PHP 설치

WordPress 운영에 필요한 PHP 7.2와 관련 확장 모듈을 webtatic 저장소를 통해 설치합니다.

# rpm -Uvh https://mirror.webtatic.com/yum/el7/webtatic-release.rpm
# yum install mod_php72w php72w-cli -y
# yum install php72w-bcmath php72w-gd php72w-mbstring php72w-mysqlnd php72w-pear php72w-xml php72w-xmlrpc php72w-process -y

# 설치 버전 확인
# php -v

MariaDB 설치 및 WordPress DB 생성

MariaDB 설치 방법은 MariaDB 10.3 설치를 참고하세요. MariaDB 설치 완료 후 WordPress 전용 데이터베이스와 계정을 생성합니다.

# mysql -u root -p

> CREATE DATABASE wordpress CHARACTER SET utf8 COLLATE utf8_bin;
> GRANT ALL PRIVILEGES ON wordpress.* TO wordpress@'localhost' IDENTIFIED BY 'password';
> FLUSH PRIVILEGES;

WordPress 설치 및 설정

WordPress 최신 패키지를 다운로드하고 DocumentRoot 경로에 배포한 후 권한을 설정합니다.

# wget https://wordpress.org/latest.tar.gz
# tar zxvf latest.tar.gz

# mv wordpress /app/doc/
# mkdir /app/doc/wordpress/wp-content/uploads
# chown -R apache:apache /app/doc/wordpress
# chmod -R 755 /app/doc/wordpress

# cd /app/doc/wordpress
# mv wp-config-sample.php wp-config.php

wp-config.php에 DB 연결 정보를 입력합니다.

# vi wp-config.php

define('DB_NAME', 'wordpress');
/** MySQL database username */
define('DB_USER', 'wordpress');
/** MySQL database password */
define('DB_PASSWORD', 'password');   // 실제 비밀번호로 변경
/** MySQL hostname */
define('DB_HOST', 'localhost');

Salt 값 설정: WordPress Salt Generator에 접속하여 출력된 텍스트를 복사한 후 wp-config.php의 'put your unique phrase here' 항목 전체를 교체합니다.

설치 완료 후 보안 강화

WordPress 설치 마법사를 완료한 후 다음 보안 설정을 추가로 진행합니다. WordPress의 xmlrpc.php는 외부 원격 게시 기능을 제공하지만, 무차별 대입 공격(brute-force)에 자주 악용됩니다. 사용하지 않는다면 Apache에서 접근을 차단합니다. 또한 WordPress 관리자 계정 이름을 admin으로 그대로 사용하면 공격 대상이 되므로, 첫 설치 시 다른 이름으로 설정하거나 설치 후 변경합니다.

# httpd.conf 또는 .htaccess에서 xmlrpc.php 접근 차단
<Files xmlrpc.php>
  Order Deny,Allow
  Deny from all
</Files>

WordPress 파일과 디렉토리 권한은 보안과 기능성의 균형이 중요합니다. PHP가 파일 업로드 및 플러그인 설치를 처리하려면 wp-content/uploadswp-content/plugins에 Apache 프로세스 계정(apache 또는 www-data)의 쓰기 권한이 필요합니다. 그러나 웹 디렉토리 전체를 777로 설정하는 것은 보안 위험이 있으므로, 755(디렉토리)와 644(파일) 조합을 기본으로 하고 uploads 디렉토리만 쓰기 권한을 부여합니다.

서비스 시작 및 접속 확인

Apache 서비스를 시작하고 브라우저에서 서버 IP 또는 도메인 주소로 접속하면 WordPress 설치 마법사 화면이 표시됩니다.

# systemctl enable httpd
# systemctl start httpd

브라우저에서 https://<서버IP>에 접속하면 WordPress 언어 선택 화면이 표시됩니다.

참고

참고 문서: WordPress 공식 설치 가이드 · Apache HTTP Server 2.4 공식 문서

아파치 https 구성

개요

Apache에서 HTTPS 구성을 위해 mod_ssl 모듈을 설치하고 OpenSSL로 Self-Signed 인증서를 생성한 후, ssl.conf와 httpd.conf에 적용하는 방법을 정리합니다. 실제 서비스에서는 공인 CA(Let’s Encrypt 등)의 인증서 사용을 권장하지만, 내부망이나 테스트 환경에서는 Self-Signed 인증서로 HTTPS를 빠르게 구성할 수 있습니다.

※ CentOS 6.x 기준으로 작성된 내용입니다. 아파치를 컴파일로 설치했을 경우 mod_ssl도 다시 컴파일로 설치를 진행해야 합니다.

HTTPS 구성 원리

HTTPS는 HTTP 통신을 TLS(Transport Layer Security)로 암호화하는 프로토콜입니다. 서버는 인증서(.crt)와 개인키(.key)를 보유하며, 클라이언트가 접속하면 TLS 핸드셰이크를 통해 인증서를 교환하고 세션 키를 협상합니다. Self-Signed 인증서는 서버 자신이 서명하므로 브라우저 신뢰 저장소에 없어 경고가 뜨지만, 내부망 서비스 암호화에는 충분합니다.

Apache에서 HTTPS를 구성하려면 mod_ssl 모듈이 필요합니다. CentOS/RHEL에서는 yum으로 설치하며, 컴파일 설치 방식의 Apache라면 --enable-ssl 옵션을 포함해 재컴파일해야 합니다. 설치 후 /etc/httpd/conf.d/ssl.conf 파일이 생성되며 이 파일에서 인증서 경로와 TLS 버전을 제어합니다.

mod_ssl, openssl 설치

mod_ssl과 openssl이 설치되어 있지 않다면 yum으로 설치합니다.

# 설치 여부 확인
# rpm -qa | grep -E "mod_ssl|openssl"

# yum install mod_ssl openssl -y

Self-Signed 인증서 생성

OpenSSL 명령으로 개인키(ca.key), CSR(ca.csr), Self-Signed 인증서(ca.crt)를 순서대로 생성한 후 Apache가 참조하는 경로에 복사합니다.

# 개인키 생성
# openssl genrsa -out ca.key 1024

# CSR(Certificate Signing Request) 생성
# openssl req -new -key ca.key -out ca.csr
# 국가/주(도)/시/사명//도메인(hostname)/// 영문으로 각 항목 입력

# Self-Signed 인증서 생성 (유효기간 10년)
# openssl x509 -req -days 3650 -in ca.csr -signkey ca.key -out ca.crt

# 생성 키 복사
# cp ca.crt /etc/pki/tls/certs/
# cp ca.key /etc/pki/tls/private/ca.key
# cp ca.csr /etc/pki/tls/private/ca.csr

# SELinux 활성화 환경에서 컨텍스트 복구 필요 시
# restorecon -RvF /etc/pki

ssl.conf 설정

/etc/httpd/conf.d/ssl.conf에서 인증서 파일 경로를 생성한 파일 경로로 수정합니다.

# /etc/httpd/conf.d/ssl.conf 수정 — 경로 및 파일명 수정
SSLCertificateFile /etc/pki/tls/certs/ca.crt
SSLCertificateKeyFile /etc/pki/tls/private/ca.key

httpd.conf 설정

HTTPS VirtualHost를 추가하고 HTTP 요청을 HTTPS로 리다이렉트하는 rewrite 규칙을 설정합니다. Apache 2.4에서는 NameVirtualHost 지시자가 불필요합니다.

# /etc/httpd/conf/httpd.conf에 추가
# NameVirtualHost *:443  <-- Apache 2.4에서는 삭제
<VirtualHost *:443>
  SSLEngine on
  SSLCertificateFile /etc/pki/tls/certs/ca.crt
  SSLCertificateKeyFile /etc/pki/tls/private/ca.key
  ServerAdmin admin@<domain>
  DocumentRoot /var/www/html
  ServerName <domain>
  ErrorLog logs/ssl_error_log
  CustomLog logs/ssl_access_log common
</VirtualHost>

# HTTP → HTTPS 리다이렉트 (mod_rewrite 활성화 필요)
<VirtualHost *:80>
  RewriteEngine On
  RewriteCond %{HTTPS} !=on
  RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L]
</VirtualHost>

서비스 재시작 및 확인

Apache를 재시작한 후 80/443 포트 리슨 상태를 확인하고, 브라우저에서 HTTP 접속 시 HTTPS로 리다이렉션되는지 확인합니다.

# CentOS 6.x
# service httpd restart

# CentOS 7.x
# systemctl restart httpd

# 80, 443 포트 리슨 확인
# netstat -ntlp

# 브라우저에서 http://<서버IP> 접속 후 https로 리다이렉션 여부 확인

Self-Signed 인증서 한계와 공인 인증서 전환

Self-Signed 인증서는 브라우저에서 “신뢰할 수 없는 인증서” 경고를 표시합니다. 사용자가 직접 예외를 추가해야 하며, 모바일 브라우저나 API 클라이언트에서는 연결 자체가 거부되기도 합니다. 외부 사용자가 접근하는 서비스라면 Let’s Encrypt 등 공인 CA에서 무료 인증서를 발급받아 적용하는 것이 권장됩니다.

현재 적용된 인증서 유효기간과 발급자는 OpenSSL 명령으로 확인합니다.

# 도메인 인증서 정보 확인 (원격)
openssl s_client -connect <domain>:443 < /dev/null 2>/dev/null | openssl x509 -noout -dates -subject

# 파일로 인증서 정보 확인
openssl x509 -in /etc/pki/tls/certs/ca.crt -noout -dates -subject

인증서 갱신 시에는 새 인증서와 키 파일을 기존 경로에 덮어쓴 뒤 systemctl reload httpd로 중단 없이 새 인증서를 반영할 수 있습니다. restart와 달리 reload는 Apache를 재시작하지 않고 설정만 다시 읽으므로 기존 연결을 끊지 않습니다.

참고

참고 문서: Apache SSL/TLS How-To 공식 문서 · OpenSSL req 명령어 문서