nx_redteam.nx source
↩ module page · 84 lines · 5180 B
1// nx_redteam.nx -- automated RED-TEAM attack playbooks (census gap) driven over R0's ta_handle. Each attack asserts
2// the SECURE outcome (blocked / escaped / no-crash); a SURVIVED attack reds. Complements the invoke gate by adding the
3// hostile-INPUT classes: JSON injection via registry data, auth-bypass, malformed-body robustness, unknown-method.
4// (In-process today; a LIVE-edge playbook over nishifamily.com is the ratchet once tools/call deploys.) license_tier: ORIGINAL
5import "nx_tools_api.nx" // ta_handle_pfx + tool_register_pfx + capt_issue + TA_CAP_SECRET + ta_* (transitive)
6import "nx_gate.nx"
7const K_MAGIC_1048576: i64 = 1048576
8const K_MAGIC_4096: i64 = 4096
9
10func rt_has(o: *u8, n: i64, ndl: *u8) -> i64 { if ta_indexof(o, n, ndl) >= 0 { return 1 } return 0 }
11func rt_mark(cond: i64, p: *i64, t: *i64, lbl: *u8) -> i64 {
12 t[0] = t[0] + 1
13 if cond == 1 { p[0] = p[0] + 1; gw(" [BLOCKED] " as *u8) } else { gw(" [VULN!! ] " as *u8) }
14 gw(lbl); gw("\n" as *u8)
15 return 0
16}
17// build "POST /mcp ... <jbody>" with optional X-Nishi-Cap header. jbody passed raw (jblen bytes) so we can inject malformed.
18func rt_req(cap: *u8, caplen: i64, jbody: *u8, jblen: i64, out: *u8) -> i64 {
19 var o: i64 = ta_cat(out, 0, "POST /mcp HTTP/1.1\r\nHost: x\r\n" as *u8)
20 if caplen > 0 { o = ta_cat(out, o, "X-Nishi-Cap: " as *u8); o = ta_catb(out, o, cap, caplen); o = ta_cat(out, o, "\r\n" as *u8) }
21 o = ta_cat(out, o, "Connection: close\r\n\r\n" as *u8)
22 o = ta_catb(out, o, jbody, jblen)
23 return o
24}
25// tools/call body with `name` into buf; returns length.
26func rt_callbody(name: *u8, buf: *u8) -> i64 {
27 var o: i64 = ta_cat(buf, 0, "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tools/call\",\"params\":{\"name\":\"" as *u8)
28 o = ta_cat(buf, o, name)
29 o = ta_cat(buf, o, "\"}}" as *u8)
30 return o
31}
32
33func main() -> i64 {
34 gw("=== nx_redteam: automated attack playbooks over R0 -- each attack MUST be blocked/escaped/survived-without-crash ===\n" as *u8)
35 let TP: *u8 = "knowledge/toolreg-test-rt-" as *u8
36 let secret: *u8 = TA_CAP_SECRET
37 let slen: i64 = ta_slen(secret)
38 let pbox: *i64 = sys_mmap(16) as *i64; pbox[0] = 0
39 let tbox: *i64 = sys_mmap(16) as *i64; tbox[0] = 0
40 let out: *u8 = sys_mmap(K_MAGIC_1048576)
41 let req: *u8 = sys_mmap(K_MAGIC_4096)
42 let jb: *u8 = sys_mmap(K_MAGIC_4096)
43
44 // RT1 INJECTION: register a tool whose description carries a raw `"` -> GET /api/tools MUST escape it (\" present) so
45 // it can't break out of the JSON string (no response-injection via registry data).
46 tool_register_pfx(TP, "rt_injtool" as *u8, "mal\"icious" as *u8, "x" as *u8, "gate" as *u8)
47 let r1: i64 = ta_cat(req, 0, "GET /api/tools HTTP/1.1\r\nHost: x\r\n\r\n" as *u8)
48 let n1: i64 = ta_handle_pfx(TP, req, r1, out)
49 var t1: i64 = 0; if rt_has(out, n1, "\\\"" as *u8) == 1 { t1 = 1 }
50 rt_mark(t1, pbox, tbox, "RT1 JSON-injection via registry data -> escaped (\\\" in output; string not broken)" as *u8)
51
52 // RT2 AUTH-BYPASS: tools/call with NO capability -> denied (-32001).
53 let b2: i64 = rt_callbody("nx_http_probe" as *u8, jb)
54 let r2: i64 = rt_req(0 as *u8, 0, jb, b2, req)
55 let n2: i64 = ta_handle_pfx(TP, req, r2, out)
56 var t2: i64 = 0; if rt_has(out, n2, "-32001" as *u8) == 1 { t2 = 1 }
57 rt_mark(t2, pbox, tbox, "RT2 invoke with NO capability -> DENIED (no ambient authority)" as *u8)
58
59 // RT3 FORGERY: tools/call with a garbage/forged capability -> denied.
60 let b3: i64 = rt_callbody("nx_http_probe" as *u8, jb)
61 let r3: i64 = rt_req("garbage.forged.token.zzzz" as *u8, 25, jb, b3, req)
62 let n3: i64 = ta_handle_pfx(TP, req, r3, out)
63 var t3: i64 = 0; if rt_has(out, n3, "-32001" as *u8) == 1 { t3 = 1 }
64 rt_mark(t3, pbox, tbox, "RT3 invoke with a FORGED/garbage capability -> DENIED (unforgeable)" as *u8)
65
66 // RT4 MALFORMED BODY: truncated JSON-RPC -> graceful (no crash; a non-empty response comes back).
67 let mal: *u8 = "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":" as *u8
68 let r4: i64 = rt_req(0 as *u8, 0, mal, ta_slen(mal), req)
69 let n4: i64 = ta_handle_pfx(TP, req, r4, out)
70 var t4: i64 = 0; if n4 > 0 { t4 = 1 }
71 rt_mark(t4, pbox, tbox, "RT4 malformed/truncated body -> handled gracefully (no crash, response returned)" as *u8)
72
73 // RT5 UNKNOWN METHOD: -> -32601 (not found), no crash.
74 let b5: i64 = ta_cat(jb, 0, "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"admin/deleteEverything\"}" as *u8)
75 let r5: i64 = rt_req(0 as *u8, 0, jb, b5, req)
76 let n5: i64 = ta_handle_pfx(TP, req, r5, out)
77 var t5: i64 = 0; if rt_has(out, n5, "-32601" as *u8) == 1 { t5 = 1 }
78 rt_mark(t5, pbox, tbox, "RT5 unknown/hostile method -> -32601 not-found (no crash, no unintended action)" as *u8)
79
80 gw("\n=== nx_redteam " as *u8); gn(pbox[0]); gw("/" as *u8); gn(tbox[0]); gw(" attacks blocked ===\n" as *u8)
81 if pbox[0] == tbox[0] { gw("RED-TEAM GREEN -- every attack in the playbook was blocked/escaped/survived. No vuln found.\n" as *u8); sys_exit(0); return 0 }
82 gw("RED-TEAM RED -- an attack SUCCEEDED. That is a vulnerability -> bank it (nx_regress_bank) + fix.\n" as *u8)
83 sys_exit(1); return 1
84}