[여기보기] WAS의 정보는 개인정보 다루듯이 보호하라

🧐 | 2023-07-06

[여기보기]는 “여기서 보안의 기본을 챙기고 가자”의 약자로, 개발 과정에서 꼭 최소한으로 챙기면 좋을 보안 기초 설정을 앞으로 하나씩 공유할 예정입니다. 기초 내용이 주를 이루겠지만, 혹시라도 빼먹고 계신 것이 없는지 가끔 한 번씩 둘러봐 주세요.

안녕하세요, 넷마블 보안실 보안개발팀 이대성입니다.

내 개인정보가 유출되었을 때 기분이 좋은 분은 없을 것입니다. 일단 피해가 없어도 괜히 기분 나쁜 건 기본이고, 실제 어딘가에 도용되어 금전적 피해를 받을 수도 있고, 갑자기 걸려오는 스팸 메일, 문자, 전화 등으로 정신적인 피해를 받을 수도 있습니다. 어쨌든 유출되면 안 되는 정보기 때문에 개인정보보호법이라는 법률로 보호하며, 위반 사례에 처벌도 가합니다.

WAS의 정보도 보안 입장에서는 개인정보와 같은 개념입니다. WAS 종류, 버전, 서버 운영체제 정보 등은 기본 설정 그대로를 사용하면 은연 중에 노출됩니다. 그리고 해당 정보를 공격자가 알게 되면 알려진 취약점을 이용해 WAS에 문제를 일으키기 쉽습니다. 그래서 WAS의 주요 정보를 보호하는 방법을 아는 일은 보안 담당자에게는 필수입니다.

이 글에서는 불필요한 파일 제거하기, 웹 서비스의 응답 헤더 수정하기, HTTP 상태 코드 페이지 바꾸기 등으로 WAS의 정보가 담긴 구성 요소들을 제어하는 방법을 소개합니다.

불필요한 파일 제거하기

WAS 안의 모든 파일이 WAS의 동작에 꼭 필요한 것은 아닙니다. WAS를 쉽게 운영할 수 있도록 돕는 예제 파일이나 템플릿, 매뉴얼 등의 파일이 함께 포함되기도 하죠. 그런데 실제 WAS를 운영할 때는 이런 파일들이 필요하지 않습니다. 서버의 상세 정보를 별도로 제공하는 조치를 완료했다면, 예제 프로그램 취약점 공격 등을 예방하도록 WAS의 기능과 직접적인 연관이 없는 불필요한 파일을 삭제하는 것이 좋습니다.

조치 방안

WAS를 설치할 때 기본으로 제공하는 샘플 디렉터리, 웹 개발 등에서 참고할 수 있는 개발 참고 문서 등을 삭제합니다.

IIS 5.0~6.0

IIS 5.0과 6.0에서는 IIS에서 기본으로 제공하는 예제 파일, 도움말, 데이터 접근, 관리자 비밀번호 변경 페이지가 있는 디렉터리를 삭제하기 바랍니다. 목록은 다음과 같습니다.

  • C:\Inetpub\iissamples (IIS 예제 파일)
  • C:\winnt\help\iishelp 혹은 C:\WINDOWS\Help\iisHelp (IIS 도움말)
  • C:\Program Files\Common Files\System\msadc\sample (데이터 접근)
  • %SystemRoot%\System32\inetsrv\iisadmpwd (관리자 비밀번호 변경 페이지)

참고로 IIS 7.0 이상은 지금 소개하는 디렉터리가 존재하지 않습니다. 해당 작업을 진행하지 않아도 괜찮습니다.

아파치 HTTP 서버

아파치 HTTP 서버 매뉴얼에 해당하는 디렉터리를 삭제하기 바랍니다. 목록은 다음과 같습니다.

  • [Apache Dir]/manual 혹은 [Apache Dir]/htdocs/manual (아파치 HTTP 서버 메뉴얼)

참고로 앞 디렉터리는 아파치 HTTP 서버를 컴파일 설치했을 때만 존재합니다. 패키지로 설치했을 때는 해당 작업을 진행하지 않아도 괜찮습니다.

톰캣

예제 파일, 호스트 관리자, 관리자, 톰캣 매뉴얼와 관련된 디렉터리를 삭제하기 바랍니다. 목록은 다음과 같습니다.

  • [Tomcat Dir]/webapps/examples (예제 파일)
  • [Tomcat Dir]/webapps/host-manager (호스트 관리자)
  • [Tomcat Dir]/webapps/manager (관리자)
  • [Tomcat Dir]/webapps/docs (톰캣 매뉴얼)

참고로 앞 디렉터리는 톰캣을 컴파일 설치했을 때만 존재합니다. 패키지로 설치했을 때는 해당 작업을 진행하지 않아도 괜찮습니다.

NGINX는 예제 파일이나 도움말 디렉터리를 제공하지 않습니다.

HTTP 응답 헤더에서 WAS 정보 숨기기

HTTP 응답 헤더는 부가적인 정보를 전달하는 HTTP 헤더의 필드 중 하나입니다. 여기에는 보통 서버 정보, 콘텐츠 타입 등이 포함됩니다. 그런데 HTTP 응답 헤더의 서버 정보에서 WAS의 버전 정보, 종류, 운영체제 등의 정보가 노출되면 시스템의 취약점을 수집할 수 있으므로 서버의 정보를 숨겨야 합니다.

조치 방안

WAS의 HTTP 응답 헤더 설정을 수정합니다.

WAS의 HTTP 응답 헤더 정보는 curl -I <URL:포트번호> 명령으로 확인할 수 있습니다.

IIS 7.0 이상

IIS라면 HTTP 응답 헤더 중 Server 항목의 정보를 숨김 처리할 수 있습니다.

먼저 URL 재작성 모듈을 설치해야 합니다. 마이크로소프트에서 제공하는 URL Rewrite를 참고해서 설치해 주세요. 설치가 완료되면 IIS 관리자에서 ‘URL 재작성’ 기능이 추가되었는지 확인합니다.

이제 ‘URL 재작성’을 실행한 후 오른쪽 위에 있는 [규칙 추가]를 선택합니다. 그리고 [아웃바운드 규칙] → [빈 규칙]을 선택한 후 [확인]을 누릅니다.

다음으로 아웃바운드 규칙 편집에서 다음 사항을 수정한 후 오른쪽의 [적용]을 누릅니다. 그리고 [규칙으로 돌아가기]를 누릅니다.

  • 이름: Removingserverheader
  • 일치 – 검색 범위: 서버 변수
  • 일치 – 변수 이름: RESPONSE_SERVER
  • 일치 – 변수 값: 패턴과 일치
  • 일치 – 패턴: .*
  • 작업 – 작업 속성 – 값: 0
  • 작업 – 작업 속성 기존 서버 변수 값 바꾸기: 체크

다음 XML 코드를 참고해 사이트별 디렉터리에 있는 web.config 파일을 수정해도 같은 설정이 적용됩니다.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <directoryBrowse enabled="false" />
        <!-- 추가 부분 시작 -->
        <rewrite>
            <outboundRules>
                <rule name="Removingserverheader" enabled="ture">
                    <match serverVariable="RESPONSE_SERVER" pattern=".*" />
                    <action type="Rewrite" value="0" />
                </rule>
            </outboundRules>
        </rewrite>
        <!-- 추가 부분 끝 -->
    </system.webServer>
</configuration>

이제 다시 ‘URL 재작성’을 확인하면 Removingserverheader라는 규칙이 추가된 것을 알 수 있습니다.

IIS를 다시 시작한 후 그리고 웹 브라우저의 개발자 도구 [네트워크]에서 [이름] 부분의 도메인을 선택하면 응답 헤더 부분의 정보를 확인할 수 있습니다.

# 적용 전
HTTP/1.1 304 Not Modified
Server: Microsoft-IIS/10.0

# 적용 후
HTTP/1.1 304 Not Modified
Server: 0

URL 재작성 규칙 적용 전에는 Server 항목에 정보가 있지만 URL 재작성 규칙 적용 후에는 Server 항목에 정보가 없는 것을 확인할 수 있습니다.

아파치 HTTP 서버

아파치 HTTP 서버는 패키지 설치일 때는 /etc/apache2/conf-enabled/security.conf의 ServerTokens 값을 Prod, ServerSignature 값을 Off로 설정하면 됩니다.

ServerTokens Prod
ServerSignature Off

컴파일 설치일 때는 먼저 [Apache Dir]/conf/extra/httpd-default.conf에서 ServerTokens 값을 Prod, ServerSignature 값을 Off로 설정합니다. 그리고 [Apache Dir]/conf/httpd.conf 중 다음 설정 부분의 주석을 해제해서 httpd-default.conf의 설정을 불러오도록 바꿉니다.

# Various default settings
# 주석을 해제해 설정 적용
Include conf/extra/httpd-default.conf

아파치 HTTP 서버를 재시작한 후 응답 요청을 확인하면 Server 항목이 Apache/2.4.52 (Ubuntu)에서 Apache로 바뀌는 것을 알 수 있습니다.

# 적용 전
HTTP/1.1 200 OK
Server: Apache/2.4.52 (Ubuntu)

# 적용 후
HTTP/1.1 200 OK
Server: Apache

톰캣

[Tomcat Dir]/server.conf 혹은 [Tomcat Dir]/conf/server.xml을 열고 server 항목에 서버 정보를 나타내는 설정 값이 있다면 Unknown Server로 바꿔줍니다.

<Connector port="8080" protocol="HTTP/1.1" 
           connectionTimeout="20000"
           redirectPort="8443"
           server="Unknown Server" />

톰켓을 다시 재시작한 후 응답 요청을 확인하면 Server 항목의 값이 Unknown Server으로 출력되는 것을 알 수 있습니다.

# 적용 전
HTTP/1.1 200
Server: Apache Tomcat

# 적용 후
HTTP/1.1 200
Server: Unknown Server

NGINX

[NGINX Dir]/nginx.conf 혹은 [NGINX Dir]/conf/nginx.conf에 server_tokens off;라는 설정을 추가해 WAS의 정보를 숨길 수 있습니다.

server_tokens off;

해당 설정은 http, server, location, if in location, limit_except 지시자에 적용할 수 있습니다.

NGINX를 재시작한 후 응답 요청을 확인하면 Server 항목이 nginx/1.18.0 (Ubuntu)에서 nginx로 바뀌는 것을 알 수 있습니다.

# 적용 전
HTTP/1.1 200 OK
Server: nginx/1.18.0 (Ubuntu)

# 적용 후
HTTP/1.1 200 OK
Server: nginx

스프링 부트

application.properties 혹은 application.yml 파일에 server.server-header 관련 설정이 있다면 이를 삭제하거나 혹은 UNKNOWN_SERVER 등으로 바꿔줍니다.

# application.properties
server.server-header=UNKNOWN_SERVER

# application.yml
server:
    port: 8080
    server-header: UNKNOWN_SERVER

스프링 부트 프로젝트를 다시 빌드한 후 HTTP 응답 헤더를 확인하면 Server 항목의 값이 UNKNOWN_SERVER로 바뀝니다.

HTTP/1.1 200
Server: UNKNOWN_SERVER

Node.js

Node.js라면 app.js 혹은 index.js 파일에 app.disable('x-powered-by'); 설정을 추가해 WAS 정보를 숨길 수 있습니다.

app.disable('x-powered-by');

Node.js 프로젝트를 다시 시작한 후 HTTP 응답 헤더를 확인하면 X-Powered-By 항목이 없어지는 것을 알 수 있습니다.

# 적용 전
HTTP/1.1 200 OK
X-Powered-By: Express

# 적용 후
HTTP/1.1 200 OK

HTTP 상태 코드 메시지 관리하기

WAS가 제공하는 HTTP 상태 코드 메시지의 기본 페이지에는 WAS의 종류, 버전 정보, 시스템의 정보 등이 포함될 때가 있습니다. 그럼 공격자가 시스템의 정보를 획득하려고 다양한 에러를 유발한 후 에러 메시지에서 시스템 정보를 얻을 수도 있습니다.

조치 방안

기본으로 제공되는 HTTP 상태 코드 메시지 페이지를 WAS 정보가 담겨 있지 않은 새로운 페이지로 바꿉니다. 여기에서는 상태 코드 400, 401, 403, 404, 500, 502를 다룬다고 가정하겠습니다.

IIS

IIS를 실행한 후 왼쪽 [연결]에서 상태 코드 메시지 페이지를 바꿀 사이트를 선택한 후 [오류 페이지]를 실행합니다. 새로운 상태 코드를 추가할 때는 오른쪽 위의 [추가]를 선택하고 기존 상태 코드를 수정할 때는 해당 상태 코드를 선택한 후 [편집]을 사용합니다. [응답 작업]에서 원하는 형태로 직접 수정한 상태 코드 페이지를 지정합니다.

혹은 웹 서비스 루트 디렉터리에 포함된 web.config의 설정을 다음처럼 수정해 HTTP 상태 코드 메시지 페이지를 바꿀 수 있습니다.

<configuration>
    <system.webServer>
        <httpErrors errorMode="Custom" existingResponse="Replace">
            <!-- 404 상태 코드 페이지 설정 -->
            <remove statusCode="404" subStatusCode="-1" />
            <error statusCode="404" prefixLanguageFilePath="" path="/error/404.html" responseMode="ExecuteURL" />
            <!-- <httpErrors> 사이에 이전이나 이후에 앞 코드와 같은 방식으로 다른 상태 코드 페이지 설정 가능 -->
        </httpErrors>
    </system.webServer>
</configuration>

아파치 HTTP 서버

패키지 설치라면 [Apache Dir]/conf-available/localized-error-pages.conf의 <IfModule mod_alias.c> 아래 부분, 컴파일 설치라면 [Apache Dir]/conf/extra/httpd-multilang-errordoc.conf를 열고 다음 설정을 수정 혹은 추가합니다.

ErrorDocument 400 <경로명/파일명>
ErrorDocument 401 <경로명/파일명>
ErrorDocument 403 <경로명/파일명>
ErrorDocument 404 <경로명/파일명>
ErrorDocument 500 <경로명/파일명>
ErrorDocument 502 <경로명/파일명>

컴파일 설치라면 [Apache Dir]/conf/httpd.conf 중 다음 설정 부분의 주석을 해제해서 httpd-multilang-errordoc.conf의 설정을 불러오도록 바꿉니다.

# 적용 후
# Multi-language error messages
Include conf/extra/httpd-multilang-errordoc.conf

톰캣

[Tomcat Dir]/conf/web.xml의 <web-app> 안에 다음처럼 <error-page>, <error-code>, <location> 설정을 추가합니다.

<error-page>
    <error-code>400</error-code>
    <location>/error/400.html</location>
    <error-code>404</error-code>
    <location>/error/404.html</location>
    <!-- 이후에 필요한 HTTP 상태 코드 설정 추가 가능 -->
</error-page>

NGINX

패키지 설치라면 [NGINX Dir]/sites-available/default의 server 구문 안, 컴파일 설치라면 [NGINX Dir]/nginx.conf의 http 구문 안에 다음 설정을 수정 혹은 추가합니다.

# 상태 코드별 일대일 설정
error_page 400 /error/400.html;
error_page 401 /error/401.html;
# 이후 생략

# 40x 상태 코드별 다대일 설정
error_page 400 401 403 404 /error/40x.html;
location /error/40x.html {
    root /var/www/html/error/;
}

error_page 500 502 /error/50x.html;
location /error/50x.html {
    root /var/www/html/error/;
}

스프링 부트

스프링 부트는 기본적으로 /error 경로에 대한 매핑을 제공합니다. 따라서 스프링 프로젝트의 src/main/resources/error에 상태 코드별로 html 파일(예: 404.html)을 작성하면 별도의 HTTP 상태 코드 페이지를 사용할 수 있습니다. 더 자세한 사항은 스프링 부트 개발 문서에서 제공하는 Custom Error Pages도 함께 참고하기 바랍니다.

Node.js

Express 프레임워크 기반으로 별도로 HTTP 상태 코드 메시지 페이지를 설정한다면 다음 코드를 참고하기 바랍니다.

const express = require('express');
const app = express();

// 404 상태 코드 메시지 페이지
app.use((req, res, next) => {
    res.status(404).sendFile(__dirname + '/error/404.html');
});

// 500 상태 코드 메시지 페이지
app.use((err, req, res, next) => {
    res.status(500).sendFile(__dirname + '/error/500.html');
});

app.listen(3000);

이젠 셸 스크립트 작성도 고려해보면 어떨까요?

WAS의 매뉴얼이나 샘플 파일은 사실 패키지 관리 도구 사용이 일상화된 요즘 상황이라면 그 존재 자체를 기억하지 못할수도 있습니다. 하지만 서비스 환경에 따라 아직 컴파일 설치를 해야 하는 때도 있고, 패키지 설치라도 특정 버전을 사용해야 할 때도 있습니다. 따라서 보안 관리 체크 리스트에 두고 한 번쯤 확인하면 좋은 사항으로 생각합니다.

HTTP의 응답 헤더는 이 글에서 다룬 내용 중 WAS 정보를 가장 잘 노출하는 대상입니다. 특히 아파치 HTTP 서버라면 단순한 WAS 정보뿐만 아니라 서버의 운영체제 정보, 서버 사이드 스크립트 언어 종류까지 노출되는 경우도 있습니다. 특히 아파치 HTTP 서버를 사용한다면 이 글에서 소개한 HTTP 응답 헤더에서 WAS 정보 숨기기는 꼭 참고하기 바랍니다.

마지막에 소개한 HTTP 상태 코드 페이지는 사실 꼭 WAS의 정보 노출이 아니라도 사용자에게 웹 사이트의 상태를 더 친절하게 알려주는 페이지로 바꾸는 데 사용하는 방법이기도 합니다. 예를 들어 404 상태 코드 페이지는 사용자가 요청한 페이지가 존재하지 않는다는 메시지를 담을 수 있고, 500 상태 코드 페이지는 서버에서 오류가 발생했다는 메시지를 담은 페이지로 바꿀 수 있습니다. 이렇게 HTTP 상태 코드 페이지를 바꾸면 사용자가 더욱 친숙한 페이지를 보게 되어 사용성이 향상되므로 자주 이용하는 방법입니다.

지금까지 보안개발팀에서 약 1년 간 여러 가지 [여기보기]를 소개한 것 같습니다. 이번 글을 마무리하면서 지금까지 소개한 여기보기 글 중 셸 스크립트를 작성해 처리할 수 있는 사항을 한 번 모아보는 것은 어떨까하는 생각이 듭니다. 좀 더 효율적으로 일하는 방법을 찾는 것도 보안 개발자의 일이니까요.