mirror of
https://github.com/elicpeter/nyx.git
synced 2026-06-09 19:45:13 +02:00
Dynamic (#77)
This commit is contained in:
parent
55247b7fcd
commit
991c84a1eb
1464 changed files with 225448 additions and 1985 deletions
13
tests/dynamic_fixtures/java/cmdi_adversarial.java
Normal file
13
tests/dynamic_fixtures/java/cmdi_adversarial.java
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// 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: Entry.runPing(String) Cap: CODE_EXEC
|
||||
|
||||
public class Entry {
|
||||
public static void runPing(String host) {
|
||||
// Coincidental oracle match — not a shell sink.
|
||||
System.out.println("NYX_PWN_791_CMDI");
|
||||
int x = host.length();
|
||||
}
|
||||
}
|
||||
27
tests/dynamic_fixtures/java/cmdi_negative.java
Normal file
27
tests/dynamic_fixtures/java/cmdi_negative.java
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
// Command injection — negative fixture.
|
||||
// Safe: exec with args array; no shell; injected metacharacters are inert.
|
||||
// Entry: Entry.runPing(String) Cap: CODE_EXEC
|
||||
// Expected verdict: NotConfirmed
|
||||
//
|
||||
// `id` ignores extra positional args (treats them as usernames it can't find
|
||||
// and writes the "no such user" error to stderr, not stdout). Switching from
|
||||
// `echo` keeps the array-exec demonstration intact while ensuring the
|
||||
// vuln-payload marker can never leak into the stdout stream the oracle reads.
|
||||
|
||||
import java.io.*;
|
||||
|
||||
public class Entry {
|
||||
public static void runPing(String host) throws Exception {
|
||||
// Sink-reachability probe: we did reach the exec call site.
|
||||
System.out.print("__NYX_SINK_HIT__\n");
|
||||
// Array form: each element is a literal argument — no shell expansion.
|
||||
String[] cmd = {"id", host};
|
||||
Process p = Runtime.getRuntime().exec(cmd);
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
System.out.println(line);
|
||||
}
|
||||
p.waitFor();
|
||||
}
|
||||
}
|
||||
20
tests/dynamic_fixtures/java/cmdi_positive.java
Normal file
20
tests/dynamic_fixtures/java/cmdi_positive.java
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
// Command injection — positive fixture.
|
||||
// Vulnerable: passes user input to /bin/sh -c via Runtime.exec.
|
||||
// Entry: Entry.runPing(String) Cap: CODE_EXEC
|
||||
// Expected verdict: Confirmed ("; echo NYX_PWN_CMDI" echoes the marker)
|
||||
|
||||
import java.io.*;
|
||||
|
||||
public class Entry {
|
||||
public static void runPing(String host) throws Exception {
|
||||
System.out.print("__NYX_SINK_HIT__\n");
|
||||
String[] cmd = {"/bin/sh", "-c", "echo hello " + host};
|
||||
Process p = Runtime.getRuntime().exec(cmd);
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
System.out.println(line);
|
||||
}
|
||||
p.waitFor();
|
||||
}
|
||||
}
|
||||
11
tests/dynamic_fixtures/java/cmdi_unsupported.java
Normal file
11
tests/dynamic_fixtures/java/cmdi_unsupported.java
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
// Command injection — unsupported fixture.
|
||||
// Entry is an instance method; test sets confidence = Low.
|
||||
// Expected verdict: Unsupported
|
||||
|
||||
import java.io.*;
|
||||
|
||||
public class Entry {
|
||||
public void execute(String cmd) throws Exception {
|
||||
Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", cmd});
|
||||
}
|
||||
}
|
||||
16
tests/dynamic_fixtures/java/fileio_adversarial.java
Normal file
16
tests/dynamic_fixtures/java/fileio_adversarial.java
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
// File I/O — adversarial collision fixture.
|
||||
// Prints the path-traversal canary marker unconditionally without reading any
|
||||
// file and without emitting __NYX_SINK_HIT__, so the oracle observes a marker
|
||||
// hit with no sink-reachability.
|
||||
// Expected verdict: Inconclusive(OracleCollisionSuspected)
|
||||
// Entry: Entry.readFile(String) Cap: FILE_IO
|
||||
|
||||
public class Entry {
|
||||
public static void readFile(String userPath) {
|
||||
// Coincidental oracle match — emits the marker string but is not a
|
||||
// file-read sink and never reaches the planted canary. Must match the
|
||||
// CANARY_MARKER in src/dynamic/corpus/path_trav/java.rs.
|
||||
System.out.println("NYX_PATHTRAVERSAL_R34D_a7f3c1d8 present");
|
||||
int x = userPath.length();
|
||||
}
|
||||
}
|
||||
28
tests/dynamic_fixtures/java/fileio_negative.java
Normal file
28
tests/dynamic_fixtures/java/fileio_negative.java
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
// File I/O — negative fixture.
|
||||
// Safe: normalizes the path and checks it stays within the base directory, so
|
||||
// the traversal payload cannot escape `testfiles/` to reach the planted canary.
|
||||
// Entry: Entry.readFile(String) Cap: FILE_IO
|
||||
// Expected verdict: NotConfirmed
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.*;
|
||||
|
||||
public class Entry {
|
||||
public static void readFile(String userPath) throws Exception {
|
||||
// Same base the harness plants the canary one level above; the
|
||||
// containment check is what makes this safe.
|
||||
Path base = Paths.get(System.getProperty("user.dir"), "testfiles").toRealPath();
|
||||
Path resolved = base.resolve(userPath).normalize();
|
||||
if (!resolved.startsWith(base)) {
|
||||
System.out.println("Access denied");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
byte[] data = Files.readAllBytes(resolved);
|
||||
int len = Math.min(data.length, 100);
|
||||
System.out.write(data, 0, len);
|
||||
} catch (IOException e) {
|
||||
System.out.println("File not found");
|
||||
}
|
||||
}
|
||||
}
|
||||
29
tests/dynamic_fixtures/java/fileio_positive.java
Normal file
29
tests/dynamic_fixtures/java/fileio_positive.java
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
// File I/O — positive fixture.
|
||||
// Vulnerable: reads file at user-controlled path without sanitization.
|
||||
// Entry: Entry.readFile(String) Cap: FILE_IO
|
||||
// Expected verdict: Confirmed.
|
||||
//
|
||||
// The harness plants a canary file (`nyx_pt_canary`, whose CONTENT is the
|
||||
// collision-resistant marker) at the workdir root and an empty `testfiles/`
|
||||
// directory beside it. Reading `testfiles/ + userPath` without normalising is
|
||||
// the traversal sink: the vuln payload `../nyx_pt_canary` escapes `testfiles/`
|
||||
// back to the planted canary, so its marker content reaches stdout.
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.*;
|
||||
|
||||
public class Entry {
|
||||
public static void readFile(String userPath) throws Exception {
|
||||
// Base directory the harness plants the canary one level above.
|
||||
Path testfileDir = Paths.get(System.getProperty("user.dir"), "testfiles");
|
||||
// Vulnerable: no normalisation / containment check on `userPath`.
|
||||
Path filePath = testfileDir.resolve(userPath);
|
||||
System.out.print("__NYX_SINK_HIT__\n");
|
||||
try {
|
||||
String content = new String(Files.readAllBytes(filePath));
|
||||
System.out.print(content);
|
||||
} catch (IOException e) {
|
||||
// silent
|
||||
}
|
||||
}
|
||||
}
|
||||
13
tests/dynamic_fixtures/java/fileio_unsupported.java
Normal file
13
tests/dynamic_fixtures/java/fileio_unsupported.java
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// File I/O — unsupported fixture.
|
||||
// Entry is an instance method; test sets confidence = Low.
|
||||
// Expected verdict: Unsupported
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.*;
|
||||
|
||||
public class Entry {
|
||||
public void serve(String path) throws Exception {
|
||||
byte[] data = Files.readAllBytes(Paths.get(path));
|
||||
System.out.write(data);
|
||||
}
|
||||
}
|
||||
24
tests/dynamic_fixtures/java/junit_test/Benign.java
Normal file
24
tests/dynamic_fixtures/java/junit_test/Benign.java
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
// Phase 14 — JUnit test method, benign.
|
||||
|
||||
// import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
public class Benign {
|
||||
@Test
|
||||
public void testRun() throws Exception {
|
||||
System.out.print("__NYX_SINK_HIT__\n");
|
||||
// Read + drop payload.
|
||||
String unused = System.getenv("NYX_PAYLOAD");
|
||||
if (unused == null) unused = "";
|
||||
String[] cmd = {"/bin/sh", "-c", "echo hello"};
|
||||
Process p = Runtime.getRuntime().exec(cmd);
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
System.out.println(line);
|
||||
}
|
||||
p.waitFor();
|
||||
}
|
||||
}
|
||||
15
tests/dynamic_fixtures/java/junit_test/Test.java
Normal file
15
tests/dynamic_fixtures/java/junit_test/Test.java
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
// Phase 14 fixture stub — minimal `@Test` annotation in the default
|
||||
// package. Lives here so the fixture's `@Test`-annotated method
|
||||
// compiles under plain javac without a junit-jupiter Maven dep. The
|
||||
// fixture's comment carries a literal `org.junit` marker so the
|
||||
// Phase 14 [`JavaShape::detect`] still selects the JUnit shape.
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface Test {
|
||||
}
|
||||
28
tests/dynamic_fixtures/java/junit_test/Vuln.java
Normal file
28
tests/dynamic_fixtures/java/junit_test/Vuln.java
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
// Phase 14 — JUnit test method, vulnerable.
|
||||
//
|
||||
// The `org.junit.jupiter.api` comment marker tells the Phase 14 shape
|
||||
// detector to select `JavaShape::JunitTest`; the actual annotation is
|
||||
// the fixture-local `@NyxTest` stub so the file compiles under a
|
||||
// dependency-free javac invocation.
|
||||
|
||||
// import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
public class Vuln {
|
||||
@Test
|
||||
public void testRun() throws Exception {
|
||||
System.out.print("__NYX_SINK_HIT__\n");
|
||||
String input = System.getenv("NYX_PAYLOAD");
|
||||
if (input == null) input = "";
|
||||
String[] cmd = {"/bin/sh", "-c", "echo hello " + input};
|
||||
Process p = Runtime.getRuntime().exec(cmd);
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
System.out.println(line);
|
||||
}
|
||||
p.waitFor();
|
||||
}
|
||||
}
|
||||
19
tests/dynamic_fixtures/java/junit_test/pom.xml
Normal file
19
tests/dynamic_fixtures/java/junit_test/pom.xml
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>nyx</groupId>
|
||||
<artifactId>junit-test-fixture</artifactId>
|
||||
<version>0.0.1</version>
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<version>5.10.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
30
tests/dynamic_fixtures/java/micronaut_route/Benign.java
Normal file
30
tests/dynamic_fixtures/java/micronaut_route/Benign.java
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
// Micronaut `@Controller`, benign.
|
||||
//
|
||||
// Same shape as the vuln but echoes a constant string instead of
|
||||
// concatenating the path variable into a shell command.
|
||||
|
||||
import io.micronaut.http.annotation.Controller;
|
||||
import io.micronaut.http.annotation.Get;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
@Controller("/run")
|
||||
public class Benign {
|
||||
@Get("/{id}")
|
||||
public String show(String id) throws Exception {
|
||||
System.out.print("__NYX_SINK_HIT__\n");
|
||||
String[] cmd = {"/bin/sh", "-c", "echo hello"};
|
||||
Process p = Runtime.getRuntime().exec(cmd);
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
|
||||
StringBuilder out = new StringBuilder();
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
out.append(line);
|
||||
out.append('\n');
|
||||
System.out.println(line);
|
||||
}
|
||||
p.waitFor();
|
||||
return out.toString();
|
||||
}
|
||||
}
|
||||
33
tests/dynamic_fixtures/java/micronaut_route/Vuln.java
Normal file
33
tests/dynamic_fixtures/java/micronaut_route/Vuln.java
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
// Micronaut `@Controller`, vulnerable.
|
||||
//
|
||||
// `@Controller("/run")` on the class + `@Get("/{id}")` on the handler
|
||||
// matches `JavaShape::MicronautRoute`. The harness keeps the real
|
||||
// Micronaut annotations on the classpath and replays the route through
|
||||
// those annotations.
|
||||
|
||||
import io.micronaut.http.annotation.Controller;
|
||||
import io.micronaut.http.annotation.Get;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
@Controller("/run")
|
||||
public class Vuln {
|
||||
@Get("/{id}")
|
||||
public String show(String id) throws Exception {
|
||||
System.out.print("__NYX_SINK_HIT__\n");
|
||||
if (id == null) id = "";
|
||||
String[] cmd = {"/bin/sh", "-c", "echo hello " + id};
|
||||
Process p = Runtime.getRuntime().exec(cmd);
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
|
||||
StringBuilder out = new StringBuilder();
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
out.append(line);
|
||||
out.append('\n');
|
||||
System.out.println(line);
|
||||
}
|
||||
p.waitFor();
|
||||
return out.toString();
|
||||
}
|
||||
}
|
||||
23
tests/dynamic_fixtures/java/micronaut_route/pom.xml
Normal file
23
tests/dynamic_fixtures/java/micronaut_route/pom.xml
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>nyx</groupId>
|
||||
<artifactId>micronaut-route-fixture</artifactId>
|
||||
<version>0.0.1</version>
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.micronaut</groupId>
|
||||
<artifactId>micronaut-http</artifactId>
|
||||
<version>4.4.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.micronaut</groupId>
|
||||
<artifactId>micronaut-core</artifactId>
|
||||
<version>4.4.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
28
tests/dynamic_fixtures/java/quarkus_route/Benign.java
Normal file
28
tests/dynamic_fixtures/java/quarkus_route/Benign.java
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
// Quarkus reactive route, benign.
|
||||
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
@Path("/run")
|
||||
public class Benign {
|
||||
@GET
|
||||
public String run(String payload) throws Exception {
|
||||
System.out.print("__NYX_SINK_HIT__\n");
|
||||
if (payload == null) payload = "";
|
||||
String[] cmd = {"/bin/sh", "-c", "echo hello"};
|
||||
Process p = Runtime.getRuntime().exec(cmd);
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
|
||||
StringBuilder out = new StringBuilder();
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
out.append(line);
|
||||
out.append('\n');
|
||||
System.out.println(line);
|
||||
}
|
||||
p.waitFor();
|
||||
return out.toString();
|
||||
}
|
||||
}
|
||||
31
tests/dynamic_fixtures/java/quarkus_route/Vuln.java
Normal file
31
tests/dynamic_fixtures/java/quarkus_route/Vuln.java
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
// Quarkus reactive route, vulnerable. The harness keeps the real
|
||||
// Jakarta REST annotations on the classpath and replays the route
|
||||
// through those annotations. Quarkus REST routes are authored with the
|
||||
// `jakarta.ws.rs` annotations below, so no live Quarkus runtime is needed.
|
||||
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
@Path("/run")
|
||||
public class Vuln {
|
||||
@GET
|
||||
public String run(String payload) throws Exception {
|
||||
System.out.print("__NYX_SINK_HIT__\n");
|
||||
if (payload == null) payload = "";
|
||||
String[] cmd = {"/bin/sh", "-c", "echo hello " + payload};
|
||||
Process p = Runtime.getRuntime().exec(cmd);
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
|
||||
StringBuilder out = new StringBuilder();
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
out.append(line);
|
||||
out.append('\n');
|
||||
System.out.println(line);
|
||||
}
|
||||
p.waitFor();
|
||||
return out.toString();
|
||||
}
|
||||
}
|
||||
28
tests/dynamic_fixtures/java/quarkus_route/pom.xml
Normal file
28
tests/dynamic_fixtures/java/quarkus_route/pom.xml
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>nyx</groupId>
|
||||
<artifactId>quarkus-route-fixture</artifactId>
|
||||
<version>0.0.1</version>
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<!--
|
||||
The route-replay harness reflects over the Jakarta REST annotations
|
||||
(`@Path`/`@GET`) at runtime; it never touches a live Quarkus server,
|
||||
so `jakarta.ws.rs-api` is the only jar it needs. Pulling the full
|
||||
`quarkus-resteasy-reactive` runtime (Vert.x, Netty, RESTEasy, 200+
|
||||
transitive jars) only bloated `-cp lib/*`, which slowed cold JVM
|
||||
startup past the 5s run timeout on contended CI runners and made
|
||||
this fixture flaky. Quarkus REST routes are written with these very
|
||||
`jakarta.ws.rs` annotations, so the shape stays faithful.
|
||||
-->
|
||||
<dependency>
|
||||
<groupId>jakarta.ws.rs</groupId>
|
||||
<artifactId>jakarta.ws.rs-api</artifactId>
|
||||
<version>3.1.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
24
tests/dynamic_fixtures/java/servlet_doget/Benign.java
Normal file
24
tests/dynamic_fixtures/java/servlet_doget/Benign.java
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
// Phase 14 — servlet doGet, benign.
|
||||
//
|
||||
// Reads `payload` from the request but never threads it into a
|
||||
// shell-interpreted slot; the cmdi marker cannot fire.
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
public class Benign {
|
||||
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws Exception {
|
||||
System.out.print("__NYX_SINK_HIT__\n");
|
||||
// Read + drop the parameter.
|
||||
String unused = req.getParameter("payload");
|
||||
if (unused == null) unused = "";
|
||||
String[] cmd = {"/bin/sh", "-c", "echo hello"};
|
||||
Process p = Runtime.getRuntime().exec(cmd);
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
resp.write(line + "\n");
|
||||
}
|
||||
p.waitFor();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
// Phase 14 fixture stub — minimal servlet request shape.
|
||||
// Lives in the default package so the harness shim's
|
||||
// `p.getName().endsWith("HttpServletRequest")` filter can match without
|
||||
// a Maven dep on `jakarta.servlet-api`.
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class HttpServletRequest {
|
||||
private final Map<String, String> params = new HashMap<>();
|
||||
private String method = "GET";
|
||||
private String body = "";
|
||||
|
||||
public void setParameter(String k, String v) { params.put(k, v); }
|
||||
public String getParameter(String k) { return params.get(k); }
|
||||
public void setMethod(String m) { this.method = m; }
|
||||
public String getMethod() { return method; }
|
||||
public void setBody(String b) { this.body = b; }
|
||||
public String getBody() { return body; }
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
// Phase 14 fixture stub — minimal servlet response shape.
|
||||
public class HttpServletResponse {
|
||||
private final StringBuilder body = new StringBuilder();
|
||||
public void write(String s) { body.append(s); }
|
||||
public String getBody() { return body.toString(); }
|
||||
}
|
||||
24
tests/dynamic_fixtures/java/servlet_doget/Vuln.java
Normal file
24
tests/dynamic_fixtures/java/servlet_doget/Vuln.java
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
// Phase 14 — servlet doGet, vulnerable.
|
||||
//
|
||||
// Reads the `payload` query parameter from the request stub and feeds
|
||||
// it through `/bin/sh -c` — payload `; echo NYX_PWN_CMDI` fires the
|
||||
// cmdi oracle marker.
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
public class Vuln {
|
||||
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws Exception {
|
||||
System.out.print("__NYX_SINK_HIT__\n");
|
||||
String input = req.getParameter("payload");
|
||||
if (input == null) input = "";
|
||||
String[] cmd = {"/bin/sh", "-c", "echo hello " + input};
|
||||
Process p = Runtime.getRuntime().exec(cmd);
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
resp.write(line + "\n");
|
||||
}
|
||||
p.waitFor();
|
||||
}
|
||||
}
|
||||
19
tests/dynamic_fixtures/java/servlet_doget/pom.xml
Normal file
19
tests/dynamic_fixtures/java/servlet_doget/pom.xml
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>nyx</groupId>
|
||||
<artifactId>servlet-doget-fixture</artifactId>
|
||||
<version>0.0.1</version>
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>jakarta.servlet</groupId>
|
||||
<artifactId>jakarta.servlet-api</artifactId>
|
||||
<version>6.0.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
20
tests/dynamic_fixtures/java/servlet_dopost/Benign.java
Normal file
20
tests/dynamic_fixtures/java/servlet_dopost/Benign.java
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
// Phase 14 — servlet doPost, benign.
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
public class Benign {
|
||||
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws Exception {
|
||||
System.out.print("__NYX_SINK_HIT__\n");
|
||||
String unused = req.getBody();
|
||||
if (unused == null) unused = "";
|
||||
String[] cmd = {"/bin/sh", "-c", "echo hello"};
|
||||
Process p = Runtime.getRuntime().exec(cmd);
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
resp.write(line + "\n");
|
||||
}
|
||||
p.waitFor();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
// Phase 14 fixture stub — minimal servlet request shape.
|
||||
// Lives in the default package so the harness shim's
|
||||
// `p.getName().endsWith("HttpServletRequest")` filter can match without
|
||||
// a Maven dep on `jakarta.servlet-api`.
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class HttpServletRequest {
|
||||
private final Map<String, String> params = new HashMap<>();
|
||||
private String method = "GET";
|
||||
private String body = "";
|
||||
|
||||
public void setParameter(String k, String v) { params.put(k, v); }
|
||||
public String getParameter(String k) { return params.get(k); }
|
||||
public void setMethod(String m) { this.method = m; }
|
||||
public String getMethod() { return method; }
|
||||
public void setBody(String b) { this.body = b; }
|
||||
public String getBody() { return body; }
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
// Phase 14 fixture stub — minimal servlet response shape.
|
||||
public class HttpServletResponse {
|
||||
private final StringBuilder body = new StringBuilder();
|
||||
public void write(String s) { body.append(s); }
|
||||
public String getBody() { return body.toString(); }
|
||||
}
|
||||
23
tests/dynamic_fixtures/java/servlet_dopost/Vuln.java
Normal file
23
tests/dynamic_fixtures/java/servlet_dopost/Vuln.java
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
// Phase 14 — servlet doPost, vulnerable.
|
||||
//
|
||||
// Reads the POST body from the request stub and feeds it through
|
||||
// `/bin/sh -c`.
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
public class Vuln {
|
||||
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws Exception {
|
||||
System.out.print("__NYX_SINK_HIT__\n");
|
||||
String input = req.getBody();
|
||||
if (input == null) input = "";
|
||||
String[] cmd = {"/bin/sh", "-c", "echo hello " + input};
|
||||
Process p = Runtime.getRuntime().exec(cmd);
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
resp.write(line + "\n");
|
||||
}
|
||||
p.waitFor();
|
||||
}
|
||||
}
|
||||
19
tests/dynamic_fixtures/java/servlet_dopost/pom.xml
Normal file
19
tests/dynamic_fixtures/java/servlet_dopost/pom.xml
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>nyx</groupId>
|
||||
<artifactId>servlet-dopost-fixture</artifactId>
|
||||
<version>0.0.1</version>
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>jakarta.servlet</groupId>
|
||||
<artifactId>jakarta.servlet-api</artifactId>
|
||||
<version>6.0.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
26
tests/dynamic_fixtures/java/spring_controller/Benign.java
Normal file
26
tests/dynamic_fixtures/java/spring_controller/Benign.java
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
// Spring `@RestController`, benign.
|
||||
//
|
||||
// Same shape as the vuln but the controller runs a fixed echo and
|
||||
// drops `payload`.
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/run")
|
||||
public class Benign {
|
||||
@Autowired
|
||||
private CommandRunner runner;
|
||||
|
||||
@GetMapping
|
||||
public String run(@RequestParam("payload") String payload) throws Exception {
|
||||
System.out.print("__NYX_SINK_HIT__\n");
|
||||
CommandRunner r = (runner != null) ? runner : new CommandRunner();
|
||||
String out = r.run("echo hello");
|
||||
System.out.print(out);
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
// Spring-injected helper service used by the controller fixtures.
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
public class CommandRunner {
|
||||
public String run(String cmd) throws Exception {
|
||||
Process p = Runtime.getRuntime().exec(new String[] {"/bin/sh", "-c", cmd});
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
|
||||
StringBuilder out = new StringBuilder();
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
out.append(line);
|
||||
out.append('\n');
|
||||
}
|
||||
p.waitFor();
|
||||
return out.toString();
|
||||
}
|
||||
}
|
||||
23
tests/dynamic_fixtures/java/spring_controller/Vuln.java
Normal file
23
tests/dynamic_fixtures/java/spring_controller/Vuln.java
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
// Spring `@RestController`, vulnerable.
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/run")
|
||||
public class Vuln {
|
||||
@Autowired
|
||||
private CommandRunner runner;
|
||||
|
||||
@GetMapping
|
||||
public String run(@RequestParam("payload") String payload) throws Exception {
|
||||
System.out.print("__NYX_SINK_HIT__\n");
|
||||
CommandRunner r = (runner != null) ? runner : new CommandRunner();
|
||||
String out = r.run("echo hello " + payload);
|
||||
System.out.print(out);
|
||||
return out;
|
||||
}
|
||||
}
|
||||
39
tests/dynamic_fixtures/java/spring_controller/pom.xml
Normal file
39
tests/dynamic_fixtures/java/spring_controller/pom.xml
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>nyx</groupId>
|
||||
<artifactId>spring-controller-fixture</artifactId>
|
||||
<version>0.0.1</version>
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<version>6.1.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
<version>6.1.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>6.1.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>6.1.5</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>jakarta.servlet</groupId>
|
||||
<artifactId>jakarta.servlet-api</artifactId>
|
||||
<version>6.0.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
13
tests/dynamic_fixtures/java/sqli_adversarial.java
Normal file
13
tests/dynamic_fixtures/java/sqli_adversarial.java
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// 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: Entry.login(String) Cap: SQL_QUERY
|
||||
|
||||
public class Entry {
|
||||
public static void login(String username) {
|
||||
// Coincidental oracle match — not a SQL sink.
|
||||
System.out.println("NYX_SQL_CONFIRMED");
|
||||
int x = username.length();
|
||||
}
|
||||
}
|
||||
12
tests/dynamic_fixtures/java/sqli_negative.java
Normal file
12
tests/dynamic_fixtures/java/sqli_negative.java
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
// SQL injection — negative fixture.
|
||||
// Safe: uses a parameterized query; payload is a bound argument.
|
||||
// Entry: Entry.login(String) Cap: SQL_QUERY
|
||||
// Expected verdict: NotConfirmed
|
||||
|
||||
public class Entry {
|
||||
public static void login(String username) {
|
||||
String template = "SELECT name FROM users WHERE name = ?";
|
||||
// Simulate parameterized execution: template is fixed.
|
||||
System.out.println("Executing: " + template + " param-len=" + username.length());
|
||||
}
|
||||
}
|
||||
13
tests/dynamic_fixtures/java/sqli_positive.java
Normal file
13
tests/dynamic_fixtures/java/sqli_positive.java
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// SQL injection — positive fixture.
|
||||
// Vulnerable: directly concatenates user input into SQL query string.
|
||||
// Entry: Entry.login(String) Cap: SQL_QUERY
|
||||
// Expected verdict: Confirmed (UNION payload echoes NYX_SQL_CONFIRMED)
|
||||
|
||||
public class Entry {
|
||||
public static void login(String username) {
|
||||
String query = "SELECT name FROM users WHERE name='" + username + "'";
|
||||
System.out.print("__NYX_SINK_HIT__\n");
|
||||
// Error-based echo: output the query so UNION payload is visible.
|
||||
System.out.println("DB query: " + query);
|
||||
}
|
||||
}
|
||||
11
tests/dynamic_fixtures/java/sqli_unsupported.java
Normal file
11
tests/dynamic_fixtures/java/sqli_unsupported.java
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
// SQL injection — unsupported fixture.
|
||||
// Entry is an instance method rather than a static method.
|
||||
// Test sets confidence = Low to get Unsupported(ConfidenceTooLow).
|
||||
// Expected verdict: Unsupported
|
||||
|
||||
public class Entry {
|
||||
public void findUser(String name) {
|
||||
String query = "SELECT * FROM users WHERE name='" + name + "'";
|
||||
System.out.println(query);
|
||||
}
|
||||
}
|
||||
13
tests/dynamic_fixtures/java/ssrf_adversarial.java
Normal file
13
tests/dynamic_fixtures/java/ssrf_adversarial.java
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// SSRF — adversarial collision fixture.
|
||||
// Prints "daemon:" unconditionally without making any HTTP request
|
||||
// and without emitting __NYX_SINK_HIT__.
|
||||
// Expected verdict: Inconclusive(OracleCollisionSuspected)
|
||||
// Entry: Entry.fetchUrl(String) Cap: SSRF
|
||||
|
||||
public class Entry {
|
||||
public static void fetchUrl(String targetUrl) {
|
||||
// Coincidental oracle match — not an HTTP sink.
|
||||
System.out.println("daemon: present");
|
||||
int x = targetUrl.length();
|
||||
}
|
||||
}
|
||||
27
tests/dynamic_fixtures/java/ssrf_negative.java
Normal file
27
tests/dynamic_fixtures/java/ssrf_negative.java
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
// SSRF — negative fixture.
|
||||
// Safe: only allows http/https scheme; file:// rejected.
|
||||
// Entry: Entry.fetchUrl(String) Cap: SSRF
|
||||
// Expected verdict: NotConfirmed
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
|
||||
public class Entry {
|
||||
public static void fetchUrl(String targetUrl) throws Exception {
|
||||
URL url = new URL(targetUrl);
|
||||
String proto = url.getProtocol();
|
||||
if (!proto.equals("http") && !proto.equals("https")) {
|
||||
System.out.println("Scheme not allowed: " + proto);
|
||||
return;
|
||||
}
|
||||
try (InputStream in = url.openStream();
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(in))) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
System.out.println(line.substring(0, Math.min(line.length(), 64)));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println("Connection error");
|
||||
}
|
||||
}
|
||||
}
|
||||
24
tests/dynamic_fixtures/java/ssrf_positive.java
Normal file
24
tests/dynamic_fixtures/java/ssrf_positive.java
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
// SSRF — positive fixture.
|
||||
// Vulnerable: makes a request to a user-controlled URL.
|
||||
// Entry: Entry.fetchUrl(String) Cap: SSRF
|
||||
// Expected verdict: Confirmed (file:///etc/passwd → "daemon:" in output)
|
||||
// Note: Java URL supports file:// scheme natively.
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
|
||||
public class Entry {
|
||||
public static void fetchUrl(String targetUrl) throws Exception {
|
||||
System.out.print("__NYX_SINK_HIT__\n");
|
||||
URL url = new URL(targetUrl);
|
||||
try (InputStream in = url.openStream();
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(in))) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
System.out.println(line);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// silent
|
||||
}
|
||||
}
|
||||
}
|
||||
12
tests/dynamic_fixtures/java/ssrf_unsupported.java
Normal file
12
tests/dynamic_fixtures/java/ssrf_unsupported.java
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
// SSRF — unsupported fixture.
|
||||
// Entry is an instance method; test sets confidence = Low.
|
||||
// Expected verdict: Unsupported
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
|
||||
public class Entry {
|
||||
public void fetch(String url) throws Exception {
|
||||
new URL(url).openStream().close();
|
||||
}
|
||||
}
|
||||
21
tests/dynamic_fixtures/java/static_main/Benign.java
Normal file
21
tests/dynamic_fixtures/java/static_main/Benign.java
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
// Phase 14 — static `main(String[])` entry, benign.
|
||||
//
|
||||
// Discards `args[0]` and runs a fixed echo — payload never reaches the
|
||||
// shell-interpreted slot so the cmdi marker cannot fire.
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
public class Benign {
|
||||
public static void main(String[] args) throws Exception {
|
||||
System.out.print("__NYX_SINK_HIT__\n");
|
||||
String[] cmd = {"/bin/sh", "-c", "echo hello"};
|
||||
Process p = Runtime.getRuntime().exec(cmd);
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
System.out.println(line);
|
||||
}
|
||||
p.waitFor();
|
||||
}
|
||||
}
|
||||
22
tests/dynamic_fixtures/java/static_main/Vuln.java
Normal file
22
tests/dynamic_fixtures/java/static_main/Vuln.java
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
// Phase 14 — static `main(String[])` entry, vulnerable.
|
||||
//
|
||||
// Payload arrives as `args[0]` and lands in a shell-interpreted
|
||||
// `Runtime.exec` invocation.
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
public class Vuln {
|
||||
public static void main(String[] args) throws Exception {
|
||||
System.out.print("__NYX_SINK_HIT__\n");
|
||||
String input = args.length > 0 ? args[0] : "";
|
||||
String[] cmd = {"/bin/sh", "-c", "echo hello " + input};
|
||||
Process p = Runtime.getRuntime().exec(cmd);
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
System.out.println(line);
|
||||
}
|
||||
p.waitFor();
|
||||
}
|
||||
}
|
||||
11
tests/dynamic_fixtures/java/static_main/pom.xml
Normal file
11
tests/dynamic_fixtures/java/static_main/pom.xml
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>nyx</groupId>
|
||||
<artifactId>static-main-fixture</artifactId>
|
||||
<version>0.0.1</version>
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
</properties>
|
||||
</project>
|
||||
23
tests/dynamic_fixtures/java/static_method/Benign.java
Normal file
23
tests/dynamic_fixtures/java/static_method/Benign.java
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
// Phase 14 — plain static method, benign.
|
||||
//
|
||||
// Invokes a fixed shell command and discards the user input — the `;`
|
||||
// in a vuln payload cannot escape because the payload is never passed
|
||||
// to a shell-interpreted argv slot.
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
public class Benign {
|
||||
public static void processInput(String input) throws Exception {
|
||||
System.out.print("__NYX_SINK_HIT__\n");
|
||||
// No-op echo of a fixed string — `input` is dropped.
|
||||
String[] cmd = {"/bin/sh", "-c", "echo hello"};
|
||||
Process p = Runtime.getRuntime().exec(cmd);
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
System.out.println(line);
|
||||
}
|
||||
p.waitFor();
|
||||
}
|
||||
}
|
||||
21
tests/dynamic_fixtures/java/static_method/Vuln.java
Normal file
21
tests/dynamic_fixtures/java/static_method/Vuln.java
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
// Phase 14 — plain static method, vulnerable.
|
||||
//
|
||||
// JDK-only. Passes user input through `/bin/sh -c` so a `;` in the
|
||||
// payload escapes into a new command (CMDI oracle marker fires).
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
public class Vuln {
|
||||
public static void processInput(String input) throws Exception {
|
||||
System.out.print("__NYX_SINK_HIT__\n");
|
||||
String[] cmd = {"/bin/sh", "-c", "echo hello " + input};
|
||||
Process p = Runtime.getRuntime().exec(cmd);
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
System.out.println(line);
|
||||
}
|
||||
p.waitFor();
|
||||
}
|
||||
}
|
||||
14
tests/dynamic_fixtures/java/static_method/pom.xml
Normal file
14
tests/dynamic_fixtures/java/static_method/pom.xml
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Phase 14 fixture pom.xml — pins JDK 17 for materialize_java parity.
|
||||
Not consumed by prepare_java (which shells out to `javac` directly);
|
||||
present so the Phase 09 Track D.2 dep-emission path has a reference. -->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>nyx</groupId>
|
||||
<artifactId>static-method-fixture</artifactId>
|
||||
<version>0.0.1</version>
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
</properties>
|
||||
</project>
|
||||
13
tests/dynamic_fixtures/java/xss_adversarial.java
Normal file
13
tests/dynamic_fixtures/java/xss_adversarial.java
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// 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: Entry.renderPage(String) Cap: HTML_ESCAPE
|
||||
|
||||
public class Entry {
|
||||
public static void renderPage(String userInput) {
|
||||
// Coincidental oracle match — not an HTML render sink.
|
||||
System.out.println("<script>NYX_XSS_CONFIRMED</script>");
|
||||
int x = userInput.length();
|
||||
}
|
||||
}
|
||||
19
tests/dynamic_fixtures/java/xss_negative.java
Normal file
19
tests/dynamic_fixtures/java/xss_negative.java
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
// XSS — negative fixture.
|
||||
// Safe: HTML-encodes special characters before output.
|
||||
// Entry: Entry.renderPage(String) Cap: HTML_ESCAPE
|
||||
// Expected verdict: NotConfirmed
|
||||
|
||||
public class Entry {
|
||||
private static String escapeHtml(String s) {
|
||||
return s.replace("&", "&")
|
||||
.replace("<", "<")
|
||||
.replace(">", ">")
|
||||
.replace("\"", """)
|
||||
.replace("'", "'");
|
||||
}
|
||||
|
||||
public static void renderPage(String userInput) {
|
||||
String safe = escapeHtml(userInput);
|
||||
System.out.print("<html><body>" + safe + "</body></html>\n");
|
||||
}
|
||||
}
|
||||
11
tests/dynamic_fixtures/java/xss_positive.java
Normal file
11
tests/dynamic_fixtures/java/xss_positive.java
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
// XSS — positive fixture.
|
||||
// Vulnerable: echoes raw user input into HTML output without escaping.
|
||||
// Entry: Entry.renderPage(String) Cap: HTML_ESCAPE
|
||||
// Expected verdict: Confirmed (<script>NYX_XSS_CONFIRMED</script> echoed)
|
||||
|
||||
public class Entry {
|
||||
public static void renderPage(String userInput) {
|
||||
System.out.print("__NYX_SINK_HIT__\n");
|
||||
System.out.print("<html><body>" + userInput + "</body></html>\n");
|
||||
}
|
||||
}
|
||||
9
tests/dynamic_fixtures/java/xss_unsupported.java
Normal file
9
tests/dynamic_fixtures/java/xss_unsupported.java
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
// XSS — unsupported fixture.
|
||||
// Entry is an instance method; test sets confidence = Low.
|
||||
// Expected verdict: Unsupported
|
||||
|
||||
public class Entry {
|
||||
public void render(String input) {
|
||||
System.out.print("<html><body>" + input + "</body></html>\n");
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue