mirror of
https://github.com/elicpeter/nyx.git
synced 2026-06-21 20:18:06 +02:00
Dynamic (#77)
This commit is contained in:
parent
55247b7fcd
commit
991c84a1eb
1464 changed files with 225448 additions and 1985 deletions
34
tests/dynamic_fixtures/json_parse_depth/go/vuln.go
Normal file
34
tests/dynamic_fixtures/json_parse_depth/go/vuln.go
Normal 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
|
||||
}
|
||||
33
tests/dynamic_fixtures/json_parse_depth/java/Vuln.java
Normal file
33
tests/dynamic_fixtures/json_parse_depth/java/Vuln.java
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
// Java 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 the parser 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.
|
||||
//
|
||||
// Java has no stdlib JSON parser. The harness ships a hand-rolled
|
||||
// iterative `NyxJsonProbe.parse(String)` helper alongside `NyxHarness`
|
||||
// so the fixture does not need to link Jackson / Gson at build time.
|
||||
// The helper returns a `java.util.List` / `java.util.Map` tree the
|
||||
// harness then walks via `NyxJsonProbe.countDepth(Object)` to produce
|
||||
// the `ProbeKind::JsonParse { depth }` record.
|
||||
public class Vuln {
|
||||
public static Object run(String value) {
|
||||
String text = value == null ? "" : value;
|
||||
if (text.contains("DEEP")) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < 256; i++) {
|
||||
sb.append('[');
|
||||
}
|
||||
for (int i = 0; i < 256; i++) {
|
||||
sb.append(']');
|
||||
}
|
||||
return NyxJsonProbe.parse(sb.toString());
|
||||
}
|
||||
return NyxJsonProbe.parse("[]");
|
||||
}
|
||||
}
|
||||
23
tests/dynamic_fixtures/json_parse_depth/javascript/vuln.js
Normal file
23
tests/dynamic_fixtures/json_parse_depth/javascript/vuln.js
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
// JavaScript 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.parse`
|
||||
// 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.
|
||||
function run(value) {
|
||||
const text = Buffer.isBuffer(value)
|
||||
? value.toString('utf8')
|
||||
: String(value);
|
||||
if (text.indexOf('DEEP') !== -1) {
|
||||
const nested = '['.repeat(256) + ']'.repeat(256);
|
||||
return JSON.parse(nested);
|
||||
}
|
||||
return JSON.parse('[]');
|
||||
}
|
||||
|
||||
module.exports = { run };
|
||||
37
tests/dynamic_fixtures/json_parse_depth/php/vuln.php
Normal file
37
tests/dynamic_fixtures/json_parse_depth/php/vuln.php
Normal 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);
|
||||
}
|
||||
}
|
||||
23
tests/dynamic_fixtures/json_parse_depth/python/vuln.py
Normal file
23
tests/dynamic_fixtures/json_parse_depth/python/vuln.py
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
# Python 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.loads`
|
||||
# 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.
|
||||
import json
|
||||
|
||||
|
||||
def run(value):
|
||||
if isinstance(value, (bytes, bytearray)):
|
||||
value = value.decode("utf-8", "replace")
|
||||
elif not isinstance(value, str):
|
||||
value = str(value)
|
||||
if "DEEP" in value:
|
||||
nested = "[" * 256 + "]" * 256
|
||||
return json.loads(nested)
|
||||
return json.loads("[]")
|
||||
23
tests/dynamic_fixtures/json_parse_depth/ruby/vuln.rb
Normal file
23
tests/dynamic_fixtures/json_parse_depth/ruby/vuln.rb
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
# Ruby 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.parse`
|
||||
# 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. `max_nesting: false` disables the json gem's depth
|
||||
# guard so the harness's depth walker sees the full 256-level shape
|
||||
# rather than triggering `JSON::NestingError` at depth 100.
|
||||
require 'json'
|
||||
|
||||
def run(value)
|
||||
text = value.to_s
|
||||
if text.include?('DEEP')
|
||||
nested = '[' * 256 + ']' * 256
|
||||
return JSON.parse(nested, max_nesting: false)
|
||||
end
|
||||
JSON.parse('[]')
|
||||
end
|
||||
34
tests/dynamic_fixtures/json_parse_depth/rust/vuln.rs
Normal file
34
tests/dynamic_fixtures/json_parse_depth/rust/vuln.rs
Normal 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)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue