mirror of
https://github.com/elicpeter/nyx.git
synced 2026-06-30 20:39:39 +02:00
feat(dynamic): remap command injection sink cap to CODE_EXEC, update corpus markers to NYX_PWN_791_CMDI, and enhance spec derivation strategies for wider coverage and consistency
This commit is contained in:
parent
738f1fedbc
commit
7027dbca0a
30 changed files with 524 additions and 130 deletions
|
|
@ -6,7 +6,7 @@ import "strings"
|
|||
type ShellRunner struct{}
|
||||
|
||||
func (ShellRunner) Run(command string) string {
|
||||
return strings.ReplaceAll(command, "NYX_PWN_CMDI", "")
|
||||
return strings.ReplaceAll(command, "NYX_PWN", "")
|
||||
}
|
||||
|
||||
type UserRepository struct {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
public class Benign {
|
||||
public static class ShellRunner {
|
||||
public String run(String command) {
|
||||
return command.replace("NYX_PWN_CMDI", "");
|
||||
return command.replace("NYX_PWN", "");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# Benign control for recursively constructed Ruby dependencies.
|
||||
class ShellRunner
|
||||
def run(command)
|
||||
command.gsub('NYX_PWN_CMDI', '')
|
||||
command.gsub('NYX_PWN', '')
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// Command injection — adversarial collision fixture.
|
||||
// Prints NYX_PWN_CMDI unconditionally without reaching a command sink
|
||||
// Prints NYX_PWN_791_CMDI unconditionally without reaching a command sink
|
||||
// and without emitting __NYX_SINK_HIT__.
|
||||
// Expected verdict: Inconclusive(OracleCollisionSuspected)
|
||||
// Entry: RunPing(host string) Cap: CODE_EXEC
|
||||
|
|
@ -10,6 +10,6 @@ import "fmt"
|
|||
|
||||
func RunPing(host string) {
|
||||
// Coincidental oracle match — not a shell sink.
|
||||
fmt.Println("NYX_PWN_CMDI")
|
||||
fmt.Println("NYX_PWN_791_CMDI")
|
||||
_ = len(host)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// Command injection — adversarial collision fixture.
|
||||
// Prints NYX_PWN_CMDI unconditionally without reaching a command sink
|
||||
// Prints NYX_PWN_791_CMDI unconditionally without reaching a command sink
|
||||
// and without emitting __NYX_SINK_HIT__.
|
||||
// Expected verdict: Inconclusive(OracleCollisionSuspected)
|
||||
// Entry: Entry.runPing(String) Cap: CODE_EXEC
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
public class Entry {
|
||||
public static void runPing(String host) {
|
||||
// Coincidental oracle match — not a shell sink.
|
||||
System.out.println("NYX_PWN_CMDI");
|
||||
System.out.println("NYX_PWN_791_CMDI");
|
||||
int x = host.length();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
// Command injection — adversarial collision fixture.
|
||||
// Prints NYX_PWN_CMDI unconditionally without reaching a command sink
|
||||
// Prints NYX_PWN_791_CMDI unconditionally without reaching a command sink
|
||||
// and without emitting __NYX_SINK_HIT__.
|
||||
// Expected verdict: Inconclusive(OracleCollisionSuspected)
|
||||
// Entry: runPing(host) Cap: CODE_EXEC
|
||||
|
||||
function runPing(host) {
|
||||
// Coincidental oracle match — not a shell sink.
|
||||
process.stdout.write('NYX_PWN_CMDI\n');
|
||||
process.stdout.write('NYX_PWN_791_CMDI\n');
|
||||
void host.length;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
<?php
|
||||
// Command injection — adversarial collision fixture.
|
||||
// Prints NYX_PWN_CMDI unconditionally without reaching a command sink
|
||||
// Prints NYX_PWN_791_CMDI unconditionally without reaching a command sink
|
||||
// and without emitting __NYX_SINK_HIT__.
|
||||
// Expected verdict: Inconclusive(OracleCollisionSuspected)
|
||||
// Entry: runPing($host) Cap: CODE_EXEC
|
||||
|
||||
function runPing($host) {
|
||||
// Coincidental oracle match — not a shell sink.
|
||||
echo "NYX_PWN_CMDI\n";
|
||||
echo "NYX_PWN_791_CMDI\n";
|
||||
$x = strlen($host);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
"""Command injection — adversarial collision fixture.
|
||||
|
||||
Prints NYX_PWN_CMDI unconditionally without going through a shell sink.
|
||||
Prints NYX_PWN_791_CMDI unconditionally without going through a shell sink.
|
||||
Expected verdict: Inconclusive(OracleCollisionSuspected).
|
||||
"""
|
||||
|
||||
|
|
@ -8,5 +8,5 @@ Expected verdict: Inconclusive(OracleCollisionSuspected).
|
|||
def process_input(user_input):
|
||||
"""Prints oracle marker without using a command execution sink."""
|
||||
# Coincidental oracle match — not a shell sink.
|
||||
print("NYX_PWN_CMDI")
|
||||
print("NYX_PWN_791_CMDI")
|
||||
return user_input.upper()
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
/// Command injection — adversarial collision fixture.
|
||||
///
|
||||
/// Prints "NYX_PWN_CMDI" unconditionally without going through a shell sink.
|
||||
/// Prints "NYX_PWN_791_CMDI" unconditionally without going through a shell sink.
|
||||
///
|
||||
/// Expected verdict: Inconclusive(OracleCollisionSuspected)
|
||||
/// oracle_fired = true (OutputContains("NYX_PWN_CMDI"))
|
||||
/// oracle_fired = true (OutputContains("NYX_PWN_791_CMDI"))
|
||||
/// sink_hit = false (__NYX_SINK_HIT__ never printed)
|
||||
/// Cap: CODE_EXEC Entry: `run(payload: &str)`
|
||||
pub fn run(payload: &str) {
|
||||
// Coincidental oracle match — not a command execution sink.
|
||||
println!("NYX_PWN_CMDI");
|
||||
println!("NYX_PWN_791_CMDI");
|
||||
let _ = payload.len();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1175,9 +1175,11 @@ mod e2e_phase_20 {
|
|||
}
|
||||
|
||||
/// Python kafka vuln must Confirm: the synthetic Kafka loopback
|
||||
/// delivers `; echo NYX_PWN_CMDI` to the handler's `os.system`
|
||||
/// which prints `NYX_PWN_CMDI` to stdout and the differential
|
||||
/// oracle reads it.
|
||||
/// delivers `; echo NYX_PWN_$((113*7))_CMDI` to the handler's
|
||||
/// `os.system`, which *executes* the injected `echo` and prints the
|
||||
/// computed marker `NYX_PWN_791_CMDI` to stdout (corpus v16 — a benign
|
||||
/// `shlex.quote` handler echoes the literal payload and never yields the
|
||||
/// marker), and the differential oracle reads it.
|
||||
#[test]
|
||||
fn kafka_python_vuln_confirms_via_run_spec() {
|
||||
let Some(outcome) = run(Lang::Python, "kafka_python", "vuln.py", "handler", "orders")
|
||||
|
|
|
|||
|
|
@ -176,7 +176,15 @@ fn assert_callgraph_rewrites_entry(
|
|||
"callgraph walk must classify the entry as HttpRoute; got {:?}",
|
||||
spec.entry_kind
|
||||
);
|
||||
assert_eq!(spec.expected_cap, cap);
|
||||
// Command injection's static sink cap `SHELL_ESCAPE` is remapped at spec
|
||||
// derivation to the driveable `CODE_EXEC` (the cap the dynamic corpus keys
|
||||
// its cmdi oracle under); every other cap passes through unchanged.
|
||||
let expected_drivable = if cap == Cap::SHELL_ESCAPE {
|
||||
Cap::CODE_EXEC
|
||||
} else {
|
||||
cap
|
||||
};
|
||||
assert_eq!(spec.expected_cap, expected_drivable);
|
||||
let _ = analysis; // accepted but not asserted on here.
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -110,7 +110,9 @@ mod spec_strategies {
|
|||
let spec = HarnessSpec::from_finding(&diag).expect("flow_steps strategy must succeed");
|
||||
assert_eq!(spec.derivation, SpecDerivationStrategy::FromFlowSteps);
|
||||
assert_eq!(spec.entry_name, "handle_request");
|
||||
assert_eq!(spec.expected_cap, Cap::SHELL_ESCAPE);
|
||||
// cmdi sink cap `SHELL_ESCAPE` remaps to the driveable `CODE_EXEC` (the
|
||||
// cap the dynamic corpus keys its command-injection oracle under).
|
||||
assert_eq!(spec.expected_cap, Cap::CODE_EXEC);
|
||||
}
|
||||
|
||||
// ── Strategy 2: FromRuleNamespace ────────────────────────────────────────
|
||||
|
|
@ -129,7 +131,8 @@ mod spec_strategies {
|
|||
|
||||
let spec = HarnessSpec::from_finding(&diag).expect("rule-namespace strategy must succeed");
|
||||
assert_eq!(spec.derivation, SpecDerivationStrategy::FromRuleNamespace);
|
||||
assert_eq!(spec.expected_cap, Cap::SHELL_ESCAPE);
|
||||
// cmdi sink cap `SHELL_ESCAPE` remaps to the driveable `CODE_EXEC`.
|
||||
assert_eq!(spec.expected_cap, Cap::CODE_EXEC);
|
||||
assert_eq!(spec.toolchain_id, "python-3");
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue