├── README.md ├── freeeee.py ├── ssti.py ├── blacklist2+.py ├── blacklist2.py ├── blacklist1.py ├── LICENSE └── final.py /README.md: -------------------------------------------------------------------------------- 1 | # py-sandbox-escape 2 | 3 | > 台科資安社 107-2 0x01 4 | 5 | - slides: https://hackmd.io/p/BJDtweFLN 6 | 7 | 在玩 `ssti.py` 之前,記得先 `pip install Flask` 8 | -------------------------------------------------------------------------------- /freeeee.py: -------------------------------------------------------------------------------- 1 | while True: 2 | try: 3 | inp = raw_input("> ") 4 | ret = None 5 | exec "ret=" + inp 6 | if ret != None: 7 | print ret 8 | except Exception, e: 9 | print 'Exception:', e -------------------------------------------------------------------------------- /ssti.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, render_template_string, config, request 2 | 3 | app = Flask(__name__) 4 | 5 | @app.route('/') 6 | def index(): 7 | name=request.args.get('name') 8 | template = '

hello {}!

'.format(name) 9 | print(template) 10 | return render_template_string(template) 11 | 12 | app.run() -------------------------------------------------------------------------------- /blacklist2+.py: -------------------------------------------------------------------------------- 1 | def make_secure(): 2 | Q____Q = __builtins__.__dict__.keys() 3 | Q____Q.remove('raw_input') 4 | Q____Q.remove('print') 5 | for x in Q____Q: 6 | del __builtins__.__dict__[x] 7 | 8 | 9 | 10 | make_secure() 11 | 12 | 13 | while True: 14 | try: 15 | inp = raw_input("> ") 16 | ret = None 17 | exec "ret=" + inp 18 | if ret != None: 19 | print ret 20 | 21 | except Exception, e: 22 | print 'Exception:', e 23 | -------------------------------------------------------------------------------- /blacklist2.py: -------------------------------------------------------------------------------- 1 | def make_secure(): 2 | Q____Q = ['open', 3 | 'file', 4 | 'execfile', 5 | 'compile', 6 | # 'reload', 7 | '__import__', 8 | 'eval', 9 | 'input', 10 | # and anything you want 11 | ] 12 | for func in Q____Q: 13 | del __builtins__.__dict__[func] 14 | 15 | 16 | make_secure() 17 | 18 | 19 | while True: 20 | try: 21 | inp = raw_input("> ") 22 | ret = None 23 | exec "ret=" + inp 24 | if ret != None: 25 | print ret 26 | 27 | except Exception, e: 28 | print 'Exception:', e 29 | -------------------------------------------------------------------------------- /blacklist1.py: -------------------------------------------------------------------------------- 1 | 2 | def check_secure(inp): 3 | Q____Q = [ 4 | 'exec', 5 | 'open', 6 | 'file', 7 | 'execfile', 8 | 'import', 9 | 'eval', 10 | 'input', 11 | 'hacker' 12 | # and anything you want 13 | ] 14 | for s in Q____Q: 15 | if s in inp: 16 | raise Exception("Sorry, '"+ s +"' is not allowed.") 17 | 18 | while True: 19 | try: 20 | inp = raw_input("> ") 21 | check_secure(inp) 22 | ret = None 23 | exec "ret=" + inp 24 | if ret != None: 25 | print ret 26 | 27 | except Exception, e: 28 | print 'Exception:', e -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 ꌗᖘ꒒ꀤ꓄꒒ꀤꈤꍟ 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /final.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python -u 2 | 3 | # TJCTF 2018 Abyss 4 | 5 | from __future__ import print_function 6 | from code import InteractiveConsole 7 | import code 8 | import sys 9 | 10 | text_banned = ["__class__", "__base__", "__subclasses__", "_module", "open", "eval", "execfile", "exec", "compile", "repr", "__"] 11 | banned = ["vars", "getattr", "setattr", "delattr", "input", "raw_input", "help", "open", "memoryview", "eval", "exec", "execfile", "super", "file", "reload", "staticmethod", "property", "intern", "coerce", "buffer", "apply"] 12 | text_banned.extend(banned) 13 | 14 | global open 15 | open = open 16 | b = __builtins__ 17 | for each in b.__dict__.keys(): 18 | if ("__" in each or each in banned) and each != "__name__": 19 | locals()[each] = b.__dict__[each] # we save a copy for ourselves 20 | del b.__dict__[each] 21 | 22 | class PseudoFile(object): 23 | 24 | def __init__(self, sh): 25 | self.sh = sh 26 | 27 | def write(self, s): 28 | self.sh.write(s) 29 | 30 | def writelines(self, lines): 31 | for line in lines: 32 | self.write(line) 33 | 34 | def flush(self): 35 | pass 36 | 37 | def isatty(self): 38 | return True 39 | 40 | 41 | class Shell(code.InteractiveConsole): 42 | "Wrapper around Python that can filter input/output to the shell" 43 | 44 | def __init__(self): 45 | code.InteractiveConsole.__init__(self) 46 | self.thread = None 47 | 48 | def push(self, line): 49 | for any in text_banned: 50 | if any in line: 51 | print("Sorry, '%s' is not allowed." % any) 52 | sys.stdout.flush() 53 | return 54 | return code.InteractiveConsole.push(self, line) 55 | 56 | def raw_input(self, prompt=""): 57 | print(">>>", end=" ") 58 | sys.stdout.flush() 59 | a = "" 60 | try: 61 | a = sys.stdin.readline().strip() 62 | except EOFError: 63 | pass 64 | return a 65 | 66 | def runcode(self, _code): 67 | global open 68 | org_stdout = sys.stdout 69 | sys.stdout = PseudoFile(self) 70 | try: 71 | exec _code in self.locals 72 | except SystemExit: 73 | raise 74 | except: 75 | print("The Abyss consumed your error.") 76 | else: 77 | if code.softspace(sys.stdout, 0): 78 | print 79 | 80 | sys.stdout = org_stdout 81 | 82 | def interact(self, banner=None): 83 | try: 84 | sys.ps1 85 | except AttributeError: 86 | sys.ps1 = ">>> " 87 | try: 88 | sys.ps2 89 | except AttributeError: 90 | sys.ps2 = "... " 91 | cprt = 'Type "help", "copyright", "credits" or "license" for more information.' 92 | if banner is None: 93 | self.write("Python %s on %s\n%s\n(%s)\n" % 94 | (sys.version, sys.platform, cprt, 95 | self.__class__.__name__)) 96 | else: 97 | self.write("%s\n" % str(banner)) 98 | more = 0 99 | while 1: 100 | try: 101 | if more: 102 | prompt = sys.ps2 103 | else: 104 | prompt = sys.ps1 105 | try: 106 | line = self.raw_input(prompt) 107 | # Can be None if sys.stdin was redefined 108 | encoding = getattr(sys.stdin, "encoding", None) 109 | if encoding and not isinstance(line, unicode): 110 | line = line.decode(encoding) 111 | except EOFError: 112 | self.write("\n") 113 | break 114 | else: 115 | more = self.push(line) 116 | except KeyboardInterrupt: 117 | self.write("\nKeyboardInterrupt\n") 118 | self.resetbuffer() 119 | more = 0 120 | 121 | def main(): 122 | banner = "The Abyss stares back." 123 | 124 | shell = Shell() 125 | shell.locals['__builtins__'] = b 126 | shell.interact(banner=banner) 127 | 128 | if __name__=="__main__": 129 | main() --------------------------------------------------------------------------------