羊城杯复盘

Posted by Azeril on September 2, 2023

2023年“羊城杯”网络安全大赛-本科院校组

ezyaml

题目给出了源码

import tarfile
from flask import Flask, render_template, request, redirect
from hashlib import md5
import yaml
import os
import re


app = Flask(__name__)

def waf(s):#一个waf过滤了黑名单
    flag = True
    blacklist = ['bytes','eval','map','frozenset','popen','tuple','exec','\\','object','listitems','subprocess','object','apply']
    for no in blacklist:
        if no.lower() in str(s).lower():
            flag= False
            print(no)
            break
    return flag


def extractFile(filepath, type):

    extractdir = filepath.split('.')[0]#以.做分割,取前面的
    if not os.path.exists(extractdir):  #如果不存在,则会自动创建文件夹
        os.makedirs(extractdir)


    if type == 'tar':
        tf = tarfile.TarFile(filepath)
        tf.extractall(extractdir)#把 tar文件内容,放到上面目录中
        return tf.getnames()#返回目录名字

@app.route('/', methods=['GET'])#get传参
def main():
        fn = 'uploads/' + md5().hexdigest()
        if not os.path.exists(fn):
            os.makedirs(fn)  #不存在则进行创建
        return render_template('index.html')


@app.route('/upload', methods=['GET', 'POST'])#上传文件的路由
def upload():

    if request.method == 'GET':
        return redirect('/')

    if request.method == 'POST':
        upFile = request.files['file']
        print(upFile)
        if re.search(r"\.\.|/", upFile.filename, re.M|re.I) != None:#格式多行模式忽略大小写,过滤了.. /
            return "<script>alert('Hacker!');window.location.href='/upload'</script>"

        savePath = f"uploads/{upFile.filename}"
        print(savePath)
        upFile.save(savePath)

        if tarfile.is_tarfile(savePath):#保存的文件是否是一个tar文件
            zipDatas = extractFile(savePath, 'tar')#提取里面的数据
            return render_template('result.html', path=savePath, files=zipDatas)
        else:
            return f"<script>alert('{upFile.filename} upload successfully');history.back(-1);</script>"


@app.route('/src', methods=['GET'])#/src路由
def src():
    if request.args:
        username = request.args.get('username')  #传参username
        with open(f'config/{username}.yaml', 'rb') as f:#到这里其实有点懵,我咋知道网站有啥yaml文件,咋打开。。。。
            Config = yaml.load(f.read())
            return render_template('admin.html', username="admin", message="success")
    else:
        return render_template('index.html')


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8000)

简单分析

首先一定需要传一个tar的文件,(考虑软链接)
/src读取yaml,会不会是upload上传确认了config目录,然后tar包里面是一个yaml文件
感觉非常正确

image-20230902233838745

image-20230902234028567


Creative Commons License
本作品采用CC BY-NC-ND 4.0进行许可。转载,请注明原作者 Azeril 及本文源链接。