DEV Community

Brisbane Web Developer
Brisbane Web Developer

Posted on

Scan a directory to find infected files with Docker and Clam AntiVirus (ClamAV)

Summary

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
Enter fullscreen mode Exit fullscreen mode

Create/Update Database

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

/somewhere/clamav update
Enter fullscreen mode Exit fullscreen mode

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 .
Enter fullscreen mode Exit fullscreen mode

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 \
  $@
Enter fullscreen mode Exit fullscreen mode

Test

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

Related Post

Top comments (1)

Collapse
 
kerphi profile image
Stéphane Gully

hello, I share a recent developement I just made which is a lot related to this topic :
github.com/abes-esr/clamscan-docker

"Dockerization of ClamAV and specifically clamscan command used to scan periodicaly a specific folder for detecting trojans, viruses, malware & other malicious threats. If something bad is detected, an email is sent."