Skip to content

Metasploit msf-ws per-handler auth omission, GitLab regex-validation escape, and log-format identity confusion

Source: hourly offensive-security scan, 2026-10-13 03:3xZ GitHub Advisory wave (GitLab 19.2.8/19.3.5/19.4.2 patch batch, SAP October Patch Day, plus two framework/tooling singles with durable new axes).

Two genuinely new axes this wave, plus two strong reinforcements of standing rules:

  1. Per-handler authentication omission inside an otherwise-authenticated API — the Metasploit Framework Web Service is the canonical, fully-detailed example: twelve routes call the auth check, two do not, and the default listener is 0.0.0.0:8080.
  2. Log-format confusion: unvalidated logged content steering a log-consuming control system — fail2ban's sshd filter lets an unauthenticated attacker choose which IP gets banned by putting the token on <victim-ip> in the username field, because OpenSSH logs offered usernames verbatim.
  3. Framework-level regex validation as an unauthenticated RCE surface — GitLab's unauth CI/CD-config regex RCE continues the Spring4Shell lineage: a regex validator is itself parser attack surface.
  4. Time-of-check/time-of-use in import-URL SSRF guards — GitLab's repository-import TOCTOU leg; the guard validates one resolution, the fetch uses another.

1. Metasploit msf-ws: credential store readable/writable with zero auth (GHSA-4r4h-q2gr-cvcv / CVE-2026-87689, critical, fixed 6.5.5)

The advisory is unusually explicit: Msf::WebServices::CredentialServlet calls warden.authenticate! at the top of every mutating and read route except update_credential (PUT) and delete_credentials (DELETE) on /api/v1/credentials, and the underlying db_manager/cred.rb performs no check of its own. Any client that can reach the default 0.0.0.0:8080 listener can read, modify, or delete every stored credential record — passwords, hashes, private keys — for a shared team engagement, with no token.

Operator value:

  1. msf-ws is a recon target in its own right. Red-team and pentest teams run msf-ws (and Metasploitable-style dashboards, msfconsole RPC, Cobalt Strike team-server APIs, Sliver/Havii REST layers) on engagement hosts, VMs, and cloud boxes — often with 0.0.0.0 binds, often on management networks that assume "no one can reach this." Sweep for it: http://target:8080/api/v1/ banner, /api/v1/credentials verbs. PUT/DELETE without auth is the fingerprint; the READ legs sit behind warden, so prove read access only if the deployment's route table differs or another missing-auth servlet exists — the durable finding is the two unauthenticated mutating verbs.
  2. The audit pattern generalizes: auth is per-handler, not per-server. In web apps that attach auth as the first statement of each handler (Sinatra-style before blocks are safer; explicit per-route calls are this shape), completeness is a manual invariant one refactor away from breaking. For any HTTP API you assess: enumerate the full route table from the framework's own route registry (or the generated OpenAPI/route dump), and run every verb against every route anonymously. A single anonymous 2xx/4xx authorization-shaped response (403-from-logic vs 401-from-middleware are different animals) identifies the leg that forgot its first statement. The 401-vs-403 shape diff is the cheapest missing-handler-auth oracle.
  3. Offensive-tooling infrastructure is perpetually under-scoped in engagements — it holds collected credentials for other targets. Add "operator C2/scanner/MSF web listeners" to your own internal-sweep checklist, and treat a reachable msf-ws on an assessment as a credential-vault compromise of everything previously collected (the credential-vault axis from the Sept 20 page, now with the tooling itself as the vault host).

Safe validation boundaries: your own msf-ws instance in a lab VM only; seeded fake credential rows; never touch a live engagement's msf-ws or team-server API unless the rules of engagement explicitly cover operator infrastructure, and never exfiltrate real collected credentials — prove PUT/DELETE reachability against rows you planted.

2. fail2ban sshd filter: offered username chooses the ban target (GHSA-xw36-3g63-5wfw / CVE-2026-109786, fail2ban 0.10.5–1.1.1)

The sshd filter regex accepts an on <token> suffix after the captured host address. OpenSSH logs the offered username verbatim, so a remote unauthenticated attacker sends an auth attempt with username x VICTIM-SOURCE-IP-ADDRESS on and fail2ban attributes the failed logins to the victim IP — banning a legitimate admin, partner, or scanner out of the box on the default filter.

Operator value:

  1. Log consumers are enforcement decision-makers, and their input grammar is attack surface. fail2ban, WAF log-rule engines, SIEM correlation-driven auto-block, CDN log-based BAN features — all parse attacker-influenced strings (usernames, URLs, user-agents, Host headers) into structured decisions (ban/rate-limit/blocklist). Ask of every such product: which logged field is parsed positionally/regex-ly into an identity (IP, user, account), and can content I control extend that field's parsed value?
  2. Log-format injection → control-plane effect is the testable chain. Step 1: find the verbatim-logged field (offer a username with unique inert punctuation, read a lab log line). Step 2: check the downstream parser's grammar for suffix/separator tokens that rescope the parsed key (on <ip> here; in general: quotes, delimiters, format verbs). Step 3 — only in a lab you own or with explicit approval — prove misattribution: attacker box generates failures with the crafted username, the decoy lab IP gets banned. Impact is availability/lockout against a third party, so this is a do-not-run-in-production class; report from grammar proof + lab decision table.
  3. Attacker-friendly direction too: self-ban-evasion (spread attempts so the target's own ban logic never trips against you) and ban-spoof as nuisance/cover are in the toolkit, but the durable hunt value is recognizing your engagement's own fail2ban/WAF auto-block as a weaponizable third component when you're testing lockout behaviors.

3. GitLab October wave: unauth regex-validator RCE, Duo agent instruction injection, cache-key poisoning, and import TOCTOU (fixed 19.2.8 / 19.3.5 / 19.4.2)

The 2026-10-13 GitLab patch batch folds onto the July 29 GitLab CI/AI/import boundaries page; the legs with new axes:

  • GHSA-9hj5-r43h-h3xg / CVE-2026-97229 (critical): unauthenticated RCE via a specially crafted regular expression in a CI/CD configuration, "insufficient regular expression validation." Standing lineage: Spring4Shell-style unanchored Pattern.matches, the May 27 Symfony route-requirement anchoring leg, and the October 2 JFrog Xray parser memory-safety leg — a regex validator is a parser compiled against attacker input, and on Ruby/RE2-backtracking or PCRE-flavored stacks it is code-execution or crash surface before it ever validates anything. Durable sweep rule: for any product that gates config/YAML/route/URL fields "by regex," the regex evaluation itself is a test target — crafted nested quantifiers (polynomial/exponential backoff), alternate engine semantics (Ruby Onigmo vs PCRE vs RE2 differ on syntax acceptance), oversized constructs, and engine crash inputs all land at the gate. On GitLab specifically: pre-auth reachability implies the regex is evaluated on an untrusted-config path (project import/CI lint surface); on any GitLab banner below 19.2.8/19.3.5/19.4.2, treat CI-config regex evaluation as a checked primitive in authorized labs only — timing-based ReDoS probes on your own instance, never crash fuzzing against shared instances.
  • GHSA-5vgp-j37h-7wfx / CVE-2026-96893 (high, EE): authenticated user injects crafted content into AI agent instructions, causing unintended command execution attributed to other users — "improper neutralization of special elements in AI conversation context construction." The injection-sink-vs-attribution split is new and reportable: the agent executes with someone else's authority/context, so victim-attributed actions become the impact. This is the GitLab anchor for the standing agent-page rule (Aug 6 page family): enumerate every field that enters agent instruction/conversation context construction — issue/MR descriptions, commit messages, branch names, review comments — and test instruction-boundary neutralization with inert marker tools, proving both execution and whose identity the execution is logged under. Attribution-confusion is a distinct impact class from plain tool execution; title reports accordingly.
  • GHSA-49c6-8ph4-9vr9 / CVE-2026-14814 (high): user poisons cached responses for raw repository files via improper repository-reference validation, causing other users' CI/CD pipelines to execute crafted content and potentially expose protected environment variables. Cache-key construction from attacker-controlled references = the poisoning primitive (Xray cache-key lineage, June 22 page); the pipeline-executes-cached-content step upgrades it to secret-exposure chain. Sweep: any raw-file endpoint whose cache key includes a ref/sha/specifier you supply — try to make a cached entry for path X answer a request that should hit path Y, then follow who consumes it.
  • GHSA-mv9g-3c33-88m6 / CVE-2026-100104: SSRF to internal network via time-of-check to time-of-use race in URL validation during repository import. Canonical TOCTOU-SSRF: validator resolves URL once (passes), fetcher resolves again (redirects/DNS-rebinds internal). Test battery (owned infra only): fast-fail dual-A records, validator-visible vs fetcher-visible DNS views, 30x chains with differing internal targets per hop, TTL=0 rebinding on your own domain pointing to your own canary internal listener. GitLab import is now a named anchor for the URL-guard page family (July 30).
  • Remaining wave legs fold as inventory on the July 29 page: fine-grained-PAT scope drift family (import into out-of-scope namespaces f8h6, group integrations from project-scoped token fqqc, group label delete/modify hx4m, package-protection bypass mqc6), unauth GraphQL/notes disclosure (3g57 work items, v4cm+mvmh confidential/internal notes on public projects — GraphQL is its own authz plane: test every query type at the lowest role), Developer-triggers-downstream-pipelines-on-protected-branches (4jhf), stale scheduled-pipeline records survive project transfer (2qxc), Kubernetes-agent proxy redirect steals auth tokens (vrcj), Pages log data leaks access tokens (v4pv — sensitive data in logs class), Duo agent-platform token bypasses governance via untrusted input (v9q6), Duo Agent instruction injection (5vgp above), Pages cache-key poisoning (xw26), MR self-approval identity-resolution drift (3wqg), compliance-pipeline privilege assignment (7g5q), reporter reaches CI artifact report content (h447), Guest reads confidential epics (7rx8), package downloads on public projects (p26w), deployment-rollback settings write (f65j).

4. SAP October Patch Day: MII admin-to-Java-EE privilege elevation and tenant-slug OAuth SSRF fold onto the August 11 SAP page

Updated SAP edge/session/tenant page with: SAP MII admin submits crafted request to provision an elevated account on the underlying Java application server = break out of the application's own admin scope into platform admin (GHSA-v27c-xfw8-q954 / CVE-2026-89108 critical — the admin-to-runtime boundary: application-level admin is never the ceiling, check what accounts/objects the app can create on the substrate); SAP Cloud SDK for Python OAuth2 SSRF: attacker-controlled tenant_subdomain steers token requests → client-credentials exfiltration in multi-tenant BTP (GHSA-m3j7-wp2j-mhc3 critical — tenant name/slug as a URL-building input is the tenant-selection page's new leg: derive the token endpoint from a claim/parameter and you've let the tenant selector pick the credential destination); S/4HANA substitution/validation DSL input interpreted as executable ABAP (mw39 critical — a business DSL interpreted as full code is an authz bypass by design, DSL-to-runtime parity check); ABAP session-manager regression reintroducing a fixed authorization weakness via single-transaction mode from FLP (hxp9 — patch-day regressions mean fixed-version ≠ tested-version on every previously-reported leg; re-run old probes after upgrades); HybridTokenAuthenticator accepts tokens from unintended ambient IAS/XSUAA bindings (2v6r — ambient-issuer acceptance: enumerate every trust anchor the auth library picks up from environment config, not just the intended one); Commerce Cloud SQLi, NetWeaver EP unauth restricted-resource + reflected XSS pair, UI5/GUI-for-HTML stored XSS, Cloud Connector adjacent-network info leak, Web Dispatcher memory-corruption DoS.

Validation boundaries for the whole page

Disposable self-managed GitLab below the fix bands with synthetic users/projects, inert pipelines and no-op tools, owned redirectors/canary internal listeners, seeded fake credentials on your own msf-ws, a fail2ban lab VM you own with a decoy lab IP, and owned-tenant SAP labs or customer-approved test systems only. Never: touch live operator C2 credential stores, ban third-party IPs, fuzz regex engines against shared instances, or read real engagement secrets.

Tracked from the same wave without publication

  • The remaining ~20 GitLab low/medium legs (inventory above) — route-auth-drift and scope-drift classes already covered by the July 29 and Sept 16 pages.
  • Thin/VulDB-style AI-model-loading eval/deser singles: TinyLLaVA llm_model_name_or_path code injection, LightX2V auto_map tokenizer eval, yolov13 autobackend eval, RAE get_obj_from_str, torchdistill/sherpa-onnx/TensorLayer HDF5 deserialization, PowerInfer GGUF OOB pair — the trust_remote_code/auto_map/eval model-loading class is already the core axis of the July 16 diffusers page and Sept 11 checkpoint page; no new validation step.
  • code-projects/itsourcecode SQLi singles, clarity-upscaler stored XSS, SAP boilerplate XSS/info-leak singles (S/4HANA instance-authz hj55, customs-catalog 6jgh, MII stored XSS p86p, DOM XSS 63m2, UI5 crmc), CLA-signature admin-IDOR (reuses the principal-as-parameter axis).
  • KEV: catalog 2026.10.08, 1739 entries — unchanged this scan. ToB head SequenceHash processed; PortSwigger head Oct-6 processed; PD head Aug-16; Brutecat unchanged; disclosed sitemap DEAD (rjewel stub).