[pitboss/grind] deferred session-0002 (20260522T163126Z-7d60)

This commit is contained in:
pitboss 2026-05-22 12:37:54 -05:00
parent e4258d63ed
commit 3486056f5e
12 changed files with 1129 additions and 26 deletions

View file

@ -0,0 +1,34 @@
// Go JSON_PARSE depth-bomb vuln fixture.
//
// Models a config-driven JSON ingest endpoint that picks the parser
// input based on the request payload tag - `*_DEEP` routes through a
// deeply-nested array literal (256 levels) that drives
// `encoding/json.Unmarshal` past the 64-level depth budget;
// `*_SHALLOW` routes through a flat `[]` parse that leaves the
// predicate clear. This shape is needed by the differential runner:
// the vuln-payload attempt and the benign-control attempt both load
// the same fixture, and only the payload-routed deep branch trips the
// `JsonParseExcessiveDepth` predicate.
//
// Go's encoding/json parser is iterative so the deep input does not
// panic the stdlib; the harness walks the returned interface{} to
// compute the observed depth and emits a `ProbeKind::JsonParse` record.
package vuln
import (
"encoding/json"
"strings"
)
func Run(value string) interface{} {
text := value
if strings.Contains(text, "DEEP") {
nested := strings.Repeat("[", 256) + strings.Repeat("]", 256)
var v interface{}
_ = json.Unmarshal([]byte(nested), &v)
return v
}
var v interface{}
_ = json.Unmarshal([]byte("[]"), &v)
return v
}

View file

@ -0,0 +1,37 @@
<?php
// PHP JSON_PARSE depth-bomb vuln fixture.
//
// Models a config-driven JSON ingest endpoint that picks the parser
// input based on the request payload tag - `*_DEEP` routes through a
// deeply-nested array literal (256 levels) that drives `json_decode`
// past the 64-level depth budget; `*_SHALLOW` routes through a flat
// `[]` parse that leaves the predicate clear. This shape is needed by
// the differential runner: the vuln-payload attempt and the
// benign-control attempt both load the same fixture, and only the
// payload-routed deep branch trips the `JsonParseExcessiveDepth`
// predicate.
//
// PHP cannot monkey-patch `json_decode` itself. The harness publishes
// a global `_nyx_json_decode($s)` helper that proxies the real
// `json_decode` and records the parse depth before returning. Inside
// the synthetic `Nyx\Captured` namespace the harness eval's this
// fixture into, PHP's unqualified function-call resolution falls back
// to the global namespace, so the call site below routes through the
// harness helper at runtime. When this fixture runs standalone (no
// harness) the fallback definition near the bottom of the file kicks
// in and the helper degrades to a direct `json_decode` call.
function run($value) {
$text = is_string($value) ? $value : (string) json_encode($value);
if (strpos($text, 'DEEP') !== false) {
$nested = str_repeat('[', 256) . str_repeat(']', 256);
return _nyx_json_decode($nested);
}
return _nyx_json_decode('[]');
}
if (!function_exists('_nyx_json_decode')) {
function _nyx_json_decode($s) {
return json_decode($s, true, 4096);
}
}

View file

@ -0,0 +1,34 @@
// Rust JSON_PARSE depth-bomb vuln fixture.
//
// Models a config-driven JSON ingest endpoint that picks the parser
// input based on the request payload tag - `*_DEEP` routes through a
// 100-level nested array literal that drives `serde_json::from_str`
// past the 64-level depth budget; `*_SHALLOW` routes through a flat
// `[]` parse that leaves the predicate clear. This shape is needed
// by the differential runner: the vuln-payload attempt and the
// benign-control attempt both load the same fixture, and only the
// payload-routed deep branch trips the `JsonParseExcessiveDepth`
// predicate.
//
// `serde_json` defaults to a recursion limit of 128 stack frames
// during `from_str`, so the nesting is capped at 100 to stay under
// the parser's own guard while still overshooting the predicate's
// 64-level budget. The harness walks the returned `Value`
// iteratively to compute the observed depth and emits a
// `ProbeKind::JsonParse` record.
pub fn run(value: &str) -> serde_json::Value {
if value.contains("DEEP") {
let depth = 100usize;
let mut nested = String::with_capacity(depth * 2);
for _ in 0..depth {
nested.push('[');
}
for _ in 0..depth {
nested.push(']');
}
serde_json::from_str(&nested).unwrap_or(serde_json::Value::Null)
} else {
serde_json::from_str("[]").unwrap_or(serde_json::Value::Null)
}
}