mirror of
https://github.com/elicpeter/nyx.git
synced 2026-06-09 19:45:13 +02:00
[pitboss/grind] deferred session-0026 (20260521T201327Z-3848)
This commit is contained in:
parent
cf65e73f3a
commit
0e1365455f
3 changed files with 231 additions and 6 deletions
|
|
@ -1706,18 +1706,22 @@ pub fn emit_open_redirect_harness(spec: &HarnessSpec) -> HarnessSource {
|
|||
String captured = response.getRedirectedUrl();
|
||||
if (fixtureInvoked && captured != null) {{
|
||||
nyxRedirectProbe(captured, requestHost);
|
||||
nyxFollowLocation(captured);
|
||||
}} else {{
|
||||
nyxRedirectProbe(payload, requestHost);
|
||||
nyxFollowLocation(payload);
|
||||
}}"#
|
||||
)
|
||||
} else {
|
||||
r#" nyxRedirectProbe(payload, requestHost);"#.to_owned()
|
||||
r#" nyxRedirectProbe(payload, requestHost);
|
||||
nyxFollowLocation(payload);"#
|
||||
.to_owned()
|
||||
};
|
||||
|
||||
let imports = if has_servlet_stubs {
|
||||
"import java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\n"
|
||||
"import java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.net.HttpURLConnection;\nimport java.net.URL;\n"
|
||||
} else {
|
||||
""
|
||||
"import java.net.HttpURLConnection;\nimport java.net.URL;\n"
|
||||
};
|
||||
|
||||
let source = format!(
|
||||
|
|
@ -1757,6 +1761,31 @@ public class NyxHarness {{
|
|||
}}
|
||||
}}
|
||||
|
||||
// Phase 09 OOB closure: when the captured Location is a fully-qualified
|
||||
// loopback URL, follow it with a real GET so the OOB listener records
|
||||
// the per-finding nonce. Skips non-loopback hosts (no real network egress)
|
||||
// and any non-HTTP scheme. Best-effort: failures do not propagate, the
|
||||
// listener may still have observed the connect before the read errored.
|
||||
static void nyxFollowLocation(String location) {{
|
||||
if (location == null || location.isEmpty()) return;
|
||||
String lower = location.toLowerCase();
|
||||
if (!(lower.startsWith("http://127.0.0.1")
|
||||
|| lower.startsWith("http://localhost")
|
||||
|| lower.startsWith("http://host-gateway"))) {{
|
||||
return;
|
||||
}}
|
||||
try {{
|
||||
HttpURLConnection conn = (HttpURLConnection) new URL(location).openConnection();
|
||||
conn.setConnectTimeout(2000);
|
||||
conn.setReadTimeout(2000);
|
||||
conn.setInstanceFollowRedirects(false);
|
||||
conn.getInputStream().close();
|
||||
conn.disconnect();
|
||||
}} catch (Exception ignored) {{
|
||||
// best-effort OOB fetch
|
||||
}}
|
||||
}}
|
||||
|
||||
public static void main(String[] args) {{
|
||||
String payload = System.getenv("NYX_PAYLOAD");
|
||||
if (payload == null) payload = "";
|
||||
|
|
@ -3487,6 +3516,65 @@ mod tests {
|
|||
let _ = std::fs::remove_dir_all(&dir);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn emit_open_redirect_harness_ships_follow_location_helper() {
|
||||
let dir = std::env::temp_dir().join("nyx_phase09_test_follow_helper");
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let entry = write_servlet_fixture(
|
||||
&dir,
|
||||
"public class Vuln { public static void run(String v) { System.out.println(v); } }\n",
|
||||
);
|
||||
let mut spec = make_spec(PayloadSlot::Param(0));
|
||||
spec.expected_cap = Cap::OPEN_REDIRECT;
|
||||
spec.entry_file = entry;
|
||||
spec.entry_name = "run".into();
|
||||
let h = emit_open_redirect_harness(&spec);
|
||||
assert!(
|
||||
h.source.contains("static void nyxFollowLocation(String location)"),
|
||||
"OPEN_REDIRECT harness must declare the nyxFollowLocation helper",
|
||||
);
|
||||
assert!(
|
||||
h.source.contains("import java.net.HttpURLConnection;"),
|
||||
"OPEN_REDIRECT harness must import HttpURLConnection",
|
||||
);
|
||||
assert!(
|
||||
h.source.contains("import java.net.URL;"),
|
||||
"OPEN_REDIRECT harness must import URL",
|
||||
);
|
||||
assert!(
|
||||
h.source.contains("http://127.0.0.1"),
|
||||
"follow-location helper must whitelist loopback hosts",
|
||||
);
|
||||
assert!(
|
||||
h.source.contains("nyxFollowLocation(payload)"),
|
||||
"tier-(b) fallback must follow the synthetic payload location",
|
||||
);
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn emit_open_redirect_harness_follows_captured_location_in_tier_a() {
|
||||
let dir = std::env::temp_dir().join("nyx_phase09_test_follow_tier_a");
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let entry = write_servlet_fixture(
|
||||
&dir,
|
||||
"import javax.servlet.http.HttpServletResponse;\n\
|
||||
public class Vuln {\n public static void run(HttpServletResponse r, String v) throws Exception {\n r.sendRedirect(v);\n }\n}\n",
|
||||
);
|
||||
let mut spec = make_spec(PayloadSlot::Param(0));
|
||||
spec.expected_cap = Cap::OPEN_REDIRECT;
|
||||
spec.entry_file = entry;
|
||||
spec.entry_name = "run".into();
|
||||
let h = emit_open_redirect_harness(&spec);
|
||||
assert!(
|
||||
h.source.contains("nyxRedirectProbe(captured, requestHost);\n nyxFollowLocation(captured);"),
|
||||
"tier-(a) must follow the captured Location: value, not the raw payload",
|
||||
);
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn emit_xpath_harness_drives_fixture_through_real_xpath_when_imported() {
|
||||
let dir = std::env::temp_dir().join("nyx_phase07_test_drive_fixture");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue