python安全
Python
基础
全局变量
python 函数和类方法(对于类未重写的内置方法数据类型为装饰器 wrapper_descriptor,重写后为 function)都有一个__globals__属性可以将函数或者类方法申明的变量空间中的全局变量以字典的方式返回

如上定义了全局变量和 a 类中的内置变量,如何通过一个 b 的实例来修改他们?

获取了 b 的__init__方法后调用__globals__属性修改了全局变量以及未继承的类属性
继承链
mro[-1]:获取类的继承关系,最后一个是 class 类,也可以直接用__base__(需要保证直接继承 class)
init.globals:获取方法后调用 globals 获取全局变量
1 | |
获取实例的类之后获取它的基类,修改基类的__str__属性(也可以指向其他属性),但是无法直接修改 object 类,且需要有继承关系
sys 模块
在此基础上可以修改其他模块的属性,但是当代码复杂的时候需要利用 sys 模块
sys模块的modules属性以字典的形式包含了程序自开始运行时所有已加载过的模块,可以直接从该属性中获取到目标模块

sys 字典存放了所有加载的模组(python 中存在默认加载的模组,但是其并不一定可用),如果被 ban 掉了 os 模块,可以将其删除后重新导入

loader 加载器
loader 是为实现模块加载而设计的类,其在
importlib这一内置模块中有具体实现。令人庆幸的是importlib模块下所有的py文件中均引入了sys模块
因此只要获取一个 loader 就可以得到 sys 模块,其中__loader__属性会被默认赋值为当前模块的 loader(debug 模式为 None)
__spec__内置属性定义在 importlib 模块下,可以利用


defaults 与 kwdefaults
存放了函数默认值
沙箱逃逸
payload
1 | |
Trick
getattr 获取属性
chr()
bytes.decode

Tips:bytes 函数本身也可以寻找
Help:交互终端 rce
输入之后再输入模块名(os 获取__main__)
breakpoint():进入 Pdb 调试一句话 RCE
海象运算符:=:一个 input 执行多行命令
dir 查看方法
lambda 绕过
__doc__文档表寻找可用字符

原型链污染
应用
污染 flask secret_key(伪造秘钥)
和_got_first_request 和_static_url_path
exported_names
os.path.pardir(影响了 render_template 的解析,默认为..,flask****通过它来限制目录穿越则可把他修改为其他无关的内容)
jinjia_env(修改语法实现 ssti 绕过 waf)

os.environ
Trick
变量覆盖
for 循环

绕过空格
list 生成器和中括号

eval 导致环境变量可修改
https://www.leavesongs.com/PENETRATION/how-I-hack-bash-through-environment-injection.html
底层调用了 bash -c 指令
若环境变量可控则可以执行命令

unicode 字符

https://kdxcxs.github.io/posts/wp/idekctf-2022-task-manager-wp/
PYjail
基础

import
空格,_import_, importlib.import_module exefile(也可以open之后exec,一般要事先确认一下(path)
过滤引号
str函数
chr函数
list+dict
_doc_
bytes函数
字符串变化
[::-1]
字符串拼接(+)
eval/exec
_loader_.load_module

恢复sys.module
一个存储加载过的模块信息,里面的模块不能直接使用,需要经过import
import一个模块的时候:检查是否存在sys.module中吗,没有则创建并加载,有则不加载
此外,存在modules中的库会优先import,如果在本地创建了同名文件,需要先del
python3之后的reload需要导入importlib模块
假如被禁用了:
函数执行
system不是字符串,不能编码绕过
其他函数
getattr获取方法属性


内建模块
关于dict:一个模块对象有一个由字典对象实现的命名空间,属性的引用会被转换为这个字典中的查找,例如,m.x 等同于 m.dict[“x”]。
那如果连reload都从__builtins__中删了,就没法恢复__builtins__了,需要另寻他法。还有一种情况是利用 exec command in _global 动态运行语句时的绕过

继承关系逃逸
直接继承与间接继承
site类直接引入了os

warnings类的子类linecache引入了os

也就是先获取warnings再获取linecache再到os
行数限制
exec中\n换行
empile

海象表达式

help()
随便进一个模块 #!或者!sh
server
locals

其他
过滤. [截图] :_getitem_ pop()
python3.6:PEP498
__globals__:func_globals
_mro__: _bases _base_
引号:str

数字:
fromhex frombytes
_doc_:从帮助文档获取字符
dict(list())转换为字符串
内建函数
特殊利用
byte函数:type(str(1).encode)

抛出异常:raise OSError
unicode注入
eval(input)绕过输入长度限制
breakpoint提起时期