mod_security: How Good Is It?

by Mike on May 5, 2009 · 2 comments

in Web Server

One of the major questions anyone will want to know before they go to the time of compiling mod_security and setting it up is, what difference does it make?  To illustrate I have set up an Apache server with a default Joomla install.  Joomla, a content management program has had a history of security issues so I figured it may be a good example.  Joomla uses PHP, Apache, and MySQL in providing content management.  To evaluate the install I used nikto to scan the site.  The mod_security is set up and only uses the default settings.  The initial reason for this is to show the value of mod_security right out of the box.   The results are very interesting.  A scan by nikto without mod_security found 22 security issues to be exploited.  Once mod_security was turned on this dropped to only 2 security issues.  The conclusion, though this is a simple test, it is worth our effort to install mod_security for your web site.

Here is the output of a scan with nikto on a default Joomla installation.  Obviously there are a number of vulnerable issues here.  But the point is to see a vulnerable program without mod_security and then comparee with mod_security defaults.

perl nikto.pl -h 192.168.5.103
—————————————————————————
- Nikto 2.02/2.03     -     cirt.net
+ Target IP:       192.168.5.103
+ Target Hostname: example.com
+ Target Port:     80
+ Start Time:      2009-05-05 12:17:22
—————————————————————————
+ Server: Apache 2.2.3
- Allowed HTTP Methods: GET, HEAD, POST, OPTIONS, TRACE
+ OSVDB-877: HTTP method (‘Allow’ Header): ‘TRACE’ is typically only used for debugging and should be disabled. This message does not mean it is vulnerable to XST.
+ OSVDB-0: Retrieved X-Powered-By header: PHP/5.1.6
- /robots.txt – contains 14 ‘disallow’ entries which should be manually viewed. (GET)
+ PHP/5.1.6 appears to be outdated (current is at least 5.2.5)
+ OSVDB-0: GET /index.php?module=My_eGallery : My_eGallery prior to 3.1.1.g are vulnerable to a remote execution bug via SQL command injection.
+ OSVDB-877: TRACE / : TRACE option appears to allow XSS or credential theft. See http://www.cgisecurity.com/whitehat-mirror/WhitePaper_screen.pdf for details
+ OSVDB-8193: GET /index.php?module=ew_filemanager&type=admin&func=manager&pathext=../../../etc : EW FileManager for PostNuke allows arbitrary file retrieval.
+ OSVDB-12184: GET /index.php?=PHPB8B5F2A0-3C92-11d3-A3A9-4C7B08C10000 : PHP reveals potentially sensitive information via certain HTTP requests which contain specific QUERY strings.
+ OSVDB-3092: GET /administrator/ : This might be interesting…
+ OSVDB-3092: GET /includes/ : This might be interesting…
+ OSVDB-3092: GET /logs/ : This might be interesting…
+ OSVDB-3092: GET /tmp/ : This might be interesting…
+ OSVDB-3093: GET /index.php?base=test%20 : This might be interesting… has been seen in web logs from an unknown scanner.
+ OSVDB-3093: GET /index.php?IDAdmin=test : This might be interesting… has been seen in web logs from an unknown scanner.
+ OSVDB-3093: GET /index.php?pymembs=admin : This might be interesting… has been seen in web logs from an unknown scanner.
+ OSVDB-3093: GET /index.php?SqlQuery=test%20 : This might be interesting… has been seen in web logs from an unknown scanner.
+ OSVDB-3093: GET /index.php?tampon=test%20 : This might be interesting… has been seen in web logs from an unknown scanner.
+ OSVDB-3093: GET /index.php?topic=<script>alert(document.cookie)</script>%20 : This might be interesting… has been seen in web logs from an unknown scanner.
+ OSVDB-3268: GET /icons/ : Directory indexing is enabled: /icons
+ OSVDB-3761: GET /?pattern=/etc/*&sort=name : The TCLHttpd 3.4.2 server allows directory listings via dirlist.tcl.
+ OSVDB-3233: GET /icons/README : Apache default file found.
+ 4347 items checked: 22 item(s) reported on remote host
+ End Time:        2009-05-05 12:19:16 (114 seconds)

Scan with nikto after mod_security Turned On

perl nikto.pl -h 192.168.5.103
—————————————————————————
- Nikto 2.02/2.03     -     cirt.net
+ Target IP:       192.168.5.103
+ Target Hostname: example.com
+ Target Port:     80
+ Start Time:      2009-05-05 12:24:11
—————————————————————————
+ Server: Microsoft-IIS/6.0
+ OSVDB-877: TRACE / : TRACE option appears to allow XSS or credential theft. See http://www.cgisecurity.com/whitehat-mirror/WhitePaper_screen.pdf for details
+ OSVDB-6659: GET /qogeMRP5aumyBB9qyOZWtV2LuhprxrVJIbQeg3SxZdafxkaorJNSeBjkqxAYPn463orreDdvUURj0fdMcBg9OnkLW3Ib6eHEOXpeb7PPjDPy3QHbrUIQxQITLceYvUHvLZ8cgE4hux5BcUpwzoSFVSEGIIdAcZdxMZ5XRyykcheVKPMzVNFBSbStbZcmEjZcvODnpusudDdTaRwO2vbi4rl9WPbLfCw<font%20size=50>DEFACED<!–//– : MyWebServer 1.0.2 is vulnerable to HTML injection. Upgrade to a later version.
+ 16767 items checked: 2 item(s) reported on remote host
+ End Time:        2009-05-05 12:24:20 (9 seconds)

mod_security Log Output
This shows the interaction between nikto and mod_security.

–05bb5f20-H–
Message: Access denied with code 403 (phase 2). Match of “rx ^OPTIONS$” against “REQUEST_METHOD” required. [file "/etc/httpd/conf.d/modsecurity/modsecurity_crs_21_protocol_anomalies.conf"] [line "41"] [id "960015"] [msg "Request Missing an Accept Header"] [severity "CRITICAL"] [tag "PROTOCOL_VIOLATION/MISSING_HEADER"]
Action: Intercepted (phase 2)
Stopwatch: 1241465278939883 1413 (325 709 -)
Producer: ModSecurity for Apache/2.5.9 (http://www.modsecurity.org/); core ruleset/1.6.1.
Server: Apache/2.2.3 (CentOS) DAV/2 PHP/5.1.6

–05bb5f20-K–
SecRule “REQUEST_METHOD” “@rx ^(?:GET|HEAD)$” “phase:2,status:400,t:lowercase,t:replaceNulls,t:compressWhitespace,chain,t:none,deny,log,auditlog,msg:’GET or HEAD requests with bodies’,severity:2,id:960011,tag:PROTOCOL_VIOLATION/EVASION”
SecRule “&REQUEST_HEADERS:Accept” “@eq 0″ “phase:2,status:403,t:lowercase,t:replaceNulls,t:compressWhitespace,chain,skip:1,t:none,log,auditlog,msg:’Request Missing an Accept Header’,severity:2,id:960015,tag:PROTOCOL_VIOLATION/MISSING_HEADER”
SecRule “REQUEST_METHOD” “!@rx ^OPTIONS$” “phase:2,log,deny,status:403,t:lowercase,t:replaceNulls,t:compressWhitespace,t:none”

–05bb5f20-Z–

–58f6736b-A–
[04/May/2009:15:27:58 --0400] KPPMD38AAAEAAAz7EvAAAAAD 192.168.5.100 58715 192.168.5.103 80
–58f6736b-B–
GET /INSTALL.pgsql.txt HTTP/1.0
Connection: Keep-Alive
User-Agent: Mozilla/4.75 (Nikto/2.02 )
Content-Type: application/x-www-form-urlencoded
Host: example.com

–58f6736b-F–
HTTP/1.1 403 Forbidden
Content-Length: 291
Connection: close
Content-Type: text/html; charset=iso-8859-1

–58f6736b-H–
Message: Access denied with code 403 (phase 2). Match of “rx ^OPTIONS$” against “REQUEST_METHOD” required. [file "/etc/httpd/conf.d/modsecurity/modsecurity_crs_21_protocol_anomalies.conf"] [line "41"] [id "960015"] [msg "Request Missing an Accept Header"] [severity "CRITICAL"] [tag "PROTOCOL_VIOLATION/MISSING_HEADER"]
Action: Intercepted (phase 2)
Stopwatch: 1241465278942223 1401 (317 721 -)
Producer: ModSecurity for Apache/2.5.9 (http://www.modsecurity.org/); core ruleset/1.6.1.
Server: Apache/2.2.3 (CentOS) DAV/2 PHP/5.1.6

–58f6736b-K–
SecRule “REQUEST_METHOD” “@rx ^(?:GET|HEAD)$” “phase:2,status:400,t:lowercase,t:replaceNulls,t:compressWhitespace,chain,t:none,deny,log,auditlog,msg:’GET or HEAD requests with bodies’,severity:2,id:960011,tag:PROTOCOL_VIOLATION/EVASION”
SecRule “&REQUEST_HEADERS:Accept” “@eq 0″ “phase:2,status:403,t:lowercase,t:replaceNulls,t:compressWhitespace,chain,skip:1,t:none,log,auditlog,msg:’Request Missing an Accept Header’,severity:2,id:960015,tag:PROTOCOL_VIOLATION/MISSING_HEADER”
SecRule “REQUEST_METHOD” “!@rx ^OPTIONS$” “phase:2,log,deny,status:403,t:lowercase,t:replaceNulls,t:compressWhitespace,t:none”

–58f6736b-Z–

–649c3f45-A–
[04/May/2009:15:27:58 --0400] KPPVSX8AAAEAAAz6EcYAAAAC 192.168.5.100 58716 192.168.5.103 80
–649c3f45-B–
GET /MAINTAINERS.txt HTTP/1.0
Connection: Keep-Alive
User-Agent: Mozilla/4.75 (Nikto/2.02 )
Content-Type: application/x-www-form-urlencoded
Host: example.com

–649c3f45-F–
HTTP/1.1 403 Forbidden
Content-Length: 289
Connection: close
Content-Type: text/html; charset=iso-8859-1

–649c3f45-H–
Message: Access denied with code 403 (phase 2). Match of “rx ^OPTIONS$” against “REQUEST_METHOD” required. [file "/etc/httpd/conf.d/modsecurity/modsecurity_crs_21_protocol_anomalies.conf"] [line "41"] [id "960015"] [msg "Request Missing an Accept Header"] [severity "CRITICAL"] [tag "PROTOCOL_VIOLATION/MISSING_HEADER"]
Action: Intercepted (phase 2)
Stopwatch: 1241465278944585 1455 (355 748 -)
Producer: ModSecurity for Apache/2.5.9 (http://www.modsecurity.org/); core ruleset/1.6.1.
Server: Apache/2.2.3 (CentOS) DAV/2 PHP/5.1.6

–649c3f45-K–
SecRule “REQUEST_METHOD” “@rx ^(?:GET|HEAD)$” “phase:2,status:400,t:lowercase,t:replaceNulls,t:compressWhitespace,chain,t:none,deny,log,auditlog,msg:’GET or HEAD requests with bodies’,severity:2,id:960011,tag:PROTOCOL_VIOLATION/EVASION”
SecRule “&REQUEST_HEADERS:Accept” “@eq 0″ “phase:2,status:403,t:lowercase,t:replaceNulls,t:compressWhitespace,chain,skip:1,t:none,log,auditlog,msg:’Request Missing an Accept Header’,severity:2,id:960015,tag:PROTOCOL_VIOLATION/MISSING_HEADER”
SecRule “REQUEST_METHOD” “!@rx ^OPTIONS$” “phase:2,log,deny,status:403,t:lowercase,t:replaceNulls,t:compressWhitespace,t:none”

–649c3f45-Z–

–b5bbaa37-A–
[04/May/2009:15:27:58 --0400] KPPecn8AAAEAAAz5ENkAAAAB 192.168.5.100 58717 192.168.5.103 80
–b5bbaa37-B–
GET /sites/default/settings.php HTTP/1.0
Connection: Keep-Alive
User-Agent: Mozilla/4.75 (Nikto/2.02 )
Content-Type: application/x-www-form-urlencoded
Host: example.com

–b5bbaa37-F–
HTTP/1.1 403 Forbidden
Content-Length: 300
Connection: close
Content-Type: text/html; charset=iso-8859-1

–b5bbaa37-H–
Message: Access denied with code 403 (phase 2). Match of “rx ^OPTIONS$” against “REQUEST_METHOD” required. [file "/etc/httpd/conf.d/modsecurity/modsecurity_crs_21_protocol_anomalies.conf"] [line "41"] [id "960015"] [msg "Request Missing an Accept Header"] [severity "CRITICAL"] [tag "PROTOCOL_VIOLATION/MISSING_HEADER"]
Action: Intercepted (phase 2)
Stopwatch: 1241465278946930 1314 (311 685 -)
Producer: ModSecurity for Apache/2.5.9 (http://www.modsecurity.org/); core ruleset/1.6.1.
Server: Apache/2.2.3 (CentOS) DAV/2 PHP/5.1.6

–b5bbaa37-K–
SecRule “REQUEST_METHOD” “@rx ^(?:GET|HEAD)$” “phase:2,status:400,t:lowercase,t:replaceNulls,t:compressWhitespace,chain,t:none,deny,log,auditlog,msg:’GET or HEAD requests with bodies’,severity:2,id:960011,tag:PROTOCOL_VIOLATION/EVASION”
SecRule “&REQUEST_HEADERS:Accept” “@eq 0″ “phase:2,status:403,t:lowercase,t:replaceNulls,t:compressWhitespace,chain,skip:1,t:none,log,auditlog,msg:’Request Missing an Accept Header’,severity:2,id:960015,tag:PROTOCOL_VIOLATION/MISSING_HEADER”
SecRule “REQUEST_METHOD” “!@rx ^OPTIONS$” “phase:2,log,deny,status:403,t:lowercase,t:replaceNulls,t:compressWhitespace,t:none”

–b5bbaa37-Z–

–a3a5cf10-A–
[04/May/2009:15:27:58 --0400] KPPnhn8AAAEAAAz-Fo4AAAAH 192.168.5.100 58718 192.168.5.103 80
–a3a5cf10-B–
GET /cgi-perl/c32web.exe/GetImage?ImageName=CustomerEmail.txt%00.pdf  HTTP/1.0
Connection: Keep-Alive
User-Agent: Mozilla/4.75 (Nikto/2.02 )
Content-Type: application/x-www-form-urlencoded
Host: example.com

–a3a5cf10-F–
HTTP/1.1 400 Bad Request
Content-Length: 298
Connection: close
Content-Type: text/html; charset=iso-8859-1

–a3a5cf10-H–
Message: Access denied with code 400 (phase 2). Found 1 byte(s) in ARGS:ImageName outside range: 1-255. [file "/etc/httpd/conf.d/modsecurity/modsecurity_crs_20_protocol_violations.conf"] [line "92"] [id "960901"] [msg "Invalid character in request"] [severity "WARNING"] [tag "PROTOCOL_VIOLATION/EVASION"]
Action: Intercepted (phase 2)
Stopwatch: 1241465278949254 1489 (328 714 -)
Producer: ModSecurity for Apache/2.5.9 (http://www.modsecurity.org/); core ruleset/1.6.1.
Server: Apache/2.2.3 (CentOS) DAV/2 PHP/5.1.6

–a3a5cf10-K–
SecRule “REQUEST_METHOD” “@rx ^(?:GET|HEAD)$” “phase:2,status:400,t:lowercase,t:replaceNulls,t:compressWhitespace,chain,t:none,deny,log,auditlog,msg:’GET or HEAD requests with bodies’,severity:2,id:960011,tag:PROTOCOL_VIOLATION/EVASION”
SecRule “ARGS|ARGS_NAMES|REQUEST_HEADERS:Referer” “@validateByteRange 1-255″ “phase:2,status:400,t:lowercase,t:replaceNulls,t:compressWhitespace,deny,log,auditlog,msg:’Invalid character in request’,id:960901,tag:PROTOCOL_VIOLATION/EVASION,severity:4,t:none,t:urlDecodeUni”
SecRule “RESPONSE_STATUS” “@rx ^400$” “phase:5,status:403,t:lowercase,t:replaceNulls,t:compressWhitespace,t:none,chain,log,auditlog,pass,msg:’Invalid request’,id:960913,severity:2″

–a3a5cf10-Z–

–9587de26-A–
[04/May/2009:15:27:58 --0400] KPPwu38AAAEAAAz8FBwAAAAE 192.168.5.100 58719 192.168.5.103 80
–9587de26-B–
GET /sitemap.gz HTTP/1.0
Connection: Keep-Alive
User-Agent: Mozilla/4.75 (Nikto/2.02 )
Content-Type: application/x-www-form-urlencoded
Host: example.com

–9587de26-F–
HTTP/1.1 403 Forbidden
Content-Length: 284
Connection: close
Content-Type: text/html; charset=iso-8859-1

–9587de26-H–
Message: Access denied with code 403 (phase 2). Match of “rx ^OPTIONS$” against “REQUEST_METHOD” required. [file "/etc/httpd/conf.d/modsecurity/modsecurity_crs_21_protocol_anomalies.conf"] [line "41"] [id "960015"] [msg "Request Missing an Accept Header"] [severity "CRITICAL"] [tag "PROTOCOL_VIOLATION/MISSING_HEADER"]
Action: Intercepted (phase 2)
Stopwatch: 1241465278951611 1449 (352 722 -)
Producer: ModSecurity for Apache/2.5.9 (http://www.modsecurity.org/); core ruleset/1.6.1.
Server: Apache/2.2.3 (CentOS) DAV/2 PHP/5.1.6

–9587de26-K–
SecRule “REQUEST_METHOD” “@rx ^(?:GET|HEAD)$” “phase:2,status:400,t:lowercase,t:replaceNulls,t:compressWhitespace,chain,t:none,deny,log,auditlog,msg:’GET or HEAD requests with bodies’,severity:2,id:960011,tag:PROTOCOL_VIOLATION/EVASION”
SecRule “&REQUEST_HEADERS:Accept” “@eq 0″ “phase:2,status:403,t:lowercase,t:replaceNulls,t:compressWhitespace,chain,skip:1,t:none,log,auditlog,msg:’Request Missing an Accept Header’,severity:2,id:960015,tag:PROTOCOL_VIOLATION/MISSING_HEADER”
SecRule “REQUEST_METHOD” “!@rx ^OPTIONS$” “phase:2,log,deny,status:403,t:lowercase,t:replaceNulls,t:compressWhitespace,t:none”

–9587de26-Z–

–12adf90c-A–
[04/May/2009:15:27:58 --0400] KPP6838AAAEAAAz4D90AAAAA 192.168.5.100 58720 192.168.5.103 80
–12adf90c-B–
GET /content/sitemap.gz HTTP/1.0
Connection: Keep-Alive
User-Agent: Mozilla/4.75 (Nikto/2.02 )
Content-Type: application/x-www-form-urlencoded
Host: example.com

–12adf90c-F–
HTTP/1.1 403 Forbidden
Content-Length: 292
Connection: close
Content-Type: text/html; charset=iso-8859-1

–12adf90c-H–
Message: Access denied with code 403 (phase 2). Match of “rx ^OPTIONS$” against “REQUEST_METHOD” required. [file "/etc/httpd/conf.d/modsecurity/modsecurity_crs_21_protocol_anomalies.conf"] [line "41"] [id "960015"] [msg "Request Missing an Accept Header"] [severity "CRITICAL"] [tag "PROTOCOL_VIOLATION/MISSING_HEADER"]
Action: Intercepted (phase 2)
Stopwatch: 1241465278954227 1302 (306 718 -)
Producer: ModSecurity for Apache/2.5.9 (http://www.modsecurity.org/); core ruleset/1.6.1.
Server: Apache/2.2.3 (CentOS) DAV/2 PHP/5.1.6

–12adf90c-K–
SecRule “REQUEST_METHOD” “@rx ^(?:GET|HEAD)$” “phase:2,status:400,t:lowercase,t:replaceNulls,t:compressWhitespace,chain,t:none,deny,log,auditlog,msg:’GET or HEAD requests with bodies’,severity:2,id:960011,tag:PROTOCOL_VIOLATION/EVASION”
SecRule “&REQUEST_HEADERS:Accept” “@eq 0″ “phase:2,status:403,t:lowercase,t:replaceNulls,t:compressWhitespace,chain,skip:1,t:none,log,auditlog,msg:’Request Missing an Accept Header’,severity:2,id:960015,tag:PROTOCOL_VIOLATION/MISSING_HEADER”
SecRule “REQUEST_METHOD” “!@rx ^OPTIONS$” “phase:2,log,deny,status:403,t:lowercase,t:replaceNulls,t:compressWhitespace,t:none”

–12adf90c-Z–

–70636e7d-A–
[04/May/2009:15:27:58 --0400] KPQEH38AAAEAAAz9FwcAAAAF 192.168.5.100 58721 192.168.5.103 80
–70636e7d-B–
GET /icons/README HTTP/1.0
Connection: Keep-Alive
User-Agent: Mozilla/4.75 (Nikto/2.02 )
Content-Type: application/x-www-form-urlencoded
Host: example.com

–70636e7d-F–
HTTP/1.1 403 Forbidden
Content-Length: 286
Connection: close
Content-Type: text/html; charset=iso-8859-1

–70636e7d-H–
Message: Access denied with code 403 (phase 2). Match of “rx ^OPTIONS$” against “REQUEST_METHOD” required. [file "/etc/httpd/conf.d/modsecurity/modsecurity_crs_21_protocol_anomalies.conf"] [line "41"] [id "960015"] [msg "Request Missing an Accept Header"] [severity "CRITICAL"] [tag "PROTOCOL_VIOLATION/MISSING_HEADER"]
Action: Intercepted (phase 2)
Stopwatch: 1241465278956575 1581 (492 857 -)
Producer: ModSecurity for Apache/2.5.9 (http://www.modsecurity.org/); core ruleset/1.6.1.
Server: Apache/2.2.3 (CentOS) DAV/2 PHP/5.1.6

–70636e7d-K–
SecRule “REQUEST_METHOD” “@rx ^(?:GET|HEAD)$” “phase:2,status:400,t:lowercase,t:replaceNulls,t:compressWhitespace,chain,t:none,deny,log,auditlog,msg:’GET or HEAD requests with bodies’,severity:2,id:960011,tag:PROTOCOL_VIOLATION/EVASION”
SecRule “&REQUEST_HEADERS:Accept” “@eq 0″ “phase:2,status:403,t:lowercase,t:replaceNulls,t:compressWhitespace,chain,skip:1,t:none,log,auditlog,msg:’Request Missing an Accept Header’,severity:2,id:960015,tag:PROTOCOL_VIOLATION/MISSING_HEADER”
SecRule “REQUEST_METHOD” “!@rx ^OPTIONS$” “phase:2,log,deny,status:403,t:lowercase,t:replaceNulls,t:compressWhitespace,t:none”

–70636e7d-Z–

Previous post:

Next post: