Closed intelbg closed 6 years ago
Hi @intelbg,
Please check the most recent version of v3/master. The code was recently implemented there.
I did git clone -b v3/master https://github.com/SpiderLabs/ModSecurity and recompiled it again, but still the operator is missing. I a wrong in doing the git clone or I should use the branch v3/dev/inspectFile. Are this branches merged?
Can you please provide me md5 sum of the specific file?
@intelbg make sure you are cloning the repository into an empty directory.
@zimmerle I am sure it's cloned in empty directory. Is my command for git clone right?
@intelbg inspecFile support was added at https://github.com/SpiderLabs/ModSecurity/commit/1866a3a9eb59e293b12a5ca37513d3763b8bd5bb. See https://github.com/SpiderLabs/ModSecurity/blob/v3/master/src/operators/inspect_file.cc for reference.
"$ git clone -b v3/master https://github.com/SpiderLabs/ModSecurity" should work to clone to a new directory. To update your local repository with the current master "$git pull" should do the trick.
Hi @intelbg, @zimmerle, @victorhora,
I've been digging into libmodsecurity + clamav integration, and googled to this issue, so I decided to post some of my results here instead of creating another one.
The v3/master branch, as of https://github.com/SpiderLabs/ModSecurity/commit/480a2f89d786956bd98e41941c001e6afbd22728, does have working support for the @inspectFile operator.
Test env:
root@vagrant:/# lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 16.04.4 LTS
Release: 16.04
Codename: xenial
root@vagrant:/# dpkg -l | fgrep clamav
ii clamav 0.99.4+addedllvm-0ubuntu0.16.04.1 amd64 anti-virus utility for Unix - command-line interface
ii clamav-base 0.99.4+addedllvm-0ubuntu0.16.04.1 all anti-virus utility for Unix - base package
ii clamav-daemon 0.99.4+addedllvm-0ubuntu0.16.04.1 amd64 anti-virus utility for Unix - scanner daemon
ii clamav-freshclam 0.99.4+addedllvm-0ubuntu0.16.04.1 amd64 anti-virus utility for Unix - virus database update utility
ii libclamav7 0.99.4+addedllvm-0ubuntu0.16.04.1 amd64 anti-virus utility for Unix - library
ModSecurity config part:
root@vagrant:/# cat /etc/nginx/modsec/main.conf
Include /etc/nginx/modsec/modsecurity.conf
SecRule FILES_TMPNAMES "@inspectFile /usr/local/bin/runav.pl" \
"phase:2,t:none,deny,msg:'Virus found in uploaded file',id:'399999'"
The /usr/local/bin/runav.pl
script - note that it was modified ("1" and "0" in output have been swapped around, see below) and a bit differ from the "official" one at https://github.com/SpiderLabs/owasp-modsecurity-crs/blob/v3.0/master/util/av-scanning/runav.pl:
#!/usr/bin/env perl
#
# runav.pl
# Copyright (c) 2004-2011 Trustwave
#
# This script is an interface between ModSecurity and its
# ability to intercept files being uploaded through the
# web server and ClamAV.
$CLAMDSCAN = "clamdscan";
if ($#ARGV != 0) {
print "Usage: runav.pl <filename>\n";
exit;
}
my ($FILE) = shift @ARGV;
$cmd = "$CLAMDSCAN --stdout --no-summary $FILE";
$input = `$cmd`;
$input =~ m/^(.+)/;
$error_message = $1;
$output = "1 Unable to parse clamscan output [$1]";
if ($error_message =~ m/: Empty file\.?$/) {
$output = "0 empty file";
}
elsif ($error_message =~ m/: (.+) ERROR$/) {
$output = "1 clamscan: $1";
}
elsif ($error_message =~ m/: (.+) FOUND$/) {
$output = "1 clamscan: $1";
}
elsif ($error_message =~ m/: OK$/) {
$output = "0 clamscan: OK";
}
print "$output\n";
Test request for good file:
root@vagrant:/# curl -i -F 'upload=@"/tmp/configs.tar.gz"' http://localhost/modsec-full/upload/a/b/c/
HTTP/1.1 100 Continue
HTTP/1.1 200 OK
Server: nginx/1.13.9
Date: Tue, 20 Mar 2018 11:49:43 GMT
Content-Type: text/plain
Content-Length: 38
Connection: keep-alive
5522:4d3d67931da1f3de75c5b156140b174b
Test request for bad file (http://www.eicar.org/86-0-Intended-use.html):
root@vagrant:/# curl -i -F 'upload=@"/tmp/eicar.com"' http://localhost/modsec-full/upload/a/b/c/
HTTP/1.1 100 Continue
HTTP/1.1 403 Forbidden
Server: nginx/1.13.9
Date: Tue, 20 Mar 2018 11:50:34 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
<html>
<head><title>403 Forbidden</title></head>
<body bgcolor="white">
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.13.9</center>
</body>
</html>
Log for bad file:
2018/03/20 04:50:34 [info] 18473#18473: *6 ModSecurity: Access denied with code %d (phase 2). Matched "Operator `InspectFile' with parameter `/usr/local/bin/runav.pl' against variable `FILES_TMPNAMES:eicar.com' (Value: `eicar.com' ) [file "/etc/nginx/modsec/main.conf"] [line "31"] [id "399999"] [rev ""] [msg "Virus found in uploaded file"] [data ""] [severity "0"] [ver ""] [maturity "0"] [accuracy "0"] [hostname "127.0.0.1"] [uri "/modsec-full/upload/a/b/c/"] [unique_id "152154663498.971791"] [ref "v321,9"], client: 127.0.0.1, server: , request: "POST /modsec-full/upload/a/b/c/ HTTP/1.1", host: "localhost"
2018/03/20 04:50:34 [warn] 18473#18473: *6 [client 127.0.0.1] ModSecurity: Warning. Matched "Operator `InspectFile' with parameter `/usr/local/bin/runav.pl' against variable `FILES_TMPNAMES:eicar.com' (Value: `eicar.com' ) [file "/etc/nginx/modsec/main.conf"] [line "31"] [id "399999"] [rev ""] [msg "Virus found in uploaded file"] [data ""] [severity "0"] [ver ""] [maturity "0"] [accuracy "0"] [hostname "127.0.0.1"] [uri "/modsec-full/upload/a/b/c/"] [unique_id "152154663498.971791"] [ref "v321,9"], client: 127.0.0.1, server: , request: "POST /modsec-full/upload/a/b/c/ HTTP/1.1", host: "localhost"
Also, every run of external script from @inspectFile
operator produces two log lines in nginx error log (level "notice"):
2018/03/20 05:26:10 [notice] 18473#18473: signal 17 (SIGCHLD) received from 18603
2018/03/20 05:26:10 [notice] 18473#18473: unknown process 18603 exited with code 0
The 18473 in the above example is a pid of nginx worker process - so there is a fork/exec every time @inspectFile
is being iterated, and obviously this blocks nginx worker during the execution time.
Finally, I had to modify runav.pl
to swap around "1" and "0" in output in order to make it work as expected:
Corresponding parts of ModSecurity debug log, good case:
[4] Starting phase REQUEST_BODY. (SecRules 2)
[9] Multipart: Boundary: ------------------------de27167d9e098491
[9] Multipart: Added part header "Content-Disposition" "form-data; name="upload"; filename="configs.tar.gz"".
[9] Multipart: Added part header "Content-Type" "application/octet-stream".
[9] Multipart: Content-Disposition name: upload.
[9] Multipart: Content-Disposition filename: configs.tar.gz.
[9] Multipart: Added file part to the list: name "upload" file name "configs.tar.gz" (offset 160, length 5314)
[4] Multipart: Cleanup started (remove files Not set)
[9] This phase consists of 5 rule(s).
[4] (Rule: 200002) Executing operator "Eq" with param "0" against REQBODY_ERROR.
[9] Target value: "0" (Variable: REQBODY_ERROR)
[4] Rule returned 0.
[9] Matched vars cleaned.
[4] (Rule: 200003) Executing operator "Eq" with param "0" against MULTIPART_STRICT_ERROR.
[9] Target value: "0" (Variable: MULTIPART_STRICT_ERROR)
[4] Rule returned 0.
[9] Matched vars cleaned.
[4] (Rule: 200004) Executing operator "Eq" with param "0" against MULTIPART_UNMATCHED_BOUNDARY.
[9] Target value: "0" (Variable: MULTIPART_UNMATCHED_BOUNDARY)
[4] Rule returned 0.
[9] Matched vars cleaned.
[4] (Rule: 200005) Executing operator "StrEq" with param "0" against TX:regex(^MSC_).
[4] Rule returned 0.
[9] Matched vars cleaned.
[4] (Rule: 399999) Executing operator "InspectFile" with param "/usr/local/bin/runav.pl" against FILES_TMPNAMES.
[9] Target value: "configs.tar.gz" (Variable: FILES_TMPNAMES:configs.tar.gz)
[4] Rule returned 0.
[9] Matched vars cleaned.
Bad case:
[4] Starting phase REQUEST_BODY. (SecRules 2)
[9] Multipart: Boundary: ------------------------7379d86185e7c6b7
[9] Multipart: Added part header "Content-Disposition" "form-data; name="upload"; filename="eicar.com"".
[9] Multipart: Added part header "Content-Type" "application/octet-stream".
[9] Multipart: Content-Disposition name: upload.
[9] Multipart: Content-Disposition filename: eicar.com.
[9] Multipart: Added file part to the list: name "upload" file name "eicar.com" (offset 155, length 68)
[4] Multipart: Cleanup started (remove files Not set)
[9] This phase consists of 5 rule(s).
[4] (Rule: 200002) Executing operator "Eq" with param "0" against REQBODY_ERROR.
[9] Target value: "0" (Variable: REQBODY_ERROR)
[4] Rule returned 0.
[9] Matched vars cleaned.
[4] (Rule: 200003) Executing operator "Eq" with param "0" against MULTIPART_STRICT_ERROR.
[9] Target value: "0" (Variable: MULTIPART_STRICT_ERROR)
[4] Rule returned 0.
[9] Matched vars cleaned.
[4] (Rule: 200004) Executing operator "Eq" with param "0" against MULTIPART_UNMATCHED_BOUNDARY.
[9] Target value: "0" (Variable: MULTIPART_UNMATCHED_BOUNDARY)
[4] Rule returned 0.
[9] Matched vars cleaned.
[4] (Rule: 200005) Executing operator "StrEq" with param "0" against TX:regex(^MSC_).
[4] Rule returned 0.
[9] Matched vars cleaned.
[4] (Rule: 399999) Executing operator "InspectFile" with param "/usr/local/bin/runav.pl" against FILES_TMPNAMES.
[9] Target value: "eicar.com" (Variable: FILES_TMPNAMES:eicar.com)
[9] Matched vars updated.
[4] Running [independent] (non-disruptive) action: msg
[9] Saving msg: Virus found in uploaded file
[4] Rule returned 1.
That makes me think that there is an error in https://raw.githubusercontent.com/SpiderLabs/owasp-modsecurity-crs/v3.0/master/util/av-scanning/runav.pl - but I'm not sure as I don't have any knowledge on how @inspectFile
is working in ModSecurity 2.x - are there any differences in parsing stdout, or in something else?
Hope this helps someone.
For future reference: https://github.com/SpiderLabs/ModSecurity/issues/1646#issuecomment-382914522
Hello, I wondered if this is the right place where to ask and I am sorry if it's not. I would like to use clamAV scanning with mod security in nginx and found the following guide:
https://malware.expert/scan-every-file-clam-antivirus-scanner-modsecurity/
Although I receive the following error on the rule:
SecRule FILES_TMPNAMES "@inspectFile /usr/local/bin/runav.pl" \ "phase:2,t:none,block,msg:'Virus found in uploaded file',id:'399999'"
Operator: InspectFile is not yet supported. Is it possible to use another operator to accomplish this task or is it planned to be implemented? I am using libmodsecurity version 3 with nginx connector and cars v3 too.
Thank you in advance.