blitzstrike 2.4.40 → 2.4.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/dist/index.js +234 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,31 @@ All notable changes to Blitz Strike are documented here.
|
|
|
5
5
|
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/).
|
|
7
7
|
|
|
8
|
+
## [2.4.42] — 2026-09-14
|
|
9
|
+
|
|
10
|
+
### Added — Duplicate Parameter Precedence Fuzzer (WAF-bypass oracle)
|
|
11
|
+
|
|
12
|
+
- New `src/param-precedence.ts`: determine how the app resolves duplicate
|
|
13
|
+
parameters + alternate delimiters (`;` `,` `%26` `%3b` `|` `[]` `%00` `+`),
|
|
14
|
+
and classify first-wins / last-wins / mixed precedence.
|
|
15
|
+
- New `param_precedence` tool: baseline A/B + differential per variant, with a
|
|
16
|
+
DERIVED waf_bypass_hint (inject via the WAF/app disagreement).
|
|
17
|
+
- System prompt: added a "LIVE PENTEST + TARGETING" directive wiring the new
|
|
18
|
+
black-box tools (cache_gap / blind_oracle / param_precedence) and source
|
|
19
|
+
targeting tools (action_surface / security_state / framework_knowledge /
|
|
20
|
+
variant_scan / patch_analyze) into a coherent, evidence-first workflow.
|
|
21
|
+
|
|
22
|
+
## [2.4.41] — 2026-09-14
|
|
23
|
+
|
|
24
|
+
### Added — Blind Differential Oracle (calibration-based sink detection)
|
|
25
|
+
|
|
26
|
+
- New `src/blind-oracle.ts`: detect which sink a request parameter reaches
|
|
27
|
+
WITHOUT a malicious payload — calibration + differential. Arithmetic
|
|
28
|
+
identities (`id=1` vs `id=1+0`/`id=2-1`) reveal SQL/expression context; SSTI
|
|
29
|
+
arithmetic (`test${7*7}`) reveals template engines; a unique marker reveals
|
|
30
|
+
XSS reflection. Benign probes (numbers + operators), deterministic inference.
|
|
31
|
+
- New `blind_oracle` tool: WAF-safe blind detection for sql/ssti/xss.
|
|
32
|
+
|
|
8
33
|
## [2.4.40] — 2026-09-14
|
|
9
34
|
|
|
10
35
|
### Added — Web Cache Key Normalization Gap Fuzzer (live, black-box)
|
package/dist/index.js
CHANGED
|
@@ -57506,6 +57506,209 @@ async function cacheGapScan(baseUrl, endpoint, opts = {}) {
|
|
|
57506
57506
|
};
|
|
57507
57507
|
}
|
|
57508
57508
|
|
|
57509
|
+
// src/blind-oracle.ts
|
|
57510
|
+
function arithmeticProbes(value) {
|
|
57511
|
+
const n = Number(value);
|
|
57512
|
+
if (Number.isNaN(n) || value.trim() === "")
|
|
57513
|
+
return [];
|
|
57514
|
+
return [
|
|
57515
|
+
{ sink: "sql_arithmetic", name: "plus_zero", payload: `${n}+0` },
|
|
57516
|
+
{ sink: "sql_arithmetic", name: "minus_zero", payload: `${n}-0` },
|
|
57517
|
+
{ sink: "sql_arithmetic", name: "times_one", payload: `${n}*1` },
|
|
57518
|
+
{ sink: "sql_coercion", name: "leading_zero", payload: `0${value}` },
|
|
57519
|
+
{ sink: "sql_coercion", name: "float_form", payload: `${n}.0` }
|
|
57520
|
+
];
|
|
57521
|
+
}
|
|
57522
|
+
function sstiProbes(value) {
|
|
57523
|
+
return [
|
|
57524
|
+
{ sink: "ssti", name: "dollar_math", payload: `${value}\${7*7}` },
|
|
57525
|
+
{ sink: "ssti", name: "hash_math", payload: `${value}#{7*7}` },
|
|
57526
|
+
{ sink: "ssti", name: "mustache_math", payload: `${value}{{7*7}}` }
|
|
57527
|
+
];
|
|
57528
|
+
}
|
|
57529
|
+
function xssProbe(value, marker) {
|
|
57530
|
+
return { sink: "xss", name: "marker", payload: `${value}${marker}` };
|
|
57531
|
+
}
|
|
57532
|
+
function classifyBlindProbe(input) {
|
|
57533
|
+
const same = input.bodyHash === input.baselineHash;
|
|
57534
|
+
let signal = false;
|
|
57535
|
+
let reason = "";
|
|
57536
|
+
if (input.sink === "sql_arithmetic" && same) {
|
|
57537
|
+
signal = true;
|
|
57538
|
+
reason = "arithmetic identity returned the SAME result as the bare value — the parameter is evaluated arithmetically (SQL/expression context).";
|
|
57539
|
+
} else if (input.sink === "sql_coercion" && same) {
|
|
57540
|
+
signal = true;
|
|
57541
|
+
reason = "type-coerced variant returned the SAME result — the parameter is normalized numerically (SQL typed column).";
|
|
57542
|
+
} else if (input.sink === "ssti" && !same && /49/.test(input.body)) {
|
|
57543
|
+
signal = true;
|
|
57544
|
+
reason = "the SSTI arithmetic (7*7) rendered as 49 in the response — the parameter reaches a template engine (SSTI).";
|
|
57545
|
+
} else if (input.sink === "xss" && input.marker && input.body.includes(input.marker)) {
|
|
57546
|
+
signal = true;
|
|
57547
|
+
reason = "the unique marker was reflected in the response — the parameter reaches HTML output (reflected).";
|
|
57548
|
+
}
|
|
57549
|
+
return { same_as_baseline: same, signal, reason };
|
|
57550
|
+
}
|
|
57551
|
+
async function blindOracle(baseUrl, param, value, opts = {}) {
|
|
57552
|
+
const base = baseUrl.replace(/\/+$/, "");
|
|
57553
|
+
const sinks = opts.sinks ?? ["sql", "ssti", "xss"];
|
|
57554
|
+
const marker = `zz${Math.random().toString(36).slice(2, 10)}zz`;
|
|
57555
|
+
const headers = { "User-Agent": "Mozilla/5.0 (blitzstrike oracle probe)" };
|
|
57556
|
+
const timeoutMs = opts.timeoutMs ?? 8000;
|
|
57557
|
+
const build = (payload) => `${base}?${encodeURIComponent(param)}=${encodeURIComponent(payload)}`;
|
|
57558
|
+
let baselineHash = "";
|
|
57559
|
+
let baselineSize = 0;
|
|
57560
|
+
let baselineStatus = 0;
|
|
57561
|
+
try {
|
|
57562
|
+
const r = await fetch(build(value), { headers, redirect: "manual", signal: AbortSignal.timeout(timeoutMs) });
|
|
57563
|
+
baselineStatus = r.status;
|
|
57564
|
+
const body = await r.text();
|
|
57565
|
+
baselineHash = sha256(body);
|
|
57566
|
+
baselineSize = body.length;
|
|
57567
|
+
} catch (e) {
|
|
57568
|
+
return { error: "baseline fetch failed", base_url: base, param, detail: String(e) };
|
|
57569
|
+
}
|
|
57570
|
+
const probes = [];
|
|
57571
|
+
if (sinks.includes("sql"))
|
|
57572
|
+
probes.push(...arithmeticProbes(value));
|
|
57573
|
+
if (sinks.includes("ssti"))
|
|
57574
|
+
probes.push(...sstiProbes(value));
|
|
57575
|
+
if (sinks.includes("xss"))
|
|
57576
|
+
probes.push(xssProbe(value, marker));
|
|
57577
|
+
const results = [];
|
|
57578
|
+
for (const p of probes) {
|
|
57579
|
+
const t0 = Date.now();
|
|
57580
|
+
try {
|
|
57581
|
+
const r = await fetch(build(p.payload), { headers, redirect: "manual", signal: AbortSignal.timeout(timeoutMs) });
|
|
57582
|
+
const timing = Date.now() - t0;
|
|
57583
|
+
const status = r.status;
|
|
57584
|
+
const body = await r.text();
|
|
57585
|
+
const bodyHash = sha256(body);
|
|
57586
|
+
const cls = classifyBlindProbe({
|
|
57587
|
+
baselineHash,
|
|
57588
|
+
baselineSize,
|
|
57589
|
+
bodyHash,
|
|
57590
|
+
size: body.length,
|
|
57591
|
+
sink: p.sink,
|
|
57592
|
+
name: p.name,
|
|
57593
|
+
body,
|
|
57594
|
+
marker
|
|
57595
|
+
});
|
|
57596
|
+
results.push({
|
|
57597
|
+
sink: p.sink,
|
|
57598
|
+
name: p.name,
|
|
57599
|
+
payload: p.payload,
|
|
57600
|
+
status,
|
|
57601
|
+
size: body.length,
|
|
57602
|
+
timing_ms: timing,
|
|
57603
|
+
body_hash: bodyHash.slice(0, 12),
|
|
57604
|
+
same_as_baseline: cls.same_as_baseline,
|
|
57605
|
+
signal: cls.signal,
|
|
57606
|
+
reason: cls.reason
|
|
57607
|
+
});
|
|
57608
|
+
} catch {
|
|
57609
|
+
results.push({ sink: p.sink, name: p.name, payload: p.payload, status: 0, size: 0, timing_ms: 0, body_hash: "", same_as_baseline: false, signal: false, reason: "fetch error/timeout" });
|
|
57610
|
+
}
|
|
57611
|
+
}
|
|
57612
|
+
const signals = results.filter((r) => r.signal === true);
|
|
57613
|
+
return {
|
|
57614
|
+
base_url: base,
|
|
57615
|
+
param,
|
|
57616
|
+
value,
|
|
57617
|
+
baseline: { status: baselineStatus, size: baselineSize, body_hash: baselineHash.slice(0, 16) },
|
|
57618
|
+
probes_tested: results.length,
|
|
57619
|
+
signals_found: signals.length,
|
|
57620
|
+
signals,
|
|
57621
|
+
all: results,
|
|
57622
|
+
interpretation: "A signal means the parameter reaches that sink (evidence: the differential). Verify live before reporting — the oracle is a detection hint, not proof."
|
|
57623
|
+
};
|
|
57624
|
+
}
|
|
57625
|
+
|
|
57626
|
+
// src/param-precedence.ts
|
|
57627
|
+
function generatePrecedenceVariants(param, a, b) {
|
|
57628
|
+
const enc = encodeURIComponent;
|
|
57629
|
+
const variants = [
|
|
57630
|
+
{ name: "duplicate_amp", qs: `${enc(param)}=${enc(a)}&${enc(param)}=${enc(b)}` },
|
|
57631
|
+
{ name: "semicolon", qs: `${enc(param)}=${enc(a)};${enc(param)}=${enc(b)}` },
|
|
57632
|
+
{ name: "comma", qs: `${enc(param)}=${enc(a)},${enc(param)}=${enc(b)}` },
|
|
57633
|
+
{ name: "encoded_amp", qs: `${enc(param)}=${enc(a)}%26${enc(param)}=${enc(b)}` },
|
|
57634
|
+
{ name: "encoded_semicolon", qs: `${enc(param)}=${enc(a)}%3b${enc(param)}=${enc(b)}` },
|
|
57635
|
+
{ name: "pipe", qs: `${enc(param)}=${enc(a)}|${enc(param)}=${enc(b)}` },
|
|
57636
|
+
{ name: "array", qs: `${enc(param)}[]=${enc(a)}&${enc(param)}[]=${enc(b)}` },
|
|
57637
|
+
{ name: "null_byte", qs: `${enc(param)}=${enc(a)}%00${enc(b)}` },
|
|
57638
|
+
{ name: "space", qs: `${enc(param)}=${enc(a)}+${enc(b)}` }
|
|
57639
|
+
];
|
|
57640
|
+
return variants;
|
|
57641
|
+
}
|
|
57642
|
+
function classifyPrecedence(input) {
|
|
57643
|
+
const h = input.bodyHash;
|
|
57644
|
+
if (h === input.hashA) {
|
|
57645
|
+
return { winner: "A", split: true, detail: "value A won (the first/leftmost value) — first-wins precedence for this delimiter." };
|
|
57646
|
+
}
|
|
57647
|
+
if (h === input.hashB) {
|
|
57648
|
+
return { winner: "B", split: true, detail: "value B won (the last/rightmost value) — last-wins precedence for this delimiter." };
|
|
57649
|
+
}
|
|
57650
|
+
return { winner: "neither", split: false, detail: "neither A nor B matched — the delimiter may be literal (not a parameter separator) or the values were joined." };
|
|
57651
|
+
}
|
|
57652
|
+
async function paramPrecedenceScan(baseUrl, param, valueA, valueB, opts = {}) {
|
|
57653
|
+
const base = baseUrl.replace(/\/+$/, "");
|
|
57654
|
+
const headers = { "User-Agent": "Mozilla/5.0 (blitzstrike precedence probe)" };
|
|
57655
|
+
const timeoutMs = opts.timeoutMs ?? 8000;
|
|
57656
|
+
const enc = encodeURIComponent;
|
|
57657
|
+
const fetchHash = async (qs) => {
|
|
57658
|
+
try {
|
|
57659
|
+
const r = await fetch(`${base}?${qs}`, { headers, redirect: "manual", signal: AbortSignal.timeout(timeoutMs) });
|
|
57660
|
+
const body = await r.text();
|
|
57661
|
+
return { status: r.status, hash: sha256(body) };
|
|
57662
|
+
} catch (e) {
|
|
57663
|
+
return { status: 0, hash: "", error: String(e) };
|
|
57664
|
+
}
|
|
57665
|
+
};
|
|
57666
|
+
const baseA = await fetchHash(`${enc(param)}=${enc(valueA)}`);
|
|
57667
|
+
const baseB = await fetchHash(`${enc(param)}=${enc(valueB)}`);
|
|
57668
|
+
if (baseA.error || baseB.error) {
|
|
57669
|
+
return { error: "baseline fetch failed", base_url: base, param, detail: baseA.error ?? baseB.error };
|
|
57670
|
+
}
|
|
57671
|
+
if (baseA.hash === baseB.hash) {
|
|
57672
|
+
return { error: "baseline A and B produce identical responses — pick two values with a distinguishable effect", base_url: base, param };
|
|
57673
|
+
}
|
|
57674
|
+
const variants = generatePrecedenceVariants(param, valueA, valueB);
|
|
57675
|
+
const results = [];
|
|
57676
|
+
let firstWins = 0;
|
|
57677
|
+
let lastWins = 0;
|
|
57678
|
+
for (const v of variants) {
|
|
57679
|
+
const r = await fetchHash(v.qs);
|
|
57680
|
+
if (r.error) {
|
|
57681
|
+
results.push({ name: v.name, qs: v.qs, status: 0, body_hash: "", winner: "neither", split: false, detail: "fetch error/timeout" });
|
|
57682
|
+
continue;
|
|
57683
|
+
}
|
|
57684
|
+
const cls = classifyPrecedence({ hashA: baseA.hash, hashB: baseB.hash, bodyHash: r.hash, name: v.name });
|
|
57685
|
+
if (cls.winner === "A")
|
|
57686
|
+
firstWins++;
|
|
57687
|
+
else if (cls.winner === "B")
|
|
57688
|
+
lastWins++;
|
|
57689
|
+
results.push({ name: v.name, qs: v.qs, status: r.status, body_hash: r.hash.slice(0, 12), winner: cls.winner, split: cls.split, detail: cls.detail });
|
|
57690
|
+
}
|
|
57691
|
+
let precedence = "ambiguous";
|
|
57692
|
+
if (firstWins > 0 && lastWins === 0)
|
|
57693
|
+
precedence = "first_wins";
|
|
57694
|
+
else if (lastWins > 0 && firstWins === 0)
|
|
57695
|
+
precedence = "last_wins";
|
|
57696
|
+
else if (firstWins > 0 && lastWins > 0)
|
|
57697
|
+
precedence = "mixed_by_delimiter";
|
|
57698
|
+
return {
|
|
57699
|
+
base_url: base,
|
|
57700
|
+
param,
|
|
57701
|
+
value_a: valueA,
|
|
57702
|
+
value_b: valueB,
|
|
57703
|
+
precedence,
|
|
57704
|
+
first_wins_count: firstWins,
|
|
57705
|
+
last_wins_count: lastWins,
|
|
57706
|
+
variants_tested: results.length,
|
|
57707
|
+
results,
|
|
57708
|
+
waf_bypass_hint: precedence === "first_wins" ? "the app uses the FIRST duplicate value — a WAF that inspects the LAST value is bypassed with ?param=benign¶m=payload." : precedence === "last_wins" ? "the app uses the LAST duplicate value — a WAF that inspects the FIRST value is bypassed with ?param=payload¶m=benign." : "precedence is mixed by delimiter — map which delimiter the WAF validates vs which the app binds, then inject via the disagreement."
|
|
57709
|
+
};
|
|
57710
|
+
}
|
|
57711
|
+
|
|
57509
57712
|
// src/enterprise-benchmark.ts
|
|
57510
57713
|
import { existsSync as existsSync11, readFileSync as readFileSync20, readdirSync as readdirSync6, statSync as statSync3 } from "node:fs";
|
|
57511
57714
|
import { join as join18, resolve } from "node:path";
|
|
@@ -57745,8 +57948,7 @@ function createServer() {
|
|
|
57745
57948
|
` + `- Keep trying every lead AND every chain step until each is verified/executed or blocked, THEN generate_report. Never deliver a bare surface map, and never stop at 'found X' when X enables more.
|
|
57746
57949
|
|
|
57747
57950
|
` + "TWO PATHS:\\n" + "- Source path on disk -> blitz_scan / taint_file / eagle_eye2 (static).\\n" + "- Live URL -> live_recon / active_scan / strike_verify (web-hunting).\\n\\n" + `DEEPEN A FINDING: attack_plan(target, tech, params) to get the prioritized vector plan (decide what to test next with data); list_chains (escalation), chain_links (compose), technique_lookup(cls), payload_lookup, bypass_lookup (blocked). Phase doctrine: read_skill(bs-orchestrate-engagement | bs-web-hunting | bs-source-audit | bs-verify-finding). Campaign plan: read_playbook(target-type). On any failure call retry_guidance(signal) / model_fallback(signal) before giving up.
|
|
57748
|
-
` +
|
|
57749
|
-
` + `PRECISION ANALYSIS — chrome-devtools MCP is MANDATORY, not optional:
|
|
57951
|
+
` + "KNOWLEDGE BASE (discover, don't guess): skillLookup(topic) / listSkills for the 40 attack-path + hunting skills (ap-*, hp-*, bs-*); list_attack_vectors / attack_vectors(cat) for the 34-category vector taxonomy; taxonomy(kind) for OWASP/CWE/ASVS/API-top-10; read_playbook(type) for the 17 campaign playbooks; list_manuals / read_tool_manual for 317 tool references; list_tools / run_catalog_tool for the 141-tool catalog. Every tool, skill, and data layer is reachable from these. CROSS-TARGET INTELLIGENCE: strike_resolve auto-records confirmed/false_positive verdicts into the empirical ledger; query it with intelligence(action=hit_rates/top_vectors) so a new target on a known tech inherits historical hit-rates (attack_plan already blends them into success_probability). LIVE PENTEST + TARGETING (black-box, WAF-safe): cache_gap(base_url, endpoint) fuzzes path-normalization + static-extension variants for cache deception/poisoning; blind_oracle(base_url, param, value) detects which SINK a param reaches (sql/ssti/xss) via benign arithmetic (id=1+0, test${7*7}) WITHOUT a malicious payload; param_precedence(base_url, param, A, B) maps duplicate-parameter precedence (first/last-wins) for WAF-bypass. SOURCE TARGETING: action_surface(code) maps every wp_ajax_* action to its vuln class + DERIVED priority (what to look for WHERE); security_state(sanitizers, sink) gives a wrong-context sanitization verdict; framework_knowledge(framework) returns auth/nonce primitives for 9 frameworks; variant_scan(root, signature) mass-sweeps an install base for ONE bug family; patch_analyze(old, new) REVERSES a security patch into the 0-day, and its mine_signature feeds variant_scan to sweep unpatched copies. All of these are DETECTION HINTS — verify each live (strike_verify / browser_validate) before it enters the report.\n" + `PRECISION ANALYSIS — chrome-devtools MCP is MANDATORY, not optional:
|
|
57750
57952
|
` + `- When a lead needs DOM/JS precision — DOM-XSS sink execution, AJAX endpoint + payload interception, JS runtime errors, redirect chains, SSO/token flow, or anything a static HTML glance cannot prove — call drive_devtools(target). It spawns chrome-devtools-mcp and drives a REAL headless browser (navigate -> list_network_requests -> list_console_messages -> evaluate_script), giving reproducible evidence instead of a guess.
|
|
57751
57953
|
` + `- Before calling it, check_mcp() to confirm the browser MCP is available; if not, blitzstrike install-tools or npm i -g chrome-devtools-mcp. Never substitute eyeballing minified JS or a static sink guess when a live browser can PROVE it. This is the precision + consistency layer.
|
|
57752
57954
|
` + "EXTERNAL MCP SERVERS (verified, connect them — NOT one-shot CLIs): chrome-devtools-mcp (29 tools: list_network_requests/get_network_request for raw HTTP interception, list_console_messages for JS errors + DOM-XSS, evaluate_script to run JS, take_screenshot) -> stdio chrome-devtools-mcp --headless --chromeArg=--no-sandbox --chromeArg=--disable-gpu (as root/container this is MANDATORY or the browser crashes; add --proxyServer http://127.0.0.1:8080 to route through Burp, --acceptInsecureCerts for bad TLS). burp-suite-mcp (proxy history + active scan + repeater) -> NOT npm: build the JAR (git clone https://github.com/PortSwigger/mcp-server.git && cd mcp-server && ./gradlew embedProxyJar), load it in Burp Extensions, then connect the client to http://127.0.0.1:9876 (SSE) or the stdio proxy java -jar mcp-proxy-all.jar --sse-url http://127.0.0.1:9876."
|
|
@@ -58505,6 +58707,36 @@ ${statusLine}` : statusLine },
|
|
|
58505
58707
|
}, async ({ base_url, endpoint, max_variants }) => {
|
|
58506
58708
|
return { content: [{ type: "text", text: JSON.stringify(await cacheGapScan(base_url, endpoint, { maxVariants: max_variants })) }] };
|
|
58507
58709
|
});
|
|
58710
|
+
server.registerTool("blind_oracle", {
|
|
58711
|
+
title: "Blind differential oracle (calibration-based sink detection)",
|
|
58712
|
+
description: "LIVE (black-box, WAF-safe): detect which sink a request parameter reaches WITHOUT a malicious payload — calibration + differential. Arithmetic identities (id=1 vs id=1+0 / id=2-1) reveal SQL/expression context; SSTI arithmetic (test${7*7}) reveals template engines; a unique marker reveals XSS reflection. Benign probes (numbers + operators, no quotes/commands), deterministic byte-level inference.",
|
|
58713
|
+
inputSchema: {
|
|
58714
|
+
base_url: string2().describe("Target base URL"),
|
|
58715
|
+
param: string2().describe("Parameter name to probe (e.g. id)"),
|
|
58716
|
+
value: string2().describe("Baseline value for the parameter (e.g. 1)"),
|
|
58717
|
+
sinks: string2().optional().describe("JSON array of sinks to probe (default ['sql','ssti','xss'])")
|
|
58718
|
+
}
|
|
58719
|
+
}, async ({ base_url, param, value, sinks }) => {
|
|
58720
|
+
let s;
|
|
58721
|
+
try {
|
|
58722
|
+
s = sinks ? JSON.parse(sinks) : undefined;
|
|
58723
|
+
} catch {
|
|
58724
|
+
return { content: [{ type: "text", text: JSON.stringify({ error: "invalid sinks JSON" }) }] };
|
|
58725
|
+
}
|
|
58726
|
+
return { content: [{ type: "text", text: JSON.stringify(await blindOracle(base_url, param, value, { sinks: s })) }] };
|
|
58727
|
+
});
|
|
58728
|
+
server.registerTool("param_precedence", {
|
|
58729
|
+
title: "Duplicate parameter precedence fuzzer (WAF-bypass oracle)",
|
|
58730
|
+
description: "LIVE (black-box): determine how the app resolves duplicate parameters + alternate delimiters (; , %26 %3b | [] %00 + #). Reveals the WAF-bypass vector — if the WAF validates one value and the app binds another, inject via the disagreement. Deterministic: baseline A/B + differential per variant.",
|
|
58731
|
+
inputSchema: {
|
|
58732
|
+
base_url: string2().describe("Target base URL"),
|
|
58733
|
+
param: string2().describe("Parameter name (e.g. id)"),
|
|
58734
|
+
value_a: string2().describe("First value (e.g. 1)"),
|
|
58735
|
+
value_b: string2().describe("Second value (e.g. 2)")
|
|
58736
|
+
}
|
|
58737
|
+
}, async ({ base_url, param, value_a, value_b }) => {
|
|
58738
|
+
return { content: [{ type: "text", text: JSON.stringify(await paramPrecedenceScan(base_url, param, value_a, value_b)) }] };
|
|
58739
|
+
});
|
|
58508
58740
|
server.registerTool("payload_lookup", {
|
|
58509
58741
|
title: "Look up exploit payloads",
|
|
58510
58742
|
description: "INTEL: find a payload collection (66 categories from PayloadsAllTheThings).",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "blitzstrike",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.42",
|
|
4
4
|
"description": "Blitz Strike — a universal MCP security-audit toolbelt. BLITZ sweeps the attack surface, EAGLE-EYE traces source-to-sink, STRIKE verifies live. 57 attack chains, 130-tool catalog, intelligence data layer. One server, every agent.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|