Check a host against rogue/threat device signatures. Args: vendor: MAC OUI vendor string (e.g. "Espressif Inc.") mac: full MAC address (e.g. "AC:67:B2:01:23:45") hostname: device hostname if known ports: list of open port numbers/strings Returns: lis
(vendor, mac, hostname='', ports=None)
| 607 | |
| 608 | |
| 609 | def detect_threats(vendor, mac, hostname='', ports=None): |
| 610 | """Check a host against rogue/threat device signatures. |
| 611 | |
| 612 | Args: |
| 613 | vendor: MAC OUI vendor string (e.g. "Espressif Inc.") |
| 614 | mac: full MAC address (e.g. "AC:67:B2:01:23:45") |
| 615 | hostname: device hostname if known |
| 616 | ports: list of open port numbers/strings |
| 617 | |
| 618 | Returns: |
| 619 | list of matched threat dicts, each with: |
| 620 | id, name, severity, category, description |
| 621 | Empty list if no threats detected. |
| 622 | """ |
| 623 | if not vendor and not mac and not hostname: |
| 624 | return [] |
| 625 | |
| 626 | vendor_lower = (vendor or '').lower() |
| 627 | hostname_lower = (hostname or '').lower() |
| 628 | mac_upper = (mac or '').upper() |
| 629 | mac_prefix = mac_upper[:8] if len(mac_upper) >= 8 else '' |
| 630 | |
| 631 | port_set = set() |
| 632 | for p in (ports or []): |
| 633 | try: |
| 634 | port_set.add(int(str(p).split('/')[0])) |
| 635 | except (ValueError, IndexError): |
| 636 | pass |
| 637 | |
| 638 | matches = [] |
| 639 | for sig in _THREAT_SIGNATURES: |
| 640 | # Each criterion that is present must match (AND logic) |
| 641 | matched = True |
| 642 | criteria_count = 0 |
| 643 | |
| 644 | # Vendor keyword check |
| 645 | if 'vendor_keywords' in sig: |
| 646 | criteria_count += 1 |
| 647 | if not any(kw in vendor_lower for kw in sig['vendor_keywords']): |
| 648 | matched = False |
| 649 | |
| 650 | # MAC OUI prefix check |
| 651 | if 'mac_prefixes' in sig: |
| 652 | criteria_count += 1 |
| 653 | if not any(mac_prefix == pfx for pfx in sig['mac_prefixes']): |
| 654 | matched = False |
| 655 | |
| 656 | # Hostname keyword check |
| 657 | if 'hostname_keywords' in sig: |
| 658 | criteria_count += 1 |
| 659 | if not any(kw in hostname_lower for kw in sig['hostname_keywords']): |
| 660 | matched = False |
| 661 | |
| 662 | # Required ports (ALL must be open) |
| 663 | if 'port_required' in sig: |
| 664 | criteria_count += 1 |
| 665 | if not all(p in port_set for p in sig['port_required']): |
| 666 | matched = False |
no test coverage detected