
Laufzeit-Schwachstellenscanner: findet CVEs in den Diensten, die tatsächlich auf einem Host ausgeführt werden, und stuft sie nach Netzwerkexposition ein.
# OffSeq Threat Finder
[](https://github.com/offseq/threat-finder/actions/workflows/ci.yml)
[](https://crates.io/crates/threat-finder)
[](https://docs.rs/threat-finder)
[](#license)
**threat-finder** findet die verwundbare Software, die _tatsächlich_ auf einem Host läuft – nicht das, was ein Manifest behauptet – und zeigt Ihnen, welche Ergebnisse **netzwerkerreichbar** sind. Es löst jeden laufenden Dienst (und mit `--scope all` auch jedes installierte Betriebssystem-Paket) in eine exakte [Package-URL](https://github.com/package-url/purl-spec) auf und gleicht sie mit dem [OffSeq-Radar](https://radar.offseq.com)-Katalog ab, wobei ökosystemnative Versionsregeln verwendet werden, sodass zurückportierte/behobene Builds nicht fälschlich markiert werden.

```text
Vulnerability summary (highest risk first):
openssh-server@1:8.9p1-3ubuntu0.6 — 1 finding(s) [PUBLIC tcp 0.0.0.0:22]
[ACT-NOW 92] HIGH CVE-2024-6387 [KEV] regreSSHion: remote code execution in OpenSSH
→ fix: 1:8.9p1-3ubuntu0.10 https://radar.offseq.com/threat/…
[email protected] — 1 finding(s)
[SCHEDULE 41] MED CVE-2023-44487 HTTP/2 Rapid Reset
2 confirmed finding(s) across 2 asset(s); 1 exposed, 1 known-exploited.
```
## Installation
```sh
brew install offseq/tap/threat-finder # Homebrew (macOS/Linux), prebuilt
cargo binstall threat-finder # prebuilt binary, no toolchain
cargo install threat-finder # from source
```
Vorgefertigte Archive für Linux/macOS (x86_64 + arm64) und Windows (x86_64) finden Sie auf der [Releases-Seite](https://github.com/offseq/threat-finder/releases/latest). Für den Build aus dem Quellcode ist Rust ≥ 1.87 erforderlich. Linux, macOS, die BSDs und Windows werden alle unterstützt.
## Schnellstart
```sh
export OFFSEQ_API_KEY=... # from https://radar.offseq.com/console
threat-finder
```
Scannt die laufenden Dienste, gibt eine nach Risiko sortierte Zusammenfassung aus und schreibt den vollständigen JSON-Bericht nach `/tmp/threats.json`. Fügen Sie `--scope all` hinzu, um auch jedes installierte Betriebssystem-Paket zu scannen.
## Verwendung
```sh
threat-finder [OPTIONS]
```
| Flag | Beschreibung |
|------|-------------|
| `-o, --output <PATH>` | Schreibt den JSON-Bericht nach `PATH` (Standard: Eingabeaufforderung oder `/tmp/threats.json`) |
| `--json` | Gibt den JSON-Bericht anstelle einer Datei auf stdout aus |
| `--scope <SCOPE>` | `running` (Standard) oder `all` (+ jedes installierte Betriebssystem-Paket) |
| `--severity <LEVEL>` | Nur Ergebnisse ab `critical\|high\|medium\|low` melden |
| `--strict` | Koordinaten-unbestätigte Ergebnisse verwerfen (nur bestätigte melden) |
| `--fail-on <WHAT>` | Mit Exit-Code `5` beenden, wenn passende Ergebnisse vorliegen: `any\|critical\|high\|medium\|low\|kev\|exposed` |
| `--sarif <PATH>` | Zusätzlich einen SARIF-2.1.0-Bericht schreiben (für Code-Scanning-UIs) |
| `--include <GLOB>` / `--exclude <GLOB>` | Assets nach Namens-Glob filtern (wiederholbar) |
| `-q, --quiet` | Banner, Fortschritt und Zusammenfassung unterdrücken |
| `--no-color` | ANSI-Farben deaktivieren |
| `-y, --yes` | Standardwerte annehmen, nie nachfragen (CI/Cron) |
| `--reset` | API-Schlüssel erneut eingeben, den gespeicherten ignorieren |
| `--register` | Den gescannten Host bei Radar zur kontinuierlichen Überwachung registrieren (ohne Nachfrage) |
| `--no-register` | Bei diesem Lauf nicht registrieren und nicht zur Überwachung auffordern |
| `--host-name <NAME>` | Anzeigenamen des Hosts, der mit einer Registrierung gesendet wird |
| `--unregister` | Die Inventarliste dieses Hosts aus Radar entfernen und beenden |
| `--windows-missing-updates` | (Windows) Zusätzlich ausstehende Sicherheitsupdates vom Windows Update Agent auflisten (Online-Scan; mit erhöhten Rechten ausführen) |
| `-h, --help` / `-V, --version` | Hilfe / Version |
```sh
# CI: only high+ findings, JSON to stdout, no prompts
OFFSEQ_API_KEY=… threat-finder --yes --json --severity high > report.json
# Fail the build only when a network-exposed service has a known-exploited CVE
OFFSEQ_API_KEY=… threat-finder --yes --quiet --fail-on exposed
```
**Exit-Codes:** `0` ok · `1` Lookup-/E/A-Fehler · `2` kein API-Schlüssel · `3` nicht unterstütztes Betriebssystem · `4` Ratengrenze/Kontingent oder API-Zugriff erforderlich (Upgrade nötig) · `5` `--fail-on`-Schwelle erreicht.
**API-Schlüssel** (erhalten Sie einen über die [Radar-Konsole](https://radar.offseq.com/console)), wird in dieser Reihenfolge aufgelöst:
1. Die Umgebungsvariable `OFFSEQ_API_KEY` (am besten für CI/Cron).
2. Der gespeicherte Schlüssel in `$XDG_CONFIG_HOME/offseq-rust/config.toml` (`0600`), sofern nicht `--reset` angegeben ist.
3. Eine interaktive, verdeckte Eingabeaufforderung auf einem TTY – wird dann für das nächste Mal gespeichert.
Nicht-interaktiv (`--yes` / kein TTY) ohne verfügbaren Schlüssel endet mit Exit-Code `2`.
Setzen Sie `OFFSEQ_CONFIG_DIR`, um den Speicherort der Konfiguration zu überschreiben (Standard: das betriebssystemspezifische Benutzerkonfigurationsverzeichnis) – praktisch für Container/CI, die einen deterministischen Pfad benötigen.
## So funktioniert es
**Exakter Koordinaten-Abgleich.** Jedes Asset wird zu einem purl mit seiner _vollen_ Version (Epoche + Distro-Revision) und einem `?distro=`-Qualifier, z. B. `pkg:deb/ubuntu/openssh-server@1:8.9p1-3ubuntu0.6?distro=jammy`. Das Inventar wird in gebündelten `POST /match/batch`-Aufrufen (eine Anfrage pro Block entsprechend der Tarifstufe) **serverseitig mit ökosystemnativen Versionsregeln** (dpkg/rpm/apk/semver) abgeglichen – so wird ein zurückportierter und behobener Build wie `1.18.0-6+deb11u3` korrekt nicht markiert, und es gibt kein clientseitiges Versionsraten. Ergebnisse werden anhand des `confirmed`-Flags der API aufgeteilt: Bestätigte Treffer werden gemeldet; Koordinatentreffer, deren Version nicht bestätigt werden kann, werden separat als **unbestätigt / Triage** angezeigt (vom Zähler, `byCve` und `--fail-on` ausgeschlossen; verwerfen Sie sie mit `--strict`).
**Netzwerkexpositions-Korrelation.** Manifest-Scanner (Trivy, Grype, osv-scanner) lesen Paketlisten; externe Scanner (Nessus, OpenVAS) benötigen einen zweiten Host. Dieses Tool ordnet den Prozess jedes laufenden Dienstes den Sockets zu, auf denen er **lauscht** (`/proc/net` unter Linux, `lsof` unter den anderen Unix-Systemen, `Get-NetTCPConnection` / `netstat` unter Windows) und klassifiziert die Erreichbarkeit – `loopback` / `private` / `public`. Ein verwundbarer Dienst auf `0.0.0.0` ist ein ganz anderes Risiko als einer auf `127.0.0.1`: Ergebnisse werden zuerst nach Exposition eingestuft, und `--fail-on exposed` macht genau das zur CI-Bedingung. Es werden keine Pakete gesendet. Ergebnisse enthalten außerdem CISA **KEV** und **EPSS**.
**Expositionsbewusste Priorisierung.** Jedes Ergebnis erhält einen `riskScore` (0–100) und ein SSVC-artiges `decision`-Band – **`act-now` · `soon` · `schedule` · `track`** – kombiniert aus Schweregrad, EPSS, KEV und der **Netzwerkexposition** des zugehörigen Assets. Die Zusammenfassung beginnt jede Zeile mit einem Badge im Stil `[ACT-NOW 92]` und sortiert danach, sodass die wenigen öffentlich erreichbaren, bekanntermaßen ausgenutzten Probleme auf einem lauten Host nach oben schwimmen. Der Score verwendet lokal und serverseitig dieselbe Formel (die Radar-Überwachungsansicht fügt einen kleinen Bonus hinzu, wenn ein KEV-Ergebnis sein Fälligkeitsdatum überschritten hat – ein Datum, das die CLI nicht kennt) und erscheint in `--json` und SARIF (`properties`).
## Kontinuierliche Überwachung
Ein einmaliger Scan ist nur eine Momentaufnahme. Registrieren Sie einen Host einmal, und Radar beobachtet ihn weiter: Wenn eine **neu veröffentlichte CVE** eine seiner Koordinaten betrifft, erhalten Sie eine Warnung (E-Mail + Konsole), priorisiert nach Exposition – kein erneuter Scan erforderlich.
Nach einem interaktiven Scan fragt das Tool:
```text
Add these 42 services to Radar for continuous monitoring & alerts? [Y/n/never]
```
`Y` registriert diesen Host; `n` überspringt diesen Lauf; `never` merkt sich Ihre Wahl (sie wird in der Konfiguration gespeichert und Sie werden nicht erneut gefragt). Bei einem erneuten Scan meldet es außerdem **Drift** (`+added / -removed / ~changed`) und alle Ergebnisse, die **seit Ihrem letzten Scan neu** sind. Verwalten Sie Ihre Hosts – Überwachung umschalten, Ergebnisse anzeigen, abmelden – unter **Inventory** in der [Radar-Konsole](https://radar.offseq.com/console).
Für die Automatisierung können Sie die Eingabeaufforderung überspringen: `--register` registriert nicht-interaktiv (in CI standardmäßig deaktiviert), `--no-register` verzichtet auf die Registrierung, `--host-name <NAME>` beschriftet den Host und `--unregister` entfernt ihn. Eine stabile Pro-Host-ID und Ihre Eingabeaufforderungs-Präferenz befinden sich in `$XDG_CONFIG_HOME/offseq-rust/config.toml`. Die Registrierung ändert niemals den Exit-Code – ein Überwachungs-Aussetzer lässt Ihren Scan nicht fehlschlagen. Erfordert einen Basic/Pro/Enterprise-Plan (oder Pro-Konsole).
## Umfang & Abdeckung
`--scope running` (Standard) scannt laufende Dienste – die kleine, signalstarke Menge, deren Exposition korreliert werden kann. `--scope all` listet zusätzlich **jedes installierte Betriebssystem-Paket** auf (`dpkg`/`rpm`/`pacman`/`apk`/`brew`/`pkg`/`pkg_info`) und erweitert die abgeglichene Oberfläche um das 10–50-Fache. Ein Paket, das auch einen laufenden, exponierten Prozess unterstützt, behält diese Exposition (Assets werden dedupliziert und nach Koordinate zusammengeführt). Der Kernel wird unter `--scope all` als sein Paket (`linux-image…`) abgedeckt.
> `--scope all` kann Hunderte bis Tausende von Paketen ergeben. Im kostenlosen Tarif (15 Lookups/Stunde) führt dies zu einer Ratengrenze; das Tool warnt, wenn das Inventar das Budget überschreitet. (Die Lookups sind bereits gebündelt; ein lokaler Ergebniscache ist auf der Roadmap.)
## Unterstützung pro Betriebssystem
| Betriebssystem | Erkennung | Koordinatenquelle |
|----|-----------|-------------------|
| Linux (systemd) | `ListUnits` → `/proc/<pid>/exe` | dpkg / rpm / pacman / apk |
| Linux (SysV/OpenRC) | `service --status-all` / `rc-status` | Paketdatenbank |
| macOS | `launchctl list` → `ps` (nur Drittanbieter) | Homebrew |
| FreeBSD / DragonFly | `service -e` | `pkg` |
| OpenBSD | `rcctl ls started` | `pkg_info` |
| NetBSD | `/etc/rc.d` Status | `pkg_info` |
| Solaris / illumos | `svcs` → `svcprop` | Sonde (`--version`) |
| Windows | `Win32_Service` → `Get-NetTCPConnection` / `netstat` | Registry / winget / Appx / Chocolatey / Scoop → CPE; npm / pip / dotnet → purl; der Betriebssystem-Build → CPE |
Wenn kein Paket eine Binärdatei besitzt, fällt die Version auf eine gehärtete `--version`-Sonde zurück (nur absoluter Pfad, bereinigte Umgebung). Unter macOS werden Apple-Systemdienste (`com.apple.*`, SIP-geschützte Pfade) übersprungen – sie werden durch die Betriebssystemversion abgedeckt, und das Abfragen von Hunderten davon ist sinnlos.
Unter **Windows** wird alles über die eingebaute `powershell.exe` gesammelt (keine zusätzliche Laufzeit, kein Admin für das Kerninventar). Installierte Apps werden über eine kuratierte Namenstabelle auf NVD-CPEs abgebildet (nicht zugeordnete Apps fallen auf eine Namenssuche zurück, statt falsch zu raten); die Betriebssystemedition/der Build wird zu einem feature-qualifizierten OS-CPE (z. B. `windows_11_23h2`); und `--windows-missing-updates` fügt eine optionale Windows-Update-Agent-Meldung über ausstehende Sicherheitspatches hinzu.
## Ausgabe
JSON mit deterministischen (sortierten) Schlüsseln und ohne Zeitstempel, sodass sich Berichte sauber diffen lassen:
- **`services`** – `pkg@version` → bestätigte Ergebnisse (`cveId`, `severity`, `cvssScore`, `epss`, `kev`, `riskScore`, `decision`, `confirmed`, `matchedRange`, `matchBasis`, `fixedVersions`, `remediation`, `cwes`, `references`, `radarUrl`), zuerst das höchste Risiko.
- **`unconfirmed`** – Koordinatentreffer, deren Version nicht bestätigt werden konnte (Triage).
- **`assets`** – `pkg@version` → `{ exe, versionSource, exposed, reachability, listeners }` (`versionSource` = `package-db` | `probe`; `reachability` deckt TCP **und** UDP ab).
- **`byCve`** – jede CVE über alle betroffenen Assets zusammengefasst („einmal patchen, vieles beheben").
- **`errors`** – Lookup-Fehler pro Asset, damit ein Fehler nie als „sauber" gelesen wird.
- **`registration`** – vorhanden, wenn der Lauf den Host registriert hat: `host_id`, `monitoring`, `drift`, `summary`, `newSinceLastCount`.
- **`meta`** – `{ tool, version, schemaVersion }` (`schemaVersion` 2).
Ein SARIF-2.1.0-Bericht (`--sarif`) ist ebenfalls für Code-Scanning-UIs verfügbar.
## Das OffSeq-Ökosystem
| | |
|---|---|
| [**OffSeq**](https://offseq.com) | EU-Sicherheitsaudits, Bedrohungsüberwachung, CISO-as-a-Service, NIS2-Konformität |
| [**Radar**](https://radar.offseq.com) | Echtzeit-Bedrohungsinformationen – der Katalog, gegen den threat-finder abgleicht |
| [**Radar Console**](https://radar.offseq.com/console) | Abonnements, benutzerdefinierte Feeds und Ihr `OFFSEQ_API_KEY` |
| [**Radar API**](https://radar.offseq.com/api-docs) | REST-Dokumentation für den hier verwendeten `/match`-Endpunkt |
| [**Radar Threats**](https://radar.offseq.com/threats) | Durchsuchbare CVE-/Malware-/Bedrohungsakteur-Datenbank |
| [**Radar Feeds**](https://radar.offseq.com/feeds) | Benutzerdefinierte Feeds, die CISA, CIRCL, ThreatFox, … aggregieren |
| [**Radar Pricing**](https://radar.offseq.com/pricing) | Kostenloser Tarif bis Enterprise |
| [**Breach**](https://breach.offseq.com) | Überwachung von Dark-Web-Datenlecks & exponierten Anmeldedaten |
| [**Veil**](https://veil.offseq.com) | Clientseitige PNG-Steganografie (AES-256-GCM) |
| [**Guard**](https://offseq.com/guard/) | KI-gestützter Website-Sicherheits- & Compliance-Analyst |
| [**Training**](https://training.offseq.com) | PECB-akkreditierte Sicherheits- & Datenschutzkurse |
## Entwicklung
```sh
cargo build --release
cargo test # unit tests
cargo test -- --ignored # + macOS live-discovery smoke test
cargo clippy --all-targets
```
Die Engine ist eine Bibliotheks-Crate (`find_threats`) mit einer `Collector`-Abstraktion (derzeit laufende Dienste und OS-Pakete; als Nächstes Lockfiles / Container / SBOM), sodass die Binärdatei ein schlankes CLI darüber ist.
## Lizenz
Zweifach lizenziert unter [MIT](https://github.com/offseq/threat-finder/blob/main/LICENSE) oder [Apache-2.0](https://github.com/offseq/threat-finder/blob/main/LICENSE), je nach Ihrer Wahl.