Implementing Security Best Practices
1. Disabling Directory Listing
| Directive | Values | Description |
|---|---|---|
| Options | -Indexes |
Disables directory listing for the specified directory or its subdirectories |
| Options | Indexes |
Enables directory listing (default behavior if not overridden) |
Example: Disabling directory listing for a specific directory
<Directory "/var/www/html/private">
Options -Indexes
</Directory>
Note: The
-Indexes directive prevents users from viewing the contents of directories when no index file (e.g., index.html) is present.
2. Hiding Server Version
By default, Apache includes server version information in HTTP response headers and error pages. Hiding this information enhances security by preventing attackers from identifying the server type and version.
| Directive | Values | Description |
|---|---|---|
| ServerTokens | Prod, Major, Minor, Minimal, OS, Full |
Controls the level of information included in the Server header. Prod is recommended for production environments. |
| ServerSignature | On, Off |
Determines whether the server signature is included in error pages. Set to Off to hide version details. |
Example: Configuring Server Tokens and Signature
<IfModule mod_server.c>
ServerTokens Prod
ServerSignature Off
</IfModule>
Note: Setting
ServerTokens Prod ensures that only the server name (e.g., "Apache") is sent in the Server header, without version details.
3. Removing Server Signature
| Directive | Values | Description |
|---|---|---|
| ServerSignature | Off |
Hides the server signature from error pages and directory listings |
| ServerTokens | Prod |
Reduces the amount of information exposed in the Server header to just "Apache" |
Example: Configuring Server Signature Removal
<IfModule mod_security2.c>
SecServerSignature "Apache"
</IfModule>
ServerSignature Off
ServerTokens Prod
Note: Setting
ServerTokens Prod ensures that only the server name is shown in the HTTP response header, not the full version string.
4. Configuring Secure File Permissions
| Permission | Description | Recommended Setting | Notes |
|---|---|---|---|
| Owner | User who owns the files and directories | root or dedicated user | Ensure only authorized users have ownership |
| Group | Group that owns the files and directories | www-data or apache | Use a dedicated group for web server access |
| Read (r) | Allows reading file contents | 4 | Only necessary for files that need to be read |
| Write (w) | Allows modifying file contents | 2 | Restricted to necessary directories like logs or uploads |
| Execute (x) | Allows executing files or traversing directories | 1 | Only required for scripts and directories |
Example: Setting Secure Permissions
chown -R root:www-data /var/www/html
chmod -R 750 /var/www/html
chmod 640 /var/www/html/config.php
Note: Avoid setting permissions to 777 as it grants full access to all users.
Warning: Incorrect file permissions can lead to security vulnerabilities such as unauthorized access or code execution.
| File Type | Recommended Permissions | Explanation |
|---|---|---|
| Web Root Files | 640 |
Readable by owner and group, not world-readable |
| Log Files | 640 |
Secure and readable by log reader |
| Configuration Files | 640 |
Prevent unauthorized access to sensitive settings |
| Upload Directories | 750 |
Allow write access to web server, restrict others |
| Executable Scripts | 750 |
Allow execution by owner and group, not others |
5. Implementing ModSecurity WAF
| Directive | Description | Default Value | Notes |
|---|---|---|---|
| SecRuleEngine | Enables or disables ModSecurity | Off |
Set to On to enable rules, DetectionOnly for logging only |
| SecRequestBodyAccess | Enables or disables request body inspection | Off |
Required for rule matching on request bodies |
| SecResponseBodyAccess | Enables or disables response body inspection | Off |
Useful for detecting malicious content in responses |
| SecRule | Defines a rule to match against requests | N/A | Used in conjunction with SecRuleEngine |
Example: Basic ModSecurity Configuration
<IfModule mod_security2.c>
SecRuleEngine On
SecRequestBodyAccess On
SecResponseBodyAccess On
SecRule "REQUEST_URI" "/admin/" "id:1001,phase:1,deny,msg:\"Access Denied\""
</IfModule>
Note: ModSecurity requires the
mod_security2 module to be installed and enabled in Apache.
Warning: Misconfigured rules can block legitimate traffic. Always test in a staging environment before deploying to production.
| Rule Type | Description | Use Case |
|---|---|---|
| Core Rule Set (CRS) | Predefined set of OWASP-modified rules | Recommended for most users to start with |
| Custom Rules | Rules written specifically for your application | Use when you need to address specific threats or business logic |
| Whitelist Rules | Rules that exempt certain traffic from inspection | Useful for known good endpoints or services |
Key Configuration Options
SecRuleEngine: Controls whether ModSecurity is active.SecRequestBodyAccess: Enables inspection of request bodies.SecResponseBodyAccess: Enables inspection of response bodies.
6. Restricting HTTP Methods
| Method | Description | Restriction Status | Notes |
|---|---|---|---|
| GET | Retrieve data from the server | ALLOWED | Standard method for reading resources |
| POST | Send data to the server for processing | ALLOWED | Used for form submissions and API calls |
| PUT | Update or replace existing resources | RESTRICTED | May pose security risks if not properly validated |
| DELETE | Remove resources from the server | RESTRICTED | High-risk operation; should be protected with authentication |
| PATCH | Partially update a resource | ALLOWED | Used in REST APIs for partial updates |
| HEAD | Retrieve headers only (no body) | ALLOWED | Useful for checking resource existence or metadata |
| OPTIONS | Discover supported methods for a resource | ALLOWED | Used by CORS and client-side discovery tools |
Example: Restricting HTTP Methods with mod_security
<IfModule mod_security.c>
SecRule REQUEST_METHOD "^(PUT|DELETE)$" \
"msg:\"Disallowed HTTP Method\", \
log, deny, status:405"
</IfModule>
Note: The
OPTIONS method should generally be allowed to support CORS and client-side discovery, but it can be restricted in sensitive environments.
7. Preventing Hotlinking
| Directive | Description | Usage |
|---|---|---|
| RewriteEngine | Enables or disables the rewrite engine | RewriteEngine on |
| RewriteCond | Defines a condition for the rewrite rule | RewriteCond %{HTTP_REFERER} !^https?://(www\.)?yourdomain\.com/ [NC] |
| RewriteRule | Defines the rewrite rule to block hotlinking | RewriteRule \.(jpg|jpeg|png|gif|webp)$ - [F,L] |
Example: Preventing Hotlinking with Rewrite Rules
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?yourdomain\.com/ [NC]
RewriteRule \.(jpg|jpeg|png|gif|webp)$ - [F,L]
</IfModule>
Note: This configuration blocks direct access to images from external domains. It does not prevent users from copying the image URL and viewing it directly in their browser.
8. Disabling Trace Method
| Directive | Values | Description |
|---|---|---|
| TraceEnable | Off |
Disables the TRACE method to prevent potential security vulnerabilities such as XSS attacks. |
Note: The TRACE method can be exploited in Cross-Site Tracing (XST) attacks. It's recommended to disable it for enhanced security.
9. Securing Sensitive Directories
| Directory | Security Level | Configuration |
|---|---|---|
| /private | High | <Directory "/private"> Require all denied</Directory> |
| /logs | Medium | <Directory "/var/log"> Require all denied</Directory> |
| /config | High | <Directory "/etc/httpd/conf"> Require all denied</Directory> |
Example: Restricting Access to Sensitive Directories
<Directory "/var/www/html/private">
Require all denied
</Directory>
<Directory "/var/www/html/secure">
Require ip 192.168.1.0/24
</Directory>
Note: Ensure that sensitive directories like
/private, /logs, and /config are not accessible via web requests to prevent unauthorized access.
Warning: Misconfiguring directory permissions can expose sensitive data. Always test configurations in a staging environment before deploying to production.
10. Using Fail2ban with Apache
| Feature | Description | Configuration |
|---|---|---|
| fail2ban-client status | Check the status of fail2ban jails | fail2ban-client status |
| jail.conf | Configuration file for fail2ban rules | /etc/fail2ban/jail.conf |
| apache-badbots | Jail to block bad bots | Matches logs with bot signatures |
| apache-noscript | Jail to block scripts in Apache logs | Blocks access to .php, .asp files |
Example: Basic Fail2ban Configuration for Apache
[apache-badbots]
enabled = true
filter = apache-badbots
logpath = /var/log/apache2/access.log
maxretry = 1
bantime = 3600
ignoreip = 127.0.0.1/8
Example: Apache Log Format for Fail2ban
LogFormat "%h %l %u %t "%r" %>s %O "%{Referer}i" "%{User-Agent}i"" combined
Note: Ensure Apache logs are in a readable format for fail2ban to parse correctly.
Warning: Misconfiguring fail2ban can block legitimate users. Always test in a staging environment.
11. Implementing Request Size Limits
| Directive | Description | Default Value | Notes |
|---|---|---|---|
| LimitRequestBody | Sets the maximum allowed size of a request body in bytes. | 0 (unlimited) | Useful to prevent abuse or denial-of-service attacks. |
| LimitRequestFields | Sets the maximum number of request header fields. | 1000 | Prevents excessive header fields from consuming resources. |
| LimitRequestFieldSize | Sets the maximum allowed size of a request header field in bytes. | 8190 | Helps prevent oversized header fields from causing issues. |
| LimitRequestLine | Sets the maximum allowed size of a request line in bytes. | 8190 | Prevents overly long HTTP request lines from consuming memory. |
Example: Setting Request Size Limits
<IfModule mod_reqtimeout.c>
LimitRequestBody 10485760
LimitRequestFields 2000
LimitRequestFieldSize 8192
LimitRequestLine 8192
</IfModule>
Note: These directives are effective only when the
mod_reqtimeout module is loaded.
Warning: Setting
LimitRequestBody too low may prevent legitimate uploads (e.g., large file uploads). Ensure that limits are appropriate for your application's needs.
12. Performing Regular Security Audits
Example: Basic security audit configuration
<IfModule mod_security2.c>
SecRuleEngine On
SecAuditLog /var/log/apache2/security_audit.log
SecAuditLogFormat json
SecAuditLogParts ABCDEFHI
</IfModule>
| Directive | Description | Default | Notes |
|---|---|---|---|
| SecRuleEngine | Enables or disables the rule engine | Off | Must be set to On for security rules to be processed |
| SecAuditLog | Path to the audit log file | None | Must be writable by Apache user |
| SecAuditLogFormat | Format of the audit log (json or native) | native | JSON format is more structured and easier to parse |
| SecAuditLogParts | Parts of the request to log | ABCEFHI | Each letter represents a part of the request (A=Request Headers, B=Request Body, etc.) |
Note: Ensure the audit log directory has proper permissions to prevent unauthorized access.
Warning: Audit logs can grow very large. Implement log rotation to manage disk space.