mod_security is enabled when ClamAV malware scanning is enabled. This can be checked and toggled using the system.virus-scanner Scope.
# If false, malware scanning is disabled
cpcmd scope:get system.virus-scanner
# Enable malware scanning
cpcmd scope:set system.virus-scanner clamav
# Likewise, to disable it
cpcmd scope:set system.virus-scanner false
# Testing
An EICAR test (opens new window) file may be used to evaluate whether mod_security is setup correctly.
TIP
It may be necessary to disable anti-virus software briefly to download the test file. EICAR is a universal test for anti-virus software. If AV is working correctly, then EICAR will be deleted/quarantined once it's downloaded onto your machine.
Create a test HTML file named "test-upload.html", which accepts a form upload. Place this file in /var/www/html
:
cat > /var/www/html/test-upload.html <<- EOF
<! DOCTYPE html>
<html>
<body>
<form action="test-upload.html" method="post" enctype="multipart/form-data">
<input type="file" name="file" id="fileToUpload">
<input type="submit" value="Upload Test" name="submit">
</form>
</body>
</html>
EOF
Next access https://<SERVER IP>/test-upload.html and upload the EICAR text file. If mod_security is working as intended, it will return a "406 Not Acceptable" status code. Alternatively you may test it via cURL too:
echo 'K5B!C%@NC[4\CMK54(C^)7PP)7}$RVPNE-FGNAQNEQ-NAGVIVEHF-GRFG-SVYR!$U+U*' | tr '[A-Za-z]' '[N-ZA-Mn-za-m]' | curl -F 'file=@-' http://<SERVER IP>/test-upload.html
DETAILS
EICAR characters are transliterated using ROT-13 to avoid detection by anti-virus software, otherwise submission is identical to desktop submission.
Additional logging evidence will be present in /var/log/messages and /var/log/httpd.
Feb 12 14:48:56 testing clamd[6668]: fd[12]: {HEX}EICAR.TEST.3.UNOFFICIAL(44d88612fea8a8f36de82e1278abb02f:68) FOUND
# via modsec_audit.log
192.168.0.147 192.168.0.147 - - [12/Feb/2020:14:53:25 --0500] "POST /test-upload.html HTTP/1.1" 406 249 "-" "-" XkRXtW8X20xyKcESfznVdwAAAE4 "-" /20200212/20200212-1453/20200212-145325-XkRXtW8X20xyKcESfznVdwAAAE4 0 2276 md5:175e0cfd277ec488f0c1b401e06b68c0
# via modsec_debug.log
[12/Feb/2020:14:53:25 --0500] [192.168.0.147/sid#558bcb9dcac8][rid#7f00d80e11c0][/test-upload.html][1] Access denied with code 406 (phase 2). Virus Detected [file "/etc/httpd/modsecurity.d/activated_rules/clamav.conf"] [line "5"] [id "1010101"] [msg "Malicious File Attachment"] [severity "ALERT"]
# Lua testing
Testing from a HTML upload applet is sufficient for most situations; however, additional testing may be done to isolate the Lua/ClamAV segment. Apache <=> mod_security <=> Lua <=> ClamAV. Create a m.log() method for interoperability.
Call lua
passing off the runAV.lua script to it:
lua -i /etc/httpd/modsecurity.d/runAV.lua
Then create a stub logger to evaluate the file /eicar with an EICAR signature:
m = {}
function m:log(log)
print(log)
end
print(main('/eicar'))
Confirmation will be similar, reporting the virus found.
# Whitelisting
Signatures may be whitelisted using virus-scanner.signature-whitelist
Scope. Each signature is normalized into a format understood by ClamAV. For example to whitelist {HEX}EICAR.TEST.3.UNOFFICIAL(44d88612fea8a8f36de82e1278abb02f:68)
from the above example:
cpcmd scope:set virus-scanner.signature-whitelist '{HEX}EICAR.TEST.3.UNOFFICIAL(44d88612fea8a8f36de82e1278abb02f:68)'
Internally the signature will be saved as {HEX}EICAR.TEST.3
to /var/lib/clamav/custom-whitelist.ign2
. Whitelisted signatures can be retrieved using the complementary method, get
.
cpcmd scope:get virus-scanner.signature-whitelist
# Malware bypass
New in 3.2.26
Malware scans may be bypassed using a special environment variable in the request. An optional value may be specified as a secret to prevent a client from purposefully defeating malware protection.
# Allow bypass marker usage
cpcmd scope:set cp.bootstrapper modsec_clamav_marker True
# Update HTTP configuration
upcp -sb apache/modsecurity
Marker Value | Purpose |
---|---|
True | Enable bypass usage |
False | Disable bypass usage |
alphanumeric value | Requires .htaccess to match this value |
For example, if modsec_clamav_marker
does not specify a value, then the following .htaccess (opens new window) directive bypasses scans:
SetEnv BYPASS_SCAN ""
If modsec_clamav_marker
is acba3trCZ
, then the following .htaccess (opens new window) directive would allow a client to bypass scanning:
SetEnv BYPASS_SCAN "acba3trCZ"
Likewise the server secret would be set with,
# Allow bypass marker usage
cpcmd scope:set cp.bootstrapper modsec_clamav_marker acba3trCZ
# Update HTTP configuration
upcp -sb apache/modsecurity
Specifying a marker value allows periodic rotation of protection keys.
# Remote anti-virus
When multiple servers exist in a cluster, it's beneficial to designate one server ClamAV duties. Such an arrangement is easy to accomplish.
DoS risks
Use cpcmd rampart:whitelist CLIENT.IP.ADD.RESS
to whitelist each client IP on the ClamAV scanner. There is no protection against malicious usage resulting in information disclosure or denial of service attacks. There is absolutely zero authentication. Firewall authorization is the only safety.
You have been warned. See also ClamAV's official bulletin (opens new window).
Assuming 1.2.2.1 is the ClamAV scanner and 1.2.2.3 is a participating node using 1.2.2.1 to scan malware:
On host, 1.2.2.1:
cpcmd scope:set cp.bootstrapper clamav_clamd_tcp_addr 1.2.2.1
upcp -sb clamav/setup
# Allow communication from 1.2.2.3 to bypass firewall
cpcmd rampart:whitelist 1.2.2.3
On client, 1.2.2.3
cpcmd scope:set cp.bootstrapper clamav_clamd_tcp_addr 1.2.2.1
# Setting true implicitly sets clamav_clamd_local_socket to null
cpcmd scope:set cp.bootstrapper clamav_client_only true
cpcmd scope:set cp.bootstrapper clamav_enabled true
upcp -sb clamav/setup
Then perform an EICAR test on client to confirm communication,
echo 'K5B!C%@NC[4\CMK54(C^)7PP)7}$RVPNE-FGNAQNEQ-NAGVIVEHF-GRFG-SVYR!$U+U*' | tr '[A-Za-z]' '[N-ZA-Mn-za-m]' > /eicar
clamdscan /eicar
rm -f /eicar
# Troubleshooting
# 406 Not Acceptable on POST
ClamAV has determined the file to contain potential malware. Run the file through VirusTotal.com (opens new window) first to confirm the file does not contain malware and this is a false positive. The signature may be whitelisted following the "Whitelisting" section above.
# 413 Request Entity Too Large on POST
When sending a large payload (> 256 KB) as a POST, mod_security will reject the content with a 413 Request Entity Too Large
response. This occurs from a combination of the request size and form encoding type ("enctype"). When submitting files, the form enctype should be set as "multipart/form-data". A form default encoding type is "application/x-www-form-urlencoded" and unsuitable for sending large files (RFC 1867 (opens new window) § 3.2). Moreover, specifying "multipart/form-data" allows a file to suggest its MIME disposition and character encoding (RFC 2388 (opens new window) § 5.6).
mod_security sets a POST limit of 256 KB. This may be raised using Bootstrapper. Size is in bytes. The following example sets the limit to 4 MB using builtin arithmetic in bash.
cpcmd scope:set cp.bootstrapper modsec_limit_nofiles $((4*1024*1024))
upcp -sb apache/modsecurity
A preferred workaround is to correct the form by specifying enctype="multipart/form-data"
for the offending code as this is the correct way to submit large files and binary data.
# Slow upload
Each file created by the web server is scanned with ClamAV when enabled. Uploading a multitude of files, such as during a WordPress site import using a plugin, will result in extended processing times. Bypassing scans using an environment variable is recommended for short-term usage.