Cisco-Talos / clamav

ClamAV - Documentation is here: https://docs.clamav.net
https://www.clamav.net/
GNU General Public License v2.0
4.48k stars 708 forks source link

Get "Access denied. ERROR" from clamd when the file to scan is not in $HOME or /tmp #1328

Open jsuto opened 3 months ago

jsuto commented 3 months ago

Describe the bug

I have an application that writes files to /var/piler/tmp/0 dir. The app uses clamd over the unix socket to pass the file's full path, then read clamd's response whether it's a clean file or not. The problem is that no matter of the ownership or the permissions on the file, it seems that clamd always returns Access denied. ERROR message if the file to be scanned is not either in $HOME or /tmp.

How to reproduce the problem

I used this code snippet to scan files (reduced to the relevant part only):

int clamd_scan(char *tmpfile){
   int s, n;
   char buf[MAXBUFSIZE], scan_cmd[MAXBUFSIZE];
   struct sockaddr_un server;

   strcpy(server.sun_path, "/run/clamav/clamd.ctl");
   server.sun_family = AF_UNIX;

   if((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1){
      printf("ERR: create socket\n");
      return 1;
   }

   if(connect(s, (struct sockaddr *)&server, strlen(server.sun_path) + sizeof (server.sun_family)) == -1){
      printf("CLAMD ERR: connect to socker\n");
      return 1;
   }

   snprintf(scan_cmd, sizeof(scan_cmd)-1, "SCAN %s\r\n", tmpfile);
   send(s, scan_cmd, strlen(scan_cmd), 0);

   n = recvtimeout(s, buf, sizeof(buf), TIMEOUT);
   close(s);

   printf("CLAMD DEBUG: %d %s", n, buf);

   return 0;
}

clamconf -n output:

Checking configuration files in /etc/clamav

Config file: clamd.conf
-----------------------
PreludeAnalyzerName = "ClamAV"
LogFile = "/var/log/clamav/clamav.log"
LogFileMaxSize = "4294967295"
LogTime = "yes"
LogVerbose = "yes"
LogRotate = "yes"
ExtendedDetectionInfo = "yes"
LocalSocket = "/var/run/clamav/clamd.ctl"
LocalSocketGroup = "clamav"
LocalSocketMode = "666"
MaxConnectionQueueLength = "15"
StreamMaxLength = "26214400"
MaxThreads = "12"
ReadTimeout = "180"
SendBufTimeout = "200"
SelfCheck = "3600"
User = "clamav"
BytecodeTimeout = "60000"
MaxScanTime = "120000"
MaxScanSize = "104857600"
MaxFileSize = "26214400"
MaxRecursion = "16"
MaxEmbeddedPE = "10485760"
MaxHTMLNormalize = "10485760"
MaxHTMLNoTags = "2097152"
MaxScriptNormalize = "5242880"
PCREMatchLimit = "10000"
PCRERecMatchLimit = "5000"
PCREMaxFileSize = "26214400"

Config file: freshclam.conf
---------------------------
LogFileMaxSize = "4294967295"
LogTime = "yes"
LogRotate = "yes"
UpdateLogFile = "/var/log/clamav/freshclam.log"
Checks = "24"
DatabaseMirror = "db.local.clamav.net", "database.clamav.net"
MaxAttempts = "5"
ReceiveTimeout disabled
clamav-milter.conf not found

Software settings
-----------------
Version: 1.0.5
Optional features supported: MEMPOOL AUTOIT_EA06 BZIP2 LIBXML2 PCRE2 ICONV JSON 

Database information
--------------------
Database directory: /var/lib/clamav
daily.cvd: version 27362, sigs: 2065366, built on Fri Aug  9 08:39:28 2024
main.cvd: version 62, sigs: 6647427, built on Thu Sep 16 12:32:42 2021
bytecode.cvd: version 335, sigs: 86, built on Tue Feb 27 15:37:24 2024
Total number of signatures: 8712879

Platform information
--------------------
uname: Linux 6.8.0-31-generic #31-Ubuntu SMP PREEMPT_DYNAMIC Sat Apr 20 00:40:06 UTC 2024 x86_64
OS: Linux, ARCH: x86_64, CPU: x86_64
Full OS version: Ubuntu 24.04 LTS
zlib version: 1.3 (1.3), compile flags: a9
platform id: 0x0a21a5a508000000000d0200

Build information
-----------------
GNU C: 13.2.0 (13.2.0)
sizeof(void*) = 8
Engine flevel: 165, dconf: 165
micahsnyder commented 2 months ago

Hi @jsuto sorry you didn't get a response from me way sooner.

You're probably running clamd as your own user account and it likely does not have permission to open other files to scan them.

If you run clamd using sudo or as root, then it should run as the clamav user. In that cause it probably won't even be able to scan stuff under $HOME.

Either you should have clamd run as a user that has read access to everything (not recommended), or else send an INSTREAM or FDPASS scan request. Both INSTREAM and FDPASS will require your program to open the file first in order to send it. That means running your program with sudo/root or else some other user account that just has read access to everything that you need to scan.

INSTREAM will stream the whole file contents over the socket to clamd. Clamd will write it to a temp file and then scan the temp file.

FDPASS will open the file and send the file handle. We don't have example code/documentation on how to do this, so you'll have to look into the clamdscan code to figure it out.