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
11
tests/dynamic_fixtures/php/cli_script/benign.php
Normal file
11
tests/dynamic_fixtures/php/cli_script/benign.php
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
// Phase 15 — CLI script with $argv, benign.
|
||||
// Validates $argv[1] then runs a fixed echo.
|
||||
|
||||
$payload = $argv[1] ?? '';
|
||||
if (!preg_match('/^[A-Za-z0-9]{1,32}$/', $payload)) {
|
||||
echo "invalid\n";
|
||||
exit(0);
|
||||
}
|
||||
$out = shell_exec("echo hello");
|
||||
echo $out;
|
||||
6
tests/dynamic_fixtures/php/cli_script/composer.json
Normal file
6
tests/dynamic_fixtures/php/cli_script/composer.json
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"name": "nyx/cli-script-fixture",
|
||||
"require": {
|
||||
"php": ">=8.0"
|
||||
}
|
||||
}
|
||||
9
tests/dynamic_fixtures/php/cli_script/vuln.php
Normal file
9
tests/dynamic_fixtures/php/cli_script/vuln.php
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
// Phase 15 — CLI script with $argv, vulnerable.
|
||||
// Top-level body reads $argv[1] and pipes to /bin/sh -c.
|
||||
|
||||
echo "__NYX_SINK_HIT__\n";
|
||||
|
||||
$payload = $argv[1] ?? '';
|
||||
$out = shell_exec("echo hello " . $payload);
|
||||
echo $out;
|
||||
12
tests/dynamic_fixtures/php/cmdi_adversarial.php
Normal file
12
tests/dynamic_fixtures/php/cmdi_adversarial.php
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
// Command injection — adversarial collision fixture.
|
||||
// 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_791_CMDI\n";
|
||||
$x = strlen($host);
|
||||
}
|
||||
22
tests/dynamic_fixtures/php/cmdi_negative.php
Normal file
22
tests/dynamic_fixtures/php/cmdi_negative.php
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
// Command injection — negative fixture.
|
||||
// Safe: uses escapeshellarg() and discards the captured output.
|
||||
// Entry: runPing($host) Cap: CODE_EXEC
|
||||
// Expected verdict: NotConfirmed
|
||||
//
|
||||
// Pairs with cmdi_positive.php for differential confirmation. The
|
||||
// captured output is intentionally discarded so a literal payload such
|
||||
// as "; echo NYX_PWN_CMDI" (which escapeshellarg already neutralises
|
||||
// against the shell parser) cannot leak through stdout and trip the
|
||||
// OutputContains oracle.
|
||||
|
||||
function runPing($host) {
|
||||
// Sink-reachability probe: we did reach the shell_exec call site.
|
||||
echo "__NYX_SINK_HIT__\n";
|
||||
// escapeshellarg wraps in single quotes and escapes internal quotes.
|
||||
$safe = escapeshellarg($host);
|
||||
// Capture but discard: command runs under the sanitiser, output is
|
||||
// not surfaced to the oracle.
|
||||
$output = shell_exec('echo hello ' . $safe);
|
||||
unset($output);
|
||||
}
|
||||
13
tests/dynamic_fixtures/php/cmdi_positive.php
Normal file
13
tests/dynamic_fixtures/php/cmdi_positive.php
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
// Command injection — positive fixture.
|
||||
// Vulnerable: passes user input directly to shell_exec.
|
||||
// Entry: runPing($host) Cap: CODE_EXEC
|
||||
// Expected verdict: Confirmed ("; echo NYX_PWN_CMDI" echoes the marker)
|
||||
|
||||
function runPing($host) {
|
||||
echo "__NYX_SINK_HIT__\n";
|
||||
$output = shell_exec('echo hello ' . $host);
|
||||
if ($output !== null) {
|
||||
echo $output;
|
||||
}
|
||||
}
|
||||
10
tests/dynamic_fixtures/php/cmdi_unsupported.php
Normal file
10
tests/dynamic_fixtures/php/cmdi_unsupported.php
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
// Command injection — unsupported fixture.
|
||||
// Entry is a class method; test sets confidence = Low.
|
||||
// Expected verdict: Unsupported
|
||||
|
||||
class Runner {
|
||||
public function execute($cmd) {
|
||||
shell_exec($cmd);
|
||||
}
|
||||
}
|
||||
12
tests/dynamic_fixtures/php/fileio_adversarial.php
Normal file
12
tests/dynamic_fixtures/php/fileio_adversarial.php
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
// File I/O — adversarial collision fixture.
|
||||
// Prints "root:" unconditionally without reading any file
|
||||
// and without emitting __NYX_SINK_HIT__.
|
||||
// Expected verdict: Inconclusive(OracleCollisionSuspected)
|
||||
// Entry: runReadFile($userPath) Cap: FILE_IO
|
||||
|
||||
function runReadFile($userPath) {
|
||||
// Coincidental oracle match — not a file read sink.
|
||||
echo "root: present\n";
|
||||
$x = strlen($userPath);
|
||||
}
|
||||
20
tests/dynamic_fixtures/php/fileio_negative.php
Normal file
20
tests/dynamic_fixtures/php/fileio_negative.php
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
// File I/O — negative fixture.
|
||||
// Safe: realpath + prefix validation prevents directory traversal.
|
||||
// Entry: runReadFile($userPath) Cap: FILE_IO
|
||||
// Expected verdict: NotConfirmed
|
||||
|
||||
function runReadFile($userPath) {
|
||||
$baseDir = '/var/data';
|
||||
$filePath = realpath($baseDir . '/' . $userPath);
|
||||
if ($filePath === false || strpos($filePath, $baseDir . DIRECTORY_SEPARATOR) !== 0) {
|
||||
echo "Access denied\n";
|
||||
return;
|
||||
}
|
||||
$content = @file_get_contents($filePath);
|
||||
if ($content !== false) {
|
||||
echo substr($content, 0, 100);
|
||||
} else {
|
||||
echo "File not found\n";
|
||||
}
|
||||
}
|
||||
14
tests/dynamic_fixtures/php/fileio_positive.php
Normal file
14
tests/dynamic_fixtures/php/fileio_positive.php
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
// File I/O — positive fixture.
|
||||
// Vulnerable: reads file at user-controlled path without sanitization.
|
||||
// Entry: runReadFile($userPath) Cap: FILE_IO
|
||||
// Expected verdict: Confirmed (../../../../etc/passwd → "root:" in output)
|
||||
|
||||
function runReadFile($userPath) {
|
||||
$filePath = '/var/data/' . $userPath;
|
||||
echo "__NYX_SINK_HIT__\n";
|
||||
$content = @file_get_contents($filePath);
|
||||
if ($content !== false) {
|
||||
echo $content;
|
||||
}
|
||||
}
|
||||
13
tests/dynamic_fixtures/php/fileio_unsupported.php
Normal file
13
tests/dynamic_fixtures/php/fileio_unsupported.php
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
// File I/O — unsupported fixture.
|
||||
// Entry is a class method; test sets confidence = Low.
|
||||
// Expected verdict: Unsupported
|
||||
|
||||
class FileServer {
|
||||
public function serve($path) {
|
||||
$content = @file_get_contents($path);
|
||||
if ($content !== false) {
|
||||
echo $content;
|
||||
}
|
||||
}
|
||||
}
|
||||
17
tests/dynamic_fixtures/php/route_closure/benign.php
Normal file
17
tests/dynamic_fixtures/php/route_closure/benign.php
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
// Phase 15 — Slim/Laravel-style route closure, benign.
|
||||
// Validates payload before invoking sink.
|
||||
|
||||
$GLOBALS['__nyx_route'] = function ($payload) {
|
||||
if (!preg_match('/^[A-Za-z0-9]{1,32}$/', (string)$payload)) {
|
||||
echo "invalid\n";
|
||||
return "invalid";
|
||||
}
|
||||
$out = shell_exec("echo hello");
|
||||
echo $out;
|
||||
return $out;
|
||||
};
|
||||
|
||||
if (false) {
|
||||
$app->get('/run', $GLOBALS['__nyx_route']);
|
||||
}
|
||||
6
tests/dynamic_fixtures/php/route_closure/composer.json
Normal file
6
tests/dynamic_fixtures/php/route_closure/composer.json
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"name": "nyx/route-closure-fixture",
|
||||
"require": {
|
||||
"php": ">=8.0"
|
||||
}
|
||||
}
|
||||
17
tests/dynamic_fixtures/php/route_closure/vuln.php
Normal file
17
tests/dynamic_fixtures/php/route_closure/vuln.php
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
// Phase 15 — Slim/Laravel-style route closure, vulnerable.
|
||||
// Reads payload and pipes to /bin/sh -c.
|
||||
// Entry: route closure Cap: CODE_EXEC
|
||||
|
||||
echo "__NYX_SINK_HIT__\n";
|
||||
|
||||
$GLOBALS['__nyx_route'] = function ($payload) {
|
||||
$out = shell_exec("echo hello " . $payload);
|
||||
echo $out;
|
||||
return $out;
|
||||
};
|
||||
|
||||
// Slim-shape marker so PhpShape::detect picks RouteClosure.
|
||||
if (false) {
|
||||
$app->get('/run', $GLOBALS['__nyx_route']);
|
||||
}
|
||||
12
tests/dynamic_fixtures/php/sqli_adversarial.php
Normal file
12
tests/dynamic_fixtures/php/sqli_adversarial.php
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
// SQL injection — adversarial collision fixture.
|
||||
// Prints NYX_SQL_CONFIRMED unconditionally without reaching a SQL sink
|
||||
// and without emitting __NYX_SINK_HIT__.
|
||||
// Expected verdict: Inconclusive(OracleCollisionSuspected)
|
||||
// Entry: login($username) Cap: SQL_QUERY
|
||||
|
||||
function login($username) {
|
||||
// Coincidental oracle match — not a SQL sink.
|
||||
echo "NYX_SQL_CONFIRMED\n";
|
||||
$x = strlen($username);
|
||||
}
|
||||
11
tests/dynamic_fixtures/php/sqli_negative.php
Normal file
11
tests/dynamic_fixtures/php/sqli_negative.php
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
// SQL injection — negative fixture.
|
||||
// Safe: uses PDO prepared statement; payload is a bound param, not concatenated.
|
||||
// Entry: login($username) Cap: SQL_QUERY
|
||||
// Expected verdict: NotConfirmed
|
||||
|
||||
function login($username) {
|
||||
$template = "SELECT name FROM users WHERE name = ?";
|
||||
// Simulate parameterized execution: template is fixed.
|
||||
echo "Executing: " . $template . " param-len=" . strlen($username) . "\n";
|
||||
}
|
||||
12
tests/dynamic_fixtures/php/sqli_positive.php
Normal file
12
tests/dynamic_fixtures/php/sqli_positive.php
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
// SQL injection — positive fixture.
|
||||
// Vulnerable: directly concatenates user input into SQL query string.
|
||||
// Entry: login($username) Cap: SQL_QUERY
|
||||
// Expected verdict: Confirmed (UNION payload echoes NYX_SQL_CONFIRMED)
|
||||
|
||||
function login($username) {
|
||||
$query = "SELECT name FROM users WHERE name='" . $username . "'";
|
||||
echo "__NYX_SINK_HIT__\n";
|
||||
// Error-based echo: output the query so UNION payload is visible.
|
||||
echo "DB query: " . $query . "\n";
|
||||
}
|
||||
12
tests/dynamic_fixtures/php/sqli_unsupported.php
Normal file
12
tests/dynamic_fixtures/php/sqli_unsupported.php
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
// SQL injection — unsupported fixture.
|
||||
// Entry is a class method — entry kind unsupported.
|
||||
// Test sets confidence = Low to get Unsupported(ConfidenceTooLow).
|
||||
// Expected verdict: Unsupported
|
||||
|
||||
class UserRepository {
|
||||
public function findUser($name) {
|
||||
$query = "SELECT * FROM users WHERE name='" . $name . "'";
|
||||
echo $query . "\n";
|
||||
}
|
||||
}
|
||||
12
tests/dynamic_fixtures/php/ssrf_adversarial.php
Normal file
12
tests/dynamic_fixtures/php/ssrf_adversarial.php
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
// SSRF — adversarial collision fixture.
|
||||
// Prints "daemon:" unconditionally without making any HTTP request
|
||||
// and without emitting __NYX_SINK_HIT__.
|
||||
// Expected verdict: Inconclusive(OracleCollisionSuspected)
|
||||
// Entry: fetchUrl($url) Cap: SSRF
|
||||
|
||||
function fetchUrl($url) {
|
||||
// Coincidental oracle match — not an HTTP sink.
|
||||
echo "daemon: present\n";
|
||||
$x = strlen($url);
|
||||
}
|
||||
18
tests/dynamic_fixtures/php/ssrf_negative.php
Normal file
18
tests/dynamic_fixtures/php/ssrf_negative.php
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
// SSRF — negative fixture.
|
||||
// Safe: only allows http/https scheme; file:// and others rejected.
|
||||
// Entry: fetchUrl($url) Cap: SSRF
|
||||
// Expected verdict: NotConfirmed
|
||||
|
||||
function fetchUrl($url) {
|
||||
$parsed = parse_url($url);
|
||||
$scheme = $parsed['scheme'] ?? '';
|
||||
if ($scheme !== 'http' && $scheme !== 'https') {
|
||||
echo "Scheme not allowed: " . $scheme . "\n";
|
||||
return;
|
||||
}
|
||||
$content = @file_get_contents($url);
|
||||
if ($content !== false) {
|
||||
echo substr($content, 0, 64);
|
||||
}
|
||||
}
|
||||
14
tests/dynamic_fixtures/php/ssrf_positive.php
Normal file
14
tests/dynamic_fixtures/php/ssrf_positive.php
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
// SSRF — positive fixture.
|
||||
// Vulnerable: fetches a user-controlled URL via file_get_contents.
|
||||
// PHP's file_get_contents supports file:// scheme natively.
|
||||
// Entry: fetchUrl($url) Cap: SSRF
|
||||
// Expected verdict: Confirmed (file:///etc/passwd → "daemon:" in output)
|
||||
|
||||
function fetchUrl($url) {
|
||||
echo "__NYX_SINK_HIT__\n";
|
||||
$content = @file_get_contents($url);
|
||||
if ($content !== false) {
|
||||
echo $content;
|
||||
}
|
||||
}
|
||||
13
tests/dynamic_fixtures/php/ssrf_unsupported.php
Normal file
13
tests/dynamic_fixtures/php/ssrf_unsupported.php
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
// SSRF — unsupported fixture.
|
||||
// Entry is a class method; test sets confidence = Low.
|
||||
// Expected verdict: Unsupported
|
||||
|
||||
class HttpClient {
|
||||
public function fetch($url) {
|
||||
$content = @file_get_contents($url);
|
||||
if ($content !== false) {
|
||||
echo $content;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
tests/dynamic_fixtures/php/top_level_script/benign.php
Normal file
11
tests/dynamic_fixtures/php/top_level_script/benign.php
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
// Phase 15 — top-level script (no function entry), benign.
|
||||
// Validates payload before invoking sink.
|
||||
|
||||
$payload = getenv('NYX_PAYLOAD') ?: '';
|
||||
if (!preg_match('/^[A-Za-z0-9]{1,32}$/', $payload)) {
|
||||
echo "invalid\n";
|
||||
exit(0);
|
||||
}
|
||||
$out = shell_exec("echo hello");
|
||||
echo $out;
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"name": "nyx/top-level-script-fixture",
|
||||
"require": {
|
||||
"php": ">=8.0"
|
||||
}
|
||||
}
|
||||
9
tests/dynamic_fixtures/php/top_level_script/vuln.php
Normal file
9
tests/dynamic_fixtures/php/top_level_script/vuln.php
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
// Phase 15 — top-level script (no function entry), vulnerable.
|
||||
// Body reads NYX_PAYLOAD env var directly and pipes to /bin/sh -c.
|
||||
|
||||
echo "__NYX_SINK_HIT__\n";
|
||||
|
||||
$payload = getenv('NYX_PAYLOAD') ?: '';
|
||||
$out = shell_exec("echo hello " . $payload);
|
||||
echo $out;
|
||||
12
tests/dynamic_fixtures/php/xss_adversarial.php
Normal file
12
tests/dynamic_fixtures/php/xss_adversarial.php
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
// XSS — adversarial collision fixture.
|
||||
// Prints the XSS oracle marker unconditionally without rendering any template
|
||||
// and without emitting __NYX_SINK_HIT__.
|
||||
// Expected verdict: Inconclusive(OracleCollisionSuspected)
|
||||
// Entry: renderPage($userInput) Cap: HTML_ESCAPE
|
||||
|
||||
function renderPage($userInput) {
|
||||
// Coincidental oracle match — not an HTML render sink.
|
||||
echo "<script>NYX_XSS_CONFIRMED</script>\n";
|
||||
$x = strlen($userInput);
|
||||
}
|
||||
10
tests/dynamic_fixtures/php/xss_negative.php
Normal file
10
tests/dynamic_fixtures/php/xss_negative.php
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
// XSS — negative fixture.
|
||||
// Safe: uses htmlspecialchars() before output.
|
||||
// Entry: renderPage($userInput) Cap: HTML_ESCAPE
|
||||
// Expected verdict: NotConfirmed
|
||||
|
||||
function renderPage($userInput) {
|
||||
$safe = htmlspecialchars($userInput, ENT_QUOTES, 'UTF-8');
|
||||
echo '<html><body>' . $safe . '</body></html>' . "\n";
|
||||
}
|
||||
10
tests/dynamic_fixtures/php/xss_positive.php
Normal file
10
tests/dynamic_fixtures/php/xss_positive.php
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
// XSS — positive fixture.
|
||||
// Vulnerable: echoes raw user input into HTML output without escaping.
|
||||
// Entry: renderPage($userInput) Cap: HTML_ESCAPE
|
||||
// Expected verdict: Confirmed (<script>NYX_XSS_CONFIRMED</script> echoed)
|
||||
|
||||
function renderPage($userInput) {
|
||||
echo "__NYX_SINK_HIT__\n";
|
||||
echo '<html><body>' . $userInput . '</body></html>' . "\n";
|
||||
}
|
||||
10
tests/dynamic_fixtures/php/xss_unsupported.php
Normal file
10
tests/dynamic_fixtures/php/xss_unsupported.php
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
// XSS — unsupported fixture.
|
||||
// Entry is a class method; test sets confidence = Low.
|
||||
// Expected verdict: Unsupported
|
||||
|
||||
class TemplateEngine {
|
||||
public function render($input) {
|
||||
echo '<html><body>' . $input . '</body></html>' . "\n";
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue