Files
rpcscope/docs/ARCHITECTURE.md
T
2026-10-15 12:34:26 -04:00

78 lines
6.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Architecture
RPCScope separates collection from interpretation so that external tool changes do not silently change the meaning of a finding.
```text
targets (expanded, resolved, deduplicated, capped)
|
+-- independent TCP/135 + TCP/445 discovery
| +-- RPC-only hosts remain in scope
| +-- unreachable: stop here, retain discovery in JSON only
| +-- reachable: queue host pipelines only
+-- NetExec SMB inventory -------+
+-- enum4linux-ng JSON ----------+--> normalized HostEvidence
+-- Impacket rpcdump ------------+ |
+-- optional MSF scanner --------+ v
+-- opt-in CLDAP precondition ---+ (not a patch detector)
deterministic rules
|
+---------------+---------------+
| |
report.json report.md
```
## Trust boundaries
- Collector output is untrusted input. Parsers extract only labelled facts and never execute data from results.
- Credentials are passed to external tools only when the operator supplies them. Recorded command metadata redacts passwords.
- Live collection is gated by `--i-am-authorized`; offline analysis does not require the flag.
- A UUID match establishes interface exposure. It does not establish vulnerable code, reachable opnums, authorization, patch state, or exploitability.
- A CVE-level finding requires a purpose-built scanner result or a separately implemented, testable evidence predicate.
## Data model
`HostEvidence` is the stable seam of the project. Collectors contribute:
- identity: address, hostname, domain, OS fingerprint;
- SMB posture: SMBv1, signing, null/guest session state;
- shares: name, read/write access, comment;
- RPC surface: UUID, version, protocol label, provider, binding/endpoint;
- checks: explicit scanner name and outcome;
- check details: the actual attributed result marker and any evidence conflicts;
- collection: pending, success, failure, or skipped state for each collector;
- sources: raw artifact paths.
Rules consume only this model. They do not parse terminal output and do not invoke tools.
Dedicated checks are registered in `rpcscope/catalog.py`. CLI NetExec checks run in single-module, bounded live-host batches; unrelated modules remain separate processes. The five bind-only exposure methods share `METHOD=All` only when the complete unchanged set was selected. Each check keeps a separate normalized result. `longlogon` is native Python and estimates a naming precondition over CLDAP, not vulnerability or patch status.
The registry also distinguishes interface exposure and information gathering. Accepted RPC binds are `exposed`; spooler registrations and OXID interface results are `observed`. They become informational findings rather than CVE verdicts. `CheckAttempt` preserves backend-specific evidence, and conflicting positive/negative results are highlighted directly in minimal reports.
`advisories.py` contains a separate review-only metadata registry for 2020–2026 issues. `sync-cves` refreshes fixed Microsoft CNA records without changing `catalog.CHECKS`, importing code, or generating host vulnerability verdicts.
Discovery uses `--discovery-workers` (256 by default) for lightweight TCP probing and NetExec inventory. A check batch has at most `--jobs` live targets (8 by default, capped at 128 per command) and the same NetExec thread limit. Batches run sequentially; afterward the Python host pool has at most `--jobs` active futures. This avoids nested concurrency multiplication. Host pipelines run native/optional MSF checks, RPC dump, then optional full enum4linux. Full enum is enabled by `--deep` in the CLI; the library retains the old defaults. Dead targets never receive pending checks or host futures. TCP timeout/closed are completed reachability outcomes; an unprobed target indicates a real discovery interruption/deadline, while local resource exhaustion is explicitly a scan failure.
A thread-safe progress callback emits task start/finish events to stderr for reachable hosts and silently advances counts for unreachable ones. A separate callback publishes atomic report snapshots as host jobs finish. Parsing uses original in-memory output, while saved artifacts and check details redact supplied credentials; redaction cannot alter target addresses or detection markers before classification.
Execution completion is independent of evidence certainty. `inconclusive` and `suspected` are completed results; ordinary skipped checks are counted outside the eligible denominator. Failed processes, pending work and cancellation remain partial. Text and Markdown show reachable hosts; JSON retains the full expanded scope and all discovery states.
`netexec.py` plans batches and inspects installed CLI capabilities without importing scanner code. Help inspection is cached; read-only share semantics must be known. Output is indexed once by IP/module/port, and known zero-exit host exceptions do not masquerade as successful collection. See `NETEXEC_REVIEW.md` for pinned upstream references and verification limits.
## Rule quality bar
Every rule should include a stable ID, severity, confidence, exact evidence, impact, remediation, and a primary reference when one exists. New rules need positive and negative fixtures. Avoid CVE claims based only on banners, UUIDs, OS names, or open ports.
## NDRaider boundary
NDRaider can statically recover interface UUIDs and typed NDR method grammars from Windows binaries, then generate structure-aware fuzz inputs. That complements RPCScope in a lab workflow:
1. RPCScope observes a vendor UUID on an authorized target.
2. The assessor obtains the matching server binary through an approved process.
3. NDRaider analyzes the binary offline and exports grammar JSON.
4. A future importer correlates UUID/version/method counts with the remote observation.
5. Any live fuzzing remains a separate, explicit active-testing profile.
Keeping that boundary prevents a fast inventory scan from unexpectedly becoming a fuzzer.
See `CHECKER_POLICY.md` for the CVE synchronization and future proof-of-execution requirements.