Repository navigation
feat(attack-path): add a native complex file finding type (#6647) - #7016
Conversation
|
/review docs
|
|
Two things before merge:
Heads-up: the rebase will hit the just-merged #7017 (complex-finding sub-field matcher), which still carries the interim share_name -> file that your PR moves to native share/file. That matcher is my area, I'll pair with you on the reconciliation so nothing regresses. |
|
Thanks Laurent.
Rather than push that auto-merged resolution, I'd like to take you up on the pairing offer: I'll resolve the two front conflicts, and we settle |
|
Thanks Seb, you're right that the matcher is the real silent-regression risk. I dug into both backend auto-merges and they're not equal:
So: you take the two front files + keep the graph-service auto-merge; I own the matcher + its tests. One thing to confirm: your registry maps file.share -> ShareName, so I could let share_name also match file findings. I'd scope the graph matcher to share_name -> {share} only (a file isn't a share, otherwise spurious edges); the file->ShareName link stays a runtime-chaining concern. Good with that? |
303d30b to
057376d
Compare
|
Rebased onto current What I took (front) + the graph-service auto-merge
Heads-up: the auto-merge silently corrupted one of my front tests — the same risk you flagged, but on the front side
Didn't touch On the One caveat: I couldn't run the front suite locally in this worktree (its |
31d099c to
3bddb4a
Compare
Codecov Report❌ Patch coverage is ❌ Your project check has failed because the head coverage (7.48%) is below the target coverage (80.00%). You can increase the head coverage or adjust the target coverage. Additional details and impacted files@@ Coverage Diff @@
## main #7016 +/- ##
============================================
- Coverage 44.48% 44.44% -0.05%
+ Complexity 9628 9626 -2
============================================
Files 2733 2734 +1
Lines 83446 83450 +4
Branches 12815 12827 +12
============================================
- Hits 37125 37089 -36
- Misses 43552 43569 +17
- Partials 2769 2792 +23
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
…elabelling them as file (#6647)
Introduce a real `file` finding type end to end, replacing the interim share->file stand-in removed in the previous change. A file is a complex finding (not a primitive): the same basename means different things by location, so it carries file_name + path + share (empty for local files) + host. Its stored value is the full location (a unique dedup key) while the front shows only the basename; the `share` sub-field reuses ShareName so a file discovered on a share links back to its share finding. Model / chaining: - ContractOutputType.File, PrimitiveType.FileName + FilePath, ComplexType.File. - Register File as complex and map its sub-fields (file_name -> FileName, path -> FilePath, share -> ShareName, host, asset_id). API: - FileOutputProcessor (complex, mirrors ShareOutputProcessor): validate requires file_name; toFindingValue builds the UNC path for share files (\\host\share\dir\file) or a host-prefixed path for local files. - AttackPathGraphService: a `files` counter and a "files" drawer category, mirroring shares; AttackPathKeyMatcher reconciles file_name -> file. - AttackPathCounters gains a `files` field. Front: - maskFindingValue shows a file as its basename (full path kept in the detail panel); "Captured Files" card + files filter/category; ContractOutputElementType.file. - api-types regenerated inputs (AttackPathCounters.files, "file" in the type unions), i18n key across all nine locales. Docs: update the add-contract-output-type skill (a located file is complex, and the JSON-metadata output path for spider_plus). Requires the file output type in client-python and the spider_plus producer in the netexec injector.
… findings (#6647) Autolearn on the add-contract-output-type skill: a registry entry only makes the ContractOutputElement appear on the contract; findings are produced only when an extractor populates the field (e.g. netexec `text` is declared but has no extractor, so it yields no findings).
724fcd2 to
8632d90
Compare
Adds a native
filefinding type end to end and surfaces it in the attack path, so files discovered on SMB shares (NetExecspider_plus) become first-class findings.Completes the kill-chain: nmap → 445 → SMB → enum shares (
share) → spider_plus (fileon that share) — e.g. asecret.ps1onSYSVOLholding a hard-coded password shows up as a file finding you can pivot from.Self-contained: the interim
share → filestand-in removal (formerly #6999, now closed) is already folded into this PR. Targetsmain.Why complex, not primitive
The same basename means different things by location. A
fileis a complex finding carryingfile_name+path+share(empty for local files, e.g. a future FTP/NFS--ls) +host. Its stored value is the full location (a unique dedup key, so twosecret.ps1never merge) while the front renders only the basename; thesharesub-field reusesPrimitiveType.ShareNameso a share-hosted file links back to itssharefinding.Changes
Model / chaining —
ContractOutputType.File,PrimitiveType.FileName+FilePath,ComplexType.File; registered complex with its sub-field → primitive map (file_name→FileName,path→FilePath,share→ShareName,host,asset_id).API —
FileOutputProcessor(complex, mirrorsShareOutputProcessor):validaterequiresfile_name;toFindingValuebuilds\\host\share\dir\filefor share files, a host-prefixed path for local files.AttackPathGraphServicegains afilescounter +filesdrawer category (mirrorsshares);AttackPathKeyMatcherreconcilesfile_name → file;AttackPathCountersgainsfiles.Front —
maskFindingValueshows a file as its basename (full path in the detail panel); "Captured Files" card +filesfilter/category;ContractOutputElementType.file;api-types(AttackPathCounters.files,"file"in the type unions); i18n across all nine locales.Docs — updated the
add-contract-output-typeskill: a located file is complex (not primitive), and the JSON-metadata output path used byspider_plus.Tests (validated locally)
FileOutputProcessorTest(10) — validate + value formatting (UNC / local / same-name-distinct-by-share).ChainingTypeRegistryTest— File resolves complex, sub-fields → primitives incl.share→ShareName.AttackPathShareTypeApiTest— extended: share and file each count under their own name; file on graph node / collapsed counts /filescounter.maskFindingValue('file')→ basename,FILTER_TO_FINDING_TYPES.files,findingCategoryNoun('file'). check-ts + eslint + vitest green.Dependencies
fileoutput type)spider_plusproducer)Behind the
ATTACK_PATHfeature flag.