Modsecurity 를활용한 apache 웹서버보안강화 오늘과내일홍석범 antihong@tt.co.kr 웹서비스보안강화요소 웹서비스보안요소 단 점 보안성있는안전한웹프로그램 -. 보안프로그래밍의어려움 -. 프로그램취약성인지의어려움 -. 프로그램의업데이트 / 수정 / 패치의어려움 Apache 등웹서버에서의보안설정 -. 기초적수준에서의보안설정만지원됨 웹방화벽, IPS 등보안솔루션도입 -. 상용솔루션의경우비용부담 -. 무료솔루션의경우정책적용의어려움 / 기술지원한계 -. 상세룰적용시오탐및성능상이슈 2
웹서버설정 (httpd.conf) 보안 -. 버전정보유출차단 -. 계정정보유출차단 -. 파일정보유출차단 -. 접근통제 3 버전정보유출차단 ServerTokens Prod (httpd.conf) expose_php = Off (php.ini) # curl --head http://www.php.net/ HTTP/1.1 200 OK Date: Mon, 23 Apr 2007 05:51:55 GMT Server: Apache/1.3.37 (Unix) PHP/5.2.1 ServerTokens X-Powered-By: PHP/5.2.1 expose_php Last-Modified: Mon, 23 Apr 2007 05:37:59 GMT Content-language: en Set-Cookie: COUNTRY=KOR%2C; expires=mon, 30-Apr-2007 05:51:55 GMT; path=/; domain=.php.net Connection: close Content-Type: text/html;charset=utf-8 ServerTokens Prod : Server: Apache ServerTokens Min : Server: Apache/1.3.37 ServerTokens OS : Server: Apache/1.3.37 (Unix) ServerTokens Full : Server: Apache/1.3.37 (Unix) PHP/5.2.1 MyMod/1.2 http://monkey.org/~pilot/arirang/ arirang -s 211.47.65.2 -e 211.47.65.253 211.47.65.2 Server: Apache 211.47.65.3 Server: Apache/1.3.27 (Unix) PHP/4.2.3 4
계정정보유출차단 http://ip/~id/ 로확인 < 계정이존재하는경우 > < 계정이존재하지않는경우 > <IfModule mod_userdir.c> UserDir public_html </IfModule> <IfModule mod_userdir.c> UserDir disabled UserDir enabled user1, user2 </IfModule> 5 파일정보유출차단 httpd.conf 에서모든 indexes 설정제거필요 <Files ~ "\.bak$ \.old$ \.log$ \.c $\.inc$"> Order allow,deny Deny from all </Files> 또는 AddHandler cgi-script.cgi.pl.bak.old.log.inc AddType application/x-httpd-php.php.bak. old 6
접근통제설정 (httpd.conf) httpd.conf 이용시 <Directory /home/abc/> Order deny, allow 뒤쪽에선언된것이우선이자기본 Deny from all Allow from 192.168.64 Allow from 192.168.65 </Directory> 7 접근통제설정 (.htaccess) AuthName "Only Members" AuthType Basic AuthUserFile /usr/data/.htpasswd ErrorDocument 401 " ABC 직원만접근가능합니다. <Limit GET POST> require valid-user Satisfy all order deny,allow Satisfy all 두조건모두적합해야함. allow from 192.168.1 any 하나만적합하면됨. allow from 210.60.58.217 미설정시 all 이기본설정값 deny from all </Limit> 8
-. Open Source Web Application Firewall(WAF) 상용솔루션 (commercial support) (http://www.breach.com/) -. 탐지 / 차단방식 (1) negative model (anomaly, unusual. 룰 40번 ) (2) positive model ( 허용이외차단, 룰 20/30번 ) (3) known weakness ( 특정 pattern) -. 로그관리를위한별도의 console 제공 http://www.modsecurity.org/ -. Core rule을통해차단 http protection common web attacks protection trojan protection error hiding 등 9 버전에따른차이점 분류 지원되는 apache 버전 설치방법 Processing phase 설정방법 modsecurity 1.x Apache 1.x/2.x 모두지원 apxs 를사용한 DSO 및정적 (static) 으로컴파일모두지원 Inbound(Request body) / Outbound(Response body) 지원 apache 1.x 의경우 <IfModule mod_security.c> apache 2.x의경우 <IfModule security_module> modsecurity 2.x Apache 2.x 만지원 별도의 Makefile 을이용한 DSO 방식만지원 Request header(phase:1) Request body(phase:2) Response header(phase:3) Response body(phase:4) logging(phase:5) <IfModule security2_module> 10
설치방법 (rpm-dso) -. rpm 버전의 apache 에 modsecurity 를탑재하는경우 1. # rpm -q httpd httpd-2.0.52-28.ent.centos4 2. modsecurity Makefile 을열어 20 번째줄에있는 top_dir 을다음과같이변경 변경전 ) top_dir 변경후 ) = /apps/apache22 top_dir = /etc/httpd 3. make; make install 이후 /usr/lib/httpd/modules/mod_security2.so 생성됨 4. httpd.conf 에추가 LoadFile /usr/lib/libxml2.so LoadModule security2_module modules/mod_security2.so 5. httpd 재가동 # /etc/rc.d/init.d/httpd restart 11 설치방법 ( 소스컴파일 -DSO) -.Apache 를소스컴파일하여 modsecurity 를탑재하는경우 1. 아파치설치 #./configure --enable-so --enable-unique-id # make; make install 2. modsecurity 의 Makefile 을열어 20 번째줄에있는 top_dir 을다음과같이변경 변경전 ) top_dir 변경후 ) = /apps/apache22 top_dir = /usr/local/apache2 3. make; make install 이후 /usr/local/apache2/modules/mod_security2.so 생성됨 4. httpd.conf 에추가 LoadFile /usr/lib/libxml2.so LoadModule security2_module modules/mod_security2.so 5. httpd 재가동 # /usr/local/apache2/bin/apachectl restart 12
작동여부확인방법 SecServerSignature "Microsoft-IIS/5.0 설정후 # curl --head http://127.0.0.1/ Server: Microsoft-IIS/5.0 modsecurity 적용시 Server: Apache/2.2.4 (Unix) modsecurity 미적용시 13 룰 (rule) 설정방법 # mkdir /usr/local/apache2/conf/modsecurity # mv *.conf /usr/local/apache2/conf/modsecurity/ httpd.conf 에추가 Include conf/modsecurity/*.conf modsecurity_crs_10_config.conf 기본룰 modsecurity_crs_15_customrules.conf whitelist/customizing 룰생성. modsecurity_crs_20_protocol_violations.conf modsecurity_crs_21_protocol_anomalies.conf modsecurity_crs_30_http_policy.conf modsecurity_crs_35_bad_robots.conf core 룰 modsecurity_crs_40_generic_attacks.conf modsecurity_crs_45_trojans.conf modsecurity_crs_50_outbound.conf modsecurity_crs_55_marketing.conf 10->15->20 등순으로우선순위가적용되므로 10,15 만수정하고나머지는룰업데이트등을고려하여그대로유지하도록함 14
modsecurity console -. 웹을통해실시간통합로그관리가가능한패키지프로그램 (web+db) -. 1개의콘솔에서 3개의센서까지무료로제공 -. 상용버전 (Enterprise Manager Console) 은 breach를통해제공 -. JDK / JRE 1.4 이상에서작동함 -. 메일등으로알람 (notify) 기능 -. pdf로보고서작성기능제공 15 console 설치방법 # tar zxvfp modsecurity-console_1_0_2_unix.tar.gz # cd modsecurity-console #./modsecurity-console No suitable Java Virtual Machine could be found on your system. The version of the JVM must be at least 1.4. Please define INSTALL4J_JAVA_HOME to point to a suitable JVM. You can also try to delete the JVM cache file /root/.install4j 에러메시지 http://java.sun.com/ 에서 jdk1.5 다운로드및설치 #./jdk-1_5_0_09-linux-i586.bin 엔터만입력 # export INSTALL4J_JAVA_HOME=/usr/local/src/modsecurity-console/jdk1.5.0_09 #./modsecurity-console start 8886/tcp 리슨확인 16
console 설정방법 Sensors => Add Sensor 클릭 httpd.conf 에아래설정추가 SecAuditEngine RelevantOnly SecAuditLogRelevantStatus "^(?:5 4 d[^4])" SecAuditLogType Concurrent SecAuditLogParts ABCDEFGHZ SecAuditLogStorageDir /usr/local/apache2/logs/data/ SecAuditLog /usr/local/apache2/logs/data/modsec-audit.log SecAuditLog " /usr/local/apache2/bin/modsec-auditlog-collector.pl /usr/local/apache2/logs/data/ /usr/local/apache2/logs/modsec-audit.log" http://xx.xx.xx.xx:8886/static/modsec-auditlog-collector 파일저장 my $CONSOLE_HOST = "218.236.xx.xxx"; my $CONSOLE_PORT = "8886"; my $CONSOLE_USERNAME = "alpha1"; my $CONSOLE_PASSWORD = "sensor1"; 17 console 로그조회 18
오탐 (false positive) 에대한대응방법 -. 어떤 application 이든오탐은있을수있다. -. 처음에는 DetectionOnly 모드로사용해야한다. -. 특정룰에오탐이있다고룰자체를삭제하면또다른오탐 (false negative) 의원인이될수있으므로커스터마이징이필요하다. -. 로그 (log) 에원인과해결방법이있다. ( 만약특정한로그만자세히보고자할경우 ) 특정조건만상세로그를볼수있음 SecRule REMOTE_ADDR "^192.168.10.69$ phase:1,log,pass,ctl:debugloglevel=9 SecRule REQUEST_URI "^/path/to/script.pl$" phase:1,log,pass,ctl:debugloglevel=9 -. 상세한로그설정은 performance impact 유발가능예 )-. snort등의룰 (rule) 설정 X -. 정규식을이용룰최소화 SecRule REQUEST_URI file1.cgi SecRule REQUEST_URI (file1 file2)\.cgi SecRule REQUEST_URI file2.cgi 19 탐지로그예 Request : CONNECT mx1.mail.yahoo.com:25 HTTP/1.0 Response : HTTP/1.1 405 Method Not Allowed Allow: GET,HEAD,POST,OPTIONS,TRACE Content-Length: 318 Connection: close Content-Type: text/html; charset=iso-8859-1 Alert Message : Request Missing a Host Header Request Missing a User Agent Header Warning. Operator EQ match: 0. Method is not allowed by policy Warning. Match of "rx ^((?:(?:POS GE)T OPTIONS HEAD))$" against "REQUEST_METHOD" required. 20
탐지룰설정방법 modsecurity_crs_10_config.conf -. SecRuleEngine (On Off DetectionOnly) 초기에 DetectionOnly 로운영후 On 으로조정 -. SecAuditLogType (Serial Concurrent) 이벤트를한파일에저장 / 별도파일에저장 -. SecAuditLogParts "ABCDEFGHZ 로그를저장하는형식정의 B:request header C:request body 등.. -. SecServerSignature "Microsoft IIS/5.0 -. SecUploadDir /tmp -. SecUploadKeepFiles (On Off RelevantOnly) 21 탐지룰설정방법 modsecurity_crs_15_customrules.conf SecRule REMOTE_ADDR "^192.168.1.30$" phase:1,chain,nolog,allow,ctl:ruleengine=off SecRule REQUEST_HEADERS:User-Agent "^Payment/1.0 (Pay Java HTTP Request Object)" Virtual(External) Patching <LocationMatch ^/app/login.asp$ > SecFule ARGS:username "!^ w+$ deny,log > </Location> 예 ) 문자열영역이스케이프시퀸스 d : 어떤숫자 [0-9] 를의미 w : 어떤워드문자 [_0-9a-zA-Z] s : 화이트스페이스 Rule 관련사이트 : http://www.gotroot.com/ 22
탐지룰설정방법 modsecurity_crs_20_protocol_violations.conf 정상적인 http protocol 위반접속요구 (request header) -. SecDefaultAction "log,deny,phase:1,status:400 Bad Request 응답 -. SecRule REQUEST_METHOD "^(GET HEAD)$" "chain,deny,log,auditlog,status:400, msg:'get or HEAD requests with bodies', severity:'2',id:'960011'" SecRule REQUEST_HEADERS:Content-Length "!^0?$" -. SecRule REQUEST_URI ^http:/ "deny,log,auditlog,status:400, msg:'proxy access attempt', severity:'2',id:'960014'" 23 탐지룰설정방법 modsecurity_crs_21_protocol_anomalies.conf 정상적인 http protocol 위반접속요구 (request header) -. SecRule &REQUEST_HEADERS:Host "@eq 0" "skip:1,log,auditlog,msg:'request Missing a Host Header',id:'960008',severity:'4'" SecRule REQUEST_HEADERS:Host "^$" "log,auditlog,msg:'request Missing a Host Header',id:'960008',severity:'4'" -. SecRule REQUEST_HEADERS:Host "^[ d.]+$" "deny,log,auditlog,status:400, msg:'host header is a numeric IP address', severity:'2',id:'960017' 초기에가장많은오탐을유발하는룰임 24
탐지룰설정방법 modsecurity_crs_30_http_policy.conf http 정책에대한룰 -. SecRule REQUEST_METHOD "!^((?:(?:POS GE)T OPTIONS HEAD))$" "phase:1,log,auditlog,status:501,msg:'method is not allowed by policy', severity:'2',id:'960032'" -. SecRule REQUEST_PROTOCOL "!^HTTP/(0.9 1.[01])$" "t:none, deny,log,auditlog,status:505, msg:'http protocol version is not allowed by policy', severity:'2',id:'960034'" -. SecRule REQUEST_BASENAME ".ba(?:[kt] ckup) exe key mdb old)$" "t:urldecodeuni, t:lowercase, deny,log,auditlog,status:500, msg:'url file extension is restricted by policy', severity:'2',id:'960035'" 25 탐지룰설정방법 modsecurity_crs_35_bad_robots.conf User-Agent 에대한룰 : 고급화된공격차단보다는스캐너등차단목적 -.SecRule HTTP_User-Agent "n(?:-stealth sauditor essus ikto) (?:jaascoi paro)s \.nasl)" \ "deny,log,auditlog,status:404,msg:'request Indicates a Security Scanner Scanned the Site',id:'990002',severity:'2'" 26
탐지룰설정방법 modsecurity_crs_40_generic_attacks.conf sql injection/ php injection/command access 에대한룰 -. SecRule REQUEST_FILENAME ARGS ARGS_NAMES REQUEST_HEADERS!REQUEST_HEADERS:Referer dbms_java)\b i(?:n(?:to\b\w*?\b(?:dump out)file sert\b\w*?\binto ner\b\w*?\bjoin)\b (?:f(?:\b\w*?\( \W*?\bbenchmark null\b) snull\b)\w*?\() (?:having or and)\b\s+?(?:\d{1,10} '[^=]{1,10}')\s *?[=<>]+ (?:print\]\b\w*?\@ root)\@ c(?:ast\b\w*?\( oalesce\b)) (?:;\W*?\b(?:shutdown drop) \ @\@version)\b '(?:s(?:qloledb a) msdasql dbo)')" \"capture,t:replacecomments,ctl:auditlogparts=+e,log,auditlog,msg:'sql Injection Attack. Matched signature <%{TX.0}>',id:'950001',severity:'2' -. SecRule ARGS ARGS_NAMES REQUEST_HEADERS "echo\b\w*?\by+)\b c(?:md(?:(?:32)?\.exe\b \b\w*?\/c) d(?:\ b\w*?[\\\/] \W*?\.\.) hmod.{0,40}?\+.{0,3}x)) [\;\ \`]\W*?\b(?:(?:c(?:h(?:grp mod own sh) md pp c ) p(?:asswd ython erl ing s) n(?:asm map c ) f(?:inger tp) (?:kil mai)l (?:xte)?rm ls(?:of)? telnet unam e echo id)\b g(?:\+\+ cc\b)) \/(?:c(?:h(?:grp mod own sh) pp c) p(?:asswd ython erl ing s) telnet una me echo id)(?:[\'\"\ \;\`\-\s] $)) \"capture,ctl:auditlogparts=+e,deny,log,auditlog,status:501,msg:'system Command Injection. Matched signature <%{TX.0}> ',id:'950006',severity:'2'" 27 탐지룰설정방법 modsecurity_crs_45_trojans.conf trojan 이나백도어에대한접근룰 -. SecRule REQUEST_FILENAME "root\.exe" \ "t:urldecodeuni,t:htmlentitydecode,ctl:auditlogparts=+e,deny,log,auditlog,status:40 4,msg:'Backdoor access',id:'950921',severity:'2' -. SecRule RESPONSE_BODY "(?:<title>[^<]*?(?:\b(?:(?:c(?:ehennemden gitelnet) gamma web shell)\b imhabirligi phpftp) (?:r(?:emote explorer 57shell) aventis klasvayv zehir)\b \.::(?:news remote php shell injection::\. rhtools\b) ph(?:p(?:(?: commander -terminal)\b remoteview) vayv) myshell) \b(?:(?:(?:microsoft windows\b.{,10}\bversion\b.{,20}(c) copyright 1985-.{,10}\bmicrosoft corp ntdaddy v1\.9 - obzerve \ fux0r inc)\. (?:www\.sanalteror\.org - indexer and read haxplor)er php(?:konsole shell) c99shell)\b aventgrup\.<br> drwxr))" \ "phase:4,ctl:auditlogparts=+e,deny,log,auditlog,status:404,msg:'backdoor access',id:'950922',severity:'2'" 28
웹쉘작동예 29 탐지룰설정방법 modsecurity_crs_50_outbound.conf 에러등특정결과값을통해정보를취득하려는시도차단 -. SecRule RESPONSE_BODY "(?:>\[to parent directory\]<\/a><br> <title>index of.*?<h1>index of)" \ "ctl:auditlogparts=+e,deny,log,auditlog,status:40 3,msg:'Directory Listing',id:'970013',severity:'4' 30
탐지룰설정방법 modsecurity_crs_50_outbound.conf SecRule RESPONSE_BODY "error converting the \w+ value.*? to a column of data typ)e upplied argument is not a valid (?:(?:m(?:s y) postgre)sql o(?:racle dbc))) (?:you have an error in your sql incorrect) syntax near SQL Server does not exist or access denied)\ rror '800a01b8') microsoft (?:ole db provider for.{0,30} error ' (?:warning: mysql_connect\(\) postgresql query failed): (?:\[microsoft\]\[odbc ora-\d{5}:) )" \ "ctl:auditlogparts=+e,deny,log,auditlog,status:500,msg:'sql Information Leakage',id:'970003',severity:'4' MS-SQL 의경우 ) http://domain.com/index.asp?id=10 UNION SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLES Error 출력값 Microsoft OLE DB Provider for ODBC Drivers error '80040e07' [Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value 'table1' to a column of data type int. /index.asp, line 5 table1 이라는테이블명을알수있음 31 Modsecurity 설정후성능측정 ab -n 1000 -c 100 http://target_server/index.html Rule 무설정 ( 기본설정 ) 시 20_protocol_violations 21_protocol_anomalies 30_http_policy 35_bad_robots 40_generic_attacks 45_trojans 50_outbound 40/50만적용시모두적용시 성능 (Requests per second) 5617.98 [#/sec] 5291.01 [#/sec] 4807.69 [#/sec] 5128.21 [#/sec] 5319.15 [#/sec] 4000.00 [#/sec] 5050.51 [#/sec] 5154.64 [#/sec] 3448.28 [#/sec] ( 커스터마이징시 :4100~) 2680.97 [#/sec] 퍼센트 (%) 100% 94% 85% 91% 94% 71% 90% 91% 61%(73%~) 48% 32
Modsecurity 설정후성능측정 ab -n 1000 -c 100 http://target_server/test.cgi Rule 무설정 ( 기본설정 ) 시 20_protocol_violations 21_protocol_anomalies 30_http_policy 35_bad_robots 40_generic_attacks 45_trojans 50_outbound 40/50만적용시모두적용시 성능 (Requests per second) 841.04 [#/sec] 795.54 [#/sec] 806.45 [#/sec] 801.28 [#/sec] 800.64 [#/sec] 724.64 [#/sec] 794.28 [#/sec] 766.28 [#/sec] 686.81 [#/sec] 커스터마이징시 (725~) 634.12 [#/sec] 퍼센트 (%) 100% 94% 96% 95% 95% 86% 94% 91% 81%(~86%) 75% 33 결론 -. 불필요한룰을삭제하고, custommizing 한다면성능저하없이이용가능함예 ) sql injection 차단룰만설정시 95% 내외 -. 초기에는오탐에대비, DetectionOnly 로설정후로그를보며 Customizing 하여야함 -. DoS 공격등에는별도의방법으로대처필요 $iptables -A INPUT -m geoip! --src-cc KR -j DROP $iptables -A INPUT -p tcp --syn --dport 80 -m connlimit --connlimit-above 30 -j DROP -. 메일링리스트를통해최신정보습득및정보공유필요 34
Q & A 질문 : antihong@tt.co.kr 35