Skip to content

Fix ScanMalware attribution to subdomain tenants - #953

Open
Jonas Lejon (jonaslejon) wants to merge 1 commit into
microsoft:mainfrom
jonaslejon:fix/scanmalware-host-attribution
Open

Jonas Lejon (jonaslejon) wants to merge 1 commit into
microsoft:mainfrom
jonaslejon:fix/scanmalware-host-attribution

Conversation

@jonaslejon

Copy link
Copy Markdown
Contributor

What this fixes

For a dns or hostname lookup, the ScanMalware provider picks the newest completed scan whose matched_on contains url. The scan list for a host also holds its subdomains, and on a shared platform a subdomain is an unrelated tenant. So in v3.1.0 a lookup of netlify.app or workers.dev returns Severity high, Verdict Malicious, taken from a tenant's phishing page, and -quick attaches that tenant's scan as LastScanUrl.

A scan is now selected only when its own host is the observable's host, or its www. name, as well as matched_on containing url. This builds on cd856f7, which moved LastScan / LastScanUrl / LastTitle onto the selected scan; this change narrows which scan is selected. URL lookups already required the exact URL and are unchanged, as are IP lookups.

Disclosure: I run ScanMalware and wrote this provider (#938).

Before and after, live against scanmalware.com

Through ScanMalware().lookup_ioc(...), v3.1.0 against this branch:

Observable v3.1.0 this branch
netlify.app high, Malicious, LastScanUrl a tenant information, no scan attached
workers.dev high, Malicious, LastScanUrl a tenant information, no scan attached
github.io Low Risk from https://excelformulabot.github.io information, no scan attached
netlify.app (-quick) LastScanUrl a tenant no scan attached
example.com Low Risk, its own scan unchanged
https://gilded-macaron-79e0e2.netlify.app/ (url) high, Malicious unchanged

Result stays True and Scans keeps the full count; only the scan the details and verdict come from is stricter.

Tests

tests/context/test_scanmalware.py gains 8 test cases (22 to 30). Five fail on main: a subdomain tenant (with and without -quick), the platform's own scan behind a newer tenant scan, a lookalike host (example.com.ru under example.com), and a deeper subdomain under a hostname. Three guard against over-tightening: the www. name, letter case and an explicit port still count.

  • pytest tests/context/test_tiproviders.py tests/context/test_scanmalware.py: 71 passed
  • ruff check msticpy --ignore PLW0603: clean
  • pylint with the CI flags: 10.00/10
  • mypy with the CI flags: no issues

The same rule is in the MISP expansion module (MISP/misp-modules#916, released in v3.0.11).

The scan list for a host also holds its subdomains. On a shared platform
a subdomain is an unrelated tenant, so a lookup of netlify.app or
workers.dev took a tenant phishing page's verdict (Severity high), and
-quick attached the tenant's scan as LastScanUrl.

A scan is now selected only when its own host is the observable's host or
its www name, in addition to matched_on containing "url". URL lookups
already required the exact URL and are unchanged.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant