Scan a directory to find infected files with Docker and Clam AntiVirus (ClamAV)
Tags: linux, security, wordpress, docker
Published: 2020-11-05 12:08:53

## Summary

- [Last time I tried to check vulnerabilities for WordPress with Docker and WPScan](https://dev.to/brisbanewebdeveloper/check-vulnerabilities-for-wordpress-in-your-local-network-with-docker-and-wpscan-2dgp), I noticed that solution does not let me check about the files already infected in WordPress.

- So I decided to have a look at other ones and picked [ClamAV](https://www.clamav.net/). And I could not have used it by installing directly to my server. Docker Time!

## About ClamAV

It did not see my test PHP file having malicous codes (but not doing anything malicous actually) as infected file, but it did for some other files I got via Internet.

## Usage

### Make the script executable

```
chmod 700 /somewhere/clamav
```

### Create/Update Database

This downloads the database in your home directory. You must do this at first and run this periodically.

```
/somewhere/clamav update
```

### Scan Dicretory

It takes time until you see the output from Docker Container. On my iMac it takes about 30 seconds:

```
/somewhere/clamav scan -r directory_to_scan

# Examples
/somewhere/clamav scan -r /var/www/public_html
cd /var/www && /somewhere/clamav scan -r $(pwd)/public_html
cd /var/www/public_html && /somewhere/clamav scan -r .
```

## The Script

```
/somewhere/clamav
==========
#!/bin/bash

hasDocker=$(which docker)
if [ -z "$hasDocker" ];
then
  echo "You must install Docker"
  exit
fi

#
# Download Docker Image if not downloaded
#
hasClamAv=$(docker images | egrep "^mkodockx/docker-clamav")
if [ -z "$hasClamAv" ];
then
  echo
  echo "Downloading the image for clamAV"
  docker pull mkodockx/docker-clamav:alpine
fi

#
# This script creates the database directory under your home directory
#
base_dir=~/clamav
if [ ! -d "$base_dir" ];
then
  mkdir -p $base_dir
  echo "Created $base_dir"
fi

#
# Export /etc/freshclam.conf
#
# to scan with http://www.rfxn.com/downloads/rfxn.* as well
# https://www.rfxn.com/
# https://malware.expert/howto/extending-clamav-signatures-with-rfxn-database-for-php-malwares/
#
script_file="$base_dir/export_freshclam.sh"
conf_file="$base_dir/freshclam.conf"
if [ ! -f "$conf_file" ];
then
  rm -f $conf_file && \
  echo "#!/bin/bash" > $script_file && \
  echo "" >> $script_file && \
  echo "/bin/touch /var/lib/clamav/freshclam.conf" >> $script_file && \
  echo "/bin/cat /etc/clamav/freshclam.conf >> /var/lib/clamav/freshclam.conf" >> $script_file && \
  echo "/bin/echo DatabaseCustomURL http://www.rfxn.com/downloads/rfxn.ndb >> /var/lib/clamav/freshclam.conf" >> $script_file && \
  echo "/bin/echo DatabaseCustomURL http://www.rfxn.com/downloads/rfxn.hdb >> /var/lib/clamav/freshclam.conf" >> $script_file && \
  echo "/bin/echo DatabaseCustomURL http://www.rfxn.com/downloads/rfxn.yara >> /var/lib/clamav/freshclam.conf" >> $script_file && \
  docker \
    run \
    --rm \
    -it \
    -v $base_dir:/var/lib/clamav \
    mkodockx/docker-clamav:alpine \
    /bin/sh /var/lib/clamav/export_freshclam.sh && \
  rm -f $script_file && \
  echo "Exported /etc/clamav/freshclam.conf to $conf_file" && \
  echo "Added http://www.rfxn.com/downloads/rfxn.* to $conf_file"
fi

#
# Scan with https://github.com/Hestat/lw-yara.git as well
#
lw_yara="$base_dir/lw-yara"
if [ ! -d "$lw_yara" ];
then
  echo "Downloading Yara Ruleset to $lw_yara"
  git clone https://github.com/Hestat/lw-yara.git $lw_yara
fi

cmd=$1

#
# Update the database
#
if [ "$cmd" == "update" ];
then

  cd $lw_yara && \
  git fetch && \
  git reset --hard origin/master && \
  cd -

  exec docker \
    run \
    --rm \
    -it \
    -v $base_dir:/var/lib/clamav \
    mkodockx/docker-clamav:alpine \
    /usr/bin/freshclam --config-file=/var/lib/clamav/freshclam.conf

  exit

fi

#
# Scan
#
if [ "$cmd" == "scan" ];
then

  #
  # The last argument is to be the path to scan and it needs to be absolute path
  # In case you want to avoid figuring the exact path, you can do like this:
  #
  # cd directory_to_scan; clamav .
  # clamav $(pwd)/directory_to_scan
  #
  scan_dir=${!#}

  if [ "$scan_dir" == "." ];
  then
    scan_dir=$(pwd)
  fi

  if [ ! -d "$scan_dir" ];
  then
    echo "Invalid directory $scan_dir"
    exit
  fi

  echo
  echo "Scanning directory $scan_dir"
  echo "(It may take about 30 seconds until you see the first output)"
  echo

  # Take out the first and last argument
  set -- "${@:2:$(($#-2))}"

  exec docker \
    run \
    --rm \
    -it \
    -v $conf_file:/etc/clamav/freshclam.conf \
    -v $base_dir:/var/lib/clamav \
    -v $scan_dir:/code:ro \
    mkodockx/docker-clamav:alpine \
    /usr/bin/clamscan \
      -d /var/lib/clamav \
      -d /var/lib/clamav/lw-yara/lw-rules_index.yar \
      $@ \
      /code

  exit

fi

#
# Non-Scan Command
#

#
# You must execute something like /bin/bash
# The default behaviour which is to start ClamAV Daemon happens otherwise
#
if [ -z "$cmd" ];
then
  echo "You must execute something"
  exit
fi

echo
echo "Excuting $cmd..."
echo

exec docker \
  run \
  --rm \
  -it \
  -v $base_dir:/var/lib/clamav \
  mkodockx/docker-clamav:alpine \
  $@
```

## Test

```
mkdir -p ~/tmp
cd ~/tmp
git clone https://github.com/Te-k/php-malicious-sample .
/somewhere/clamav scan -r --exclude="\.git" .
```

## Related Post

- [Check vulnerabilities for WordPress in your local network with Docker and WPScan](https://dev.to/brisbanewebdeveloper/check-vulnerabilities-for-wordpress-in-your-local-network-with-docker-and-wpscan-2dgp)