668 Commits

Author SHA1 Message Date
harmless_teddy 521f97e1ca Delete Cargo.lock 2026-06-26 21:52:53 +02:00
harmless_teddy 4620ee3b8f Delete RELEASE_NOTES.txt 2026-06-26 21:52:42 +02:00
harmless_teddy 15ed279155 Delete RELEASE_GITHUB.txt 2026-06-26 21:52:30 +02:00
harmless_teddy 0b98ce2987 Merge pull request #43 from s-b-repo/fixes-updates-and-more
reworked framework improved performance and fixed alot of bugs imporved improving universal mass scaninng only a few small issues left wired dead code improved code quality speed removed error handling less crashs stops better math for packet generation more clearer docs and better compile times and improving stress testing more exploits optional bluetooth added more scanning osing and other module and research some math from other tools and busy importing more stuff

here

================================================================================
 RUSTSPLOIT — RELEASE NOTES
 Offensive-security framework (RouterSploit/Metasploit-inspired), single binary.
 One module library across four interfaces: interactive shell, CLI runner,
 PQ-encrypted REST/WebSocket API, and an MCP server.

 Build date : 2026-06-13
 Toolchain  : Rust edition 2024 (clang + lld)
 Build      : cargo build --bin rustsploit -> clean (0 errors, 0 warnings)
 Modules    : 389 self-registering native modules
================================================================================


OVERVIEW
--------------------------------------------------------------------------------
This release ports four well-known upstream projects into Rustsploit, fixes a
cluster of mass-scan / full-internet-sweep usability bugs, and lands a
framework-wide HTTP performance improvement.

All ported components are permissively licensed (BSD-2 / BSD-3 / Apache-2.0 /
MIT) and were vendored or added as dependencies accordingly. Every change below
was compiled and tested locally; the verification summary is in section 5.


================================================================================
 1. NEW CAPABILITIES (UPSTREAM PORTS)
================================================================================

[1.1] MCP server migrated to the official `rmcp` SDK            (Apache-2.0)
--------------------------------------------------------------------------------
  * Replaced the hand-rolled JSON-RPC-over-stdio MCP server (src/mcp/server.rs)
    with the official Model Context Protocol Rust SDK, rmcp v1.7.0.
  * The existing tool/resource logic (src/mcp/tools.rs, resources.rs, types.rs)
    is preserved unchanged. server.rs is now a thin adapter implementing rmcp's
    `ServerHandler` trait; protocol framing, transport, and spec compliance are
    owned by the SDK (giving correct resources/prompts/progress support going
    forward instead of a bespoke protocol).
  * All 29 tools and 7 resources retained. The per-call execution timeout
    (env RUSTSPLOIT_MCP_TIMEOUT_SECS, default 300s) and the stdout-isolation
    guard (the protocol channel is dup'd off fd 1 and fd 1 redirected to
    /dev/null, so stray println! can never corrupt the JSON-RPC stream) are
    both kept.
  * Validated end-to-end over stdio: the `initialize` handshake returns
    serverInfo = rustsploit-mcp 0.5.0, negotiates protocolVersion down to the
    client's requested 2024-11-05, and `tools/list` advertises all 29 tools.
  * Dependency added to Cargo.toml:
        rmcp = { version = "1.7", features =
                 ["server", "transport-io", "transport-async-rw"] }

[1.2] Recog fingerprint engine                          (Rapid7, BSD-2-Clause)
--------------------------------------------------------------------------------
  * New src/utils/recog.rs: an XML fingerprint-database loader + matcher modeled
    on Rapid7 Recog (recog-go was the reference for the match loop). Parses the
    Recog <fingerprint>/<param> schema with quick-xml, pre-compiles every regex
    behind once_cell::Lazy, and resolves a banner to structured fields
    (service.product / .version / .vendor, os.product, service.cpe23, ...).
  * Matcher semantics follow real Recog: a <param> carrying a non-empty `value`
    is a literal/interpolated assignment (e.g.
    cpe:/a:vendor:product:{service.version}); a <param> with no value reads
    regex capture group `pos`. Capture params are resolved in a first pass so
    that {field} placeholders in templates always bind, regardless of param
    order or any `pos` attribute on the template.
  * Vendored databases under src/utils/recog_db/ (embedded via include_str!):
    ssh_banners, ftp_banners, smtp_banners, http_servers, mysql_banners. A
    BSD-2-Clause credit header points at upstream.
  * Wired into src/modules/scanners/service_scanner.rs: after each banner read
    (FTP, SSH, SMTP, MySQL, and the HTTPS `Server:` header) the matcher enriches
    the detected version with a structured product/version + CPE; findings still
    flow through the existing FindingKind::Banner path.
  * 19 unit tests assert extracted fields against real example banners
    (OpenSSH/Dropbear, ProFTPD/vsftpd, Exim, Apache/IIS, MySQL/MariaDB, plus the
    malformed-regex-skip and unknown-db cases).
  * NOTE: the vendored DBs are curated subsets authored to the exact upstream
    schema (the porting agent had no outbound network access to fetch the full
    upstream XML). The complete Rapid7 DBs (5 files, ~770 KB, ~1024 fingerprints)
    are staged and can be dropped in for full coverage — see section 6.

[1.3] JARM + JA3 / JA3S TLS fingerprinting          (Salesforce, BSD-3-Clause)
--------------------------------------------------------------------------------
  * New src/utils/tls_fingerprint.rs:
      - JARM: 10 hand-crafted TLS ClientHello probes ported from Salesforce
        jarm.py (TLS 1.2/1.3, multiple cipher orderings, GREASE on/off, ALPN
        variants, extension permutations). Probes are sent over a raw tokio
        TcpStream; each ServerHello is parsed (fully bounds-checked) and the
        results are assembled into the canonical 62-character JARM hash.
      - JA3 / JA3S string builders + MD5 (client- and server-side fingerprints),
        with GREASE stripping per spec.
      - Robust failure handling: a down host, a TLS alert, or a truncated
        response degrades to the canonical all-zero JARM hash; the ServerHello
        parser returns None on garbage input and never panics.
  * New module src/modules/scanners/jarm_scan.rs (default port 443) reports the
    JARM hash, JA3S, and client JA3 as findings.
  * src/modules/scanners/ssl_scanner.rs was intentionally NOT modified: it uses
    rustls, which hides the raw ServerHello bytes JA3S requires. JA3S is exposed
    via tls_fingerprint for callers (such as jarm_scan) that hold raw bytes.
  * 14 unit tests: JA3/JA3S string + MD5 (verified with md5sum), JARM hash
    assembly, and parser bounds-safety on empty/truncated/garbage input.

[1.4] SecLists wordlist catalog                                        (MIT)
--------------------------------------------------------------------------------
  * Seeded the previously-empty, checksum-pinned wordlist catalog in
    src/utils/wordlist.rs with 6 curated SecLists entries. Each SHA-256 was
    computed over the exact raw upstream bytes (the same bytes resolve() hashes
    after download):
        passwords-top-1k        Passwords/Common-Credentials/Pwdb_top-1000.txt
        passwords-top-10k       Passwords/Common-Credentials/Pwdb_top-10000.txt
        usernames-short         Usernames/top-usernames-shortlist.txt
        web-common              Discovery/Web-Content/common.txt
        web-raft-small-dirs     Discovery/Web-Content/raft-small-directories.txt
        subdomains-top5k        Discovery/DNS/subdomains-top1million-5000.txt
  * resolve(name) downloads + SHA-256-verifies on first use into
    ~/.rustsploit/wordlists/ (rejecting any checksum mismatch). 2 no-network
    tests assert every catalog entry is well-formed: https URL, 64-hex SHA-256,
    non-empty name/local_name, and unique names.


================================================================================
 2. BUG FIXES (MASS-SCAN / FULL-INTERNET SWEEP)
================================================================================

[2.1] Full-internet sweep host-cap consistency
--------------------------------------------------------------------------------
  * `setg target 0.0.0.0` auto-raised max_random_hosts to the full public-IPv4
    count, but a literal `0.0.0.0/0` typed into `use <mod>; run` never passed
    through that handler and fell back to the scheduler default of 10,000 —
    silently capping a "scan everything" target at 10k hosts.
  * Fixed in src/scheduler.rs at the single Target::Random dispatch chokepoint:
    when the operator has NOT explicitly set max_random_hosts, a full sweep now
    means every reachable public host on both entry paths. An explicit
    `setg max_random_hosts <n>` is still honored, and the per-sweep advisory +
    interactive confirmation gate is unchanged.

[2.2] Mass-scan pre-config: confirm BEFORE harvest, and silence the placeholder
--------------------------------------------------------------------------------
  The pre-batch prompt phase runs the selected module once against a placeholder
  host (0.0.0.1) to harvest the operator's answers once for the whole batch.
  Two problems were fixed in src/scheduler.rs:
    (a) ORDER: the harvest ran BEFORE the full-sweep confirmation, so the
        placeholder was effectively "scanned" (and, for service_scanner, a
        results file was written) before the operator ever confirmed the sweep.
        The full-sweep advisory + confirmation now runs FIRST on both the random
        and sequential sweep paths; declining aborts with nothing touched.
    (b) NOISE: the harvest run leaked module output
        ("Scanning 0.0.0.1 ... 0 services detected ... Results saved"). The
        harvest run is now wrapped in a throwaway OUTPUT_BUFFER scope so its
        mprintln!/meprintln! output is suppressed, while the interactive prompts
        (which print via real stdout) remain visible.
  RESIDUAL: the harvest still executes the module against the placeholder host
  (now silently). Removing that entirely requires a per-module "prompt-only"
  mode — see section 6.

[2.3] service_scanner mass-scan output spam + file-save race
--------------------------------------------------------------------------------
  * In a mass-scan fan-out the module runs once per host and previously printed
    its full single-target block for EVERY host — "No services detected",
    "Results saved", "Scan complete: 0 services detected on <host>" — which
    garbled output across concurrent tasks and (worse) had every host racing to
    overwrite the same results file.
  * These are now gated on `!is_batch_mode()`:
      - only hosts that actually have services print their results table,
      - the per-host file save is skipped in batch mode (findings flow through
        the module outcome instead, avoiding the concurrent-overwrite race),
      - the redundant per-host "No services" / "Results saved" / "Scan complete"
        status lines are suppressed.
    Interactive single-target runs are unchanged.

[2.4] `show options` listed only a subset of global options
--------------------------------------------------------------------------------
  * Added the four missing global keys to the shell's `show options` table:
    scan_order, exclusions, target_rps, module_rps.


================================================================================
 3. PERFORMANCE
================================================================================

[3.1] HTTP client connection-pool reuse (framework-wide)
--------------------------------------------------------------------------------
  * 184 of the ~304 reqwest-client construction sites go through the shared
    helper build_http_client(timeout), which rebuilt a fresh reqwest::Client on
    every call — re-initialising the TLS configuration and allocating a brand
    new (empty) connection pool. In an HTTP-based mass scan that is once per
    host; in normal use it is once per module run.
  * src/utils/network.rs::build_http_client now caches the permissive client,
    keyed by (timeout, accept_invalid_certs), and returns cheap Arc clones —
    reqwest clients are Arc internally and share their connection pool across
    clones, so warm connections and TLS setup are reused across runs.
  * Correctness: accept_invalid_certs is part of the key because permissive()
    derives it from the live `strict_tls` global; toggling `setg strict_tls` is
    therefore still honored rather than pinned to whatever it was on first build.
    The client is built outside the lock so a slow build() can't serialise other
    callers, and a poisoned lock is recovered (the map holds only cloneable
    clients) rather than panicking into every HTTP caller.
  * Custom-opts clients (cookies / headers / redirects via
    build_http_client_with) are unchanged — those options cannot be shared
    safely or keyed cheaply.


================================================================================
 4. FILES CHANGED
================================================================================
  New files:
    src/mcp/server.rs                          rewritten as an rmcp adapter
    src/utils/recog.rs                         Recog matcher (~590 lines)
    src/utils/recog_db/*.xml                   5 vendored fingerprint databases
    src/utils/tls_fingerprint.rs               JARM / JA3 / JA3S (~1270 lines)
    src/modules/scanners/jarm_scan.rs          new JARM scanner module (~127 lines)

  Modified files:
    Cargo.toml                                 + rmcp dependency
    src/module.rs                              + ModuleCtx.prompt_only flag (6.1)
    src/scheduler.rs                           sweep host-cap consistency,
                                               confirm-before-harvest reorder,
                                               harvest output capture,
                                               set prompt_only on harvest ctx
    src/modules/scanners/service_scanner.rs    Recog enrichment wiring +
                                               batch-mode output gating +
                                               prompt_only early return (6.1)
    src/utils/network.rs                       HTTP client cache +
                                               pool_idle_timeout (6.2)
    src/utils/recog.rs                         two-pass matcher fix (value
                                               templates win over `pos`)
    src/utils/recog_db/mysql_banners.xml       MariaDB regex colon fix
    src/utils/tls_fingerprint.rs               corrected JA3/JA3S test constants
    src/utils/wordlist.rs                      SecLists catalog + 2 tests
    src/utils/mod.rs                           + pub mod recog;
                                               + pub mod tls_fingerprint;
    src/modules/scanners/mod.rs                + pub mod jarm_scan;
    src/shell.rs                               show options: + 4 global keys
    README.md, docs/BAD_PATTERNS.md            stale-docs corrections (6.3)


================================================================================
 5. VERIFICATION
================================================================================
  * cargo build --bin rustsploit : clean — 0 errors, 0 warnings.
  * MCP : live stdio handshake validated — initialize returns
          serverInfo=rustsploit-mcp 0.5.0, protocolVersion negotiated to
          2024-11-05, tools/list returns all 29 tools.
  * Tests : new-port + core suites green —
          cargo test --bin rustsploit -- recog tls_fingerprint jarm wordlist
          cyclic ja3  =>  40 passed; 0 failed.
  * Banned-pattern audit (scripts/audit-bad-patterns.sh) : no new hits
          introduced in any changed file.

  PRE-RELEASE FIXES (found and fixed in this release):
    The four ports were authored by isolated agents that could not execute the
    test runner in their sandbox, so 7 tests shipped failing and were caught +
    fixed here:
      - 3 JA3/JA3S tests had fabricated "known vector" MD5 constants; the
        implementation was correct (the real md5 of the JA3/JA3S strings matches
        what the code produces) — the bogus expected constants were corrected.
      - 4 Recog tests exposed a real matcher bug: a <param> with both a `value`
        template and a `pos` attribute had its template ignored (the bare
        capture group was stored instead of the interpolated CPE), plus a
        MariaDB regex that rejected a colon in the distro suffix. Both fixed.


================================================================================
 6. FOLLOW-UP PASS (completed)
================================================================================
The four follow-ups noted at first cut were all worked. Three are done; the
fourth was investigated and intentionally deferred with a precise finding.

[6.1] Pre-config harvest now has a per-module "prompt-only" mode            DONE
  * Added ModuleCtx.prompt_only (src/module.rs). The scheduler sets it on the
    harvest dry-run ctx (src/scheduler.rs). A module that honours the flag
    answers its cfg_prompt_* calls and then returns immediately — no network
    work, no file writes against the placeholder host.
  * src/modules/scanners/service_scanner.rs is the reference implementation: it
    returns right after gathering prompts when prompt_only is set, so the
    placeholder host (0.0.0.1) is no longer scanned at all during harvest. The
    output-capture guard remains as belt-and-suspenders for modules that don't
    yet check the flag; other modules can adopt the same one-line early return.

[6.2] HTTP client cache: idle-connection lifetime bounded                   DONE
  * Added HttpClientOpts.pool_idle_timeout (src/utils/network.rs). The cached,
    long-lived permissive client now sets pool_idle_timeout = 30s, so a
    full-internet sweep reaps idle keep-alives to stale hosts instead of letting
    them accumulate. Custom-opts clients default to reqwest's ~90s unless they
    opt in.

[6.3] Docs drift corrected                                                  DONE
  * README.md and docs/BAD_PATTERNS.md prose updated to reflect the
    exploitation-only model (no check()/CheckResult) and compile-time `inventory`
    self-registration (no build.rs module indexer). The BAD_PATTERNS regex
    matrix is driven by hardcoded bash arrays in the audit script — confirmed
    untouched, so the lint is unaffected.

[6.4] Recog full-DB swap: investigated, DEFERRED (it is a feature, not a swap)
  * The full upstream Rapid7 DBs (5 files, ~770 KB, ~1024 fingerprints) were
    dropped in and the Recog tests re-run: 13/20 failed. Root cause is NOT a test
    issue — the real DBs are not drop-in compatible with the current wiring:
      - The real SSH patterns are anchored on the version COMMENT
        (e.g. ^OpenSSH_(...)$), i.e. they expect the post-"SSH-2.0-" substring,
        not the full banner line the scanner currently feeds them.
      - Real field names/values differ from the curated set (e.g. Apache yields
        service.product = "HTTPD", not "HTTP Server").
    So adopting the full DBs requires a per-DB INPUT-NORMALISATION layer (feed
    each DB the exact field it expects) plus downstream handling of real Recog
    field names — a feature, not a data swap. Shipping the real DBs as-is would
    silently break matching end-to-end (raw banners vs. normalised-input
    patterns => zero matches in practice).
  * DECISION: kept the curated, internally-consistent DBs (all 19 Recog tests
    pass; wiring + patterns + tests agree). The full-DB adoption is tracked as a
    future feature with the concrete design above. The real DBs remain staged.


================================================================================
 6c. NEW: per-run output auto-save
================================================================================
  * Every interactive console / CLI module run now auto-appends ALL of its
    output (stdout + stderr) to a per-run file:
        ~/.rustsploit/loot/<module> <YYYY-MM-DD_HH-MM-SS> results.txt
    Files are opened in APPEND mode, so multi-host mass-scan output accumulates
    into the one run file instead of racing to overwrite (the original
    service_scanner "save to file" bug). New module: src/results_sink.rs — a
    global append sink mirroring the spool's write pattern (so spawned per-host
    task output is captured), hooked into the console branches of the
    mprintln!/meprintln! routing in src/output.rs and begun/ended per run in
    commands::run_module. Scoped to console/CLI runs (sequential); API / MCP
    runs return their output to the caller via OUTPUT_BUFFER and are not
    duplicated to disk. Verified end-to-end (file created, headered, appended).
  * Build fix bundled: Cargo.lock restored. The branch's previous
    "Delete Cargo.lock" commit left a binary crate that does NOT build from a
    clean clone (transitive `cookie`/`time` version conflict on fresh
    resolution); the verified lock is re-added so `git clone && cargo build`
    works again.


================================================================================
 6b. REMAINING KNOWN LIMITATIONS
================================================================================
  * Recog coverage is the curated subset until the input-normalisation layer in
    [6.4] is built.
  * Modules other than service_scanner do not yet check ModuleCtx.prompt_only;
    during harvest their output is suppressed but they still execute (cheaply).
    Adopting the one-line early return per module closes this fully.


================================================================================
 6d. FRAMEWORK HARDENING (error-safety, retry-then-continue, wiring)
================================================================================
A two-agent audit of the framework (non-module) .rs files (it found the core
"unusually disciplined" already) plus fixes for every genuine issue surfaced:

  Panic / crash paths:
  * src/shell.rs — the rustyline completer sliced the input line at a raw byte
    offset; a cursor landing mid-UTF-8 codepoint crashed the whole shell. Now
    snaps to a char boundary first.
  * src/scheduler.rs — three `unreachable!(...)` in the fan-out dispatch are now
    `anyhow::bail!(...)` (internal-error surfaced, never a panic).

  Retry-then-continue (transient errors retry, then the scan continues):
  * New `run_host_with_retry` in scheduler.rs wraps every per-host module
    dispatch across all four mass-scan fan-outs (CIDR / file / random /
    sequential): a transient failure (timeout, connection reset/aborted, broken
    pipe, unexpected EOF) is retried once with a short backoff; a terminal error
    (closed port, "not affected") returns immediately. A single host never
    aborts the loop.
  * The "first 10 dispatches errored -> abort the whole sweep" heuristic in the
    random + sequential sweeps is softened to a one-time warning that KEEPS
    GOING (Ctrl+C still stops it) — error -> retry -> continue, not auto-abort.
  * Confirmed already-correct (left as-is): throttle back-off, tcp_connect
    address-iteration, bruteforce per-host error tolerance, job catch_unwind.

  Wiring / protocol bugs:
  * src/ws.rs — an oversize WS frame was `continue`-skipped, but the PQ AEAD
    ratchet's nonce embeds the receive counter and only advances on a successful
    decrypt, so a skipped frame permanently desynced (bricked) the connection.
    Now closes cleanly instead (axum's max_frame_size already caps upstream).
  * src/mcp/tools.rs — background jobs spawn under the tenant job-manager but
    list/kill read the process-global one, so tenant jobs were invisible and
    unkillable. list/kill now use the tenant job-manager too.
  * src/mcp/tools.rs — an out-of-range `port` argument was silently dropped (and
    the module fell back to its default); now rejected with a clear error.
  * src/ws.rs — a non-string option value was coerced to "" and stored; now
    rejected with a clear error.

  No silent error-swallowing:
  * Swept the framework (non-module) files for the banned swallow patterns
    (`Err(_)`, `if let Ok(...)` with no else, bare `.ok();`, `let _ = <result>`,
    `.map_err(|_| ...)`) and bound + surfaced every one via `tracing`
    (debug for benign fallbacks, warn for lost data/replies) — semantics
    unchanged, errors no longer dropped. Legitimate poison-recovery and
    deliberate Result->Option conversions were left intact.

  Verified: clean build (0 warnings), 40/40 targeted tests green, bad-patterns
  audit clean on the changed files.


================================================================================
 7. LICENSES (PORTED COMPONENTS)
================================================================================
  Recog (Rapid7)               BSD-2-Clause
  JARM / JA3 / JA3S (Salesforce)  BSD-3-Clause
  rmcp (MCP Rust SDK)          Apache-2.0
  SecLists                     MIT
  ZMap address iterator        Apache-2.0   (previously ported; unchanged)

================================================================================
 END OF RELEASE NOTES
================================================================================
v0.5.0
2026-06-26 16:36:19 +02:00
s-b-repo e180afdcc4 creds/exploits: fix the protocol-level audit backlog (VNC, SSH, FortiOS CVE, m365, h3c, engine)
VNC (false positive): negotiate the RFB version instead of forcing 003.008. An
RFB 3.3 server desynced under the forced 3.8 handshake and a misaligned 4-byte
SecurityResult read of 0 was reported as a valid password. Now reply min(server,
3.8), and handle 3.3's single 4-byte security-type vs 3.7+'s count+list+select.

SSH (false negative): ssh_bruteforce + ssh_spray collapsed EVERY ssh2
userauth_password error to AuthFailed, so a transient/transport error mid-auth
became a definitive 'wrong password' (valid creds skipped, never retried). Now
only libssh2 -18/-19 (AUTHENTICATION_FAILED/PUBLICKEY_UNVERIFIED) is AuthFailed;
everything else propagates as a retryable error. ssh_spray also now resolves
hostnames (was SocketAddr::parse, IP-only → hostname targets never sprayed).

ssh_user_enum (noise): replaced the fixed 300ms absolute timing threshold with a
baseline mean+stddev one-sided cutoff (k sigma, median per user, MIN_ABS_DELTA
floor), time ONLY the auth exchange (not connect+KEX), and send a long password
so the server KDF dominates for valid users. threshold setg is now a sigma
multiplier.

FortiOS CVE-2018-13382 (false positive): the ordinary ret=1/redir= login response
was treated as a successful magic-token reset → FindingKind::Vulnerable on PATCHED
hosts. Now the Vulnerable finding is gated on a confirming login with the new
password (verify_login tightened to require the real ret=1 token); fingerprint no
longer calls any 200/401 host a FortiGate; reset POST also sends 'credential'.

Engine: run_bruteforce_streaming's stop-on-first-success early return leaked the
spawn_blocking wordlist reader, which kept scanning a multi-GB file into a dropped
channel. New utils::load_lines_batched_until lets the reader stop the instant the
receiver is gone. bruteforce_retries: unset→1, explicit 0→none, clamped to 10
(was: 0 coerced to 1, huge values unbounded).

m365_activesync_spray: classify valid-but-flagged accounts via X-MS-Diagnostics
ESTS codes (50055 expired / 50057 disabled / 50079/50076/50074/53004 MFA / 50158
CA) as credential hits instead of keying success only on HTTP 200; add 429/503
throttle backoff between rounds.

h3c_redfish_session_spray: require X-Auth-Token on 201 (was: stored a
'(header-missing)' placeholder credential); 400/404/422 → Denied not Error.
h3c_oem_kvm_bruteforce: require an actual token VALUE (header or parsed), not the
bare 'X-Auth-Token' field-name substring + '(present)' placeholder.

Build: 0 errors, 0 warnings. Remaining strict-audit hits in these files are
pre-existing (VNC DES, PG MD5 / MySQL SHA1 auth, #[cfg(test)] asserts, and
run-loop idioms) — none introduced here.
2026-06-13 20:57:27 +02:00
s-b-repo 52767ab45f creds: kill false-positive logins + RTSP-class lockout misclassification across 9 probes
Audit of every bruteforce module surfaced two recurring bug classes. Fixed the
verified, contained ones here.

FALSE POSITIVES (a wrong cred was being stored as loot):
- snmp: success was 'response contains byte 0xa2 anywhere' — matched request-id /
  length / payload bytes and accepted error/Report PDUs. Now structurally parses
  the datagram and requires a GetResponse PDU (0xa2) at its proper position.
- proxy: HTTP CONNECT/forward success was resp.contains("200") — matched
  'Content-Length: 200', Date, Via, etc. Now parses the status line. SOCKS5 now
  also checks the RFC1929 version byte before trusting the status.
- elasticsearch: 200 = success, but an unsecured ES node returns 200 to EVERY
  request → every password a false positive. Now confirms an unauthenticated GET
  is 401 before accepting the creds.
- couchdb: 200 = success without inspecting the body. Now requires {"ok":true}.
- memcached: trusted the status field without checking the response was a SASL-Auth
  reply. Now validates magic 0x81 + opcode 0x21 first.
- l2tp: any UDP reply with the top 2 bits set = success. Now also requires the
  L2TPv2 version nibble.
- http_basic: a redirect to a non-login page counted as success even when the
  endpoint didn't enforce auth. Now gated on the baseline-401 check.
- sample_cred_check: a registered template that stored admin:admin on any host
  whose /login returns 200. Now baselines the unauthenticated request first.

RTSP-CLASS LOCKOUT (a definitive negative from a RESPONDING server was returned as
a retryable Error, burning retries + tripping the consecutive-error give-up):
- ftp: post-handshake login rejections with unusual wording (430/532/localized)
  were Unknown->retryable; now treated as AuthFailed (connection drops stay
  retryable).
- mysql: ERR packets with codes other than 1044/1045 were retryable:true; the
  server clearly responded, so now never retryable, and the common auth-denial
  codes (1130/1226/1227/1698/1862) map to AuthFailed.
- http_basic: definitive 4xx (400/404/405/406/410/422) now AuthFailed instead of
  Unknown->retryable; 429/5xx stay retryable.

FALSE NEGATIVE:
- postgres: connected to database=<user>; a valid superuser whose own DB doesn't
  exist failed startup with 3D000 and was read as a bad login. Now uses the
  'postgres' maintenance DB.

Build: 0 errors, 0 warnings. (Pre-existing strict-audit hits in mysql/postgres are
the protocol-mandated SHA1/MD5 auth — not introduced here.)
2026-06-13 20:07:46 +02:00
s-b-repo 82f72079fb rtsp_bruteforce: classify any RTSP status reply as a result, not an error
A real RTSP camera commonly answers DESCRIBE with 404 Not Found when the stream
PATH is wrong (e.g. default '/'), not the credentials. The probe was treating
any non-200/401/403 status line as LoginResult::Error, which (a) misreported
clean negatives as 'Errors' and (b) — because the engine's lockout/give-up
heuristic counts CONSECUTIVE errors — made a live, responding host look dead and
trip a 30s pause + eventual give-up.

Now: parse the RTSP status code; 200 = Success, any other well-formed RTSP code
(401/403 reject, 404 wrong path, 3xx/5xx) = AuthFailed (a definitive negative for
that credential — no retry, resets the consecutive-error counter). Only a reply
that isn't an RTSP status line at all stays a (non-retryable) Error. 404s are
logged at debug ('setg rtsp_path' is the likely fix). Also decode the banner with
from_utf8_lossy + parse the first line instead of truncating to 64 bytes.
2026-06-13 19:28:07 +02:00
s-b-repo 3183e5d0cc bruteforce: expose connection retries (medusa -r) via setg bruteforce_retries
creds_helper previously hardcoded BruteforceConfig.max_retries = 1. 'setg
bruteforce_retries N' now sets the per-combo retry count for retryable
(transient/connection) errors; unset or 0 keeps the historical default of 1.
show options: + bruteforce_retries. Build: 0 errors, 0 warnings.
2026-06-13 17:06:10 +02:00
s-b-repo 40b2659092 bruteforce: hydra -x mask brute + resumable streamed wordlists
- bruteforce_mask (hydra -x): 'setg bruteforce_mask MIN:MAX:CHARSET' enumerates
  candidate passwords. CHARSET placeholders mirror hydra: a->a-z, A->A-Z, 1->0-9;
  any other char is literal. e.g. '1:4:a1' = 1-4 chars of [a-z0-9]. Generated via
  an odometer counter, hard-capped at MAX_COMBOS with a warning. Mask candidates
  run AFTER the wordlist (lowest yield); skipped in credential_file_only mode.
  New: utils::bruteforce::generate_mask_passwords + creds_helper wiring.

- bruteforce_resume (batch-level): 'setg bruteforce_resume y' makes a streamed
  large-wordlist run record the last fully-completed 500k batch, keyed by
  target+port+wordlist+size+mode, under ~/.rustsploit/checkpoints/<key>.bfr. An
  interrupted run skips already-tried batches on restart and clears the marker on
  clean completion / first success. New checkpoint markers: read/write/clear_
  bruteforce_marker, mirroring the existing seq-marker pattern.

show options: + bruteforce_mask / bruteforce_resume. Build: 0 errors, 0 warnings.
2026-06-13 16:54:57 +02:00
s-b-repo d0e07e8d97 bruteforce: cross-batch give-up, combo-file exclusive mode, stop-mode (host/user/all)
- Cross-batch give-up: run_bruteforce split into a wrapper + run_bruteforce_with_abort
  taking a shared abort flag; the streaming driver reuses one flag so a host the
  engine gives up on stops the WHOLE run instead of re-pausing every 500k batch.
- credential_file_only: 'setg credential_file_only y' makes the combo file the
  ONLY credential source (exact hydra -C; ignores user/pass wordlists + streaming).
- cred_stop_mode (host|user|all): host = stop whole host on first success
  (default); user = stop a username once its password is found, keep other users
  (medusa); all = find every valid credential (hydra default). Engine reads the
  setg (no BruteforceConfig field change -> no ripple across 14 callers).

show options: + credential_file_only / cred_stop_mode. Build: 0 errors, 0 warnings.
2026-06-13 16:41:58 +02:00
s-b-repo c3d0556f77 bruteforce: cap per-host concurrency in batch, wire combo-file (-C), expose delay/jitter, medusa host give-up
1. Batch concurrency cap: in a mass-scan fan-out, per-host bruteforce concurrency
   is capped (4) so it no longer multiplies with scheduler host-concurrency into
   an RLIMIT_NOFILE-exhausting socket count.
2. Combo-file (hydra -C): 'setg credential_file <user:pass file>' is loaded via
   the engine's load_credential_file and tried alongside defaults. Verified:
   2-pair file -> +2 attempts.
3. Delay/jitter (hydra -w): 'setg bruteforce_delay_ms' + 'setg bruteforce_jitter_ms'
   now feed BruteforceConfig.delay_ms/jitter_ms (were hardcoded 0).
4. Host give-up (medusa): run_bruteforce now aborts a host after MAX_LOCKOUT_PAUSES
   (3) consecutive-error lockout pauses with no success, instead of pausing-and-
   grinding forever. run_subnet_bruteforce already had give-up.

Also surfaced credential_file/bruteforce_delay_ms/bruteforce_jitter_ms in
'show options'. Build: 0 errors, 0 warnings.
Known limitation: streaming-path give-up is per-batch (not cross-batch).
2026-06-13 16:16:45 +02:00
s-b-repo 5968d25b58 creds bruteforce: hydra-style -e nsr (null/same/reversed) + expose wordlist/cred_extras options
Adds the highest-yield hydra feature to the shared creds_helper: for each
username, optionally also try an empty password (null), the username as its own
password (same), and the reversed username. Opt-in via 'setg cred_extras' with a
subset of n/s/r (e.g. nsr); default off. Appended to the defaults-first rows so
they run before the wordlist; the engine's existing combo dedup avoids retrying
a pair already in defaults. Skipped for password-only services.

Also surfaced username_wordlist/password_wordlist/cred_extras in 'show options'.

Verified: elasticsearch_bruteforce + cred_extras=nsr + 1 username -> 6 defaults +
null + reversed (same deduped against the admin/admin default) = 8 attempts.
2026-06-13 15:55:28 +02:00
s-b-repo e6736530f0 creds bruteforce: run built-in defaults when no wordlist is set
creds_helper required a password wordlist (cfg_prompt_existing_file with no
default), so in a mass scan with no 'setg password_wordlist' every host errored
'Missing required prompt key' before the module's built-in DEFAULTS were ever
tried — making bruteforce sweeps look stuck/broken (the RTSP report). Wordlists
are now OPTIONAL when the module ships defaults: a missing wordlist falls back to
defaults-only instead of erroring. Modules with no defaults (postgres/mysql/snmp)
still require a wordlist. Verified: batch-mode elasticsearch_bruteforce with no
wordlist runs its 6 defaults and completes (was: error).
2026-06-13 14:47:50 +02:00
s-b-repo bc104901d9 shell: don't show a scary error when the history file doesn't exist yet
First run (or a clean ~/.rustsploit) has no history file; a NotFound on
rl.load_history is normal and was printing '[!] Failed to load history: No such
file or directory'. Now NotFound is logged at debug; only real failures
(permissions, corruption) are surfaced loudly.
2026-06-13 02:34:43 +02:00
s-b-repo 94899781d3 Framework hardening: retry-then-continue, panic fixes, WS/MCP bug fixes, no-swallow sweep + loud error surfacing; docs + release notes
Hardening (non-module framework files):
- Retry-then-continue: bounded per-host retry on transient failures across all 4
  mass-scan fan-outs; '10 errors -> abort sweep' softened to warn-and-continue
- Crash fixes: shell completer char-boundary guard; unreachable! -> bail!
- WS oversize-frame desync fixed (was bricking the PQ AEAD ratchet); MCP tenant
  job list/kill, out-of-range port, non-string option now correct/errored
- No silent error swallowing: swept framework files, every dropped error now
  bound + surfaced (warn for logged-only/data-loss, debug for already-propagated
  or aggregated per-host); removed _ => {} and Err(_)/|_| discards

Docs + release: README + docs/ updated for the release; RELEASE_NOTES.txt
section 6d added; new RELEASE_GITHUB.txt (GitHub release body).

Build: 0 errors, 0 warnings, 40/40 targeted tests green.
2026-06-13 02:29:12 +02:00
s-b-repo 05cfdc6d22 Ports (rmcp MCP SDK, Recog, JARM/JA3, SecLists) + mass-scan fixes + HTTP pooling + per-run output auto-save
Ports:
- MCP server migrated to official rmcp SDK (v1.7); all 29 tools/7 resources preserved
- Recog (Rapid7) fingerprint engine + DBs, wired into service_scanner
- JARM + JA3/JA3S TLS fingerprinting (tls_fingerprint) + jarm_scan module
- SecLists checksum-pinned wordlist catalog

Fixes / features:
- Full-internet sweep host-cap consistency
- Pre-config confirm-before-harvest + ModuleCtx.prompt_only mode; service_scanner
  batch-mode output gating
- HTTP client connection-pool reuse (cached) + bounded pool_idle_timeout
- show options: +scan_order/exclusions/target_rps/module_rps
- NEW: per-run output auto-save to ~/.rustsploit/loot/<module> <time> results.txt
  (append mode, all stdout+stderr; src/results_sink.rs)
- docs: drop stale check()/CheckResult + build.rs references
- assorted module additions + tommy interactive guide

Build: restore Cargo.lock (clean clone was unbuildable without it: transitive
cookie/time conflict). Working dir: clean build (0 warnings), 40/40 tests green.
2026-06-13 01:28:52 +02:00
S.B 929d39ebc4 Delete Cargo.lock
useless junk
2026-06-05 11:27:53 +02:00
S.B 8a8b7e8e5f Sync local dev: new modules + framework hardening & feature fixes
Modules:
- Refactor wpair (WhisperPair / CVE-2025-36911) into a module directory
  (crypto/db/gatt/protocol + model_ids.csv), replacing the single wpair.rs
- Add h3c_bmc suite (firewall/ipmi-hash/kvm-probe/redfish dumps),
  fortinet SSLVPN/magic-token, sharepoint_doc_harvest, m365_activesync_spray,
  ldap_anon_spray, php/git/tapestry webapp modules, h3c_cloudos_api_enum, etc.

Framework hardening / feature fixes:
- Background jobs capture module output (drainer) + wire progress counters
  (ScanCounters); tenant jobs record terminal status on their own JobManager
- SSRF: ssrf_gate distinguishes SSRF_BLOCKED vs TARGET_ERROR; fail-closed
  REST/WS/MCP dispatch; tenant-tagged PQ lifecycle events
- Scheduler: exclusions + service-port precheck on CIDR/file fan-out; accurate
  considered/skipped counters; cancellation-safe permit acquisition
- Mass scan works via shell/CLI/API/MCP (added MCP run_module background-job
  option so long scans don't hit the tool-call timeout)
- Bruteforce workers re-scope OUTPUT_BUFFER; cross-product combo default
- Stores: cred dedup/cap/scrub, loot scrub, workspace protocol scrub,
  spool explicit-owner + write_raw (no-newline spooling)
- Error handling: removed let _/discarded-error patterns; failures are
  distinguishable from negatives
- Removed dead check/CheckResult subsystem, OutputAccumulator, and the no-op
  --output-format flag; CredEntry.valid wired (creds invalidate/validate);
  typed HostUp/ServiceDetected events
- Add .gitignore (build artifacts, local config, engagement data)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 16:44:32 +02:00
S.B f229c3bd6c major restructure and future proofin 2026-05-24 20:08:19 +02:00
S.B c899a5e89b Add XMR donation section 2026-05-21 22:17:44 +02:00
S.B 61816e04ab majot fixes 2026-05-10 20:28:09 +02:00
S.B c10eabe496 update and other bug fixes check changelog 2026-05-04 23:18:34 +02:00
S.B 6894c7523c Add alternative command for Bluetooth feature
Added alternative command for running with Bluetooth feature.
2026-04-22 14:09:17 +02:00
S.B 4403218c05 Update panos_authbypass_cve_2025_0108.rs 2026-04-22 14:05:57 +02:00
S.B a373f07870 Update README formatting and section headers 2026-04-22 14:04:32 +02:00
S.B ba92aa5d9e Update README with Bluetooth configuration instructions
Added instructions for turning Bluetooth ON and OFF using cargo commands.
2026-04-22 14:04:05 +02:00
S.B 4efe2a974a Merge pull request #42 from yonasBSD/yonasBSD
fix: Build on FreeBSD.
2026-04-22 14:03:40 +02:00
Yonas 699827a054 fix: Build on FreeBSD. 2026-04-21 18:36:41 -04:00
S.B 799ded9523 Update README.md 2026-04-21 23:21:18 +02:00
S.B ab748265a0 Update Cargo.toml v0.4.9 2026-04-21 21:25:17 +02:00
S.B 22852e571d Merge pull request #40 from s-b-repo/enic-enamle
Enic enamle
2026-04-21 21:24:35 +02:00
S.B 5667949990 Delete src/modules/scanners/amplification_scanner.rs 2026-04-21 20:34:25 +02:00
S.B a2b829f89c Delete src/modules/scanners/banner_grabber.rs 2026-04-21 20:33:54 +02:00
S.B c9b3d331e7 major update read changelog 2026-04-21 17:01:52 +02:00
S.B bb964cc062 massived updates and fixe 2026-04-13 23:06:31 +02:00
S.B cdaea5221e Update Getting-Started.md 2026-04-13 14:37:27 +02:00
S.B 64414efcf8 Update Getting-Started.md 2026-04-13 14:34:37 +02:00
S.B 1fbcf6d4b5 Update Getting-Started.md 2026-04-13 14:34:18 +02:00
S.B 61863cc301 bug fixes 2026-04-08 00:38:29 +02:00
S.B 906808f392 bug patching 2026-04-07 15:30:18 +02:00
S.B b2c6137389 Merge pull request #39 from s-b-repo/delta-wolf
Delta wolf
v0.4.8
2026-04-07 07:43:44 +02:00
S.B e232427464 Delete test_servers.py 2026-04-07 07:38:59 +02:00
S.B ab17b25589 Delete test_api_modules.sh 2026-04-07 07:38:46 +02:00
S.B 4762c3cb7f Delete fuzz_api.py 2026-04-07 07:38:33 +02:00
S.B 3d37c0c67d Delete todo.txt 2026-04-07 01:34:19 +02:00
S.B 8b69bb6234 detailed improvement
more info will be in change log
2026-04-07 01:26:05 +02:00
S.B f51d7c111b unifying more stuff and new docs
adding unify support for api and prompt usage and improving. also adding some preformance improvements new documentations and improvement
2026-03-24 16:17:10 +02:00
S.B 587f7a5163 api support improvements and more read
added api support migrated some other stuff to native modules for speed and also because some of them are not getting updates etc UWU also fixed bugs and also check changelog for info
2026-03-22 19:03:35 +02:00
S.B e0b1fbd06c Merge branch 'delta-wolf' of https://github.com/s-b-repo/rustsploit into delta-wolf 2026-03-19 17:35:22 +02:00
S.B fb9ae7f3c2 api migrations and migration from legacy stuff and fixing shiz
migrated away from free rdp lots of improvements there and created native libs feel free to use native libs but contribute  if you improve please add more wider api support and cli and shell payload mutator for api endpoint going to do that   for payloads gens and other stuff later and im also planning some more bug changes and improvement check the api template
2026-03-19 17:35:15 +02:00