沙箱逃逸


免责声明

本文档仅供学习和研究使用,请勿使用文中的技术源码用于非法用途,任何人造成的任何负面影响,与本人无关.


相关文章


什么是沙箱逃逸

沙箱逃逸,就是在给我们的一个代码执行环境下,脱离种种过滤和限制,最终拿到 shell。


python如何执行命令

python 可以使用以下几个模块执行系统命令

import os
import subprocess
import commands
import pty

os.system('ifconfig')
os.popen('ifconfig')
commands.getoutput('ifconfig')
commands.getstatusoutput('ifconfig')

subprocess.call('ifconfig', shell = True)
subprocess.Popen('ifconfig', shell = True)

pty.spawn('ifconfig')

对于不同的 py 版本可能情况不一样,记得获取当前的 Python 环境

timeit 模块

用于测试小代码片段的运行时间(number 即表示测试的次数):

platform 模块

类似 os 模块的 popen,可以执行命令:

codecs 模块

可以用来读文件:

exec()、eval()、execfile()、compile() 函数

exec():动态运行代码段,返回值为 None

eval():计算单个表达式的值,有返回值

execfile():动态运行某个文件中的代码

compile():将一个字符串编译为字节代码


字符串过滤的绕过

如果是某个字符串被过滤了,可以对它进行一些变换:

如果是关键字被过滤了,可以使用 getattr。getattr 接收两个参数,第一个是模块或对象,第二个是一个字符串。它会在模块或对象中搜索指定的函数或属性:

也可以使用 # coding:<encoding> 编码整个文件.


import 花式处理

import 关键字用来导入包,沙箱中对一些包或是函数进行了屏蔽,从 import 的不同方法到 import 的本质有多种不同的绕过方法。

使用其他的方式来导入其他包名


f修饰符

在PEP 498(python > 3.6.0)中引入了新的字符串类型修饰符:f或F,用f修饰的字符串将可以执行代码.可以理解为字符串外层套了一个exec().


模块路径

Python 中的所有包都是以 .py 文件的形式存在的,说明所有 import 进来的包一开始都预先在某个位置了。一般和系统相关的信息都在 sys 下,使用 sys.path 查看各个包的路径:

如果把 sys、os、reload 等一系列模块都过滤掉了,使用什么方法来绕过呢?导入模块的过程其实就是把对应模块的代码执行一遍的过程,在知道模块对应路径的情况下,就可以相应地执行它:

在 execfile 被禁止的情况下,还可以用 open 读入文件,并使用 exec 来执行相应的代码:


内置函数

python存在一些内置函数(即默认已经导入的函数),对应的内置模块__builtins__.

内置函数 dir() 在没有参数的时候返回本地作用域中的名称列表, 有参数的时候返回参数对象的有效属性列表. 可以通过 dir(__builtins__) 获取内置函数列表, 然后通过 dict 引入模块, dict 的作用是列出一个模组 / 类 / 对象下所有的属性和函数.

如果一些内置函数被删除, 可以通过 reload(__builtins__) 重新载入.

在 python3.x 版本中,__builtin__ 变成了 builtins 模块, 而且需要导入.

dir 和 __dict__

dir 和 __dict__ 可以用来查看类或对象下的所有属性信息:

和 sys.modules 配合使用获得一个模块的引用:

func_code 的利用

函数的 func_code 属性可以被用来查看函数的参数个数以及变量,还能看到函数对应的字节码:

使用 dis 库可以获取函数对应汇编格式的字节码:

object类基础函数

Python 允许多重继承,即一个子类有多个父类。__mro__ 属性可以用来查看一个子类所有的父类;__bases__ 可以获取上一层的继承关系:

python 的 object 类中集成了很多的基础函数, 可以通过创建对象来引用.

寻找特殊模块的方法:__class__, 获得当前对象的类;__bases__, 列出其基类;__mro__, 列出解析方法的调用顺序(即类的继承关系);__subclasses__(), 返回子类列表;__dict__, 列出当前属性 / 函数的字典; func_globals, 返回一个包含函数全局变量的字典引用.

比如 ().__class__.__bases__[0].__subclasses__()[40] 对应的是 file 类.在 open 等文件操作被限制的情况下可以用下面的方法读取文件内容(__subclasses__ 即用来查看对象的所有子类;

其他的一些执行命令的方法(通过获取其他已经载入了 os 等模块的类进行调用):

可以编写一个函数对导入了 os 或 sys 的库进行一个遍历:


伪 private 属性和函数

Python 中以双下划线开头的函数和属性是 private 的,但是这种 private 只是形式上的,表示这个函数不应该在本类之外的地方进行访问,而是否遵守则取决于具体的实现。公有的函数和属性,使用其名字直接进行访问;而私有的属性和函数,使用 下划线+类名+函数名 进行访问:


构造 so 库

编译一个 so 库,并写入指定的路径:

调用 ctypes 来载入 so 库:


修改 GOT 表

把 fopen 的 GOT 改为 system。先用 objdump 查找