Python SQL 注入攻击及其防护措施:编写安全的数据库查询

Python SQL 注入攻击及其防护措施:编写安全的数据库查询

SQL 注入(SQL Injection)是一种常见且危险的安全漏洞,攻击者通过操纵应用程序的数据库查询输入,执行未经授权的操作,可能会导致数据库数据泄露、篡改,甚至破坏整个数据库。特别是在使用编程语言(如 Python)开发与数据库交互的 Web 应用程序时,开发者如果没有严格检查用户输入,就可能为 SQL 注入攻击留下漏洞。

在本文中,我们将深入了解 SQL 注入的原理、常见的攻击方式以及如何在 Python 中编写安全的数据库查询,防止 SQL 注入攻击。

在这里插入图片描述

一、什么是 SQL 注入攻击?

SQL 注入是指攻击者通过将恶意的 SQL 代码插入到应用程序的数据库查询语句中,从而改变原始 SQL 语句的逻辑,执行未经授权的查询或命令。它是由于应用程序在处理用户输入时,直接将用户的输入嵌入到 SQL 语句中而没有经过正确的处理或转义。

1. SQL 注入的原理

为了更好地理解 SQL 注入的工作原理,我们来看一个简单的示例:

假设我们有一个登录页面,它通过以下 SQL 查询语句来验证用户的用户名和密码:

SELECT * FROM users WHERE username = 'user_input' AND password = 'password_input';

如果用户输入 usernameadminpassword1234,那么 SQL 查询将变为:

SELECT * FROM users WHERE username = 'admin' AND password = '1234';

但如果攻击者输入的用户名为 ' OR '1'='1,而密码为 ' OR '1'='1,SQL 查询将变为:

SELECT * FROM users WHERE username = '' OR '1'='1' AND password = '' OR '1'='1';

因为 '1'='1' 永远为真,所以这个查询将绕过身份验证,攻击者可以以任何身份登录。

2. SQL 注入的危害

SQL 注入的危害包括但不限于:

  • 未经授权的访问:攻击者可以通过 SQL 注入绕过身份验证,访问系统中的敏感数据。
  • 数据泄露:攻击者可以获取数据库中的敏感信息,例如用户名、密码、财务信息等。
  • 数据篡改:攻击者可以插入、更新或删除数据库中的数据。
  • 系统破坏:攻击者甚至可以破坏整个数据库或执行破坏性的操作。

二、如何检测 SQL 注入漏洞?

SQL 注入漏洞通常存在于没有正确处理用户输入的应用程序中,特别是那些通过字符串拼接来构造 SQL 查询的程序。为了检测 SQL 注入漏洞,开发者可以:

  1. 手动测试:尝试在用户输入字段中输入常见的 SQL 注入语句,如 OR '1'='1'-- 等。
  2. 使用安全测试工具:使用专业的安全测试工具(如 SQLMap、OWASP ZAP)扫描 Web 应用程序,检测是否存在 SQL 注入漏洞。
  3. 代码审查:检查代码中的 SQL 查询,特别是那些通过拼接字符串生成的 SQL 语句,确认是否存在用户输入未经过滤直接插入 SQL 语句的情况。

三、Python 中 SQL 注入的示例

为了更清楚地理解 SQL 注入问题,以下是 Python 中通过 sqlite3 模块执行不安全 SQL 查询的示例:

import sqlite3# 连接数据库
conn = sqlite3.connect(':memory:')
cursor = conn.cursor()# 创建一个简单的用户表
cursor.execute('''CREATE TABLE users (username TEXT, password TEXT)''')
cursor.execute('''INSERT INTO users (username, password) VALUES ('admin', 'password123')''')
conn.commit()# 不安全的查询方式
def unsafe_login(username, password):query = f"SELECT * FROM users WHERE username = '{username}' AND password = '{password}'"cursor.execute(query)return cursor.fetchone()# 测试 SQL 注入
user_input_username = "admin' OR '1'='1"
user_input_password = "wrong_password' OR '1'='1"# 执行不安全的查询
user = unsafe_login(user_input_username, user_input_password)
if user:print("Login successful!")
else:print("Login failed!")

输出结果

即使输入的密码是错误的,由于 SQL 注入的存在,这段代码仍然会输出“Login successful!”,因为查询中的 OR '1'='1' 总是为真,从而导致 SQL 语句成功执行。

四、如何防止 SQL 注入攻击?

为了防止 SQL 注入,开发者应避免直接将用户输入拼接到 SQL 查询中。相反,应该使用预处理语句(Prepared Statements)和参数化查询(Parameterized Queries),确保用户输入被安全处理。

1. 使用参数化查询

参数化查询是一种安全的 SQL 查询方式,它将用户输入与 SQL 语句分离,确保用户输入被作为数据处理,而不是代码执行。以下是 Python 中使用参数化查询的示例:

import sqlite3# 安全的查询方式
def safe_login(username, password):query = "SELECT * FROM users WHERE username = ? AND password = ?"cursor.execute(query, (username, password))return cursor.fetchone()# 测试安全查询
user = safe_login(user_input_username, user_input_password)
if user:print("Login successful!")
else:print("Login failed!")

在这个示例中,? 是占位符,sqlite3 模块会自动处理用户输入,确保其不会被解释为 SQL 代码。这样可以有效防止 SQL 注入攻击。

2. 使用 ORM(对象关系映射)

在使用 Python 的 Web 框架(如 Django、Flask)开发时,ORM 是防止 SQL 注入的另一种常用方式。ORM 将数据库表映射为 Python 类,通过对象方法来执行数据库操作,避免了手动编写 SQL 语句的风险。

例如,在 Flask 中使用 SQLAlchemy ORM 时,查询语句如下:

from flask_sqlalchemy import SQLAlchemydb = SQLAlchemy()class User(db.Model):id = db.Column(db.Integer, primary_key=True)username = db.Column(db.String(80), unique=True, nullable=False)password = db.Column(db.String(120), nullable=False)# 安全的查询方式
user = User.query.filter_by(username=user_input_username, password=user_input_password).first()

SQLAlchemy 自动处理查询中的参数,防止 SQL 注入。

3. 其他防护措施

除了使用参数化查询和 ORM 外,以下是一些其他的防护措施:

  • 输入验证与过滤:对用户输入进行严格的验证和过滤,确保输入符合预期的格式和内容。
  • 最小权限原则:数据库用户应该只拥有应用程序所需的最低权限,防止恶意用户利用 SQL 注入攻击执行高权限操作。
  • 使用 Web 应用防火墙:可以使用 Web 应用防火墙(WAF)来检测和拦截潜在的 SQL 注入攻击。
  • 记录和监控:设置日志记录机制,监控异常的 SQL 查询行为,及时发现并处理潜在的安全漏洞。

五、实践:编写安全的查询代码

假设我们要开发一个简单的 Flask 应用,允许用户通过登录页面访问系统。为了确保应用程序不受 SQL 注入攻击的影响,我们可以使用 Flask 和 SQLAlchemy 来编写安全的查询代码。

1. 创建 Flask 项目

首先,创建并配置一个 Flask 项目,使用 SQLAlchemy 作为 ORM:

pip install Flask Flask-SQLAlchemy
from flask import Flask, request
from flask_sqlalchemy import SQLAlchemyapp = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)class User(db.Model):id = db.Column(db.Integer, primary_key=True)username = db.Column(db.String(80), unique=True, nullable=False)password = db.Column(db.String(120), nullable=False)@app.route('/login', methods=['POST'])
def login():username = request.form['username']password = request.form['password']# 使用 ORM 查询用户user = User.query.filter_by(username=username, password=password).first()if user:return f"Welcome, {user.username}!"else:return "Login failed."if __name__ == '__main__':db.create_all()  # 初始化数据库app.run(debug=True)

2. 安全测试

为了测试安全性,我们可以尝试输入恶意的 SQL 语句,例如在用户名字段中输入 ' OR '1'='1。因为 SQLAlchemy 使用了 ORM 查询方式,SQL 注入攻击将不起作用。

3. 提升安全性

除了使用 ORM 防止 SQL 注入之外,我们还可以对输入

进行进一步的验证和过滤,例如使用正则表达式限制用户名的格式,确保输入是合法的字符串。

六、总结

SQL 注入攻击是 Web 开发中常见且严重的安全问题,开发者在编写数据库查询时必须格外谨慎。通过使用参数化查询、ORM 以及其他安全实践,可以有效防止 SQL 注入攻击,保护应用程序和用户的数据安全。

本文详细介绍了 SQL 注入的原理、攻击方式以及防护措施,并通过 Python 示例展示了如何编写安全的数据库查询。希望通过这些内容,读者可以掌握如何在 Python 项目中防止 SQL 注入,编写更加安全的应用程序。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/452449.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

闯关leetcode——136. Single Number

大纲 题目地址内容 解题代码地址 题目 地址 内容 Given a non-empty array of integers nums, every element appears twice except for one. Find that single one. You must implement a solution with a linear runtime complexity and use only constant extra space. …

leetcode30:串联所有单词的字串

给定一个字符串 s 和一个字符串数组 words。 words 中所有字符串 长度相同。 s 中的 串联子串 是指一个包含 words 中所有字符串以任意顺序排列连接起来的子串。 例如,如果 words ["ab","cd","ef"], 那么 "abcdef…

thinkpad E14 GEN5 加内存

1、正面 2、背面 3、角落 松掉所有螺丝后,用塑料撬片沿着角落开始撬。把所有的卡口都撬开就可以了。 4、内存盖子 取下背板,就看到内存区域了。上面覆盖了一个散热金属盖子。 拿掉金属盖子。 5、内存卡口 我的这代笔记本是板载16G DDR4 3200内存&…

Java 类和对象详解(下)

个人主页:鲤鱼王打挺-CSDN博客 目录 💗前言: 💯一.static关键字 1. 为什么要使用static 2. static 修饰成员变量: 3. static 修饰成员方法: ​编辑 4. 静态代码块 5.静态导入包 💯二.…

C++进阶——set和map

目录 前言 一、set 1.set的基本介绍 2.set的使用 2.1构造与迭代器 2.2插入 2.3删除 2.4查找 2.5获取需要的区间 2.6一些使用示例 3.set和multiset的区别 4.set相关oj题目 二、map 1.map的基本介绍 2.map的使用 2.1构造与迭代器 2.2增删查以及获取区间 2.3数据…

【C语言】strtok、strerror函数

1、strtok函数使用 注意:使用strtok时包含头文件:string.h strtok函数原型: char* strtok(char* str, const char* sep); (1)sep参数指向一个字符串,定义了用作分隔符的字符集合。 &#x…

xlsx xlsx-style-vite 实现前端根据element 表格导出excel且定制化样式 背景 列宽等

前言 先看下最终效果图吧,需要的可以参考我的实现方式 这是最终导出的表格文件 类似这种的,特定单元格需要额外标注,表头也有月份然后细分的,表格组件是这样的 注意 别使用xlsx-style 这个库,太多问题了,…

优阅达携手 Theobald 亮相新加坡科技周,助力企业 SAP 数据集成与应用

针对不同用户需求量身定制解决方案,帮助企业轻松应对从数据提取到分析、从开发到流程管理的 SAP 数据挑战。 上周,2024 新加坡科技周在滨海湾金沙会议展览中心圆满落幕。在为期两天的活动中,七大专题展览同时进行,超过 2,000 家…

【Router】路由器中NAT、NAPT、NPT是什么?

参考链接 NAT vs. NAPT: What’s the Difference? IPv6 Network Prefix Translation (NPt) | pfSense Documentation (netgate.com) 趣谈NAT/NAPT的原理,这篇不可不读! - 知乎 (zhihu.com) NAT (Network Address Translation) NAT说明 NAT&#x…

Java | Leetcode Java题解之第486题预测赢家

题目&#xff1a; 题解&#xff1a; class Solution {public boolean PredictTheWinner(int[] nums) {int length nums.length;int[] dp new int[length];for (int i 0; i < length; i) {dp[i] nums[i];}for (int i length - 2; i > 0; i--) {for (int j i 1; j …

SQL Server 2019数据库“正常,已自动关闭”

现象&#xff1a; SQL Server 2019中&#xff0c;某个数据库在SQL Server Management Studio&#xff08;SSMS&#xff09;中的状态显示为“正常&#xff0c;已自动关闭”。 解释&#xff1a; 如此显示&#xff0c;是由于该数据库的AUTO_ CLOSE选项被设为True。 在微软的官…

webAPI中的排他思想、自定义属性操作、节点操作(配大量案例练习)

一、排他操作 1.排他思想 如果有同一组元素&#xff0c;我们想要某一个元素实现某种样式&#xff0c;需要用到循环的排他思想算法&#xff1a; 1.所有的元素全部清除样式 2.给当前的元素设置样式 注意顺序能不能颠倒&#xff0c;首先清除全部样式&#xff0c;再设置自己当前的…

位运算题目-Java实现-LeetCode题解:判断字符是否唯一-丢失的数字-两整数之和-只出现一次的数字 II-消失的两个数字

这里是Themberfue 上一篇文章讲完了常见位运算的技巧以及总结 那么本章则通过五道题来运用这些技巧 判定字符是否唯一 题目解析 本题要求判断给定字符串中的字符是否唯一&#xff0c;也就是每个字符是否只出现一次 算法讲解 本题用哈希表遍历每一个字符也可以解决 如果这题使…

设计模式02-桥接模式(Java)

4.2 桥接模式 **1.定义&#xff1a;**将抽象与实现分离&#xff0c;使它们可以独立变化。它是用组合关系代替继承关系来实现&#xff0c;从而降低了抽象和实现这两个可变维度的耦合度。 2.结构&#xff1a; 抽象化角色 &#xff1a;定义抽象类&#xff0c;并包含一个对实现化…

【conda】创建、激活、删除虚拟环境

前言一、创建虚拟环境二、删除虚拟环境总结 前言 主要是记录一下步骤 一、创建虚拟环境 地址栏输入cmd&#xff0c;唤起命令符栏目&#xff0c;就可以在指定目录下创建虚拟环境了。 这样方便日后在pycharm直接配置虚拟环境。 conda create -n yolo5-lite python3.9 -y简单来说…

诺贝尔物理学奖:机器学习与神经网络的时代

前言 2024年&#xff0c;诺贝尔物理学奖首次颁发给机器学习与神经网络领域的研究者&#xff0c;标志着科学评奖标准的历史性转变。这一决定引发了学术界的广泛关注&#xff0c;也促使人们深入思考科学研究及其应用的未来。 机器学习与物理学的交融 传统上&#xff0c;诺贝尔物…

Linux中部署Mysql保姆级教程

一、版本说明 本文的版本号是5.7.30&#xff0c;5.6及以上版本的MySQL要求Linux系统虚拟内存不能小于1G&#xff0c;否则MySQL可能无法运行。 二、安装前的准备 2.1查看系统自带的Mariadb rpm -qa|grep mariadb 安装mysql为什么需要卸载mariadb&#xff1a; 以前的Li…

ReactOS系统中搜索给定长度的空间地址区间中的二叉树

搜索给定长度的空间地址区间 //搜索给定长度的空间地址区间 MmFindGapTopDown PVOID NTAPI MmFindGap(PMADDRESS_SPACE AddressSpace,ULONG_PTR Length,ULONG_PTR Granularity,BOOLEAN TopDown );PMADDRESS_SPACE AddressSpace,//该进程用户空间 ULONG_PTR Length,//寻找的空…

java--网络编程

网络的相关概念 网络通信 1.概念:两台设备之间通过网络实现数据传输2.网络通信:将数据通过网络从一台设备传输到另一台设备3.java.net包下提供了一系列的类或接口&#xff0c;供程序员使用&#xff0c;完成网络通信 网络 概念&#xff1a;两台或多台设备通过一定物理设备连接…

P2-3与P2-4.【C语言基本数据类型、运算符和表达式】第三节与第四节

讲解视频&#xff1a; P2-3.【基本数据类型、运算符和表达式】第三节 P2-4.【基本数据类型、运算符和表达式】第四节 目录 必备知识与理论 任务实施 必备知识与理论 C语言中把除了控制语句和输入输出以外的几乎所有的基本操作都作为运算符处理。 其运算符和表达式数量之多&a…