가. 웹 서버 프로세스를 위한 계정
Apache와 관련된 사용자 계정은 크게 두 가지가 있다.
● Apache 서버가 설치 및 구동을 위한 계정 - 운영체제에 로그인하여 Apache를 설치하고, 웹서버를 시작/종료 시키는 계정
※ 웹 서비스를 위한 포트로 1024번 미만 포트번호(80 번 포함)를 사용하기 위해서는 이 계정이 root이어야 한다.
● 웹 서버 프로세스를 위한 계정 - 웹 서버 데몬이 시작된 후 일반사용자의 웹 접속을 처리하기 하기 위하여 생성되는 프로세스가 사용하는 계정
“웹서버 프로세스 계정”의 경우 반드시 로그인할 수 없는 계정 즉, 쉘(shell)이 없는 계정으로 설정하여야 한다. 일반적으로는 사용자 ID와 그룹으로 쉘이 없는“nobody”계정을 사용한다. 아래 그림처럼 /etc/passwd파일과 /etc/shadow파일의 nobody 계정에 대하여 맨 마지막에 /bin/sh, /bin/csh등 shell을 명시하는 부분이 제외되어 있음을 확인 할 수 있다.
nobody:x:99:99:Nobody:/: nobody:*:11900:0:99999:7::: |
또한, 이러한 계정(쉘이 없는계정, 아래 예에서는“nobody”)이 실제 웹 서비스에 적용되려면 아파치 설정파일(httpd.conf)에서“User”,“ Group”지시자(directive)가 아래와 같이 설정되어야 한다.
User nobody Group nobody |
나. 웹 서버 DocumentRoot의 설정
웹 서버 DocumentRoot는 모든 웹 컨텐트가 저장될 디렉토리 구조이며 이 디렉토리에 위치된 컨텐츠는 웹을 통하여 공개된다. 따라서 가능하면 이 디렉토리는 시스템의 루트 파일시스템 등과는 별도의 파일시스템을 사용해야 한다.
Apache 기본 설치시에는 htdocs 디렉토리를 DocumentRoot로 사용하고 있는데 이를 바꾸도록 한다. htdocs 디렉토리에는 공개될 필요가 없거나 공격에 악용될 수 있는 시스템 관련 정보가 담긴 파일이 기본적으로 설치 될 수 있다.
“/usr/local/www”를 DocumentRoot로 지정하고자 할 경우 httpd.conf 파일에서 다음과 같이 할 수 있다.
#DocumentRoot“ /usr/local/apache/htdocs” DocumentRoot“ /usr/local/www” |
웹 서버 데몬은 chroot에 설치하는 것을 권고한다. 만약 웹서버 데몬이 공격당했다고 하더라도 공격자는 chroot 디렉토리로 정해놓은 디렉토리 이외로는 접근할 수 없어 피해를 최소화할 수 있다.
다. 불필요한 CGI 스크립트 제거
Apache 배포판에는 불필요한 CGI 스크립트들이 포함되어 있어 공격에 이용될 수 있다. Apache
설치시 기본적으로 cgi-bin 디렉토리에 설치되는 모든 CGI 스크립트들은 제거하는 것이 안전
하다.
라. Apache 환경파일(httpd.conf)의 설정
● 디렉토리 리스팅 방지
- 웹 브라우저에서 사용자가 URL을 입력했을 경우, 웹 컨텐츠가 없을 경우 기본적으로 디렉토리 리스트를 보여주는 것을 방지해야 한다.
- DocumentRoot 디렉토리 내의 모든 파일들이 리스팅되는 것을 방지하기 위해서는 환경설정화일(httpd.conf)“ Options”지시자에서“Indexes”옵션을 제거한다.
● 심블릭 링크의 사용 방지
- 웹 서버에서 심블릭 링크를 이용해서 기존의 웹 문서 이외의 파일시스템에 접근하는 것이 가능하나 심각한 보안 문제를 야기시킬 수 있다. 가령 시스템 자체의 root 디렉토리(/)를 링크 걸게 되면 웹서버 구동 사용자 권한(nobody)으로 모든 파일시스템의 파일에 접근할 수 있게 된다.(예를 들면 /etc/passwd을 공개하게 될 수도 있다.)
- 이를 방지하기 위해서는“Options”지시자에서 심블릭 링크를 가능하게 하는 옵션인 “FollowSymLinks”를 제거함으로써 이를 막을 수 있다.
● SSI(Server Side Includes) 사용 제한
- SSI는 HTML 페이지 안에 위치하고 있으며, 동적인 웹 페이지를 제공할 수 있도록 한다. 하지만 SSI가 포함된 파일은“exec cmd”를 사용해서 어떤 CGI 스크립트나 프로그램들을 Apache가 구동하는 사용자와 그룹 권한으로 실행시킬 수 있다.
- 이 SSI 페이지가 스크립트나 프로그램을 실행시킬 수 없도록 하기 위해서는“Options”지시자에“IncludesNoExec”옵션을 추가함으로써 차단할 수 있다.
● CGI 실행디렉토리 제한
- 사용자들이 CGI 스크립트들을 어느 디렉토리에서나 실행할 수 있도록 할 경우 악의적인 사용자가 CGI 프로그램을 업로드한 후 이를 실행하여 임의의 명령을 실행시킬 수 있다.
- 따라서, CGI 프로그램의 실행은 관리자가 지정한 특정 디렉토리에서만 가능하도록 제한할 필요가 있다. CGI 실행은“ScriptsAlias”지시자에 의해서 실행가능한 디렉토리를 제한할 수 있다.“ ScriptsAlias”지시자 문법은 다음과 같다.
정의방법: ScriptAlias URL-path file-path | directory-path |
예를들어 cgi-bin이라는 디렉토리에서만 CGI프로그램을 실행가능하도록 할 경우 다음과 같이 지정할 수 있다.
ScriptAlias /cgi-bin/“ /usr/local/apache/cgi-bin/” |
앞서 언급한 디렉토리 리스팅, 심블릭 링크, SSI 등에 대한 제어는“Options”지시자에 의해 제어가 가능하다.
정의방법: Options [+|-]option [[+|-]option] ... |
“Options”지시자에서 사용할 수 있는 옵션값은 다음 표와 같다.
옵션값 | 설명 |
All | MultiViews를 제외한 모든 옵션을 줌(default 설정값임) |
None | 옵션을 주지 않음 |
ExecCGI | CGI 프로그램 실행을 가능하게 함 |
FollowSymLinks | 심볼릭 링크로의 이동을 가능하게 함 |
Includes | Server Side Includes를 가능하게 함 |
IncludesNOEXEC | Server-side includes는 가능하지만 CGI 스크립트나 프로그램들은 실행할 수 없도록 함. |
Indexes | 해당 디렉토리 안에 DirectoryIndex에 명기된 파일(index.html 등)이 없을 경우 디렉토리와 파일 목록을 보여줌 |
MultiViews | 유사한 파일이름을 찾아 주는 기능을 실행함(예를들어 index라고만 입력하더라도 index.*를 찾아 보여줌) |
SymLinksIfOwnerMatch | The server will only follow symbolic links for which the target file or directory is owned by the same user id as the link. |
● httpd.conf 설정 예시
- DocumentRoot 디렉토리가 다음과 같이 설정되어 있다고 하자.
<directory“ www”="" local="" usr=""> Options Indexes FollowSymLinks </directory“> |
- 이 경우 다음 그림과 같이 DirectoryIndex에 정의된 초기 파일(index.html) 이 존재하지 않을 경우 디렉토리내의 파일목록을 리스트업 해 준다.
또한, FollowSymLinks로 인해 루트 디렉토리(/)에 심블릭 링크된 system.html 파일(ln -s / system.html)을 열었을 경우 DocumentRoot 디렉토리 상위의 passwd 파일까지 열람이 가능함을 알 수 있다.
<directory“ www”="" local="" usr=""> Options IncludesNoExec </directory“> |
이 경우 초기 파일(index.html)이 존재하지 않을 경우 디렉토리 리스트를 보여 주는 것이 아니라 오류 창을 띄워주는 것을 확인할 수 있다.
● 웹 서버 응답 메시지 헤더 정보 숨기기
- 웹서버 해더 정보란 다음과 같이 클라이언트가 Apache 웹서버에 접속했을 때 웹서버에서는 응답 메시지의 헤더를 말한다.
[root@hcjung conf]# telnet xxx.xxx.xxx.xxx 80 Trying xxx.xxx.xxx.xxx... Connected to xxx.xxx.xxx.xxx. Escape character is‘ ^]’. GET / HTTP/1.1 HTTP/1.1 400 Bad Request Date: Tue, 15 Oct 2002 11:25:10 GMT Server: Apache/1.3.19 (Unix) PHP/4.0.4pl1 |
- 이 정보는 공격자에 의해 Apache 웹서버 버전별 또는 구동되고 있는 응용프로그램에 잘 알려진 취약점을 공격하는데 유용하게 악용될 수 있으며, 인터넷 웜과 같은 자동화된 공격에서도 이러한 banner 정보가 사용되어지기도 한다. 따라서 공격자에게 웹서버의 버전과 같은 banner 정보를 숨기는 것이 안전하다.
- Apache 웹서버에서는“ServerTokens”지시자를 수정함으로써 헤더에 의해 전송되는 정보를 바꿀 수 있다.
정의방법: ServerTokens Minimal|ProductOnly|OS|Full |
- ServerTokens 지시자를 이용하여 설정할 수 있는 각 키워드와 표시되는 헤더 정보는 다음
과 같다.
키워드 | 제공하는 정보 | 예 |
Prod[uctOnly] | 웹서버 종류 | Server: Apache |
Min[imal] | Prod 키워드 제공 정보 + 웹서버 버전 | Server: Apache/1.3.0 |
OS | Min 키워드 제공 정보 + 운영체제 | Server: Apache/1.3.0 (Unix) |
Full | OS 키워드 제공 정보 + 설치된 모듈(응용프로그램) 정보 |
Server: Apache/1.3.0 (Unix) PHP/3.0 MyMod/1.2 |
- 공격자를 속이기 위해서 서버의 헤더 정보를 앞에서 명기한 내용과는 전혀 다른 내용으로 조작하여 클라이언트에 보낼 수도 있는데 이를 위해서는 Apache 소스코드를 수정한후 재컴파일하여야 한다.
마. 사용자 인증
(1). 사용자 인증의 종류
① 기본 사용자 인증(Basic Authentication)
● 기본 사용자 인증은 Apache에서 제공되는 htpasswd를 이용하여 사용자 계정을 생성하고 인증하는 방법이다.
● 패스워드가 암호화되어서 저장되지만 클라이언트에서 서버로 전송되는 도중에는 암호화되지 않아 전송 중 노출될 수 있다.
② 다이제스트 사용자 인증(Digest Authentication)
● 기본 사용자 인증과 마찬가지로 Apache에서 제공되는 htpasswd를 이용하여 사용자 계정을 생성하고 인증하는 방법이다.
● 기본 사용자 인증과의 차이점은 패스워드를 MD5 암호화 해쉬하여 전송하므로 전송중에도 비교적 안전하지만 인증에 사용되는 패스워드만 암호화되고 데이터는 평문으로 전송됨을 주지할 필요가 있다.
③ 어플리케이션에서의 인증(데이터베이스 등 로그인 정보유지)
● 어플리케이션에서의 인증은 Apache에서 제공되는 htpasswd 명령을 이용하지 않고 사용자 이름과 패스워드를 데이터베이스에 저장하고 이를 이용하여 인증하는 방법이다.
● 데이터베이스에 저장된 사용자 계정에 대한 정보는 기업의 보안정책에 따라 다르지만 일반 적으로, 암호화나 단방향 함수(해쉬)등을 적용하여 저장 하는 것이 안전하다. (내부자에 의한 정보유출 방지)
바. 기본 사용자 인증
● 기본 사용자 인증은 크게 다음과 같은 두가지 절차로 설정할 수 있다.
(1) 패스워드 파일 생성
- 아파치 설치시 제공되는 htpasswd 명령을 이용하여 패스워드 파일을 생성한다. htpasswd 파일의 사용법은 다음과 같다.
사용법: htpasswd [-cmdps] passwordfile username |
- 패스워드 파일을 최초로 생성할 경우에는 -c 옵션을 사용하여 새로운 패스워드 파일을 만든다.
[root@hcjung bin]# ./htpasswd -c /usr/local/apache/passwords hcjung New password: Re-type new password: Adding password for user hcjung |
- 이후, 새로운 사용자를 추가하고자 할 경우에는 -c 옵션을 빼고 사용하면 된다. 실수로 -c 옵션을 줄 경우 기존에 등록된 사용자들이 지워지므로 주의하여야 한다.
[root@hcjung bin]# ./htpasswd /usr/local/apache/passwords webmaster |
- 생성된 패스워드 파일은 가능한 안전한 장소에 보관하고 웹서버 자체가 읽을 수 있는 최소한의 권한만을 주어야만 한다. 만일 웹서버가 nobody 사용자와 nobody 그룹으로 구동된다면 다음과 같이 소유권과 접근권한을 줄 수 있다.
[root@hcjung bin]# chown root.nobody /usr/local/apache/passwords [root@hcjung bin]# chmod 640 /usr/local/apache/passwords |
(2) 패스워드 파일을 사용가능하도록 환경설정
- 패스워드 파일의 생성이 끝났으면 Apache 웹서버에게 이 파일을 사용할 수 있도록 설정하여 주어야 한다.
- 먼저 각 디렉토리별로 사용자 인증을 하기 위해서 httpd.conf 파일 내의 AllowOverride 지시자의 옵션을 None에서 AuthConfig 또는 All로 바꾼다.(사용자 인증만을 위해서는 AuthConfig 사용을 권고)
<directory“ www”="" local="" usr=""> AllowOverride AuthConfig </directory“> |
그리고, 사용자 인증이 필요한 디렉토리에 다음의 지시자들이 포함된 .htaccess 파일을 생성 한다.
옵션값 | 설명 |
AuthType | 인증 형태(Basic 또는 Digest) |
AuthName | 인증 영역(웹 브라우저의 인증창에 표시됨) |
AuthUserFile | 사용자 패스워드 파일의 위치 |
FollowSymLinks | 심볼릭 링크로의 이동을 가능하게 함 |
AuthGroupFile | 그룹 파일의 위치(옵션) |
Require | 접근을 허용할 사용자 또는 그룹 정의 ex) Require user userid [userid] ... Require group group-name [group-name] ... Require valid-user |
앞서 패스워드 파일에 등록된 hcjung와 webmaste만이 웹서버에 접속 할 수 있도록 하기 위해서는 다음과 같이 설정할 수 있다.
[root@hcjung /root]# cd /usr/local/www [root@hcjung www]# vi .htaccess AuthType Basic AuthName“ Welcome HyunCheol’s Home” AuthUserFile /usr/local/apache/passwords Require user hcjung webmaste |
- 위에서 접근을 허용할 사용자를 hcjung와 webmaster로 한정을 했는데 패스워드 파일에 등록된 모든 사용자들이 접근할 수 있도록 하기 위해서는 사용자를 지정하는 대신“Require valid-user”라고 하면 된다.
- 정상적으로 사용자 인증 설정이 완료되었을 경우 웹 브라우져에서 웹서버 접속시 다음과 같은 사용자 이름과 암호를 묻는 인증창이 뜨게 된다.
- 사용자 이름과 암호가 정확하게 입력된 경우는 웹 페이지 접속이 가능하지만 정확하지 않을 경우 다음과 같은 경고창이 뜨고 접속을 허가하지 않는다.
사. SSL 인증서 또는 웹 암호화 솔루션의 적용
● 웹을 통하여 회원신상, 금융거래, 카드번호 등 데이터의 기밀성이 요구되는 데이터가 전송된다면 SSL을 적용하거나 기타 웹 암호화 제품의 적용을 고려하여야 한다.
● Apache에서는 mod-ssl을 이용하여 SSL 암호화를 적용할 수 있다.
● SSL의 적용은 기본적으로 OpenSSL을 이용한 Apache용 SSL모듈(apache/mod-ssl)을 이용하여 생성한 자체 SSL 인증서를 이용할 수도 있고, 유료로 제공되는 SSL인증서를 이용할 수 도 있다.
● 자체 SSL인증서와 유료 인증서 방식의 차이점은 접속하는 사용자 관점에서 해당 사이트가 정말로 그 사용자가 믿고(알고)있는 웹 사이트인지 여부에 대하여 제3자(인증기관)이 보증해 주느냐 안해주느냐의 차이다. 데이터에 이용되는 암호화 수준은 알고리즘과 키길이와 관련되므로 별개의 문제이다.
아. 보안 패치
● Apache설치후 버전별로 발견된 취약점은 ApacheWeek (http://www.apacheweek.com/security/) 에서 확인할 수 있다.
● 가능한 주기적으로 보안 패치정보를 확인후 조치하여야 한다. Apache 웹서버 관련 취약점에 대한 패치는 http://www.apache.org/dist/httpd/patches/ 에서 다운받을 수 있다.
자. 설정파일 및 데이터 백업
● 초기 서버 설정 파일들과 이후의 기본적인 설정파일들은 일반에 공개되거나 다른 변화가 일어나기 전에 백업해서 보관되어져야 한다. 또한 시스템 설정이 변경될 때마다 이력관리가 필요하고 다수의 수정이 있을 경우에는 반드시 백업을 하도록 한다.
● 주요 백업 데이터는 다음과 같은 것이 있다.
- 아파치 각종 환경설정 파일
- 아파치 설치과정에 사용된 Install 파일(경우에 따라 Rebuild에 많은 시간을 단축할 수
있음)
- 사용자 프로그램 소스(PHP, JSP, CGI등)
- 웹서비스와 관계된 데이터 베이스 등
차. 로그 설정 및 분석
● 아파치는 두 개의 로그 파일을 사용하는데, 에러 로그와 액세스 로그이다. 에러 로그는 아파치 서버의 에러 정보를 기록하고, 액세스 로그는 아파치 서버가 처리하는 모든 요청에 대한 정보를 기록한다.
● 로그 파일의 위치는 httpd.conf 파일에서 지정한다.
# # ErrorLog : The location of th error log file # if you do not specify an ErrorLog directive within a # container, error messages relating to that virtual host will be # Logged herer. if you *do*define an error logfile for a #container, that host's errors will be logged therer and not here. # ErrorLog/var/log/httpd/error_log # # The location and format of the access logfile (Common Logfile Format). # If you do not define any access logfiles within a # container, they will be logged here. Contrariwise, if you *do* #define per-access logfiles, transactions will be # logged therein and *not*in this file. Custom Log/var/log/httpd/access_log common |
(1) 에러 로그
● 에러 로그 파일의 포맷은 비교적 자유로운 형식인데, 대부분의 경우 다음과 같은 정보가 포 함된다.
[Wed Oct 11 14:32:52 2000] [error] [client 127.0.0.1] client denied by server configuration:/ export/home/live/ap/htdocs/test |
① 메시지의 날짜와 시간
② 에러의 위험도
③ 에러를 발생시킨 클라이언트의 IP주소
④ 에러 메시지의 내용 (클라이언트가 요청한 문서를 파일 시스템 경로로 표현)
● 에러 로그 파일에 기록될 에러의 위험도 수준은 다음과 같이 httpd.conf파일에서 LogLevel 지시자를 이용하여 지정할 수 있다.
# # LogLevel:control the number of messages logged to the error_log # Possible values include: debug, info, notice, warn, error, crit. # alert, emerg. # LogLevel error |
(2) 엑세스 로그
● 액세스 로그는 서버가 처리하는 모든 요청에 대한 정보를 기록한다. 액세스 로그의 위치와 로그 포맷은 CustomLog 지시자를 통해 지정된다. LogFormat 지시자를 이용해서 다양한 로그 포맷을 만들어 놓고, 간단하게 선택하여 사용할 수 있다.
● 액세스 로그로 사용되는 공통적인 로그 포맷은 Common Log Format(CLF)과 Combined Log Format(CLF)이다.
가) Common Log Format(CLF): 많은 다른 웹 서버에서도 동일하게 생성되는 포맷이고, 많은 로그 분석 프로그램이 읽을 수 있는 포맷이다. httpd.conf 파일에서 다음과 같이 설정할 수 있다.
LogFormat "%h %1 %u %t \" %\" %>s %b" common CustomLog logs/access_log common |
● LogFormat 지시자는 하나의 포맷 스트링을 정의하고 common이라는 닉네임을 붙인다.
CustomLog 지시자는 로그가 저장될 파일의 위치와 이름, 그리고 저장될 로그의 포맷을 정 의한다.
● 이 포맷에 의해 생성된 로그는 다음과 같다.
172.16.5.100 - jun [ 08/Apr/2003:16:03:43 + 0900] "GET / php HTTP/1.1"301 |
① 클라이언트의 IP 주소(%h) HostnameLookups이 On으로 설정되어 있으면 IP주소 대신 호 스트네임을 찾아서 저장한다(이 설정으로 서버가 크게 느려질 수 있기 때문에 가능하면 사용 하지 않도록 한다).
② 클라이언트의 identity(%l) 클라이언트 컴퓨터의 identd에 의해 결정된 클라이언트 identity. IdentityCheck가 On으로 설정되어 있지 않으면 이 정보를 찾지 않는다(이 설정으로 서버가 느려질 수 있고, identity 정보도 신뢰하기 어렵기 때문에 가능하면 사용하지 않도 록 한다).
③ HTTP 인증을 받은 사용자의 ID(%u) 인증을 받지 못한 경우에(상태 코드가 401인 경우) 이값은 부정확하다. 또한 요청받은 문서가 인증을 요구하지 않는 경우에는 -로 표시된다.
④ 서버가 요청 처리를 끝낸 시간(%t) [일/월/년:시:분:초 지역]
⑤ 클라이언트의 요청 내용(\ %r\ ) 사용한 메소드, 요청한 자원, 사용한 프로토콜
⑥ 상태코드(%>s) 서버가 클라이언트에게 보낸 상태 코드. 2XX(성공), 3XX (redirection), 4XX(클라이언트에 의한 에러), 5XX(서버에 의한 에러). 상세한 상태 코드는 부록을 참고한다.
⑦ 클라이언트에게 전송된 컨텐츠의 크기 response header 부분은 포함되지 않는다. 클라이언트에게 전송된 컨텐츠가 없으면 이 값은 -로 표시된다.
나) 다음은 Combined Log Format :
● httpd.conf 파일에서 다음과 같이 설정할 수 있다.
LogFormat "%h %l %u %t \"%r\" %>s %b \"% i\" \"%i\"" combined CustomLog log/acces_log combined |
● 이 포맷은 두 개의 필드를 제외하면 Common Log Format과 동일하다. 추가된 필드는 퍼센트 지시자 %i를 사용하고 있는데, header는 HTTP request header 중 일부가 될 수 있다. 이 포맷에 의해 생성된 로그는 다음과 같다.
172.16.5.100 - jun [ 08/Apr/2003:16:03:43 + 0900] "GET / php HTTP/1.1"301 313 "-" "Mozilla/4.0 (compatible: MSIE 6.0: Windows NT 5,0)" |
① 클라이언트가 요청한 자원이 include되었거나 링크된 페이지(\ %I\) 위 예제에 서는 그러한 페이지가 없음
② 클라이언트 브라우저에 대한 정보(\ %I\)
다) 로그 설정시 유의사항
● 아파치는 대부분의 경우 root권한으로 로깅을 수행하는데, 시스템사용자는 아파치의 로그 파일을 다른 중요 시스템 파일에 대한 링크로 대체하여, root 권한으로 다른 중요 시스템 파일의 내용을 변경할 수 있다.
● 따라서, 일반사용자는 로그가 저장되는 디렉토리에 대해 쓰기 권한이 없도록 설정해야 한다.
● 또한 로그 파일에 클라이언트가 제공하는 데이터가 들어갈 경우 악의적인 클라이언트가 제어 문자 등을 로그 파일에 삽입하여 웹 서버를 침해할 수 있다. 특히 클라이언트가 웹 서비스를 통해서 아파치의 로그 파일을 볼 수 없도록 해야 한다.
ModSecurity를 이용한 아파치 웹서버 보안
o 요청(request) 필터링
- 클라이언트로부터 웹요청이 들어올 때 웹서버 또는 다른 모듈들이 처리하기 전에
ModSecurity가 요청 내용을 분석하여 사전에 필터링한다.
o 우회 방지 기술
- 경로와 파라미터를 분석하기 전에 정규화시켜 우회 공격을 차단한다.
- 즉, “//”, “\/”, “.”, “%00” 등 우회 공격용 스트링을 제거하고, 인코딩된 URL을 디코딩한다.
o HTTP 프로토콜 이해
- 엔진이 HTTP 프로토콜을 이해하기 때문에 아주 전문적이고 미세한 필터링을 수행할 수 있다.
o POST 페이로드(payload) 분석
- GET 방식 뿐만 아니라 POST 메소드를 사용해서 전송되는 컨텐츠도 가로채어 분석할 수 있다.
o 감사 로깅
- POST를 포함하여 모든 요청의 모든 상세한 부분들까지 추후 분석을 위해서 로깅될 수 있다.
- MosSecurity에서 차단기능을 비활성화시킨 후, 강력한 로깅 기능만으로 침입탐지 시스템 역할을
수행할 수 있도록 한다.
o HTTPS 필터링
- 엔진은 웹서버에 임베디드되어 있기 때문에 복호화 한 후에 요청 데이터에 접근하여 HTTPS
를 통한 공격도 필터링할 수 있다.
□ ModSecurity 설치 환경
먼저 본 고에서는 다음 환경에서 ModSecurity를 설치하여 테스트하였다.
o 플랫폼 : Linux 2.6.8-2-686-smp
o 웹서버 : Apache 2.2.0
o ModSecurity 소스코드 디렉토리 : /usr/local/modsecurity-apache-1.9.2
o 아파치 소스코드 디렉토리 : /usr/local/httpd-2.2.0
o 아파치 웹서버 홈 디렉토리 : /usr/local/apache2
□ ModSecurity 프로그램 다운로드
설치하고자 하는 안정화 버전인 1.9.2는 다음 사이트에서 다운로드 받을 수 있다.
http://www.modsecurity.org/download/modsecurity-apache-1.9.2.tar.gz
다운로드 받은 후 다음의 명령으로 압축 및 패키징을 해제한다.
# tar xvzf modsecurity-apache-1.9.2.tar.gz
# mv modsecurity-apache-1.9.2 /usr/local/
# cd modsecurity-apache-1.9.2
# ls -al
drwxr-xr-x 6 1000 1000 4096 2006-01-17 03:36 .
drwxrwsr-x 12 root staff 4096 2006-02-22 16:07 ..
drwxr-xr-x 2 1000 1000 4096 2006-01-17 03:36 apache1
drwxr-xr-x 2 1000 1000 4096 2006-01-17 03:36 apache2
-rw-r--r-- 1 1000 1000 26381 2006-01-16 21:31 CHANGES
drwxr-xr-x 3 1000 1000 4096 2006-01-17 03:37 doc
-rw-r--r-- 1 1000 1000 1811 2006-01-09 21:33 httpd.conf.example-minimal
-rw-r--r-- 1 1000 1000 881 2005-11-01 22:52 INSTALL
-rw-r--r-- 1 1000 1000 17989 2003-05-29 05:36 LICENSE
-rw-r--r-- 1 1000 1000 994 2006-01-09 23:45 README
drwxr-xr-x 2 1000 1000 4096 2006-01-17 03:36 util
total 84
▷ DSO 방식 설치
DSO 방식은 아파치 웹서버의 재설치 과정없이 기존에 운영되고 있는 아파치 웹서버에 모듈을
동적으로 추가하는 방식이므로 기존에 아파치 웹서버를 이미 운영 중인 기관의 경우 DSO 방식을
선택하는 것을 권장한다. DSO 방식으로 설치하는 것은 아파치 버전에 상관없이 다음과 같이 설치
할 수 있다.
① apxs를 이용하여 ModSecurity 모듈을 컴파일하고, 설치하고, 설정을 자동으로 변경한다.
# /usr/local/apache2/bin/apxs -cia /usr/local/modsecurity-apache-1.9.2/apache2/mod_security.c
위의 명령은 mod_security.c를 컴파일 하고(-c 옵션), 공유객체를 웹서버 modules 디렉토리에
설치하고(-i 옵션), 아파치 httpd.conf 설정파일에 적절한 LoadModule 줄을 추가(-a 옵션)한다.
참고로 apxs는 아파치 웹서버의 확장모듈을 컴파일하고 설치하는 도구로써, 여러 소스와 오브
젝트파일을 LoadModule 지시어로 실행 중인 아파치 서버로 읽어 들일 수 있는 동적공유객체
(DSO)를 만든다. 위의 결과로 modules 디렉토리에 mod_security.so가 생성되고 httpd.conf 파
일에 “LoadModule security_module modules/mod_security.so” 라인이 추가된다.
② 위의 과정으로 모듈이 정상적으로 설치되었는지 확인한다.
linux-web:/usr/local/apache2/bin# ./httpd -l
Compiled in modules:
core.c
...
mod_security.c
...
mod_so.c
③ 아파치 웹서버를 재구동한다.
# <apache-home>/bin/apachectl stop
# <apache-home>/bin/apachectl start
여기까지 ModSecurity의 모듈 설치가 끝났으나, 아직 룰(Rule)에 대한 정의를 하지 않았으므로
공격을 방어하지는 못한다. 이를 구동하기 위해서는 다음 장의 ModSecurity 활성화 및 Rule 정의를
위한 환경설정을 살펴보도록 하자.
▷ 소스 컴파일을 통한 설치
DSO 방식이 아닌 정적으로 소스 컴파일 될 경우에는 ModSecurity 모듈이 웹서버의 body에 포
함되게 된다. 이 방법은 DSO 방식에 비해 다소 실행 속도가 빠르지만, 아파치 웹서버를 다시 새
롭게 설치해야 하고 설치가 약간 복잡한 단점이 있다.
또한, 아파치 버전에 따라 설치를 위한 사전 설정을 달리 해 주어야 한다.
<아파치 1.x의 경우>
$ cd <apache1-source>
$ cp <modsecurity-source>/apache1/mod_security.c ./src/modules/extra
$ ./configure --activate-module=src/modules/extra/mod_security -–enable-module=security
<아파치 2.x의 경우>
$ cd <apache2-source>
$ cp <modsecurity-source>/apache2/mod_security.c ./modules/proxy
$ ./configure -enable-security --with-module=proxy:mod_security.c
아파치 1.x 또는 아파치 2.x에서 위의 과정을 거친 후에, 일반적인 아파치 컴파일과 설치 과정을
거치면 된다.
make
make install
/usr/local/apache2/bin/apachectl start
DSO 방식과는 달리 소스 컴파일을 통한 설치시에는 httpd.conf 파일에 아무런 내용이 추가되지 않는
다. DSO 방식과 마찬가지로 ModSecurity를 활성화시키기 위해서는 다음 장의 ModSecurity 활성화 및
Rule 정의를 위한 환경설정이 필요하다.
□ ModSecurity Rule 설정 예
##### Configuration #####
SecFilterEngine On
SecFilterScanPost On
SecFilterScanOutput Off
SecFilterOutputMimeTypes "(null) text/html text/plain"
##### Validation #####
SecFilterCheckURLEncoding On
SecUploadDir /tmp
SecUploadKeepFiles Off
SecFilterCheckUnicodeEncoding Off
SecFilterForceByteRange 1 255
SecFilterDefaultAction "log,deny,status:403"
##### Logging #####
SecFilterDebugLog logs/modsec_debug.log
SecFilterDebugLevel 1
SecAuditEngine RelevantOnly
SecAuditLog logs/modsec_audit.log
##### Hardening #####
# Body를 가진 GET 또는 HEAD 요청 차단(공격 가능성 높음)
SecFilterSelective REQUEST_METHOD "^(GET|HEAD)$" chain
SecFilterSelective HTTP_Content-Length "!^$"
SecFilterSelective SERVER_PROTOCOL "!^HTTP/(0\.9|1\.0|1\.1)$"
# Content-Length가 없는 POST 요청 차단
SecFilterSelective REQUEST_METHOD "^POST$" chain
SecFilterSelective HTTP_Content-Length "^$"
SecFilterSelective HTTP_Transfer-Encoding "!^$"
##### General #####
SecFilterSelective HTTP_Host|HTTP_User-Agent|HTTP_Accept "^$"
SecFilterSelective HTTP_User-Agent "(libwhisker|paros|wget|libwww|perl|curl|java)"
##### SQL Injection Attacks #####
##### (PHPmyAdmin 같은 DB 설정 프로그램 사용시 관련 설정 변경 해야 함) #####
SecFilterSignatureAction "log,deny,msg:'SQL Injection attack'"
SecFilterSelective ARGS "delete[[:space:]]+from"
SecFilterSelective ARGS "drop[[:space:]]+database"
SecFilterSelective ARGS "drop[[:space:]]+table"
SecFilterSelective ARGS "drop[[:space:]]+column"
SecFilterSelective ARGS "drop[[:space:]]+procedure"
SecFilterSelective ARGS "create[[:space:]]+table"
SecFilterSelective ARGS "update.+set.+="
SecFilterSelective ARGS "insert[[:space:]]+into.+values"
SecFilterSelective ARGS "select.+from"
SecFilterSelective ARGS "bulk[[:space:]]+insert"
SecFilterSelective ARGS "union.+select"
SecFilterSelective ARGS "or.+1[[:space:]]*=[[:space:]]1"
SecFilterSelective ARGS "alter[[:space:]]+table"
SecFilterSelective ARGS "or 1=1--'"
SecFilterSelective ARGS "'.+--"
SecFilterSelective ARGS "into[[:space:]]+outfile"
SecFilterSelective ARGS "load[[:space:]]+data
SecFilterSelective ARGS "/\*.+\*/"
##### XSS Attacks #####
SecFilterSignatureAction "log,deny,msg:'XSS attack'"
SecFilterSelective ARGS "<script"
SecFilterSelective ARGS "javascript:"
SecFilterSelective ARGS "vbscript:"
SecFilterSelective ARGS "document\.cookie"
SecFilterSelective ARGS "document\.location"
SecFilterSelective ARGS "document\.write"
##### Command Execution #####
SecFilterSignatureAction "log,deny,msg:'Command execution attack'"
SecFilterSelective ARGS_VALUES ";[[:space:]]*(ls|id|pwd|wget)"
##### PHP Attacks #####
##### (이부분을 적용하면 쇼핑몰 결제가 안된다.) #####
SecFilterSignatureAction "log,deny,msg:'PHP Injection Attacks'"
SecFilterSelective ARGS_VALUES "^http:/"
SecFilterSelective ARGS_NAMES "(^globals\[|^globals$)"
#############################
# < 웹호스팅 업체용 >
#
# 이 Rule은 다수의 웹사이트가 운영되는 웹호스팅 서버에서 활용가능한 최소공격차단 Rule입니다.
# 이 Rule을 참고하여 각 웹사이트에 적합한 Rule로 커스트마이징하시기 바랍니다.
# Rule 커스트마이징 후에는 공격탐지시 차단하도록 SecFilterDefaultAction 에서
# pass를 deny로 수정하시기 바랍니다.
#
#############################
#############################
# 1. ModSecurity 동작 유/무
# SecFilterEngine On | Off
# On : ModSecurity 기능 활성화
# Off : ModSecurity 기능 비활성화
SecFilterEngine On
#############################
# 2. 기본 설정
# 기본적으로 룰이 매치 될 경우 행위(Action) 지정
# SecFilterDefaultAction "행위"
# 행위 : deny, pass, allow, status:apache error code
#
# 룰 커스트마이징 완료 후 공격탐지시 차단하도록 SecFilterDefaultAction 에서 pass를 deny로 수정 필요
#
# SecFilterDefaultAction "deny,log,status:406"
SecFilterDefaultAction "pass,log"
# 아파치의 기본 로그보다 자세한 공격관련 로그를 기록
SecAuditEngine RelevantOnly
SecAuditLog logs/modsec_audit.log
# 웹서버의 헤더 정보 변경
SecServerSignature "Microsoft-IIS/5.0"
# POST 메소드의 Payload를 점검
SecFilterScanPost On
# 인코딩된 문자를 일반 텍스트 문자로 변환
# 가령, 16진수로 인코딩된 %AB 형태를 일반 텍스트로 변환함
SecFilterCheckURLEncoding On
# SecFilterCheckUnicodeEncoding UTF-8 전용 서버일 경우 On
SecFilterCheckUnicodeEncoding Off
#############################
# 3. PHP 인젝션 취약 공격 방지(제로보드 대상 공격 포함)
SecFilterSignatureAction "msg:'PHP Injection Attacks'"
SecFilterSelective ARGS_VALUES "^http:/"
SecFilterSelective REQUEST_URI "/include/write\.php\?dir=(ftp|http):"
SecFilterSelective REQUEST_URI "/include/print_category\.php\?setup=1&dir=(ftp|http):"
SecFilterSelective REQUEST_URI "/zero_vote/error\.php\?dir=(ftp|http):"
SecFilterSelective REQUEST_URI "/outlogin\.php\?_zb_path=(ftp|http):"
SecFilterSelective REQUEST_URI "filename=\|"
SecFilterSelective REQUEST_URI "check_user_id\.php\?user_id=<script>alert(document\.cookie)"
#############################
# 4. 명령어 실행 방지
SecFilterSignatureAction "msg:'Command execution attack'"
SecFilterSelective ARGS_VALUES ";[[:space:]]*(ls|id|pwd|wget|cd)"
#############################
# 5. XSS 공격 방지
SecFilterSignatureAction "msg:'XSS attack'"
SecFilterSelective ARGS "alert[[:space:]]*\("
SecFilterSelective ARGS "&#[[0-9a-fA-F]]"
SecFilterSelective ARGS "eval[[:space:]]*\("
SecFilterSelective ARGS "onKeyUp"
SecFilterSelective ARGS "\x5cx[0-9a-fA-F]"
SecFilterSelective ARGS "fromCharCode"
SecFilterSelective ARGS "&\{.+\}"
SecFilterSelective ARGS "<.+>"
SecFilterSelective ARGS "vbscript:"
SecFilterSelective ARGS "http-equiv"
SecFilterSelective ARGS "-->"
SecFilterSelective ARGS "expression[[:space:]]*\("
SecFilterSelective ARGS "url[[:space:]]*\("
SecFilterSelective ARGS "innerHTML"
SecFilterSelective ARGS "document\.body"
SecFilterSelective ARGS "document\.cookie"
SecFilterSelective ARGS "document\.location"
SecFilterSelective ARGS "document\.write"
SecFilterSelective ARGS "style[[:space:]]*="
SecFilterSelective ARGS "dynsrc"
SecFilterSelective ARGS_VALUES "jsessionid"
SecFilterSelective ARGS_VALUES "phpsessid"
#############################
# 6. SSI 인젝션 관련 공격 차단
SecFilterSignatureAction "msg:'SSI injection attack'"
SecFilterSelective ARGS "<!--[[:space:]]*#[[:space:]]*exec"
SecFilterSelective ARGS "<!--[[:space:]]*#[[:space:]]*cmd"
SecFilterSelective ARGS "<!--[[:space:]]*#[[:space:]]*echo"
SecFilterSelective ARGS "<!--[[:space:]]*#[[:space:]]*include"
SecFilterSelective ARGS "<!--[[:space:]]*#[[:space:]]*printenv"
#############################
# 7. 스패머 프로그램 봇
SecFilterSignatureAction "msg:'Robot attack'"
SecFilterSelective HTTP_USER_AGENT "WebBandit"
SecFilterSelective HTTP_USER_AGENT "WEBMOLE"
SecFilterSelective HTTP_USER_AGENT "Telesoft*"
SecFilterSelective HTTP_USER_AGENT "WebEMailExtractor"
SecFilterSelective HTTP_USER_AGENT "CherryPicker*"
SecFilterSelective HTTP_USER_AGENT "NICErsPRO"
SecFilterSelective HTTP_USER_AGENT "Advanced Email Extractor*"
SecFilterSelective HTTP_USER_AGENT "EmailSiphon"
SecFilterSelective HTTP_USER_AGENT "Extractorpro"
SecFilterSelective HTTP_USER_AGENT "webbandit"
SecFilterSelective HTTP_USER_AGENT "EmailCollector"
SecFilterSelective HTTP_USER_AGENT "WebEMailExtrac*"
SecFilterSelective HTTP_USER_AGENT "EmailWolf"
SecFilterSelective HTTP_USER_AGENT "Microsoft URL Control"
SecFilterSelective HTTP_USER_AGENT "^Microsoft URL"
###########################################
# 8. 검색엔진 Recon/Google 이용한 해킹 방지
SecFilterSignatureAction "msg:'Recon/Google attack'"
SecFilterSelective HTTP_Referer "Powered by Gravity Board"
SecFilterSelective HTTP_Referer "Powered by SilverNews"
SecFilterSelective HTTP_Referer "Powered.*PHPBB.*2\.0\.\ inurl\:"
SecFilterSelective HTTP_Referer "PHPFreeNews inurl\:Admin\.php"
SecFilterSelective HTTP_Referer "inurl.*/cgi-bin/query"
SecFilterSelective HTTP_Referer "inurl.*tiki-edit_submission\.php"
SecFilterSelective HTTP_Referer "inurl.*wps_shop\.cgi"
SecFilterSelective HTTP_Referer "inurl.*edit_blog\.php.*filetype\:php"
SecFilterSelective HTTP_Referer "inurl.*passwd.txt.*wwwboard.*webadmin"
SecFilterSelective HTTP_Referer "inurl.*admin\.mdb"
SecFilterSelective HTTP_Referer "filetype:sql \x28\x22passwd values.*password values.*pass values"
SecFilterSelective HTTP_Referer "filetype.*blt.*buddylist"
SecFilterSelective HTTP_Referer "File Upload Manager v1\.3.*rename to"
SecFilterSelective HTTP_Referer "filetype\x3Aphp HAXPLORER .*Server Files Browser"
SecFilterSelective HTTP_Referer "inurl.*passlist\.txt"
SecFilterSelective HTTP_Referer "wwwboard WebAdmininurl\x3Apasswd\.txt wwwboard\x7Cwebadmin"
SecFilterSelective HTTP_Referer "Enter ip.*inurl\x3A\x22php-ping\.php\x22"
SecFilterSelective HTTP_Referer "intitle\.*PHP Shell.*Enable stderr.*filetype\.php"
SecFilterSelective HTTP_Referer "inurl\.*install.*install\.php"
SecFilterSelective HTTP_Referer "Powered by PHPFM.*filetype\.php -username"
SecFilterSelective HTTP_Referer "inurl\.*phpSysInfo.*created by phpsysinfo"
SecFilterSelective HTTP_Referer "SquirrelMail version 1\.4\.4.*inurl:src ext\.php"
SecFilterSelective HTTP_Referer "inurl\.*webutil\.pl"
#############################
# 9. PHPMyAdmin 관련 공격 취약점 적용
# "subform" 로컬 파일 포함 취약점
SecFilterSignatureAction "msg:'PHPMyAdmin attack'"
SecFilterSelective REQUEST_URI "/libraries/grab_globals\.lib\.php" chain
SecFilterSelective ARG_subform "(/|\.\.|(http|https|ftp)\:/)"
SecFilterSelective REQUEST_URI "/libraries/grab_globals\.lib\.php" chain
SecFilter "usesubform.*=.*&usesubform.*=.*&subform.*(/|\.\.|(http|https|ftp)\:/)"
# 경로 취약점
SecFilterSelective REQUEST_URI "/css/phpmyadmin\.css\.php\?GLOBALS\[cfg\]\[ThemePath\]=/etc"
SecFilterSelective REQUEST_URI "/phpMyAdmin/css/phpmyadmin\.css\.php\?GLOBALS\[cfg\]\[ThemePath\]=(/|.*\.\./)"
# 문자열변환 파라미터 크로스사이트 스크립팅 취약점
SecFilterSelective REQUEST_URI "/phpmyadmin/index\.php\?pma_username=*&pma_password=*&server=.*&lang=.*&convcharset=.*((javascript|script|about|applet|activex|chrome)*\>|(http|https|ftp)\:/)"
# Export.PHP 파일 공개 취약점
SecFilterSelective SCRIPT_FILENAME "export\.php$" chain
SecFilterSelective ARG_what "\.\."
# XSS 취약점
SecFilterSelective ARG_HTTP_HOST "(<[[:space:]]*(script|about|applet|activex|chrome)*>.*(script|about|applet|activex|chrome)[[:space:]]*>|onmouseover=|javascript\:)"
SecFilterSelective REQUEST_URI "libraries/auth/cookie\.auth\.lib\.php" chain
SecFilter "<[[:space:]]*(script|about|applet|activex|chrome)*>.*(script|about|applet|activex|chrome)[[:space:]]*>"
SecFilterSelective REQUEST_URI "/error\.php" chain
SecFilterSelective ARG_error "<[[:space:]]*(script|about|applet|activex|chrome)*>.*(script|about|applet|activex|chrome)[[:space:]]*>"
# register_globals Emulation "import_blacklist" 조작 취약점
SecFilterSelective REQUEST_URI "/grab_globals\.php" chain
SecFilterSelective ARG_import_blacklist "(<[[:space:]]*(script|about|applet|activex|chrome)*>.*(script|about|applet|activex|chrome)[[:space:]]*>|(http|https|ftp)\:/)"
#############################
# 10. 기타 공격 방지
# 허용하는 HTTP 리퀘스트 타입 (HTTP 0.9, 1.0 혹은 1.1) 이외 차단
# SecFilterSelective SERVER_PROTOCOL "!^HTTP/(0\.9|1\.0|1\.1)$" "msg:'Not allowed HTTP Protocol'"
# /etc/passwd 파일 접근 차단
SecFilterSelective THE_REQUEST "/etc/passwd"
# 웹을 이용한 SMTP redirect 금지
SecFilterSelective THE_REQUEST ^(http|https)\:/.+:25
# Directory Traversal 공격 차단
# SecFilter "\.\./"
#############################
# 11. SQL Injection 공격 차단
# PHPMyAdmin을 통한 정상적인 접속요청이 SQL Injection 공격으로 오탐될 수 있음
# PHPMyAdmin을 사용하고 있지 않을 경우 아래의 코맨트(#)를 제거하고 사용 권고
# SecFilterSignatureAction "msg:'SQL injection attack'"
# SecFilterSelective ARGS "delete[[:space:]]+from"
# SecFilterSelective ARGS "drop[[:space:]]+database"
# SecFilterSelective ARGS "drop[[:space:]]+table"
# SecFilterSelective ARGS "drop[[:space:]]+column"
# SecFilterSelective ARGS "drop[[:space:]]+procedure"
# SecFilterSelective ARGS "create[[:space:]]+table"
# SecFilterSelective ARGS "update.+set.+="
# SecFilterSelective ARGS "insert[[:space:]]+into.+values"
# SecFilterSelective ARGS "select.+from"
# SecFilterSelective ARGS "bulk[[:space:]]+insert"
# SecFilterSelective ARGS "union.+select"
# SecFilterSelective ARGS "or.+1[[:space:]]*=[[:space:]]1"
# SecFilterSelective ARGS "alter[[:space:]]+table"
# SecFilterSelective ARGS "or 1=1--'"
# SecFilterSelective ARGS "'.+--"
# SecFilterSelective ARGS "into[[:space:]]+outfile"
# SecFilterSelective ARGS "load[[:space:]]+data
# SecFilterSelective ARGS "/\*.+\*/"
댓글