Skip to content

Commit

Permalink
Initial versio of Comodo AV service
Browse files Browse the repository at this point in the history
  • Loading branch information
kam193 committed Jan 14, 2024
1 parent 0e7b6cf commit e3f31e3
Show file tree
Hide file tree
Showing 10 changed files with 264 additions and 0 deletions.
4 changes: 4 additions & 0 deletions comodo-av-service/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.env
.randomnotes/
.git/
*.pyc
50 changes: 50 additions & 0 deletions comodo-av-service/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
ARG REGISTRY=
ARG BASE_IMAGE=cccs/assemblyline-v4-service-base:stable
FROM ${BASE_IMAGE}

ENV SERVICE_PATH service.al_run.AssemblylineService

USER root
RUN apt-get update && apt-get upgrade -y && apt-get install -y wget libc6 libfontconfig1 libfreetype6 libglib2.0-0 libice6 libsm6 libssl1.1 libxrender1

RUN wget https://cdn.download.comodo.com/cis/download/installs/linux/cav-linux_x64.deb && \
dpkg -i --ignore-depends=libssl0.9.8 cav-linux_x64.deb && \
chmod 755 /opt/COMODO/*.sh && \
chmod 644 /opt/COMODO/*.so && \
chmod 644 /opt/COMODO/*.so.* && \
chgrp assemblyline /opt/COMODO/scanners/bases.cav && \
chmod 664 /opt/COMODO/scanners/bases.cav

# changing group & mode on scanner to allow DB updates

USER assemblyline
COPY requirements.txt requirements.txt

RUN pip install --no-cache-dir --user --requirement requirements.txt && rm -rf ~/.cache/pip

WORKDIR /opt/al_service
COPY . .

USER root
RUN sed -i "s/\$VERSION/$(cat VERSION)/g" service_manifest.yml

USER assemblyline

# wget -O /opt/COMODO/scanners/bases.cav http://download.comodo.com/av/updates58/sigs/bases/bases.cav

# dpkg -i --ignore-depends=libssl0.9.8 cav-linux_x64.deb
# sudo chmod 755 /opt/COMODO/*.sh
# sudo chmod 644 /opt/COMODO/*.so
# sudo chmod 644 /opt/COMODO/*.so.*
# sudo chmod 644 /usr/local/Trolltech/Qt-4.7.4-Comodo/lib/*.so
# sudo chmod 644 /usr/local/Trolltech/Qt-4.7.4-Comodo/lib/*.so.*
# sudo chmod 644 /usr/local/Trolltech/Qt-4.7.4-Comodo/plugins/sqldrivers/*.so

# /opt/COMODO/post_setup.sh -> instead: sh /opt/COMODO/load_cmdagent.sh restart

# /opt/COMODO/cmdscan -v -s /var/lib/assemblyline/eicar
# -----== Scan Start ==-----
# /var/lib/assemblyline/eicar ---> Found Virus, Malware Name is Malware
# -----== Scan End ==-----
# Number of Scanned Files: 1
# Number of Found Viruses: 1
4 changes: 4 additions & 0 deletions comodo-av-service/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
include ../common.mk

AL_SERVICE_NAME=Comodo-Antivirus
# SERVICE_NAME=assemblyline-service-template
7 changes: 7 additions & 0 deletions comodo-av-service/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Comodo-Antivirus

https://www.comodo.com/home/internet-security/antivirus-for-linux.php

The AV itself looks discontinued, but it shares definitions with other products, so it's still useful.

Pay attention to the license - in container in "/opt/COMODO/doc/eula_free.txt"
1 change: 1 addition & 0 deletions comodo-av-service/VERSION
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
4
1 change: 1 addition & 0 deletions comodo-av-service/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
assemblyline-v4-service
Empty file.
105 changes: 105 additions & 0 deletions comodo-av-service/service/al_run.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import os
import re
import shutil
import subprocess
from datetime import datetime
from time import sleep, time

from assemblyline_v4_service.common.base import ServiceBase
from assemblyline_v4_service.common.request import ServiceRequest
from assemblyline_v4_service.common.result import Result, ResultTextSection

COMODO_DB_PATH = "/opt/COMODO/scanners/bases.cav"
COMODO_SCAN_PATH = "/opt/COMODO/cmdscan"

OUTPUT_START = "-----== Scan Start ==-----"
OUTPUT_END = "-----== Scan End ==-----"

RESULT_PATTERN = re.compile(r"Found (.*), Malware Name is (.*)")


class AssemblylineService(ServiceBase):
def __init__(self, config=None):
super().__init__(config)
self.scan_timeout = 60

def _load_config(self):
self.scan_timeout = self.service_attributes.config.get("scan_timeout", self.scan_timeout)

def _wait_for_db(self, timeout=60):
start_time = time()
while time() - start_time <= timeout:
try:
info = os.stat(COMODO_DB_PATH)
modify_time = datetime.fromtimestamp(info.st_mtime)
# DB embedded in the DEB is from 2013
if modify_time.year > 2013:
break
except FileNotFoundError:
pass
sleep(0.5)
else:
raise RuntimeError("Signature DB not found after %s seconds" % timeout)

def start(self):
self.log.debug(f"start() from {self.service_attributes.name} service called")
self._load_config()
self.log.info("Waiting for signature DB to be installed")
self._wait_for_db()
self.log.info(f"{self.service_attributes.name} service started")

def _load_rules(self) -> None:
# Only one file is allowed
if self.rules_directory:
for root, subdirs, _ in os.walk(self.rules_directory):
for subdir in subdirs:
self.log.debug("Copying signature DB from %s/%s", self.rules_directory, subdir)
shutil.copyfile(os.path.join(root, subdir, "bases.cav"), COMODO_DB_PATH)
self.log.info("Signature DB installed")

def _scan(self, file_path: str) -> str:
self.log.debug("Scanning %s", file_path)
self._wait_for_db(timeout=self.scan_timeout / 10)
result = subprocess.run(
[COMODO_SCAN_PATH, "-v", "-s", file_path],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
timeout=self.scan_timeout,
)
output = result.stdout.decode("utf-8")
self.log.debug("Scan result: %s", output)
result.check_returncode()

lines = output.splitlines()

viruses = []

for line in lines:
if not line.startswith(file_path):
continue
if line.endswith("Not Virus"):
continue

parts = line.split("--->", 1)
viruses.append(parts[1].strip())

return viruses

def execute(self, request: ServiceRequest) -> None:
result = Result()
viruses = self._scan(request.file_path)
if viruses:
main_section = ResultTextSection("Viruses found")
result.add_section(main_section)
main_section.set_heuristic(1)
for virus in viruses:
main_section.add_line(virus)
name = virus
matches = RESULT_PATTERN.match(virus)
if not matches:
self.log.error("Unexpected result format: %s", virus)
else:
name = matches.group(2)
main_section.add_tag("av.virus_name", name)

request.result = result
31 changes: 31 additions & 0 deletions comodo-av-service/service/updater.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import os
import shutil
import tempfile

from assemblyline_v4_service.updater.updater import ServiceUpdater


class AssemblylineServiceUpdater(ServiceUpdater):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

def import_update(self, files_sha256, client, source, default_classification) -> None:
self.log.info(str(files_sha256))
output_dir = os.path.join(self.latest_updates_dir, source)
os.makedirs(os.path.join(self.latest_updates_dir, source), exist_ok=True)
for file, _ in files_sha256:
if not file.endswith("bases.cav"):
self.log.warning("Skipping %s because it is not a bases.cav file", file)
continue
self.log.debug("Copying %s to %s", file, output_dir)
shutil.copy(file, output_dir)

def prepare_output_directory(self) -> str:
tempdir = tempfile.mkdtemp()
shutil.copytree(self.latest_updates_dir, tempdir, dirs_exist_ok=True)
return tempdir


if __name__ == "__main__":
with AssemblylineServiceUpdater(default_pattern=".*") as server:
server.serve_forever()
61 changes: 61 additions & 0 deletions comodo-av-service/service_manifest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
name: Comodo-Antivirus
version: 4.4.0.stable$VERSION
description: Scans files using COMODO antivirus (https://www.comodo.com/home/internet-security/antivirus-for-linux.php)
enabled: true

accepts: .*
rejects: empty
stage: CORE
category: Antivirus
file_required: true
timeout: 90

# Any config key not starting with _ will be added to the clamd.conf file
config:
scan_timeout: 60 # seconds

# -1000: safe
# 0 - 299: informative
# 300 - 699: suspicious
# 700 - 999: highly suspicious
# >= 1000: malicious

heuristics:
- description: COMODO Antivirus found file to be malicious
filetype: "*"
heur_id: 1
name: COMODO - Virus detection
score: 1000

docker_config:
image: ${REGISTRY}kam193/assemblyline-service-comodo-antivirus:4.4.0.stable$VERSION
cpu_cores: 1.0
ram_mb: 2048

update_config:
update_interval_seconds: 7200 # 2 hours
generates_signatures: false
wait_for_update: true
sources:
# Only one source can be configured, any more will raise an error
- name: Comodo
uri: https://download.comodo.com/av/updates58/sigs/bases/bases.cav

dependencies:
updates:
container:
ram_mb: 1024
allow_internet_access: true
command: ["python", "-m", "service.updater"]
image: ${REGISTRY}kam193/assemblyline-service-comodo-antivirus:4.4.0.stable$VERSION
ports: ["5003"]
environment:
- name: UPDATER_DIR
value: /tmp/comodo_db/
# volumes:
# comodo-updates:
# mount_path: /opt/comodo_db/
# capacity: 2147483648 # 2 GB
# storage_class: default

run_as_core: True

0 comments on commit e3f31e3

Please sign in to comment.