Last active
July 16, 2024 15:13
-
-
Save angeloxx/97714f9108b3642460564acdcd37b34a to your computer and use it in GitHub Desktop.
ModSecurity ClamAV integration script (LUA)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/lua | |
--[[ | |
This script can be used to inspect uploaded files for viruses | |
via ClamAV. To implement, use with the following ModSecurity rule: | |
SecRule FILES_TMPNAMES "@inspectFile /opt/modsecurity/bin/modsec-clamscan.lua" "phase:2,t:none,log,deny" | |
Author: Angelo Conforti (based on Josh Amishav-Zlatin code) | |
Requires the clamav-server and clamav-scanner | |
If you use SELinux on RHEL base distro: | |
setsebool -P antivirus_can_scan_system 1 | |
And remember that CentOS ClamAV distribution has some issue | |
with permission in the "default" configuration. Use Debian and | |
you'll be happy :) | |
This program is free software: you can redistribute it and/or modify | |
it under the terms of the GNU General Public License as published by | |
the Free Software Foundation, either version 3 of the License, or | |
(at your option) any later version. | |
This program is distributed in the hope that it will be useful, | |
but WITHOUT ANY WARRANTY; without even the implied warranty of | |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
GNU General Public License for more details. | |
You should have received a copy of the GNU General Public License | |
along with this program. If not, see <http://www.gnu.org/licenses/>. | |
]]-- | |
function fsize(filename) | |
file = io.open(filename,"r") | |
local current = file:seek() | |
local size = file:seek("end") | |
file:seek("set",current) | |
file:close() | |
return size | |
end | |
function main(filename) | |
-- Configure paths | |
local clamdscan = "/usr/bin/clamdscan" | |
local clamscan = "/usr/bin/clamscan" | |
-- failoverOnClamdFailure: failover to clamscan if clamdscan report an error | |
local failoverOnClamdFailure = true | |
-- fail (and block) if clamdscan (and clamscan) fails | |
local failOnError = false | |
-- local var | |
local agent = "clamdscan" | |
-- Skip empty items because if clamd is not working and you | |
-- use the clamscan agent an empty file can take about 12 secs | |
-- to be analyzed | |
if fsize(filename) == 0 then | |
m.log(1, "[scanav skipped, file " .. filename .." size is zero]") | |
return nil | |
end | |
-- The system command we want to call with fdpass flag to | |
-- do not incur in a permission issue | |
local cmd = clamdscan .. " --fdpass --stdout --no-summary" | |
-- Run the command and get the output | |
local f = io.popen(cmd .. " " .. filename .. " || true") | |
local l = f:read("*a") | |
f:close() | |
-- Check the output for the FOUND or ERROR strings which indicate | |
-- an issue we want to block access on | |
local isVuln = string.find(l, "FOUND") | |
local isError = string.find(l, "ERROR") | |
-- If clamdscan fails and you want failover to the traditional clamscan... | |
if isError and failoverOnClamdFailure then | |
-- Try to use the clamscan program | |
m.log(1, "[clamdscan fails (" .. l .. "), failover to clamscan]") | |
agent = "clamscan" | |
cmd = clamscan .. " --stdout --no-summary" | |
f = io.popen(cmd .. " " .. filename .. " || true") | |
l = f:read("*a") | |
f:close() | |
isVuln = string.find(l, "FOUND") | |
isError = string.find(l, "ERROR") | |
end | |
if isVuln then | |
m.log(1, "[" .. agent .. " scanner message: " .. l .. "]") | |
return "Virus Detected" | |
elseif isError and failOnError then | |
-- is a error (not a virus) a failure event? | |
m.log(1, "[" .. agent .. " scanner message: " .. l .. "]") | |
return "Error Detected" | |
else | |
return nil | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment