78 lines
6.2 KiB
Markdown
78 lines
6.2 KiB
Markdown
# 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.
|