python安全

Python

基础

全局变量

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

截图

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

截图

获取了 b 的__init__方法后调用__globals__属性修改了全局变量以及未继承的类属性

继承链

mro[-1]:获取类的继承关系,最后一个是 class 类,也可以直接用__base__(需要保证直接继承 class)

init.globals:获取方法后调用 globals 获取全局变量

1
2
3
4
5
6
7
payload = {
"__class__" : {
"__base__" : {
"__str__" : "Polluted ~"
}
}
}

获取实例的类之后获取它的基类,修改基类的__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
2
3
import('os').system('sh')
___import__('os').system('cat ./flag.txt')_
open("flag").read()

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://ctf.njupt.edu.cn/archives/805

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

PYjail

基础

image-20240610152619197

import

空格,_import_, importlib.import_module exefile(也可以open之后exec,一般要事先确认一下(path)

过滤引号

str函数

chr函数

list+dict

_doc_

bytes函数

字符串变化

[::-1]

字符串拼接(+)

eval/exec

_loader_.load_module

image-20240610152942891

恢复sys.module

一个存储加载过的模块信息,里面的模块不能直接使用,需要经过import

import一个模块的时候:检查是否存在sys.module中吗,没有则创建并加载,有则不加载

此外,存在modules中的库会优先import,如果在本地创建了同名文件,需要先del

python3之后的reload需要导入importlib模块

假如被禁用了:image-20240610153312932

函数执行

system不是字符串,不能编码绕过

其他函数image-20240610153437556

getattr获取方法属性

image-20240610153513555

image-20240610153552642

内建模块

关于dict:一个模块对象有一个由字典对象实现的命名空间,属性的引用会被转换为这个字典中的查找,例如,m.x 等同于 m.dict[“x”]。

那如果连reload都从__builtins__中删了,就没法恢复__builtins__了,需要另寻他法。还有一种情况是利用 exec command in _global 动态运行语句时的绕过

image-20240610153858787

继承关系逃逸

直接继承与间接继承

site类直接引入了os

image-20240610154233610

warnings类的子类linecache引入了osimage-20240610154308261

image-20240610154324692

也就是先获取warnings再获取linecache再到os

行数限制

exec中\n换行

empile

image-20240612121536686

海象表达式

image-20240612121545670

help()

随便进一个模块 #!或者!sh

server

locals

image-20240612104521484

其他

过滤. [截图] :_getitem_ pop()

python3.6:PEP498image-20240610155737068

__globals__:func_globals

_mro__: _bases _base_

引号:str

image-20240612115730113

数字:image-20240612120104791

fromhex frombytes

_doc_:从帮助文档获取字符

dict(list())转换为字符串

内建函数

特殊利用

byte函数:type(str(1).encode)

image-20240612104158931

抛出异常:raise OSError

unicode注入

eval(input)绕过输入长度限制

breakpoint提起时期

CTF Pyjail 沙箱逃逸绕过合集 - 先知社区 (aliyun.com)

(´∇`) 欢迎回来! (cnblogs.com)


python安全
http://example.com/2024/06/27/python安全/
作者
z2zQAQ
发布于
2024年6月27日
许可协议