Apache Security - Ivan Ristic [108]
The default logging format is adequate to generate traffic statistics but inadequate for forensic analysis. We need to use the custom logging facility and design a log format that provides us with the information we need. By starting with the combined log format and adding more fields, we increase the information logged while retaining backward-compatibility with traffic analysis software.
We add six fields to the log format:
POST request body
From the application or mod_security
Unique request identifier
Created by mod_unique_id
Request processing time
From Apache
Session identifier
From the application
Application warning
From the application
Error message
From Apache
The new log format will be shown soon after discussing how the information needed for the additional fields may be obtained. For example, integration with applications is required to achieve adequate logging levels. This comes in two forms: usage of HTTP status codes and integration with PHP.
Using HTTP status codes
First, the application must make use of HTTP status codes other than 200 (which is used by default) where appropriate. These codes are very useful but not many applications utilize them. There are five code categories (see Table 8-5).
Table 8-5. HTTP status codes overview
Overall range
Defined range
Category
100-199
100-101
Informational
200-299
200-206
Successful
300-399
300-305
Redirection
400-499
400-417
Client error
500-599
500-505
Server error
The 4XX category is particularly interesting and is the one we use the most (see Table 8-6).
Table 8-6. HTTP client error status codes
Status code
Reason
400
Bad Request
401
Unauthorized
402
Payment Required
403
Forbidden
404
Not Found
405
Method Not Allowed
406
Not Acceptable
407
Proxy Authentication Required
408
Request Timeout
409
Conflict
410
Gone
411
Length Required
412
Precondition Failed
413
Request Entity Too Large
414
Request URI Too Long
415
Unsupported Media Type
416
Request Range Not Satisfiable
417
Expectation Failed
With the status codes in mind, Table 8-7 presents the codes an application should return, given various events.
Table 8-7. HTTP status code usage in response to application events
Event
Status code
Prevented hack attempt
400
Failed login attempt
401
User is denied access to a resource or an action is forbidden
403
Page not found (suitable for CMS applications)
404
Unexpected processing error (e.g., SQL query failed)
500
At first, I thought using the 401 status would be impossible since it would make the browser ask users to enter their credentials. Having done some tests, I determined that returning the status code alone (without the WWW-Authenticate header) is insufficient to trigger the authentication process. The 401 status can be used after all, and it appears in the access log.
Integration with PHP
When installed as a module, PHP integrates with Apache and allows direct communication between modules to take place. Other application engines may provide similar support. We will take advantage of the POST request body being available to the PHP code. We can, therefore, take the body and return it to Apache, along with other parameters known to the application (the username and the session identifier). This is possible because Apache has a feature called notes, which was specifically designed for inter-module communication.
The following code fragment sends some of the information from the PHP module to Apache, where the information is available for other modules to use. It creates four Apache notes: x_username, x_sessionid, x_request, and x_log.
function inform_apache($username, $sessionid) {
// reconstruct the first line of the request
$request = $_SERVER["REQUEST_METHOD"];
$request .= " " . $_SERVER["REQUEST_URI"];
// add any available