snort: 5-MOAD scan COMPLETE; mark [x] SCAN-TODO; add TICKET.md snort3-0001
snort3-0001 MOAD-0001 CWE-407: ServiceDiscovery service_candidates std::find dedup O(M*C) per packet in AppID — 72x at M=10000 (already committed) snort3-0002 MOAD-0001 CWE-407: CHP match_tally std::find_if O(M*T) per HTTP packet — 48x at T=100 (already committed) MOAD-0002/0003/0004/0005: CLEAN
This commit is contained in:
parent
0f2062b0cc
commit
1fb374fbc5
2 changed files with 61 additions and 1 deletions
60
defects/snort3-0001/TICKET.md
Normal file
60
defects/snort3-0001/TICKET.md
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
# snort3-0001: CWE-407 — ServiceDiscovery service_candidates std::find dedup O(M*C)
|
||||
|
||||
## Target
|
||||
|
||||
Snort 3 network IDS/IPS: `src/network_inspectors/appid/service_plugins/service_discovery.cc`
|
||||
|
||||
## Defect
|
||||
|
||||
`match_by_pattern()` and `get_port_based_services()` both use `std::find` to dedup
|
||||
`asd.service_candidates` (a `std::vector<ServiceDetector*>`). These functions are called
|
||||
from `get_next_service()`, invoked once per packet during the AppID service discovery
|
||||
phase while `asd.service_disco_state != APPID_DISCO_STATE_FINISHED`.
|
||||
|
||||
In `match_by_pattern()`: for each of M pattern match callbacks returned by the
|
||||
Aho-Corasick engine, `std::find` walks all C existing candidates to check for
|
||||
duplicates. Total work is O(M * C) per packet.
|
||||
|
||||
In `get_port_based_services()` (two-port midstream variant): for each detector in
|
||||
port2's list, `std::find` walks port1's candidates. Total work is O(P1 * P2) where P1,
|
||||
P2 are detector counts for each port.
|
||||
|
||||
With enterprise OpenAppID deployments shipping ~2900 Lua detectors, ports with many
|
||||
registered detectors and packets matching many patterns produce measurable overhead on
|
||||
every AppID-inspected packet.
|
||||
|
||||
## Fix
|
||||
|
||||
Seed an `std::unordered_set<ServiceDetector*> seen` from the existing candidates before
|
||||
the loop, then use `seen.insert().second` for O(1) amortized dedup. Replaces both
|
||||
`std::find` call sites.
|
||||
|
||||
## Complexity
|
||||
|
||||
O(M*C) -> O(M + C) per packet in match_by_pattern; O(P1*P2) -> O(P1 + P2) in
|
||||
get_port_based_services. Measured: 72x op-count reduction at M=10000.
|
||||
|
||||
## Severity
|
||||
|
||||
HIGH. AppID service discovery runs on every packet of every flow until the service is
|
||||
identified. In high-traffic environments (>10 Gbps), per-packet overhead compounds across
|
||||
millions of concurrent flows.
|
||||
|
||||
## Patch
|
||||
|
||||
`defects/snort3-0001/patch/snort3-0001.patch`
|
||||
|
||||
## Test
|
||||
|
||||
`defects/snort3-0001/test/Snort3ServiceCandidateDedupTest.java` — Java simulation.
|
||||
N=10000: defective 1069.7ms, fixed 14.8ms, ratio 72x. ALL PASS.
|
||||
|
||||
## All 5 MOAD Results for Snort 3
|
||||
|
||||
| MOAD | Status | Notes |
|
||||
|------|--------|-------|
|
||||
| 0001 (CWE-407) | DEFECT x2 | snort3-0001 (service_candidates, this); snort3-0002 (CHP match_tally) |
|
||||
| 0002 (Intertangle) | CLEAN | SnortConfig immutable at runtime; per-thread flow state; no god object |
|
||||
| 0003 (Leaked Context) | CLEAN | THREAD_LOCAL used correctly for per-thread packet stats; cleared per-packet |
|
||||
| 0004 (CWE-312) | CLEAN | No sensitive headers logged verbatim; HTTP extractor omits Authorization field |
|
||||
| 0005 (Thundering Herd) | CLEAN | LruCacheShared uses std::mutex lock_guard; LruCacheLocal is per-thread |
|
||||
Loading…
Add table
Add a link
Reference in a new issue