ModSecurity를 이용한 아파치 웹서보 보안 구축 Mod Security는 Apache 웹 서버를 위한 오픈 소스 웹 방화벽입니다.
주요기능
- 요청(request) 필터링 클라이언트로부터 웹요청이 들어올 때 웹서버 또는 다른 모듈들이 처리하기 전에 ModSecurity가 요청 내용을 분석하여 사전에 필터링합니다.
- 우회 방지 기술 경로와 파라미터를 분석하기 전에 정규화시켜 우회 공격을 차단합니다. 즉, “//”, “\/”, “.”, “%00” 등 우회 공격용 스트링을 제거하고, 인코딩된 URL을 디코딩합니다.
- HTTP 프로토콜 이해 엔진이HTTP 프로토콜을 이해하기 때문에 아주 전문적이고 미세한 필터링을 수행할 수 있습니다.
- POST 페이로드(payload) 분석 GET 방식 뿐만 아니라 POST 메소드를 사용해서 전송되는 컨텐츠도 가로채어 분석할 수 있습니다.
- 감사 로깅 POST를 포함하여 모든 요청의 모든 상세한 부분들까지 추후 분석을 위해서 로깅될 수 있습니다. ModSecurity에서 차단기능을 비활성화시킨 후, 강력한 로깅 기능만으로 침입탐지 시스템 역할을 수행할 수 있도록 합니다.
- HTTPS 필터링 엔진은 웹서버에 임베디드되어 있기 때문에 복호화 한 후에 요청 데이터에 접근하여HTTPS 를 통한 공격도 필터링할 수 있습니다. ModSecurity DSO 및 소스설치 하기 아파치 설치 방식에는 모듈 적재방식에 따라DSO, Static 방식이 있습니다. DSO는 아파치에 설치된 모듈이 필요할 때만 시스템에 적재하는 방식으로 시스템의 리소스(메모리, CPU)들을 적절하게 효율적으로 사용한다고 볼 수 있으며 모듈을 추가로 설치할 때에 아파치를 재 컴파일 하지 않고 모듈을 적재할 수 있는 방식입니다. Static는 아파치 가동시 모든 모듈을 함께 적재하는 방식으로 모듈을 추가로 설치할 때에 아파치를 재 컴파일 해야 하는 방식입니다. Apache 설치유형 확인하기 [root@systemen httpd-2.0.55]# httpd –l mod_so.c 위mod_so 모듈이 적재되어 있으면 DSO 방식으로 설치된 것이며 mod_so 모듈이 적재되지 않은 상태이면 Static로 설치된 것입니다.
( 1 ) Apache_1.x 대 ModSecurity DSO 방식 설치하기
modsecurity-apache_1.9.5.tar.gz 버전을 다운로드 하시면 Apache_1.x, Apache_2.x 버전에 모두 적용할 수 있습니다. ① modsecurity-apache_1.9.5.tar.gz 다운로드 http://www.modsecurity.org/download wget은 웹에서 자동적으로 파일을 받아오는데 사용되는 유틸리티이며 HTTP, HTTPS, FTP 프로토콜을 지원합니다. [root@nextline ~]# wget http://www.modsecurity.org/download/modsecurity-apache_1.9.5.tar.gz
② 압축해제 [tar 명령어 옵션] tar 명령어는 파일을 묶거나 풀 때 사용되는 리눅스 명령어 입니다. c : tar 파일을 생성할 때(여러 개의 파일을 하나의 파일로 묶을 때) v : 묶을 때나 풀어줄 때 파일들의 내용을 자세하게 보려고 할 때. z : gzip과 관련하여 압축이나 해제를 한꺼번에 하려고 할 때 사용. x : 주어진 이름의 파일에 대하여 추출 사용법: tar [옵션] 파일명 [root@nextline ~]# tar zxf modsecurity-apache_1.9.5.tar.gz 압축해제된 modsecurity-apache_1.9.5 디렉토리로 이동합니다. [root@nextline ~]# cd modsecurity-apache_1.9.5 Apache_1.x 버전에 적용하기 위해서는 apache1 디렉토리로 이동하여 컴파일을 합니다. [root@nextline modsecurity-apache_1.9.5]#cd apache1 [root@nextline apache1]# ls makefile.win mod_security.c ③mod_security.c 컴파일 apxs는 아파치 서버의 확장 모듈을 컴파일하고 설치하는 도구입니다. 옵션 설명 -i : 라이브러리 디렉토리에 so 파일 복사하라는 옵션 -a : httpd.conf 파일에 LoadModule 설정을 하라는 옵션 -c : 컴파일 하라는 옵션 [root@nextline apache1]# /usr/local/apache/bin/apxs -i -a -c mod_security.c
④ 모듈적재 확인 컴파일 완료 후/usr/local/apache/libexec 디렉토리에 mod_security.so 파일이 생성됩니다. [root@nextline apache1]# ls /usr/local/apache/libexec Httpd.exe libphp4.so mod_security.so


[vi 에디터 사용법] 사용형식: vi [옵션] [생성할 파일명/편집할 파일명] vi 에디터는 입력모드, 명령모드, 실행모드로 구분됩니다. 입력모드: vi 편집화면에서 문자를 입력할 수 있는 모드로서 입력모드로 진입하기 위해서는 i, a, o, I, A, O, R등이 있습니다. 즉 초기 vi 편집기 모드는 명령어 모드로 진입을 하기때문에 문자를 입력하기 전에 앞의 단축키중 하나를 먼저 입력해야 원하는 문자를 입력할 수 있습니다. 명령모드: 커서이동/문자삭제/문자(열)교체/문자열검색 등을 할수 있는 모드로서 입력모드에서 편집이 완료되면 Esc키를 눌러 명령모드로 진입하면 됩니다. 실행모드: 특별한 명령어를 실행하는 모드로서 명령어모드에서 ":"(콜론)를 누르면 vi 화면 하단 좌측에 vi 특수명령어를 입력할 수 있습니다. [실행모드의 일반적으로 쓰이는 특수 명령어] q : 수정 작업이 이루어지지 않은 상태에서 vi 편집기에서 빠져나옵니다. q! : 수정 작업이 이루어진 부분을 적용시키지 않고 vi 편집기를 강제로 빠져나옵니다. w : 수정된 작업을 저장합니다. wq : 수정된 작업을 저장하고 vi 편집기에서 빠져나옵니다. 초기 명령어모드-> 입력모드진입 -> 편집 -> 명령어모드 -> 실행모드 -> 종료 컴파일 작업으로httpd.conf파일에 모듈이 등록되었는지 확인합니다. [root@nextline mod_throttle-3.1.2]# vi /usr/local/apache/conf/httpd.conf LoadModule security_module libexec/mod_security.so
 ⑤phpinfo을 이용한 모듈적재 확인 php 정보를 확인하기 위하여 vi 에디터를 이용하여 php_test.php 파일을 생성합니다. [root@nextline ~]# vi /usr/local/apache/htdocs/php_test.php
 <? phpinfo(); ?> 문을 추가합니다.
 ⑥ http://해당ip/php_test.php 확인화면
 ( 2 ) Apache_2.x 대 ModSecurity DSO 방식 설치하기
Apache_1.x 대 버전과 동일한 설치 방식이 적용되며 modsecurity-apache_1.9.5 하위디렉토리에서 apache2 디렉토리에 있는 mod_security.c 파일로 컴파일 한다는 차이점이 있습니다.
① 압축해제된 modsecurity-apache_1.9.5 디렉토리로 이동합니다. [root@nextline ~]# cd modsecurity-apache_1.9.5 ② Apache_2.x 버전에 적용하기 위해서는 apache2 디렉토리로 이동하여 컴파일을 합니다. [root@nextline modsecurity-apache_1.9.5]#cd apache2 [root@nextline apache1]# ls Makefile.in config.m4 makefile.win mod_security.c ③mod_security.c 컴파일 [root@nextline apache2]# /usr/local/apache/bin/apxs -i -a -c mod_security.c
 ④ 모듈적재 확인 [root@nextline apache2]# ls /usr/local/apache/modules/ httpd.exp libphp4.so mod_security.so
 ⑤ 컴파일 작업으로httpd.conf파일에 모듈이 등록되었는지 확인합니다. [root@nextline mod_throttle-3.1.2]# vi /usr/local/apache/conf/httpd.conf LoadModule security_module libexec/mod_security.so

⑥phpinfo을 통한 모듈적재 확인 http://해당ip/php_test.php 확인화면

( 3 ) ModSecurity 룰 설정
①httpd.conf 설정파일 편집
 ②modsecurity 는 Rule 변경이 지속적으로 필요하므로 별도의 파일을 이용하기 위해 Include 지시자를 이용해 conf/modsecurity.conf 에 룰 설정파일을 별도로 생성합니다.

③ modsecurity 작동테스트 modsecurity.conf 파일에 아래 라인을 추가 후 Rule 설정이 적용되는지 확인합니다. Rule 적용 전 HEAD 값 및 Server 명 노출 화면입니다.
 ⑤Rule 파일 생성 [root@nextline ~]# vi /usr/local/apache/conf/modsecurity.conf
 ⑥Rule 설정 아래의 라인을 modsecurity.conf 에 추가합니다. #Server 명 변경 설정 SecServerSignature “Microsoft-IIS/5.0” #공격가능성이 높은 GET, HEAD 요청차단 설정 SecFilterSelective REQUEST_METHOD "^(GET|HEAD)$" chain SecFilterSelective HTTP_Content-Length "!^$" SecFilterSelective SERVER_PROTOCOL "!^HTTP/(0\.9|1\.0|1\.1)$"

⑥ 설정 적용을 위해 아파치를 재가동 합니다. [root@nextline conf]# apachectl restart
 curl을 통해 head값을 요청하면 아래와 같이 Rule 설정대로 적용한 Server 명으로 표시되며 HEAD값이 노출되지 않음을 확인할 수 있습니다.
 위와같이Rule 설정이 적용되면 ModSecurity가 정상적으로 설치된 것입니다. ⑦modsecurity.conf 에 로그 기록 설정 시 화면과 같이 modsecurity 로그가 기록됩니다.

⑧Rule 적용설명 SecFilterEngine On mod_security의 기능을 사용할 것인지 여부를 정의하며 On은 모든 요청에 대해 분석하고 Off는 분석하지 않는 설정입니다. SecFilterEngine On POST 메소드로 전달되는 playoad를 체크 할 것인지 여부를 지정합니다. SecFilterScanPost On GET뿐만 아니라 POST로 넘어오는 메시지까지 필터링 할것인지를 결정하는 옵션입니다. SecFilterCheckURLEncoding On URL로 전달되기 전에 특수문자는 encoding될 필요가 있는데, encoding된 문자가 유효한지를 체크할 지 여부를 지정합니다. SecFilterScanOutput On SecFilterOutputMimeTypes "(null) text/html text/plain" 아파치2에서 ModSecurity는 출력 필터를 지원합니다. 디폴트로 이 기능은 비활성화되어 있으므로 위와 같이 활성화시켜 주어야 합니다. 기존의 입력 필터는 웹요청이 아파치에 의해 처리되기 이전에 실행되지만 출력 필터는 아파치에 의해 웹요청이 처리 완료된 이후에 실행됩니다. 위와 같이 출력 필터를 설정한 후에 다음과 같이 “OUTPUT" 파라메터를 사용하여 특정 키워드를 가진 출력에 대해 필터링을 할 수 있습니다. SecFilterSelective OUTPUT "Fatal error:" deny,status:500 ErrorDocument 500 /php-fatal-error.html 이와 같이 공격자가 공격 정보로 이용될 수 있는 정보나 특정 명령어 실행 결과 등Critical한 결과가 실행되어 공격자에게 결과가 전달되는 것을 차단할 수 있습니다. 출력 필터는 일반 평문text와 HTML 출력에 대해서만 유용하며, 이미지와 같은 바이너리 컨텐츠에 대해 정규식을 적용한다면 서버가 느려질 수 있습니다. 디폴트로 ModSecurity는 컨텐츠 타입을 가지고 있지 않거나 “text/plan" 또는 ”text/html"을 컨텐츠 타입으로 가진 출력에 대해서만 스캔하며 스캔하고자 하는 컨텐츠 타입을 바꾸고자 할 경우에는 “SecFilterOutputMimeTypes” 지시자를 이용합니다. SecFilterOutputMimeTypes "(null) text/html text/plain" 위의 설정은ModSecurity가 평문 text 파일, HTML 파일 그리고 MIME 타입이 정의되지 않은 파일들에 대해 출력 필터를 적용하게 합니다. 출력 필터는 유용한 기능이라고 할 수 있지만 완벽하지는 못합니다. 공격자가 모니터링하고 있지 않는 컨텐츠 타입으로 바꾼다든지 출력을 인코딩하는 방법으로 필터를 우회할 가능성이 존재합니다. SecServerSignature "Microsoft-IIS/5.0" 서버나 버전 등의 정보를 임의로 변경할 수 있는 룰입니다. SecFilterCheckURLEncoding On URL로 전달되기 전에 특수문자는 encoding될 필요가 있는데, encoding된 문자가 유효한지를 체크할지 여부를 결정합니다. SecUploadDir /tmp 서버를 통해 업로드되는 파일에 대해 임시로 저장할 경로를 지정하며 최근에는 웹쉘 등을 업로드하는 경우가 많이 있으므로 어떤 파일이 서버로 업로드되는지 모니터링하고자 할 때 유용합니다. SecUploadKeepFiles Off 서버를 통해 업로드되는 파일을 별도로 복사해 저장할 것인지 여부를 지정한다. SecFilterForceByteRange 1 255 Stack Overflow 공격을 차단하기 위해 Request의 byte를 제한할 수 있다. 기본적으로는 제한이 없지만 위와 같이 설정시 1byte부터 255byte만 허용합니다. SecFilterDefaultAction "log,deny,status:403" 필터에 매칭되는 요청이 있을때 어떻게 대응할 것인지에 대한 기본 설정으로 위와 같이 설정하면 필터에 매칭 되었을 경우 요청을 차단 후404 에러를 넘겨주소 로그를 남기게 됩니다. SecFilterDefaultActio action pass : 필터링하지 않고 통과하도록 한다. deny : 필터링에 매칭될 경우 요청을 거부한다. 특별한 status를 지정하지 않으면 기본적으로 500 error로 응답한다. status : 요청이 거부되었을 경우 제공되는 HTTP 상태 코드를 지정한다. redirect : 필터링에 매칭될 경우 특정 URL로 redirect할 수 있다 exec : 필터링에 매칭될 경우 지정한 명령어 또는 cgi를 실행하도록 한다. log : 필터링에 매칭될 경우 apache의 에러 로그에 남기도록 한다. nolog : 에러 로그에 남기지 않도록 한다. pause : 요청에 응답하기 전에 지정된 밀리초동안 멈추도록 한다. SecFilter "\.\./" 일반적인 웹 요청에서 “../”와 같은 경로는 필요치 않으며 이는 웹을 통해 /etc/passwd와 같이 비정상적인 웹 요청을 위한 경우가 많으므로 차단하는 것이 바람직합니다. SecFilterDebugLog logs/modsec_debug.log SecFilterDebugLevel 1 요청이 들어올때 로그를 남길것인지 설정합니다. 0 남기지 않는 것이고, 1은 심각한 이벤트가 발생 하였을때, 2, 3으로 갈수록 자세한 정보를 남기게 됩니다. SecAuditEngine RelevantOnly SecAuditLog logs/modsec_audit.log 필터링에 매칭되는 요청에 대해서logs/modsec_audit.log 파일에 상세한 정보를 제공하도록 하며 필터에 걸리는 정보만 남기려면 On 대신 RelevantOnly를 지정합니다. SecFilterSelective REQUEST_METHOD "^(GET|HEAD)$" chain SecFilterSelective HTTP_Content-Length "!^$" SecFilterSelective SERVER_PROTOCOL "!^HTTP/(0\.9|1\.0|1\.1)$" Body를 가진 GET 또는 HEAD 요청 차단(공격 가능성 높음) SecFilterSelective REQUEST_METHOD "^POST$" chain SecFilterSelective HTTP_Content-Length "^$" SecFilterSelective HTTP_Transfer-Encoding "!^$" Content-Length가 없는 POST 요청을 차단합니다. SecFilterSelective HTTP_Host|HTTP_User-Agent|HTTP_Accept "^$" SecFilterSelective HTTP_User-Agent "(libwhisker|paros|wget|libwww|perl|curl|java)" 웹 브라우저가 아닌 어플리케이션을 이용한 접속이나 php 등에서 socket 통신등을 사용하는 경우라면 주석처리 해야 접속이 가능합니다. 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 "/\*.+\*/" SQL Injection 공격을 차단하는 설정입니다. 최근 중국발 공격 등 많은 공격이SQL Injection 취약점을 이용한 공격이므로 다음과 같이 DB Query를 통해 DB에 대한 삭제, 추가, 열람시도 등을 차단하는 것이 바람직합니다. phpmyadmin 을 사용할 경우 전부 주석처리 해야하며 이유는 phpmyadmin의 경우 페이지 argument 로 sql문을 전송하기 때문에 이부분을 살려두면 phpmyadmin은 사용이 불가능해 집니다. 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" XSS는 웹 페이지에 JavaScript와 같은 악성 스크립트를 삽입하여 다른 웹 접속자가 이를 실행시키게하는 공격입니다. 이 공격에 대한 방어는 파라메터 필터링인데 다음과 같이 설정할 수 있습니다. 위의 예는 자바스크립트, 비주얼베이직 스크립트 등 스크립트 코드를 차단하고, 스크립트에 의해 쿠키 정보가 노출되는 것을 방지하고 있습니다. SecFilterSignatureAction "log,deny,msg:'Command execution attack'" SecFilterSelective ARGS_VALUES ";[[:space:]]*(ls|pwd|wget)" 파라메터에 “ls", "pwd", "wget" 등의 키워드가 있을 경우 차단합니다. SecFilterSignatureAction "log,deny,msg:'PHP Injection Attacks'" SecFilterSelective ARGS_VALUES "^http:/" PHP Injection 공격을 차단하는 설정으로 파라메터에 URL이 들어 있는 요청을 차단합니다. SecFilterSelective ARGS_NAMES "(^globals\[|^globals$)" 전역변수GLOBALS를 이용한 공격을 막기 위해서는 다음과 같이 설정합니다. ⑨ModSecurity Rule 설정 예 ##### Configuration ##### SecFilterEngine On SecFilterScanPost On SecFilterDefaultAction "deny,log,status:404" SecFilterScanOutput Off SecFilterOutputMimeTypes "(null) text/html text/plain" SecServerSignature "Microsoft-IIS/5.0" ##### 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 ##### 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$)"
|
|