Scan uploaded files with Apache + mod_security + scanner script

Published on Author gryzli

A lot of people start thinking about scanning the uploaded files in order to improve their site security. Giving the fact that Apache is the most used web server out there, one way to achieve such thing is by using the powerfull mod_security.


Mod_Security has option, where you can tell it to scan certain uploaded files and decide if this is malicious or not.


The request flow is as follows:

  1. User request for file upload comes to Apache
  2. Mod_security executes the parser script and waits for it to return output
  3. Mod_Security checks the script output and decides whether the request must be blocked
  4. Apache returns answer to the user


Here is a step-by-step manual on configuring simple file-upload parser with mod_security

1| Configure Apache + mod_security to access RequestBody and Process uploaded files

# This configuration directives must be added in httpd.conf or relevant configuration file containing mod_security related options:

SecRuleEngine On

SecRequestBodyAccess On 

SecUploadDir /var/lib/mod_security

SecTmpDir /var/lib/mod_security

SecRequestBodyAccess On
SecTmpSaveUploadedFiles On # If you use mod_security 2.9 or above, this is NECESSARY

SecRequestBodyLimit 13107200 # Set some limit to the RequestBody we are going to process

SecRequestBodyLimitAction Reject # What to do if we exceed the RequestBodyLimit size


2| Create the rule, which will spawn external script to process file uploads

This is as simple as the following:

SecRule FILES_TMPNAMES “@inspectFile /tmp/” “id:2222, deny”


FILES_TMPNAMES – Tells mod_security to go over temporary file names (of the uploaded files)

@inspectFile /tmp/ – Tells mod_security to spawn /tmp/ for every TEMP FILE . This could be whatever you want  (bash, perl, python …etc). But you must make sure that Apache can execute this script.

“id:2222, deny”  – The id of the rule is “2222” and if the rules matches we are going to “deny”


3| Create the parser script

This is a really simple example, which can be modified in order to suit your needs


use strict; 
use warnings; 
use Data::Dumper; 

my $log_file="/tmp/mod_security_scan_log.txt"; 

open my $log_fh, ">>", "$log_file"; 

print {$log_fh} Dumper (%ENV) ;
print {$log_fh} "File to process: $ARGV[0]\n";

# If we want success 
print "0 OK"; 

The script is pretty simple and does the following:

  • Opens logfile:
  • Prints %ENV + $ARGV[0] in the temp file
  • Returns “0 OK”, which causes mod_security to pass the request


Here you must keep in mind the following things:

  1. Parser script must be executable by the Apache user (usually apache on default config)
  2. Mod_security passes the temporary file as argument 1 , which in perl is visible like $ARGV[0]
  3. Mod_security waits the parser script to execute in order to return message to the user
  4. Mod_security expects the followings 2 variations as out from the parser
    Both lines are WITHOUT “new line (\n)”
  • OR

If your output is more then the expected, mod_security won’t take action.

If the parser script DOESN’T exists or the script CAN’T BE EXECUTED, the request will be PASSED.