Skip to content

Commit

Permalink
Merge pull request #3 from OPSWAT/rename_to_metadefender_sandbox
Browse files Browse the repository at this point in the history
Rename to MetaDefender Sandbox
  • Loading branch information
anikobartos authored Apr 8, 2024
2 parents bf736e5 + 86138c8 commit 01d52af
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 61 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ name: Docker Build & Publish
on:
push:
tags:
# Assemblyline tags start with 4.4.
- '4.4.*'
# Assemblyline tags start with 4.4. or 4.5.
- '4.5.*'

env:
REGISTRY: opswat
Expand Down
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ FROM cccs/assemblyline-v4-service-base:stable

# Python path to the service class from your service directory
# The following example refers to the class "Sample" from the "sample.py" file
ENV SERVICE_PATH filescan_sandbox.FilescanSandbox
ENV SERVICE_PATH metadefender_sandbox.MetaDefenderSandbox

# Install any service dependencies here
# For example: RUN apt-get update && apt-get install -y libyaml-dev
Expand All @@ -16,7 +16,7 @@ USER assemblyline
WORKDIR /opt/al_service
COPY . .

ARG version=4.4.1.dev1
ARG version=4.5.1.dev0
USER root
RUN sed -i -e "s/\$SERVICE_TAG/$version/g" service_manifest.yml

Expand Down
24 changes: 12 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
# assemblyline-service-opswat-filescan-sandbox
# assemblyline-service-metadefender-sandbox

This repository is self-developed Assemblyline service which submits a file or a URL from Assemblyline4 to OPSWAT Filescan Sandbox, and after a successful scan its fetches and parses the result.
This repository is self-developed Assemblyline service which submits a file or a URL from Assemblyline4 to MetaDefender Sandbox (previously known as OPSWAT Filescan Sandbox), and after a successful scan its fetches and parses the result.

## Prerequirements

Using this integration it is necessary to have an OPSWAT Filescan Sandbox API-key. You can use the Activation Key that you received from your OPSWAT Sales Representative, and follow the instructions on the [License Activation page](https://docs.opswat.com/filescan/installation/license-activation) or you can create an API key on the [Community site](https://www.filescan.io/auth/signin) under API Key tab.
Using this integration it is necessary to have a MetaDefender Sandbox API-key. You can use the Activation Key that you received from your OPSWAT Sales Representative, and follow the instructions on the [License Activation page](https://docs.opswat.com/filescan/installation/license-activation) or you can create an API key on the [Community site](https://www.filescan.io/auth/signin) under API Key tab.

## Heuristics

The result contains two types of heuristic:

- __Filescan Sandbox verdict is _VERDICT___ : This is the final verdict of Filescan Sandbox and added as a ResultSection
- __MetaDefender Sandbox verdict is _VERDICT___ : This is the final verdict of MetaDefender Sandbox and added as a ResultSection
- ___VERDICT_ threat indicators__: Comes from signal groups and added as a subsection

Heuristic score is the following:

| score | Filescan Sandbox verdict |
|------:|--------------------------|
| -1000 | BENIGN |
| 150 | NO THREAT |
| 299 | UNKNOWN |
| 500 | SUSPICIOUS |
| 850 | LIKELY MALICIOUS |
| 1000 | MALICIOUS |
| score | MetaDefender Sandbox verdict |
|------:|------------------------------|
| -1000 | BENIGN |
| 150 | NO THREAT |
| 299 | UNKNOWN |
| 500 | SUSPICIOUS |
| 850 | LIKELY MALICIOUS |
| 1000 | MALICIOUS |

## Official documentation

Expand Down
26 changes: 13 additions & 13 deletions filescan_sandbox.py → metadefender_sandbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import json
import base64
import filescan_sandbox_result
import metadefender_sandbox_result

import time
import requests
Expand Down Expand Up @@ -42,9 +42,9 @@ def requests_retry_session(
return session


class FilescanSandbox(ServiceBase):
class MetaDefenderSandbox(ServiceBase):
def __init__(self, config=None):
super(FilescanSandbox, self).__init__(config)
super(MetaDefenderSandbox, self).__init__(config)
self.api_key = self.config.get("api_key")
self.host = self.config.get("host")
self.headers = {}
Expand All @@ -57,7 +57,7 @@ def start(self):
# Your service might have to do some warming up on startup to make things faster

self.log.info(f"start() from {self.service_attributes.name} service called")
self.log.debug("OPSWAT Filescan Sandbox service started")
self.log.debug("MetaDefender Sandbox service started")


def post_sample(self, request: ServiceRequest, url=None, file_path=None):
Expand Down Expand Up @@ -178,7 +178,7 @@ def execute(self, request: ServiceRequest) -> None:
assert self.poll_interval > 0 and self.timeout > 0, "Poll interval or timeout is not appropriate"
except Exception as e:
self.log.error(
"No API key or Host found for OPSWAT Filescan Sandbox. Error: {e!r}"
"No API key or Host found for MetaDefender Sandbox. Error: {e!r}"
)
raise e

Expand All @@ -188,10 +188,10 @@ def execute(self, request: ServiceRequest) -> None:
response = {}
try:
if submitted_url:
self.log.info("OPSWAT Filescan Sandbox start to scan a file")
self.log.info("MetaDefender Sandbox start to scan a file")
response = self.post_sample(request, url=submitted_url)
elif submitted_file:
self.log.info("OPSWAT Filescan Sandbox start to scan an URL")
self.log.info("MetaDefender Sandbox start to scan an URL")
response = self.post_sample(request, file_path=submitted_file)
except Exception as e:
self.log.error(f"Error occurred when scan a file/URL: {e!r}")
Expand All @@ -204,23 +204,23 @@ def execute(self, request: ServiceRequest) -> None:
rejected = response.get("rejected_files", None)
if rejected:
for rejection in rejected:
rejection_result = ResultSection('OPSWAT Filescan Sandbox rejection',
rejection_result = ResultSection('MetaDefender Sandbox rejection',
body_format=BODY_FORMAT.KEY_VALUE,
body=json.dumps(rejection))
result.add_section(rejection_result)

if response.get("reports", {}):
result = filescan_sandbox_result.result_parser(result, response)
result = metadefender_sandbox_result.result_parser(result, response)
else:
self.log.warning(f"There is no OPSWAT Filescan Sandbox reports.")
self.log.warning(f"There is no MetaDefender Sandbox reports.")

report_link = f"{self.host}/uploads/{response.get('flowId')}"
report_link_rs = ResultSection('OPSWAT Filescan Sandbox full report is available here:',
report_link_rs = ResultSection('MetaDefender Sandbox full report is available here:',
body_format=BODY_FORMAT.URL,
body=json.dumps({"name": "Filescan Sandbox report", "url": report_link}))
body=json.dumps({"name": "MetaDefender Sandbox report", "url": report_link}))
result.add_section(report_link_rs)

else:
self.log.warning(f"There is no OPSWAT Filescan Sandbox response.")
self.log.warning(f"There is no MetaDefender Sandbox response.")

request.result = result
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ def process_resources(result_section, resources):
def parse_report(report, report_id, flow_id):
compact_result = parse_compact_result(report, report_id, flow_id)
verdict_rs = ResultSection(
"OPSWAT Filescan Sandbox result",
"MetaDefender Sandbox result",
body_format=BODY_FORMAT.KEY_VALUE,
body=json.dumps(compact_result),
)
Expand Down
8 changes: 8 additions & 0 deletions release_notes.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
## Release notes

### 4.5.1.dev0

Date: 5 April, 2024

Changed:

- Integration renaming: From _OPSWAT Filescan Sandbox_ to _MetaDefender Sandbox_

### 4.4.1.dev1

Date: 8 Sept, 2023
Expand Down
42 changes: 21 additions & 21 deletions service_manifest.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# Name of the service
name: OPSWAT_Filescan_Sandbox
name: MetaDefender_Sandbox
# Version of the service
version: $SERVICE_TAG

description: This Assemblyline service interfaces with the OPSWAT Filescan Sandbox, detonating files and URLs. This integration was developed by OPSWAT. (C) OPSWAT, Inc.
description: This Assemblyline service interfaces with the MetaDefender Sandbox -previously known as OPSWAT Filescan Sandbox-, detonating files and URLs. This integration was developed by OPSWAT. (C) OPSWAT, Inc.

accepts: .*
rejects: empty
Expand All @@ -26,62 +26,62 @@ uses_metadata: true
# >= 1000: malicious

heuristics:
- description: OPSWAT Filescan Sandbox determined that the file is benign.
- description: MetaDefender Sandbox determined that the file is benign.
filetype: "*"
heur_id: 1
name: Filescan Sandbox verdict is benign.
name: MetaDefender Sandbox verdict is benign.
score: -1000
- description: OPSWAT Filescan Sandbox signal group is benign.
- description: MetaDefender Sandbox signal group is benign.
filetype: "*"
heur_id: 2
name: Benign threat indicators
score: -1000
- description: OPSWAT Filescan Sandbox determined that the file is informational/no threat.
- description: MetaDefender Sandbox determined that the file is informational/no threat.
filetype: "*"
heur_id: 3
name: Filescan Sandbox verdict is no threat.
name: MetaDefender Sandbox verdict is no threat.
score: 150
- description: OPSWAT Filescan Sandbox signal group is informational/no threat.
- description: MetaDefender Sandbox signal group is informational/no threat.
filetype: "*"
heur_id: 4
name: Informational threat indicators
score: 150
- description: OPSWAT Filescan Sandbox determined that the file is unknown.
- description: MetaDefender Sandbox determined that the file is unknown.
filetype: "*"
heur_id: 5
name: Filescan Sandbox verdict is unknown
name: MetaDefender Sandbox verdict is unknown
score: 299
- description: OPSWAT Filescan Sandbox signal group is unknown.
- description: MetaDefender Sandbox signal group is unknown.
filetype: "*"
heur_id: 6
name: Unknown threat indicators
score: 299
- description: OPSWAT Filescan Sandbox determined that the file is suspicious.
- description: MetaDefender Sandbox determined that the file is suspicious.
filetype: "*"
heur_id: 7
name: Filescan Sandbox verdict is suspicious
name: MetaDefender Sandbox verdict is suspicious
score: 500
- description: OPSWAT Filescan Sandbox signal group is suspicious.
- description: MetaDefender Sandbox signal group is suspicious.
filetype: "*"
heur_id: 8
name: Suspicious threat indicators
score: 500
- description: OPSWAT Filescan Sandbox determined that the file is likely malicious.
- description: MetaDefender Sandbox determined that the file is likely malicious.
filetype: "*"
heur_id: 9
name: Filescan Sandbox verdict is likely malicious
name: MetaDefender Sandbox verdict is likely malicious
score: 850
- description: OPSWAT Filescan Sandbox signal group is likely malicious.
- description: MetaDefender Sandbox signal group is likely malicious.
filetype: "*"
heur_id: 10
name: Likely malicious threat indicators
score: 850
- description: OPSWAT Filescan Sandbox determined that the file is malicious.
- description: MetaDefender Sandbox determined that the file is malicious.
filetype: "*"
heur_id: 11
name: Filescan Sandbox verdict is malicious
name: MetaDefender Sandbox verdict is malicious
score: 1000
- description: OPSWAT Filescan Sandbox signal group is malicious.
- description: MetaDefender Sandbox signal group is malicious.
filetype: "*"
heur_id: 12
name: Malicious threat indicators
Expand All @@ -91,7 +91,7 @@ heuristics:
# - the name of the docker container that will be created
# - CPU and ram allocation by the container
docker_config:
image: ${REGISTRY}opswat/assemblyline-service-opswat-filescan-sandbox:$SERVICE_TAG
image: ${REGISTRY}opswat/assemblyline-service-metadefender-sandbox:$SERVICE_TAG
cpu_cores: 1.0
ram_mb: 1024
allow_internet_access: true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@


sys.path.append("..")
import filescan_sandbox_result
import metadefender_sandbox_result
from assemblyline_v4_service.common.result import (
Result,
ResultSection,
Expand All @@ -22,7 +22,7 @@ def util_load_json(path: str) -> Any:
return json.loads(f.read())


class TestFilescanSandboxResult:
class TestMetaDefenderSandboxResult:
@classmethod
def setup_class(cls):
# copy yml
Expand Down Expand Up @@ -51,7 +51,7 @@ def test_parse_compact_result_bad():
.get("reports", {})
.get("93a90ffb-1aac-43f6-abdd-c579d6ae14df", {})
)
compact_result = filescan_sandbox_result.parse_compact_result(
compact_result = metadefender_sandbox_result.parse_compact_result(
raw_response,
"93a90ffb-1aac-43f6-abdd-c579d6ae14df",
"64d1fb9c2a1db2a88ac17017",
Expand All @@ -76,7 +76,7 @@ def test_parse_compact_result_informational():
.get("reports", {})
.get("21815d5f-3653-466e-a421-187423ca7b93", {})
)
compact_result = filescan_sandbox_result.parse_compact_result(
compact_result = metadefender_sandbox_result.parse_compact_result(
raw_response,
"21815d5f-3653-466e-a421-187423ca7b93",
"64de1abb9489ac1ead366732",
Expand All @@ -101,7 +101,7 @@ def test_parse_compact_result_badfile2():
.get("reports", {})
.get("d389e943-dc72-4070-aade-1d11f0457ea3", {})
)
compact_result = filescan_sandbox_result.parse_compact_result(
compact_result = metadefender_sandbox_result.parse_compact_result(
raw_response,
"d389e943-dc72-4070-aade-1d11f0457ea3",
"64de19f4a29d57e20384dac6",
Expand Down Expand Up @@ -146,7 +146,7 @@ def test_parse_compact_result_badfile2():
@staticmethod
def test_parse_compact_result_empty():
raw_response = {}
compact_result = filescan_sandbox_result.parse_compact_result(
compact_result = metadefender_sandbox_result.parse_compact_result(
raw_response,
"93a90ffb-1aac-43f6-abdd-c579d6ae14df",
"64d1fb9c2a1db2a88ac17017",
Expand Down Expand Up @@ -175,7 +175,7 @@ def test_process_allSignalGroups():

rs = ResultSection("Test", body_format=BODY_FORMAT.TEXT, body="test")

compact_result = filescan_sandbox_result.process_allSignalGroups(
compact_result = metadefender_sandbox_result.process_allSignalGroups(
rs, raw_response
)

Expand All @@ -193,7 +193,7 @@ def test_process_iocs():

rs = ResultSection("Test", body_format=BODY_FORMAT.TEXT, body="test")

compact_result = filescan_sandbox_result.process_iocs(rs, raw_response)
compact_result = metadefender_sandbox_result.process_iocs(rs, raw_response)
tags = {
"network.email.address": ["ActivationDepartment@FedRetireSoftware.com"],
"network.static.uri": [
Expand All @@ -218,7 +218,7 @@ def test_process_allOsintTags():

rs = ResultSection("Test", body_format=BODY_FORMAT.TEXT, body="test")

compact_result = filescan_sandbox_result.process_allOsintTags(rs, raw_response)
compact_result = metadefender_sandbox_result.process_allOsintTags(rs, raw_response)
tags = {"av.virus_name": ["emotet", "geodo"]}
assert rs.tags == tags

Expand All @@ -233,7 +233,7 @@ def test_process_resources():

rs = ResultSection("Test", body_format=BODY_FORMAT.TEXT, body="test")

compact_result = filescan_sandbox_result.process_resources(rs, raw_response)
compact_result = metadefender_sandbox_result.process_resources(rs, raw_response)
tags = {
"av.virus_name": ["Trojan/Riskware!my0NYEEN"],
"attribution.family": ["riskware"],
Expand Down

0 comments on commit 01d52af

Please sign in to comment.