├── 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()
--------------------------------------------------------------------------------