code wiki / _hdl_build / nx_cms_redirect_exceed_gate.nx

nx_cms_redirect_exceed_gate.nx source

↩ module page · 171 lines · 9175 B

1// nx_cms_redirect_exceed_gate.nx -- the FIRST W-RE-004 head-to-head EXCEED (redirects-404, safety axis). 2// Runs BOTH sides on the SAME corpus of Location values: 3// OURS = _redirect_location_is_safe (the shipped guard) 4// INCUMBENT = the documented no-guard baseline (accept any non-empty Location) -- the CWE-113 / 5// CWE-601 failure mode of redirect handlers that don't reject CR/LF/NUL in a Location 6// (a class WordPress redirect plugins have shipped CVEs for). 7// Ground truth per case: SAFE iff it contains no CR(0x0d)/LF(0x0a)/NUL(0x00). The harness nx_cms_exceed 8// COMPUTES the verdict from the measured scores; the gate also self-tests that the harness CANNOT 9// false-green (rejects an overclaim, reports PARITY/BEHIND honestly). Writes a CMSEXCEED line to 10// knowledge/status/cms_exceed.log ONLY on a measured AHEAD + referee-clean + self-tests pass. Exit 0 iff so. 11// license_tier: ORIGINAL 12import "nx_cms_exceed.nx" 13import "nx_http_resolve_redirect.nx" 14import "nx_syscalls.nx" 15 16func xg_w(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 17func xg_num(v: i64) -> i64 { let bb: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m}; let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48;k=1}; while m>0{t[k]=48+(m%10);m=m/10;k=k+1}; var i: i64=0; while i<k{bb[i]=t[k-1-i];i=i+1}; sys_write(1,bb,k); return 0 } 18func xg_cat(dst: *u8, off: i64, s: *u8) -> i64 { var o: i64=off; var k: i64=0; while s[k]!=(0 as u8){dst[o]=s[k];o=o+1;k=k+1} return o } 19func xg_catnum(dst: *u8, off: i64, v: i64) -> i64 { 20 var o: i64=off; let t: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m}; var k: i64=0 21 if m==0 {t[0]=48 as u8;k=1}; while m>0 {t[k]=(48+(m%10)) as u8; m=m/10; k=k+1} 22 var i: i64=0; while i<k {dst[o]=t[k-1-i]; o=o+1; i=i+1} return o 23} 24func xg_row(id: i64, ok: i64, what: *u8) -> i64 { 25 xg_w("XCDROW " as *u8); xg_num(id); xg_w(" " as *u8) 26 if ok==1 { xg_w("PASS " as *u8) } else { xg_w("FAIL " as *u8) } 27 xg_w(what); xg_w("\n" as *u8) 28 return ok 29} 30 31// incumbent oracle = the documented no-guard baseline: accept any non-empty Location (no CR/LF/NUL check). 32func xg_incumbent_accept(loc: *u8, n: i64) -> i64 { if n > 0 { return 1 } return 0 } 33 34// ground truth: 1 = SAFE (no header-injection bytes), 0 = malicious 35func xg_truth_safe(loc: *u8, n: i64) -> i64 { 36 if n <= 0 { return 0 } 37 var i: i64 = 0 38 while i < n { 39 let b: i64 = loc[i] as i64 40 if b == 0x0d { return 0 } 41 if b == 0x0a { return 0 } 42 if b == 0x00 { return 0 } 43 i = i + 1 44 } 45 return 1 46} 47 48func xg_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n } 49 50func main() -> i64 { 51 var pass: i64 = 0 52 var rows: i64 = 0 53 54 // ---- corpus: parallel arrays of (ptr, len). Clean first, then CWE-113 injections. ---- 55 let ptrs: *i64 = sys_mmap(8 * 32) as *i64 56 let lens: *i64 = sys_mmap(8 * 32) as *i64 57 var nc: i64 = 0 58 59 // clean Location values (legit redirects -- both sides SHOULD accept) 60 let c0: *u8 = "/practice/estate-planning" as *u8 61 ptrs[nc]=c0 as i64; lens[nc]=xg_slen(c0); nc=nc+1 62 let c1: *u8 = "/contact" as *u8 63 ptrs[nc]=c1 as i64; lens[nc]=xg_slen(c1); nc=nc+1 64 let c2: *u8 = "/blog/post?x=1&y=2" as *u8 65 ptrs[nc]=c2 as i64; lens[nc]=xg_slen(c2); nc=nc+1 66 let c3: *u8 = "/a/b/c" as *u8 67 ptrs[nc]=c3 as i64; lens[nc]=xg_slen(c3); nc=nc+1 68 69 // CWE-113 header-injection payloads (built with raw bytes; OURS must reject all) 70 // m0: CRLF + Set-Cookie 71 let m0: *u8 = sys_mmap(64) 72 m0[0]=47; m0[1]=120; m0[2]=0x0d; m0[3]=0x0a; var o0: i64=xg_cat(m0,4,"Set-Cookie: evil=1" as *u8) 73 ptrs[nc]=m0 as i64; lens[nc]=o0; nc=nc+1 74 // m1: bare LF 75 let m1: *u8 = sys_mmap(64) 76 m1[0]=47; m1[1]=120; m1[2]=0x0a; var o1: i64=xg_cat(m1,3,"Set-Cookie: y" as *u8) 77 ptrs[nc]=m1 as i64; lens[nc]=o1; nc=nc+1 78 // m2: bare CR 79 let m2: *u8 = sys_mmap(64) 80 m2[0]=47; m2[1]=120; m2[2]=0x0d; var o2: i64=xg_cat(m2,3,"Location: http://evil" as *u8) 81 ptrs[nc]=m2 as i64; lens[nc]=o2; nc=nc+1 82 // m3: NUL truncation 83 let m3: *u8 = sys_mmap(64) 84 m3[0]=47; m3[1]=120; m3[2]=0x00; var o3: i64=xg_cat(m3,3,"/admin" as *u8) 85 ptrs[nc]=m3 as i64; lens[nc]=o3; nc=nc+1 86 // m4: leading CRLF response-splitting 87 let m4: *u8 = sys_mmap(64) 88 m4[0]=0x0d; m4[1]=0x0a; var o4: i64=xg_cat(m4,2,"HTTP/1.1 200 OK" as *u8) 89 ptrs[nc]=m4 as i64; lens[nc]=o4; nc=nc+1 90 91 // ---- run BOTH sides on the same corpus; measure ---- 92 var our_correct: i64 = 0 93 var inc_correct: i64 = 0 94 var n_mal: i64 = 0 95 var safety_our: i64 = 0 96 var safety_inc: i64 = 0 97 var i: i64 = 0 98 while i < nc { 99 let p: *u8 = (ptrs[i]) as *u8 100 let ln: i64 = lens[i] 101 let truth: i64 = xg_truth_safe(p, ln) 102 let our_v: i64 = _redirect_location_is_safe(p, ln) 103 let inc_v: i64 = xg_incumbent_accept(p, ln) 104 if our_v == truth { our_correct = our_correct + 1 } 105 if inc_v == truth { inc_correct = inc_correct + 1 } 106 if truth == 0 { 107 n_mal = n_mal + 1 108 if our_v == 0 { safety_our = safety_our + 1 } 109 if inc_v == 0 { safety_inc = safety_inc + 1 } 110 } 111 i = i + 1 112 } 113 114 let verdict: i64 = xcd_verdict(our_correct, inc_correct) 115 116 xg_w("HEAD-TO-HEAD redirects-404 safety: ours=" as *u8); xg_num(our_correct) 117 xg_w("/" as *u8); xg_num(nc); xg_w(" incumbent=" as *u8); xg_num(inc_correct); xg_w("/" as *u8); xg_num(nc) 118 xg_w(" injections-blocked ours=" as *u8); xg_num(safety_our); xg_w("/" as *u8); xg_num(n_mal) 119 xg_w(" incumbent=" as *u8); xg_num(safety_inc); xg_w("/" as *u8); xg_num(n_mal) 120 xg_w(" verdict=" as *u8); xg_w(xcd_vname(verdict)); xg_w("\n" as *u8) 121 122 // R0: OURS is fully correct (blocks every injection AND keeps every legit redirect) 123 var ok: i64 = 0; if our_correct == nc { ok = 1 } 124 rows=rows+1; pass=pass+xg_row(0, ok, "ours fully correct (all injections blocked, no legit redirect broken)" as *u8) 125 126 // R1: the incumbent no-guard baseline is NOT fully correct (it accepts the injections) 127 ok = 0; if inc_correct < nc { ok = 1 } 128 rows=rows+1; pass=pass+xg_row(1, ok, "incumbent no-guard baseline fails (accepts CWE-113 injections)" as *u8) 129 130 // R2: the measured verdict is AHEAD 131 ok = 0; if verdict == XCD_AHEAD { ok = 1 } 132 rows=rows+1; pass=pass+xg_row(2, ok, "measured verdict = AHEAD (ours strictly beats incumbent)" as *u8) 133 134 // R3: safety axis is fully won: ours blocks all injections, incumbent blocks none 135 ok = 0; if safety_our == n_mal { if safety_inc == 0 { if n_mal > 0 { ok = 1 } } } 136 rows=rows+1; pass=pass+xg_row(3, ok, "safety axis: ours blocks all injections, incumbent blocks 0" as *u8) 137 138 // R4: REFEREE accepts this honest AHEAD claim (real measurement + ours fully correct) 139 ok = 0; if xcd_referee_ok(XCD_AHEAD, our_correct, nc) == 1 { ok = 1 } 140 rows=rows+1; pass=pass+xg_row(4, ok, "referee accepts honest AHEAD claim" as *u8) 141 142 // R5 (anti-false-green): referee REJECTS an overclaim (AHEAD while still failing a case) 143 ok = 0; if xcd_referee_ok(XCD_AHEAD, nc - 1, nc) == 0 { if xcd_referee_ok(XCD_AHEAD, 1, 0) == 0 { ok = 1 } } 144 rows=rows+1; pass=pass+xg_row(5, ok, "referee rejects overclaim (less-wrong != ahead; no-measurement != win)" as *u8) 145 146 // R6 (anti-false-green): harness reports non-wins honestly (PARITY when equal, BEHIND when worse) 147 ok = 0; if xcd_verdict(5, 5) == XCD_PARITY { if xcd_verdict(3, 7) == XCD_BEHIND { ok = 1 } } 148 rows=rows+1; pass=pass+xg_row(6, ok, "harness reports PARITY/BEHIND honestly (cannot only-ever-win)" as *u8) 149 150 xg_w("CMS-REDIRECT-EXCEED-GATE rows=" as *u8); xg_num(rows); xg_w(" pass=" as *u8); xg_num(pass); xg_w("\n" as *u8) 151 152 // honest gate: record only if measured AHEAD + referee clean + self-tests all pass 153 if pass == rows { 154 if verdict == XCD_AHEAD { 155 if xcd_referee_ok(XCD_AHEAD, our_correct, nc) == 1 { 156 let line: *u8 = sys_mmap(256) 157 var lo: i64 = xg_cat(line, 0, "CMSEXCEED feature=redirects-404 axis=safety cwe=CWE-113/601 ours=" as *u8) 158 lo = xg_catnum(line, lo, our_correct); lo = xg_cat(line, lo, "/" as *u8); lo = xg_catnum(line, lo, nc) 159 lo = xg_cat(line, lo, " incumbent=" as *u8); lo = xg_catnum(line, lo, inc_correct); lo = xg_cat(line, lo, "/" as *u8); lo = xg_catnum(line, lo, nc) 160 lo = xg_cat(line, lo, " injections-blocked=" as *u8); lo = xg_catnum(line, lo, safety_our); lo = xg_cat(line, lo, "/" as *u8); lo = xg_catnum(line, lo, n_mal) 161 lo = xg_cat(line, lo, " verdict=AHEAD\n" as *u8) 162 let gf: i64 = sys_openat_append("knowledge/status/cms_exceed.log" as *u8, 0x1a4) 163 if gf >= 0 { sys_write(gf, line, lo); sys_close(gf) } 164 xg_w("CMS-REDIRECT-EXCEED-GATE verdict=AHEAD -- measured EXCEED recorded in cms_exceed.log\n" as *u8) 165 sys_exit(0); return 0 166 } 167 } 168 } 169 xg_w("CMS-REDIRECT-EXCEED-GATE verdict=NOT-RECORDED (no fake-green: needs measured AHEAD + referee + self-tests)\n" as *u8) 170 sys_exit(1); return 1 171}