DjangoORM注入分享
DjangoORM注入
简介
这篇文章中,分享一些关于django orm相关的技术积累和如果orm注入相关的安全问题讨论。
攻击效果同数据库注入
从Django-Orm开始
开发角度
Django ORM(Object-Relational Mapping)是Django框架中用于处理数据库操作的一种机制。它允许开发者使用Python代码来描述数据库模式和执行数据库查询,进行数据库操作,如创建、读取、更新和删除数据等操作,而不需要直接编写SQL语句。通过ORM,开发者可以更直观和方便地进行数据库操作,同时保持代码的可读性和可维护性。
- 如果没有ORM,作为后端开发的需要写如下代码
# 假设需求背景 Python 开发人员想要编写一个博客网站,供人们发布文章,并希望向其应用程序添加搜索功能
def search_articles(search_term: str) -> list[dict]:results = []with get_db_connection() as conn:with conn.cursor() as cursor:cursor.execute("SELECT title, body FROM articles WHERE title LIKE %s", (f"%{search_term}%",))rows = cursor.fetchall()for row in rows:results.append({"title": row[0],"body": row[1]})return results
- 换成ORM模式开发如下
# models/article.py
from django.db import modelsclass Article(models.Model):"""The data model for Articles"""title = models.CharField(max_length=255)body = models.TextField()class Meta:ordering = ["title"]# serializers/article.py
class ArticleSerializer(serializers.ModelSerializer):"""How objects of the Article model are serialized into other data types (e.g. JSON)"""class Meta:model = Articlefields = ('title', 'body')# views/article.py
class ArticleView(APIView):"""Some basic API view that users send requests to for searching for articles"""def post(self, request: Request, format=None):# Returns the search URL parameter if present otherwise it is set to Nonesearch_term = request.data.get("search", None)if search_term is not None:articles = Article.objects.filter(title__contains=search_term)else:articles Article.objects.all()serializer = ArticleSerializer(articles, many=True)return Response(serializer.data)
安全角度
Django ORM通常可以防止SQL注入问题,因为它会自动对查询参数进行适当的转义和处理。不过,如果在使用Django ORM时不小心使用了原生的SQL查询或手动构建了SQL语句,也是有SQL注入的问题,不过这个不是这篇文章讨论的主要方向。仅作概述:
- 使用ORM的过滤器方法: 始终使用Django ORM的过滤器方法,而不是手动构建SQL查询。例如:
# 安全的查询方式
users = User.objects.filter(username=username)
- 避免使用raw()方法: raw()方法允许你编写原生SQL查询,但如果不正确处理输入,可能会导致SQL注入。
# 不安全的方式
users = User.objects.raw("SELECT * FROM auth_user WHERE username = '%s'" % username)# 安全的方式
users = User.objects.raw("SELECT * FROM auth_user WHERE username = %s", [username])
- 使用Django的QuerySet API: 尽量避免使用低级别的数据库API,Django的QuerySet API提供了足够的功能来执行大多数查询,而不需要直接编写SQL
# 安全的方式
users = User.objects.filter(email__icontains='example.com')
- 使用参数化查询: 如果必须使用自定义的SQL查询,确保使用参数化查询。
from django.db import connectiondef get_user_by_username(username):with connection.cursor() as cursor:cursor.execute("SELECT * FROM auth_user WHERE username = %s", [username])row = cursor.fetchone()return row
- 变量效验: 在处理用户输入时,始终进行变量效验,以确保输入数据的安全和有效性。
from django.db import connectiondef get_user_by_username(username):with connection.cursor() as cursor:# 使用参数化查询防止SQL注入cursor.execute("SELECT * FROM auth_user WHERE username = %s", [username])user = cursor.fetchone()return user
Django-Orm注入
首先创建一个django应用,能够获取book信息


- 此时的view逻辑为:

- 假设此时后端开发的领导有了如下的要求:
- 需要一个强大的 API 来允许用户按
book模型中的任何字段进行过滤 - 后续会不断新增表中的字段,并且希望 API 无需修改任何代码即可兼容这些更改
- 任务十分紧急
- ....
- 需要一个强大的 API 来允许用户按
- 这个时候开发十分容易写出如下代码

盲注获取敏感字段
写在前面,修改部分代码模拟一个靶场环境:
- 新增flagbook,其中isbn为敏感字段flag,真是环境flag可能为密码、手机号、token等敏感字段

Book.objects.create(title='flagbook', author='flag book', published_date=date(2020, 4, 15), isbn='flag{secret}')
- 修改后端view代码,不返回isbn字段&调整下代码


- 通过
django filter startwith进行注入获取flag
具体 django filter语法可参考 https://docs.djangoproject.com/en/5.0/ref/models/querysets/#id4
- 基础语法,查询
flagbook数据

- 盲注获取
flag poc
startswith正确时如下

startswith错误时如下

- 至此,我们就可以写脚本获取完整的
flag
泄露的条件总结
- 可以控制
filter过滤列 - ORM支持正则、
startswith类似操作 - 表中存在一个隐藏的敏感字段
多表关联的情况
在 Django 中,OneToOneField、ManyToManyField 和 ForeignKey 是用来定义模型之间关系的字段类型。每种字段类型表示不同的数据库关系。
OneToOneField
OneToOneField 表示一对一关系。一个模型实例与另一个模型实例之间有且仅有一个关联。
from django.db import modelsclass UserProfile(models.Model):user = models.OneToOneField(User, on_delete=models.CASCADE)bio = models.TextField()
在这个例子中,每个 UserProfile 实例与一个 User 实例有且只有一个关联。
ManyToManyField
ManyToManyField 表示多对多关系。一个模型实例可以与多个另一个模型实例关联,反之亦然。
class Author(models.Model):name = models.CharField(max_length=100)class Book(models.Model):title = models.CharField(max_length=100)authors = models.ManyToManyField(Author)
在这个例子中,一本书可以有多个作者,一个作者也可以写多本书。
ForeignKey
ForeignKey 表示多对一关系。一个模型实例可以与多个另一个模型实例关联,但反过来每个模型实例只能与一个实例关联。
class Publisher(models.Model):name = models.CharField(max_length=100)class Book(models.Model):title = models.CharField(max_length=100)publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE)
在这个例子中,一本书只能有一个出版社,但一个出版社可以出版多本书。
关系总结
- OneToOneField: 一对一关系
- ManyToManyField: 多对多关系
- ForeignKey: 多对一关系
demo演示
我们修改model代码如下
from django.db import modelsclass Publisher(models.Model):name = models.CharField(max_length=100)address = models.TextField()def __str__(self):return self.nameclass Category(models.Model):name = models.CharField(max_length=100)def __str__(self):return self.nameclass Book(models.Model):title = models.CharField(max_length=200)author = models.CharField(max_length=100)published_date = models.DateField()isbn = models.CharField(max_length=13, unique=True)publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE)categories = models.ManyToManyField(Category)def __str__(self):return self.titleclass BookDetail(models.Model):book = models.OneToOneField(Book, on_delete=models.CASCADE)summary = models.TextField()number_of_pages = models.IntegerField()def __str__(self):return self.book.title
- demo数据如下
import os
import django
import datetime
import randomos.environ.setdefault('DJANGO_SETTINGS_MODULE', 'MyProject.settings')
django.setup()from BookStore.models import Book, Publisher, Category, BookDetail# 清空旧数据
Publisher.objects.all().delete()
Category.objects.all().delete()
Book.objects.all().delete()
BookDetail.objects.all().delete()# 创建 Publisher 示例数据
publishers = [Publisher.objects.create(name=f'Publisher {i}', address=f'{i} Main St') for i in range(1, 6)
]# 创建 Category 示例数据
categories = [Category.objects.create(name=f'Category {i}') for i in range(1, 6)
]# 创建 Book 示例数据
books = [Book.objects.create(title=f'Book {i}',author=f'Author {i}',published_date=datetime.date(2021, 1, i),isbn=f'{1234567890123 + i}',publisher=random.choice(publishers)) for i in range(1, 6)
]# 添加 Book 到 Category
for book in books:book.categories.add(*random.sample(categories, k=2)) # 随机选择两个分类# 创建 BookDetail 示例数据
for book in books:BookDetail.objects.create(book=book,summary=f'This is the summary for {book.title}.',number_of_pages=random.randint(100, 500))print("Demo data created successfully.")
- 依旧是这个接口逻辑不变

- 一对一的方式,通过bookdetail关联 book 的isbn列数据包



- 多对一的方式,通过book 关联 publishers 的address地址列数据包



- 多对多的方式,通过book 关联 Category的name列数据包


写在最后
其余的一点思考:created_by__user__password__regex 类似这种会不会造成数据库redos攻击!因为之前学习过redos,答案很明显:几乎不大可能会。数据库的正则引擎为有限状态向量机。https://xz.aliyun.com/t/14653?
相关文章:
DjangoORM注入分享
DjangoORM注入 简介 这篇文章中,分享一些关于django orm相关的技术积累和如果orm注入相关的安全问题讨论。 攻击效果同数据库注入 从Django-Orm开始 开发角度 Django ORM(Object-Relational Mapping)是Django框架中用于处理数…...
【HBZ分享】Redis各种类型的数据结构应用场景
String(字符串类型) 计数器: incr / decr, 比如商品库存,业务号的发号器业务数据key-value缓存, 缓存结果数据,提高网站性能,缓解DB压力分布式session会话, 集群环境下存储token鉴权信息分布式锁ÿ…...
anaconda创建并且配置pytorch(完整版)
📚博客主页:knighthood2001 ✨公众号:认知up吧 ** 🎃知识星球:【认知up吧|成长|副业】介绍** ❤️如遇文章付费,可先看看我公众号中是否发布免费文章❤️ 🙏笔者水平有限,欢迎各位大…...
高级java每日一道面试题-2024年8月10日-网络篇-你对跨域了解多少?
如果有遗漏,评论区告诉我进行补充 面试官: 你对跨域了解多少? 我回答: 跨域问题,即Cross-Origin Resource Sharing(CORS),是现代Web开发中一个非常重要的概念,涉及到浏览器的安全策略——同源策略(Same…...
AtCoder Beginner Contest 365 A~E
A.Leap Year(思维) 题意: 给你一个介于 1583 1583 1583和 2023 2023 2023之间的整数 Y Y Y。 求公历 Y Y Y年的天数。 在给定的范围内, Y Y Y年的天数如下: 如果 Y Y Y不是 4 4 4的倍数,则为 365 365 …...
多机部署, 负载均衡-LoadBalance
目录 1.负载均衡介绍 1.1问题描述 1.2什么是负载均衡 1.3负载均衡的一些实现 服务端负载均衡 客户端负载均衡 2.Spring Cloud LoadBalancer 2.1快速上手实现负载均衡 2.2负载均衡策略 自定义负载均衡策略 3.服务部署(Linux) 3.1服务构建打包…...
(回溯) LeetCode 78. 子集
原题链接 一. 题目描述 给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的 子集 (幂集)。 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 示例 1: 输入:nums [1,2,3] 输出&…...
DQL数据查询语言(多表处理)—/—<7>
一、多表处理 当前有两个表,一个是学生表student,一个是分数表score student表字段名表示如下(共1000条数据): score表字段表示如下(共6000条数据): 1、求每个学生的总分 SELECT …...
力扣刷题总结
去年有段时间一直在刷题,进步神速,解决了以往刷完就忘的问题,这里总结下经验,给有需要的人参考下,核心观点就仨: 1. 打好数据结构与算法基础 2. 多刷题多练习 3. 形成自己的知识体系 下图是我梳理的知识体…...
BLDC ESC 无刷直流电子调速器驱动方式
BLDC ESC 无刷直流电子调速器驱动方式 1. 源由2. 驱动方法2.1 Trapezoidal 1202.2 Trapezoidal 1502.3 Sinusoidal 1802.4 Field-Orientated Control (FOC) 3. FOC(Field-Oriented Control)3.1 引入坐标系3.2 Clarke and Park变换Clarke 变换(…...
解决 IntelliJ IDEA 编译错误 “Groovyc: Internal groovyc error: code 1” 及 JVM 内存配置问题
在使用 IntelliJ IDEA 进行开发时,我们可能会遇到各种编译和运行错误,其中之一就是 Groovy 编译器错误(Groovyc: Internal groovyc error: code 1)或 JVM 内存不足错误。这类错误可能会影响开发效率,但通过调整 JVM 内…...
LeetCode.2940.找到Alice和Bob可以相遇的建筑
友情提示:这个方法并没有通过案例,只通过了944个案例(很难受),超时了,但是想着还是分享出来吧 题目描述: 给你一个下标从 0 开始的正整数数组 heights ,其中 heights[i] 表示第 i …...
OFD板式文件创建JAVA工具-EASYOFD 四、文字 Text
JAVA版本的OFD板式文件创建工具easyofd. 功能包含了图像、 图像、 文字、和模版页功能。同时也支持OFD文件的数字签名及验签,电子签章及验签。 本JAVA版本的easyofd使用原生方式创建板式文件,不依赖JAVA的SWT库。 项目地址:http://…...
【概念速通】李群 lie group
李群 lie group 概念速通 快速示例介绍:【引入】单位复数 (The unit complex numbers) 是李群 (lie group) 最简单的例子之一【进一步】SO(2): The 2D rotation matrices【Typical uses】SE(2): Pose of a robot in the plane Group & Lie Group 定义࿱…...
day_39
198. 打家劫舍 class Solution:def rob(self, nums: List[int]) -> int:if len(nums) 1:return nums[0]dp [0] * len(nums)dp[0], dp[1] nums[0], max(nums[0], nums[1])for i in range(2, len(nums)):dp[i] max(dp[i - 1], dp[i - 2] nums[i])return dp[len(nums) - …...
计算机系统层次结构
1.计算机系统的组成 计算机系统的组成硬件系统软件系统 2.计算机的硬件部分 2.1冯诺依曼机的结构特点: 图示: 1.五大部分由运算器(ALU),控制器(CU),存储器(主存辅存),输入设备,输出设备五大部分组成2.指…...
java语言特点
Java语言是一种广泛使用的编程语言,它具有以下几个显著的特点: 面向对象:Java是一种纯面向对象的语言,它支持类的封装、继承和多态等特性。面向对象的设计使得Java程序更加模块化,易于维护和扩展。 平台无关性…...
单元测试注解:@ContextConfiguration
ContextConfiguration注解 ContextConfiguration注解主要用于在Spring框架中加载和配置Spring上下文,特别是在测试场景中。 它允许开发者指定要加载的配置文件或配置类的位置,以便在运行时或测试时能够正确地构建和初始化Spring上下文。 基本用途和工…...
大数据-72 Kafka 高级特性 稳定性-事务 (概念多枯燥) 定义、概览、组、协调器、流程、中止、失败
点一下关注吧!!!非常感谢!!持续更新!!! 目前已经更新到了: Hadoop(已更完)HDFS(已更完)MapReduce(已更完&am…...
MySQl 中对数据表的增删改查(基础)
MySQl 中对数据表的增删改查(基础) 新增演示插入一条数据插入多条数据 查询全列查询部分列查询查询关于列名的表达式查询时用别名查询去重后的结果查询排序后的结果条件查询比较运算符和逻辑运算符 分页查询 修改删除 黑白图是在命令行里的,彩…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...
MongoDB学习和应用(高效的非关系型数据库)
一丶 MongoDB简介 对于社交类软件的功能,我们需要对它的功能特点进行分析: 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具: mysql:关系型数据库&am…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...
20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...
C# winform教程(二)----checkbox
一、作用 提供一个用户选择或者不选的状态,这是一个可以多选的控件。 二、属性 其实功能大差不差,除了特殊的几个外,与button基本相同,所有说几个独有的 checkbox属性 名称内容含义appearance控件外观可以变成按钮形状checkali…...
C++中vector类型的介绍和使用
文章目录 一、vector 类型的简介1.1 基本介绍1.2 常见用法示例1.3 常见成员函数简表 二、vector 数据的插入2.1 push_back() —— 在尾部插入一个元素2.2 emplace_back() —— 在尾部“就地”构造对象2.3 insert() —— 在任意位置插入一个或多个元素2.4 emplace() —— 在任意…...
python可视化:俄乌战争时间线关键节点与深层原因
俄乌战争时间线可视化分析:关键节点与深层原因 俄乌战争是21世纪欧洲最具影响力的地缘政治冲突之一,自2022年2月爆发以来已持续超过3年。 本文将通过Python可视化工具,系统分析这场战争的时间线、关键节点及其背后的深层原因,全面…...
