コード例 #1
0
def test_add_two_ip_at_once():
    # arrange
    verdict = Verdict()
    # act
    verdict.add_ip_addresses(['192.168.0.1', '8.8.8.8'])
    # assert
    assert verdict.ip_addresses == ['192.168.0.1', '8.8.8.8']
コード例 #2
0
def test_set_scanner_psc_version():
    # arrange
    verdict = Verdict().set_malware_family("Eicar")
    # act
    verdict.set_scanner(polyswarmclient_version="1.1.1")
    # assert
    assert verdict.scanner == {"polyswarmclient_version": "1.1.1"}
コード例 #3
0
def test_empty_verdict():
    # arrange
    verdict = Verdict()
    # act
    # assert
    with pytest.raises(ValueError):
        verdict.json()
コード例 #4
0
def test_add_domain():
    # arrange
    verdict = Verdict()
    # act
    verdict.add_domain('polyswarm.io')
    # assert
    assert verdict.domains == ['polyswarm.io']
コード例 #5
0
def test_add_ip():
    # arrange
    verdict = Verdict()
    # act
    verdict.add_ip_address('192.168.0.1')
    # assert
    assert verdict.ip_addresses == ['192.168.0.1']
コード例 #6
0
def test_set_scanner_with_vendor_version():
    # arrange
    verdict = Verdict().set_malware_family("Eicar")
    # act
    verdict.set_scanner(vendor_version="1.1.1")
    # assert
    assert verdict.scanner == {"vendor_version": "1.1.1"}
コード例 #7
0
def test_add_two_domains_at_once():
    # arrange
    verdict = Verdict()
    # act
    verdict.add_domains(['polyswarm.io', 'polyswarm.network'])
    # assert
    assert verdict.domains == ['polyswarm.io', 'polyswarm.network']
コード例 #8
0
def test_set_scanner_with_signature_version():
    # arrange
    verdict = Verdict().set_malware_family("Eicar")
    # act
    verdict.set_scanner(signatures_version="05-12-2019")
    # assert
    assert verdict.scanner == {"signatures_version": "05-12-2019"}
コード例 #9
0
def test_set_malware_family():
    # arrange
    verdict = Verdict()
    # act
    verdict.set_malware_family("Eicar")
    # assert
    assert verdict.malware_family == "Eicar"
コード例 #10
0
 def extract_verdict(scan: 'ScanResult') -> 'Optional[Verdict]':
     """Try to parse ``scan.metadata`` as a Verdict"""
     meta = getattr(scan, 'metadata', None)
     if isinstance(meta, str):
         return Verdict.parse_raw(meta)
     elif isinstance(meta, Mapping):
         return Verdict.parse_obj(meta)
     return meta
コード例 #11
0
def test_add_extra_object():
    # arrange
    verdict = Verdict().set_malware_family("Eicar")
    # act
    verdict.add_extra("new_key", {"other_key": "string_value"})
    # assert
    k, v = verdict.extra[0]
    assert k == 'new_key'
    assert v == {"other_key": "string_value"}
コード例 #12
0
def test_add_extra_array():
    # arrange
    verdict = Verdict().set_malware_family("Eicar")
    # act
    verdict.add_extra("new_key", ["string_value"])
    # assert
    k, v = verdict.extra[0]
    assert k == 'new_key'
    assert v == ["string_value"]
コード例 #13
0
def test_add_stix_string():
    # arrange
    verdict = Verdict()
    # act
    verdict.add_stix_signature(
        'oasis-open/cti-stix2-json-schemas/master/schemas/common/hex.json',
        "a0")
    # assert
    assert verdict.stix[0][
        'schema'] == 'oasis-open/cti-stix2-json-schemas/master/schemas/common/hex.json'
    assert verdict.stix[0]['signature'] == "a0"
コード例 #14
0
def test_set_scanner_arch():
    # arrange
    verdict = Verdict().set_malware_family("Eicar")
    # act
    verdict.set_scanner(architecture="x86")
    # assert
    assert verdict.scanner == {
        "environment": {
            "operating_system": None,
            "architecture": "x86"
        }
    }
コード例 #15
0
def test_set_scanner_os():
    # arrange
    verdict = Verdict().set_malware_family("Eicar")
    # act
    verdict.set_scanner(operating_system="windows")
    # assert
    assert verdict.scanner == {
        "environment": {
            "operating_system": "windows",
            "architecture": None
        }
    }
コード例 #16
0
    async def scan(self, guid, artifact_type, content, metadata, chain):
        """Scan an artifact with ClamAV

        Args:
            guid (str): GUID of the bounty under analysis, use to track artifacts in the same bounty
            artifact_type (ArtifactType): Artifact type for the bounty being scanned
            content (bytes): Content of the artifact to be scan
            metadata (dict) Dict of metadata for the artifact
            chain (str): Chain we are operating on
        Returns:
            ScanResult: Result of this scan
        """
        result = await self.clamd.instream(BytesIO(content))
        stream_result = result.get('stream', [])

        vendor = await self.clamd.version()
        metadata = Verdict().set_scanner(operating_system=platform.system(),
                                         architecture=platform.machine(),
                                         vendor_version=vendor.strip('\n'))
        if len(stream_result) >= 2 and stream_result[0] == 'FOUND':
            metadata.set_malware_family(stream_result[1].strip('\n'))
            return ScanResult(bit=True,
                              verdict=True,
                              confidence=1.0,
                              metadata=metadata.json())

        metadata.set_malware_family('')
        return ScanResult(bit=True, verdict=False, metadata=metadata.json())
コード例 #17
0
ファイル: yara.py プロジェクト: CalebFenton/polyswarm-client
    async def scan(self, guid, artifact_type, content, metadata, chain):
        """Scan an artifact with Yara.

        Args:
            guid (str): GUID of the bounty under analysis, use to track artifacts in the same bounty
            artifact_type (ArtifactType): Artifact type for the bounty being scanned
            content (bytes): Content of the artifact to be scan
            metadata (dict) Dict of metadata for the artifact
            chain (str): Chain we are operating on

        Returns:
            ScanResult: Result of this scan
        """
        matches = self.rules.match(data=content)
        sysname, _, _, _, machine = os.uname()
        metadata = Verdict().set_scanner(operating_system=sysname,
                                         architecture=machine,
                                         vendor_version=yara.__version__)
        if matches:
            # author responsible for distilling multiple metadata values into a value for ScanResult
            metadata.set_malware_family(matches[0].rule)
            return ScanResult(bit=True, verdict=True, metadata=metadata.json())

        metadata.set_malware_family('')
        return ScanResult(bit=True, verdict=False, metadata=metadata.json())
コード例 #18
0
def test_add_two_extras_at_once():
    # arrange
    verdict = Verdict().set_malware_family("Eicar")
    # act
    verdict.add_extras([("new_key", "string_value"),
                        ("new_key1", {
                            "other_key": "string_value"
                        })])
    # assert
    k, v = verdict.extra[0]
    assert k == 'new_key'
    assert v == "string_value"
    k, v = verdict.extra[1]
    assert k == 'new_key1'
    assert v == {"other_key": "string_value"}
コード例 #19
0
def test_extra_array_scanner():
    # arrange
    blob = {
        "malware_family":
        "Eicar",
        "domains": ["polyswarm.io"],
        "ip_addresses": ["192.168.0.1"],
        "stix": [{
            "schema":
            "oasis-open/cti-stix2-json-schemas/master/schemas/common/hex.json",
            "signature": "a0"
        }],
        "scanner": {
            "extra": ["test"],
            "version": "1.0.0",
            "polyswarmclient_version": "2.0.2",
            "signatures_version": "2019",
            "vendor_version": "1.0.0",
            "environment": {
                "operating_system": "windows",
                "architecture": "x86"
            }
        },
    }
    # assert
    assert Verdict.validate(blob)
コード例 #20
0
def test_validate_all_output():
    # arrange
    verdict = Verdict().set_malware_family("Eicar")\
        .add_domain('polyswarm.io')\
        .add_ip_address('192.168.0.1')\
        .add_stix_signature(
        'oasis-open/cti-stix2-json-schemas/master/schemas/common/hex.json',
        "a0"
        ) \
        .set_scanner(operating_system="windows", architecture="x86", version="1.0.0", polyswarmclient_version="2.0.2",
                     signatures_version="2019", vendor_version="1.0.0")\
        .add_extra("new_key", {"other_key": "string_value"})\
        .add_extra("new_key1", ["string_value"])\
        .add_extra("new_key2", "string_value")

    result = {
        "malware_family":
        "Eicar",
        "domains": ["polyswarm.io"],
        "ip_addresses": ["192.168.0.1"],
        "stix": [{
            "schema":
            "oasis-open/cti-stix2-json-schemas/master/schemas/common/hex.json",
            "signature": "a0"
        }],
        "scanner": {
            "version": "1.0.0",
            "polyswarmclient_version": "2.0.2",
            "signatures_version": "2019",
            "vendor_version": "1.0.0",
            "environment": {
                "operating_system": "windows",
                "architecture": "x86"
            }
        },
        "new_key": {
            "other_key": "string_value",
        },
        "new_key1": ["string_value"],
        "new_key2":
        "string_value"
    }
    # act
    blob = json.loads(verdict.json())
    # assert
    assert Verdict.validate(blob)
    assert blob == result
コード例 #21
0
 def attach_siginfo(scan: 'ScanResult') -> 'ScanResult':
     """Attach shared engine metadata to ``scan`` metadata"""
     with suppress(AttributeError):
         scanner_info = engine_info.scanner_info()
         if scanner_info:
             meta = extract_verdict(scan) or Verdict().set_malware_family('')
             scan.metadata = meta.set_scanner(**scanner_info)
     return scan
コード例 #22
0
def test_add_stix_object():
    # arrange
    verdict = Verdict()
    # act
    verdict.add_stix_signature(
        'oasis-open/cti-stix2-json-schemas/master/schemas/common/kill-chain-phase.json',
        {
            "kill_chain_name": 'asdf',
            "phase_name": "full"
        })
    # assert
    assert verdict.stix[0][
        'schema'] == 'oasis-open/cti-stix2-json-schemas/master/schemas/common/kill-chain-phase.json'
    assert verdict.stix[0]['signature'] == {
        "kill_chain_name": 'asdf',
        "phase_name": "full"
    }
コード例 #23
0
def test_builder_one_scanners_is_valid():
    # arrange
    artifact = Verdict()\
        .set_malware_family("Eicar")
    # act
    assertion = Assertion()\
        .add_artifact(artifact)
    # assert
    assert Assertion.validate(json.loads(assertion.json()))
コード例 #24
0
def test_add_artifact():
    # arrange
    artifact = Verdict() \
        .set_malware_family("Eicar")
    assertion = Assertion()
    # act
    assertion.add_artifact(artifact)
    # assert
    assert assertion.artifacts and assertion.artifacts[0] == artifact
コード例 #25
0
def test_scanalytics(statsd, engine_info, use_async, scan_result, verbose_metrics, artifact_kind):
    is_error = isinstance(scan_result, Exception)
    args = (None, str(uuid4()), artifact_kind, b'content', {}, 'home')
    type_tag = 'type:%s' % ArtifactType.to_string(artifact_kind)
    if use_async:

        @scanalytics(statsd=statsd, engine_info=engine_info, verbose=verbose_metrics)
        async def scanfn(self, guid, artifact_type, content, metadata, chain):
            if is_error:
                raise scan_result
            return scan_result

        result = asyncio.run(scanfn(*args))
    else:

        @scanalytics(statsd=statsd, engine_info=engine_info, verbose=verbose_metrics)
        def scanfn(self, guid, artifact_type, content, metadata, chain):
            if is_error:
                raise scan_result
            return scan_result

        result = scanfn(*args)

    statsd.timing.assert_called_once()

    assert isinstance(result.metadata, str)
    result_meta = Verdict.parse_raw(result.metadata)
    assert result_meta.scanner.signatures_version == engine_info.definitions_version
    assert result_meta.scanner.vendor_version == engine_info.engine_version

    if is_error:
        assert result_meta.__dict__['scan_error'] == scan_result.event_name
        assert result.bit is False
        statsd.increment.assert_called_once_with(
            SCAN_FAIL, tags=[type_tag, f'scan_error:{scan_result.event_name}']
        )
    else:
        assert result.verdict is scan_result.verdict
        assert result.bit is scan_result.bit
        verdict_tag = 'verdict:malicious' if scan_result.verdict else 'verdict:benign'

        if scan_result.bit is True:
            statsd.increment.assert_any_call(SCAN_SUCCESS, tags=[type_tag, verdict_tag])

            if verbose_metrics:
                statsd.increment.assert_any_call(
                    SCAN_VERDICT,
                    tags=[type_tag, verdict_tag],
                )
                assert statsd.increment.call_count == 2
            else:
                assert statsd.increment.call_count == 1

        elif scan_result.bit is False:
            if verbose_metrics:
                statsd.increment.assert_called_once_with(SCAN_NO_RESULT, tags=[type_tag])
コード例 #26
0
    async def scan(self, guid, artifact_type, content, metadata, chain):
        """Scan an artifact

        Args:
            guid (str): GUID of the bounty under analysis, use to track artifacts in the same bounty
            artifact_type (ArtifactType): Artifact type for the bounty being scanned
            content (bytes): Content of the artifact to be scan
            metadata (dict) Dict of metadata for the artifact
            chain (str): Chain we are operating on
        Returns:
            ScanResult: Result of this scan
        """
        results = await asyncio.gather(*[
            backend.scan(guid, artifact_type, content, chain)
            for backend in self.backends
        ])

        # Unpack the results
        bits = [r.bit for r in results]
        verdicts = [r.verdict for r in results]
        confidences = [r.confidence for r in results]
        metadatas = [r.metadata for r in results]

        asserted_confidences = [c for b, c in zip(bits, confidences) if b]
        avg_confidence = sum(asserted_confidences) / len(asserted_confidences)

        # author responsible for distilling multiple metadata values into a value for ScanResult
        metadata = metadatas[0]
        try:
            metadatas = [
                json.loads(metadata) for metadata in metadatas
                if metadata and Verdict.validate(json.loads(metadata))
            ]
            if metadatas:
                metadata = Verdict().set_malware_family(metadatas[0].get(
                    'malware_family', '')).json()
        except json.JSONDecodeError:
            logger.exception(f'Error decoding sub metadata')

        return ScanResult(bit=any(bits),
                          verdict=any(verdicts),
                          confidence=avg_confidence,
                          metadata=metadata)
コード例 #27
0
def test_invalid_artifact_throws_value_error():
    # arrange
    artifact = Verdict()\
        .add_domain("polyswarm.io")
    # act
    assertion = Assertion()\
        .add_artifact(artifact)
    # assert
    with pytest.raises(ValueError):
        assertion.json()
コード例 #28
0
def test_add_artifacts():
    # arrange
    artifact = Verdict() \
        .set_malware_family("Eicar")
    assertion = Assertion()
    # act
    assertion.add_artifacts([artifact for i in range(0, 3)])
    # assert
    assert assertion.artifacts
    assert len(assertion.artifacts) == 3
    assert assertion.artifacts[0] == artifact
コード例 #29
0
def test_scanner_null_environemnt():
    # arrange
    verdict = Verdict().set_malware_family("Eicar")
    # act
    verdict.set_scanner(version="1.0.0",
                        polyswarmclient_version="2.0.2",
                        signatures_version="2019",
                        vendor_version="1.0.0")
    # assert
    Verdict.validate(json.loads(verdict.json()))
コード例 #30
0
def test_validate_two_domains_at_once():
    # arrange
    verdict = Verdict().set_malware_family("Eicar")
    # act
    verdict.add_domains(['polyswarm.io', 'polyswarm.network'])
    # assert
    assert Verdict.validate(json.loads(verdict.json()))