QutteraWebsiteMalwareScanner

Quttera Website Malware Scanner.

Data Enrichment & Threat Intelligence · Quttera Website Malware Scanner

Details

IDQutteraWebsiteMalwareScanner
ProviderQuttera
CategoryData Enrichment & Threat Intelligence
From Version6.0.0
Docker Imagedemisto/python3:3.12.13.10116658
Supported ModulesAgentix XSIAM

README

Quttera Website Malware Scanner
This integration was integrated and tested with version v3 of QutteraWebsiteMalwareScanner

Configure QutteraWebsiteMalwareScanner in Cortex

Parameter Required
API Key True
Quttera Scanner URL True

Commands

You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.

quttera-scan-start


Start to scan a given domain

Notice: Submitting indicators using this command might make the indicator data publicly available. See the vendor’s documentation for more details.

Base Command

quttera-scan-start

Input

Argument Name Description Required
domain The name of the domain to scan. Required

Context Output

Path Type Description
QutteraWebsiteMalwareScanning.Start.error Number HTTP response from the scanner
QutteraWebsiteMalwareScanning.Start.errorstr String Status of the scan request

quttera-rescan-status


Retrieve status of submitted domain

Base Command

quttera-rescan-status

Input

Argument Name Description Required
domain The name of the domain to retrieve its status. Required

Context Output

Path Type Description
QutteraWebsiteMalwareScanning.Status.error Number Scan result request status
QutteraWebsiteMalwareScanning.Status.errorstr String Scan result request description
QutteraWebsiteMalwareScanning.Status.status.blacklisted String Is the domain blacklisted
QutteraWebsiteMalwareScanning.Status.status.files Number Amount of scanned files
QutteraWebsiteMalwareScanning.Status.status.scanner_result String Scan result
QutteraWebsiteMalwareScanning.Status.status.sensitivity String Sensitivity
QutteraWebsiteMalwareScanning.Status.status.state String Is scanning done
QutteraWebsiteMalwareScanning.Status.status.time String Time
QutteraWebsiteMalwareScanning.Status.status.url String Scanned URL

quttera-scan-report


Retrieve report of submitted domain

Base Command

quttera-scan-report

Input

Argument Name Description Required
domain The name of the domain to retrieve its report. Required

Context Output

Path Type Description
QutteraWebsiteMalwareScanning.report.error Number Retrieving domain scan return code
QutteraWebsiteMalwareScanning.report.errorstr String Retrieving domain scan report state
QutteraWebsiteMalwareScanning.report.status Dict Detailed domain scan report
QutteraWebsiteMalwareScanning.report.status.blacklisted String Is domain blacklisted
QutteraWebsiteMalwareScanning.report.status.files Number How many files were scanned
QutteraWebsiteMalwareScanning.report.status.scanner_result String Scanner result
QutteraWebsiteMalwareScanning.report.status.sensitivity String Domain sensitivity
QutteraWebsiteMalwareScanning.report.status.state String State of the domain
QutteraWebsiteMalwareScanning.report.status.time String Scan time
QutteraWebsiteMalwareScanning.report.status.url String Scanned URL

quttera-report-malware


Retrieve url blacklist and reputation

Notice: Submitting indicators using this command might make the indicator data publicly available. See the vendor’s documentation for more details.

Base Command

quttera-report-malware

Input

Argument Name Description Required
url URL to retrieve its blacklist and reputation. Required

Context Output

Path Type Description
QutteraWebsiteMalwareScanning.report Dict Retrieving url blacklist and reputation

quttera-status-blacklist


Retrieve domain blacklist and reputation

Base Command

quttera-status-blacklist

Input

Argument Name Description Required
domain The name of the domain to retrieve its blacklist and reputation. Required

Context Output

Path Type Description
QutteraWebsiteMalwareScanning.report Dict Retrieving domain blacklist and reputation

Configuration parameters

  • apikey — API Key (required)
  • base_url — Quttera Scanner URL (required)

Commands (5)

  • quttera-report-malware

    Retrieve url blacklist and reputation.

  • quttera-rescan-status

    Retrieve status of submitted domain.

  • quttera-scan-report

    Retrieve report of submitted domain.

  • quttera-scan-start

    Start to scan a given domain.

  • quttera-status-blacklist

    Retrieve domain blacklist and reputation.

import pytest
from QutteraWebsiteMalwareScanner import report_malware, rescan_status, scan_report, scan_start, status_blacklist

SERVER_URL = "scannerapi.quttera.com"
HTTPS_BASE = f"https://{SERVER_URL}/api/v3"


class ResponseMock:
    start_scan = {"error": 200, "errorstr": "success"}
    rescan_status = {
        "error": 200,
        "errorstr": "success",
        "status": {
            "blacklisted": "no",
            "files": 12,
            "scanner_result": "undef",
            "sensitivity": "HEURISTIC",
            "state": "SCAN",
            "time": 1653420189,
            "url": "domain.test",
        },
    }
    scan_report_clean = {
        "error": 200,
        "errorstr": "success",
        "status": {
            "blacklisted": "no",
            "files": 16,
            "scanner_result": "clean",
            "sensitivity": "HEURISTIC",
            "state": "DONE",
            "time": 1670147717,
            "url": "domain.test",
        },
    }
    scan_report_in_progress = {
        "error": 200,
        "errorstr": "success",
        "status": {
            "blacklisted": "no",
            "files": 16,
            "scanner_result": "clean",
            "sensitivity": "HEURISTIC",
            "state": "DOWNLOAD",
            "time": 1670147717,
            "url": "domain.test",
        },
    }
    status_blacklist = {"error": 200, "errorstr": "success", "status": {"blacklisted": "no", "url": "domain.test"}}
    report_malware = {
        "error": 200,
        "errorstr": "success",
        "report": {
            "blacklist_report": {
                "blacklist_status": "NoThreat",
                "providers": [
                    {"name": "Google", "status": "NoThreat", "time": "1511222759"},
                    {"name": "Google", "status": "NoThreat", "time": "1511222759"},
                    {"name": "MalwareDomainList", "status": "NoThreat", "time": "1511222759"},
                    {"name": "ZeusTracker", "status": "NoThreat", "time": "1511222759"},
                ],
            },
            "blacklisted_domains": {},
            "blacklisted_domains_count": 0,
            "blacklisted_iframes": {},
            "blacklisted_iframes_count": 0,
            "blacklisted_links": {},
            "blacklisted_links_count": 0,
            "domains": {"adssettings.google.com": "NoThreat", "domain.test": "NoThreat", "youtu.be": "NoThreat"},
            "domains_count": 2,
            "files": [
                {
                    "MD5": "18912736AD1E68285BBD6087610FDBF7",
                    "_severity": "clean",
                    "details": "File is clean.",
                    "dumpMD5": "00000000000000000000000000000000",
                    "endtime": "Sun Dec  4 11:18:29 2022",
                    "filename": "domain.test/website-anti-malware-monitoring",
                    "filesize": "91356",
                    "filetype": "HTML",
                    "layer": "js-emulation-layer",
                    "line": "0",
                    "offset": "0",
                    "pattern_id": "N/A",
                    "reason": "No significant issues detected.",
                    "result": "1",
                    "scantime": "5.820000",
                    "threat": "Clean",
                    "threat_name": "Undefined",
                },
                {
                    "MD5": "91274D3E5EB68C1BABBD22B55C416698",
                    "_severity": "clean",
                    "details": "File is clean.",
                    "dumpMD5": "00000000000000000000000000000000",
                    "endtime": "Sun Dec  4 11:18:37 2022",
                    "filename": "domain.test/affiliates",
                    "filesize": "67062",
                    "filetype": "HTML",
                    "layer": "js-emulation-layer",
                    "line": "0",
                    "offset": "0",
                    "pattern_id": "N/A",
                    "reason": "No significant issues detected.",
                    "result": "1",
                    "scantime": "7.224000",
                    "threat": "Clean",
                    "threat_name": "Undefined",
                },
            ],
            "http_timeout": 0.844234,
            "iframes": {
                '<iframe class%3D"embed-responsive-item">': "NoThreat",
                '<iframe width%3D"420" height%3D"315" >': "NoThreat",
            },
            "iframes_count": 7,
            "links": {
                "http://docs.fortinet.com/document/fortisoar/1.0.0/quttera/404/quttera-v1-0-0": "NoThreat",
                "http://domain.test/...": "NoThreat",
                "https://youtu.be/zphj16hzj8g": "NoThreat",
            },
        },
    }


class ClientMock:
    def __init__(self, params):
        self.mock_resp = params
        self.apikey = "1234"
        self.base_url = "api.quttera"

    def _api_request(self, domain: str, method: str, operation: str):
        return self.mock_resp


@pytest.fixture(scope="function")
def client(client_args):
    return ClientMock(client_args)


@pytest.mark.parametrize("client_args", [ResponseMock.start_scan])
def test_start_scan(client):
    """
    Given
            mock BaseClient and domain to scan When
            Calling the start scan
    Then
            Test the scan trigger response
    """
    args = {"domain": "domain.test"}
    response = scan_start(client, args)
    assert response.outputs == ResponseMock.start_scan


@pytest.mark.parametrize("client_args", [ResponseMock.rescan_status])
def test_rescan_status(client):
    """
    Given
            mock BaseClient and domain to scan
    When
            Rescan the domain
    Then
            Test the scan trigger response
    """
    args = {"domain": "domain.test"}

    response = rescan_status(client, args)
    assert response.outputs == ResponseMock.rescan_status


@pytest.mark.parametrize("client_args", [ResponseMock.scan_report_clean])
def test_scan_status_clean(client):
    """
    Given
            mock BaseClient and domain to scan
    When
            Retrieve status of scanned domain
    Then
            Test the scan status response
    """
    args = {"domain": "domain.test"}

    response = scan_report(client, args)
    assert response.readable_output == "Domain domain.test is clean"


@pytest.mark.parametrize("client_args", [ResponseMock.scan_report_in_progress])
def test_scan_status_in_progress(client):
    """
    Given
            mock BaseClient and domain to scan
    When
            Retrieve status of scanned domain
    Then
            Test the scan status response
    """
    args = {"domain": "domain.test"}

    response = scan_report(client, args)
    assert response.readable_output == "Domain domain.test is being scanned"


@pytest.mark.parametrize("client_args", [ResponseMock.status_blacklist])
def test_blacklist_status(client):
    """
    Given
            mock BaseClient and domain to scan
    When
            Retrieve the info about blacklist status of the domain
    Then
            Test the blacklist status response
    """
    args = {"domain": "domain.test"}

    response = status_blacklist(client, args)
    assert response.readable_output == "Domain domain.test is NOT blacklisted"


@pytest.mark.parametrize("client_args", [ResponseMock.report_malware])
def test_report_malware(client):
    """
    Given
            mock BaseClient and domain to scan
    When
            Retrieve the malware report for given domain
    Then
            Test the malware status response
    """
    args = {"url": "domain.test"}

    response = report_malware(client, args)
    assert response.outputs == ResponseMock.report_malware


@pytest.mark.parametrize("client", [client])
@pytest.mark.parametrize("method", ["scan_start", "rescan_status", "scan_report", "status_blacklist"])
def test_valueerror(client, method):
    with pytest.raises(ValueError):
        globals()[method](client, {"domain": ""})


class Failure:
    response = {"error": 404, "errorstr": "item not found"}


@pytest.mark.parametrize("client_args", [Failure.response])
@pytest.mark.parametrize("method", ["scan_start", "rescan_status"])
def test_failed_response(client, method):
    args = {"domain": "domain.test"}
    res = globals()[method](client, args)
    assert res.raw_response.get("errorstr") == "item not found"


@pytest.mark.parametrize("client_args", [Failure.response])
@pytest.mark.parametrize("method", ["scan_report"])
def test_failed_scan_report(client, method):
    args = {"domain": "domain.test"}
    res = globals()[method](client, args)
    assert res.readable_output == "Domain domain.test was not scanned. Scan it with !quttera-scan-start domain=domain.test"


class FailureBlacklist:
    response = {"error": 200, "errorstr": "success", "status": {"blacklisted": "no", "url": "domain.test"}}


@pytest.mark.parametrize("client_args", [FailureBlacklist.response])
@pytest.mark.parametrize("method", ["status_blacklist"])
def test_failed_status_blacklist(client, method):
    args = {"domain": "domain.test"}
    res = globals()[method](client, args)
    assert res.readable_output == "Domain domain.test is NOT blacklisted"