http-pipelining
This is an old revision of the document!
HTTP Pipelining + HTTP/2 Single Packets
Lessons learned from LACTF 2025: [WEB] whats-my-number
TL;DR: Get enough Math.random values to crack with randcrack (V8). In order to “race” (not really) and get consecutive values, you must send your requests with http pipelining or http/2 single packets.
Future References: https://github.com/nxenon/h2spacex https://www.tjc.im/vulnerabilities/request_smuggling/#http11-pipelining
const express = require("express"); const path = require("path"); const fs = require("fs"); const http = require("http"); const app = express(); const PORT = process.env.PORT || 3000; const SPAM_PERIOD = 40; let total_guesses = 0; function getRandom() { return Math.floor(Math.random() * 1e9); } app.use(express.static(path.join(__dirname, "../public"))); // Endpoint to get a random number app.get("/api/random", (req, res) => { const randomNumber = getRandom(); res.json({ randomNumber }); }); // Endpoint to guess a number app.get("/api/guess", (req, res) => { const guess = req.query.num; let guess_num; total_guesses += 1; try { guess_num = parseInt(guess); } catch (error) { console.error("Could not parse guess:", guess); res.status(500).json({ error: "Could not parse guess" }); return; } if (isNaN(guess_num)) { console.error("Could not parse guess:", guess); res.status(500).json({ error: "Could not parse guess" }); return; } let test_num = getRandom(); if (test_num === guess_num) { fs.readFile(path.join(__dirname, "../flag.txt"), "utf-8", (err, flag) => { if (err) { console.error("Failed to read flag file", err); res.status(500).json({ error: "Error reading flag file, please contact CTF organizers", }); return; } const response_msg = flag; res.json({ response_msg, total_guesses }); }); } else { let response_msg = "Wrong number! The right number is: " + test_num; res.json({ response_msg, total_guesses }); } }); // Start the server app.listen(PORT, () => { console.log(`Server is running on http://localhost:${PORT}`); }); // Spam requests to the server at some fixed interval // Use a persistent http session let failed_requests = 0; const start_spamming = () => { console.log("Starting spam requests"); const agent = new http.Agent({ keepAlive: true }); const send_request = () => { const options = { hostname: "localhost", port: PORT, path: "/api/random", method: "GET", agent: agent, }; const req = http.request(options, (res) => { let data = ""; res.on("data", (chunk) => { data += chunk; failed_requests = 0; }); }); req.on("error", (error) => { console.error("Request error: ", error); failed_requests++; // If 10 requests in a row fail, exit the program; something is wrong if (failed_requests >= 10) { console.error("Too many requests failing! Exiting program."); process.exit(1); } }); req.end(); }; setInterval(send_request, SPAM_PERIOD); }; setTimeout(start_spamming, 500);
http-pipelining.1739142170.txt.gz · Last modified: 2025/02/09 23:02 by osorin