[网络安全]SQL注入原理及常见攻击方法简析

简介: 一般而言,登录验证逻辑语句为:select * from 表名 where name(用户名)='$输入' and pass(密码)='$输入'当数据表中同时存在输入的name和pass字段时,页面将回显登录成功。

登陆验证后端逻辑

一般而言,登录验证逻辑语句为:

select * from 表名 where name(用户名)='$输入' and pass(密码)='$输入'

当数据表中同时存在输入的name和pass字段时,页面将回显登录成功。


未知用户名注入攻击原理

若后端逻辑为:select * from users where name='xx' and password='xx'


手工注入

在用户名中输入qiu' or '1=1 ,密码中同样输入qiu' or '1=1

xx被输入的内容替换,查询语句变为:

select * from users where name='qiu' or '1=1' and password='qiu' or '1=1'

等同于


SELECT * FROM users WHERE (name='qiu' or '1'='1') AND (password='qiu' OR '1'='1')

1

括号内的 OR 表达式由于包含了一个恒成立的表达式 ‘1’=‘1’,所以不论用户名与密码是否正确,它始终返回真。

查询条件变为真and真,因此,sql语句注入成功。


基于#注释符的sql注入

在 SQL 语句中,# 号被用作单行注释符号。如果在一条 SQL 语句中以 # 开头,则后面的所有文字都将被解释器忽略掉,不会被执行。


当password不能为空时,用户名输入qiu' or 1=1 #,密码满足不为空即可

注入语句等同于:


select * from users where name='qiu' or 1=1 # and password='xxx'

1

即select * from users where name='qiu' or 1=1

故sql语句注入成功


当password为可为空时,用户名输入qiu' or 1=1 #

注入语句等同于:


select * from user where name='qiu' or 1=1 #' and pass=''

1

即:

select * from user where name='qiu' or 1=1

故sql语句注入成功


基于错误消息的sql注入

当应用程序遇到异常或错误时,会返回相关的错误消息给客户端,这些消息可能包含有关SQL查询语句、数据库表结构和内容等敏感信息。

攻击者可以通过构造sql攻击语句,让应用程序触发错误或异常,并从中获取有利消息。举例如下:


SELECT * FROM users WHERE id=1 AND 1=(SELECT COUNT(*) FROM users GROUP BY CONCAT_WS(':', username, password));

1

该语句使用GROUP BY子句将用户名和密码进行连接,并通过CONCAT_WS函数指定分隔符。由于一个用户只能有一个密码,所以每个组别只有一条记录。COUNT() 函数用于返回匹配指定条件的行数,所以当我们使用COUNT函数统计结果时就可以将结果与数字1进行比较。


如果我们输入任意的用户名及密码,在数据库中查询不到该字段。导致数字1与查询结果不匹配,即1=0,该查询语句会触发一个错误消息,而错误消息可能包含有关SQL语句、数据库和表结构等敏感信息。


报错注入

报错注入是一种常见的 SQL 注入攻击方式,通过向输入参数中插入恶意 SQL 代码,从而导致数据库执行异常 SQL 语句并返回错误信息。攻击者可以通过分析错误信息来获取敏感信息或执行恶意操作。


简要分析利用字符集转换错误

攻击者在输入参数中插入特定的字符集转换函数,例如 CONVERT() 或 CAST(),从而导致数据库执行异常 SQL 语句。当数据库返回错误信息时,这些信息通常会包含一些关键信息,比如数据库名称、表名、字段名等。攻击者可以利用这些信息,进一步构造有效的注入攻击。


假设应用程序中有一个搜索功能,可以根据用户名查询用户信息。当用户输入用户名并提交查询请求时,应用程序会构造以下 SQL 查询语句:


SELECT * FROM users WHERE name='输入的用户名';

1

如果攻击者在输入框中输入以下查询条件:


' CONVERT(int, (SELECT TOP 1 password_hash FROM users)) --

1

则应用程序构造的 SQL 查询语句将变为:


SELECT * FROM users WHERE name='' CONVERT(int, (SELECT TOP 1 password_hash FROM users)) -- ';

1

这条 SQL 语句会触发数据库的异常错误,因为将一个字符串类型的参数转换为整数类型是不合法的。数据库返回的错误消息可能会包含一些关键信息,比如密码哈希值等。


报错注入与基于错误消息的sql注入区别

基于错误信息的 SQL 注入和报错注入其实是同一种攻击方式。它们都是利用了数据库执行异常 SQL 语句时返回错误信息的特性,从而获取敏感信息或执行恶意操作。

区别在于:

基于错误消息的 SQL 注入更侧重于利用错误消息中包含的关键信息,进一步构造有效的注入攻击。而报错注入则更侧重于向数据库中插入一些恶意代码或数据,从而触发数据库的异常错误。


已知用户名注入攻击原理

若已知用户名为qiu


基于- -注释符的sql注入

SQL 使用双短横线注释符号来注释掉整行的内容,并从双短横线开始一直到行末都不会被解释为有效的 SQL 语句。因此,攻击者可以在用户名或密码中添加 --,来注释掉后面的字符串,从而绕过过滤器的检测。例如用户名输入qiu'--,密码输入xx

注入语句等同于:


SELECT * FROM users WHERE username = 'qiu'--'  AND password = 'xx'

1

即SELECT * FROM users WHERE username = 'qiu'


这条 SQL 语句将只查询 users 表中用户名为qiu的记录。

基于/* */注释符的sql注入

SQL 使用斜线星号注释符号来注释掉多行的内容,从/* 开始,到*/结束的区域都会被注释掉。攻击者可以在用户名或密码中添加 /*,来注释掉后面的字符串。例如用户名输入qiu’/* ,密码输入xx

注入语句等同于:


SELECT * FROM users WHERE username = 'qiu'/* AND password = 'xx'

1

即SELECT * FROM users WHERE username = 'qiu'

这条 SQL 语句将只查询 users 表中用户名为qiu的记录。


注意:如果/*注释符号没有被正确地闭合掉,那么在执行 SQL 语句时就会出现语法错误,导致查询失败。为了避免这种情况的发生,一些 SQL 解析器会自动将后续的所有内容视为注释,直到遇到 */ 注释符号为止。


已知用户名与未知用户名攻击区别

对于未知用户名的注入攻击,注入成功后登录的是大概率是普通用户,而一般来说,获取管理员权限是黑客的主要目的。所以在知道管理员用户名时,可使用已知用户名攻击方式获取管理员权限,从而进行访问和窃取敏感数据、破坏和修改系统设置等恶意活动。同时,如果仅仅想登录系统获取相关信息,以上两种攻击方式均可选择。

sql注入绕过

一般来说,登录后端对用户名及密码有验证限制,例如:用户名、密码不能出现特殊字符等。此时常规的 SQL 注入攻击方式可能会被限制或无法成功实施。但这并不意味着 SQL 注入完全无法发生,攻击者仍然有可能利用其它漏洞点进行注入。


利用数字型注入

在数字型注入攻击中,攻击者通常会使用数字类型的变量或参数来注入恶意代码。攻击者将注入的恶意代码嵌入到数字型变量或参数中,并检查应用程序的响应结果以确定是否成功执行该注入。攻击者还可以利用数字运算符、格式字符串和其他SQL语法结构来进行数字型注入攻击。


基于布尔型运算的盲注攻击

盲注攻击是指攻击者无法直接获取查询结果,而只能通过不断猜测和推测来获得信息的一种注入攻击方式。

对于位置参数的SQL语句,攻击者可以通过修改参数值,并在其中嵌入布尔型运算符,从而利用盲注技术进行攻击。通常情况下,布尔型运算符的返回值只有真或假两种情况。

若后端语句如下:


SELECT * FROM users WHERE id = ?


其中id为位置参数,攻击者可以通过修改该参数值来构造恶意的查询语句,例如:


SELECT * FROM users WHERE id = 1 AND (SELECT COUNT(*) FROM users) > 0

1

在这个查询语句中,我们使用布尔型运算符 > 来判断user表中是否存在记录。如果该表中存在数据,那么COUNT函数返回的结果就大于0,故sql语句注入成功。通过不断尝试和推测,攻击者就可以逐步了解目标数据库的内容和结构等敏感信息。


基于联合查询的注入攻击

举例如下:


SELECT * FROM users WHERE id=1; DROP TABLE users;


这个可变参数值可以使SQL语句执行两个操作:首先查询 id 为 1 的用户信息,然后删除 users 表。因此,攻击者可以利用该漏洞非法地访问和操作数据库。

需要注意的是,由于大多数数字类型的数据都不允许附加特定的字符或语法结构。因此,攻击者需要结合使用其它方法,如二进制编码、脚本编码等,来成功地进行数字型注入攻击。


基于数字型操作符的注入攻击

攻击者还可以利用其他数字型操作符来构造注入,例如 AND、UNION、IN 等等。以 IN 操作符为例:

在 SQL 中,IN 操作符用于指定一个值集合,从而在查询时选择与该集合中任意一个值匹配的行。

例如,以下查询语句将检索 id 字段的值等于 1、2 或 3 的用户信息:


SELECT * FROM users WHERE id IN (1, 2, 3);


在数字型注入攻击中,攻击者可以利用这个操作符来向查询语句中注入恶意代码。例如:


SELECT * FROM users WHERE id IN (1, 2, 3) AND 1=1

由于布尔表达式 AND 1=1 恒成立,查询语句中前面的选择条件被忽略,而只保留了恒成立的后面的条件,从而使查询没有了限制条件。这就导致所有的用户记录都被返回。


利用模糊匹配注入

如果应用程序使用模糊匹配或通配符查询,攻击者可以在查询字符串中注入模糊匹配或通配符来扩展查询范围,检索到应用程序不打算公开的数据。

假设某个应用程序提供了一个搜索功能,可以根据关键字查询用户信息。该应用程序使用以下 SQL 查询语句来实现搜索功能:


SELECT * FROM users WHERE username LIKE '输入';


该功能使用了 LIKE 操作符。该操作符允许使用 % 和 _ 这两个通配符来代替查询字符串中的字符。

比如,abc%表示以 abc 开头的字符串,%abc表示以 abc 结尾的字符串。

例如,攻击者可输入如下语句:


xx OR 1=1--


语句变为:


SELECT * FROM users WHERE username LIKE ' xx OR 1=1-- ';

其中--可注释掉后面的语句,由于1=1恒成立,OR前的xx被省略,数据库会返回所有用户信息。


sql注入攻击思路

判断是否存在 Sql 注入漏洞

单引号判断法是一种简单的判断 SQL 注入漏洞的方法。该方法的基本原理是,在输入框中输入一个带有单引号的字符串,如果应用程序对输入参数没有进行正确的过滤和转义,则会发生语法错误,进而证明存在 SQL 注入漏洞。


具体步骤如下:


1.在输入框中输入一个带有单引号的字符串,例如 qiu'


2.观察是否发生了语法错误或异常提示


3.如果出现了语法错误或异常提示,那么说明该应用程序可能存在 SQL 注入漏洞


需要注意的是,单引号判断法只是一种初步的检测方法,不能保证能够检测所有的 SQL 注入漏洞。有些应用程序可能会对输入参数进行合理的过滤和转义,从而避免了单引号判断法的检测。


判断sql注入的类型

数字型注入的判断

假定后端逻辑为select * from <表名> where id = x


当输入x and 1=1时,sql语句变为:


select * from <表名> where id = x and 1=1


语法正确且逻辑判断为真,所以返回正常。


当输入x and 1=2时,sql语句变为:


select * from <表名> where id = x and 1=2


语法正确但是逻辑判断为假,所以返回错误。


若存在以上回显,即可判断该漏洞类型为数字型注入漏洞


字符型注入与数字型注入的区分

假定后端逻辑为select * from <表名> where id ='x'


当输入x and 1=1时,sql语句变为:


select * from <表名> where id ='x and 1=1'


当输入x' and '1'='2时,sql语句变为:


select * from <表名> where id = 'x and 1=2'


查询语句将 and 语句全部转换为了字符串,并没有进行 and 的逻辑判断,所以不会出现数字型注入中返回正常或返回错误的结果。

通过以上,即可判断:如果存在回显,则该漏洞类型不是字符型注入漏洞


字符型注入的判断:

假定后端逻辑为:select * from <表名> where id = 'x'


当输入x' and '1'='1时,sql 语句变为:


select * from <表名> where id = 'x' and '1'='1'


语法正确,逻辑判断正确,所以返回正确

当输入x' and '1'='2时,sql语句变为:


select * from <表名> where id = 'x' and '1'='2'


语法正确,但逻辑判断错误,所以返回错误

若存在以上回显,即可判断该漏洞类型为字符型注入漏洞

布尔型注入

基于布尔盲注的SQL注入攻击是一种利用目标Web应用程序对SQL查询条件正确/错误响应的不同表现来推测查询语句的正确性,从而获取数据库中敏感信息的攻击方式。

1)例如,攻击者可以构造如下SQL语句,用于判断某个字段是否存在:


SELECT CASE WHEN (username = 'admin') THEN 1 ELSE 0 END FROM users

1

这个查询语句选取了users表中的一个字段username,并通过CASE WHEN语句来判断该字段的值是否等于’admin’。如果字段的值等于’admin’,则返回1,说明该字段存在;否则,返回0,说明该字段不存在。


CASE WHEN语句是一个条件表达式,其基本形式如下:

CASE WHEN condition THEN expr1 [ELSE expr2] END

其中,condition是一个逻辑表达式,如果为真,则返回expr1;否则,返回expr2。


该类注入,是需要攻击者知道表名、列名及字段的。这里介绍一种使用ASCII码二分法逐一猜解表名、列名、字段的方法。


先确定要猜解的表名admin,再构造 SQL 查询语句,比如:


SELECT COUNT(*) FROM admin WHERE ascii(mid(table_name,N,1)) > X;

1

其中,N 表示正在猜解的字符在表名中从左到右的位置,X 表示当前猜测的 ASCII 码值。COUNT(*) 函数用于满足条件 ascii(mid(table_name,N,1)) > X 的行数。

若查询结果大于 0,则说明 实际ASCII码值大于当前猜测值,应将x取大;

反之,如果查询结果为 0,则说明实际ASCII 码值小于或等于当前猜测值,应将x取小。重复该步骤,直到找到当前字符的正确 ASCII 码值。


例如,表名第一个字符为a,a的ascii码是97。攻击者在不知道表名的情况下给x赋值,x取64,a>64,回显大于0;x取大,取96,回显大于0,再猜>100,回显小于0;x取小,取98,再猜>98,回显小于0,这样就知道ascii码是97了,即为a。


2)再者,攻击者可以通过修改查询语句中的条件表达式,来判断不同的字段是否存在或符合条件。如下语句可判断某个字段是否为数字类型:


SELECT CASE WHEN ISNUMERIC(column_name) = 1 THEN 1 ELSE 0 END FROM table_name


在这个语句中,ISNUMERIC函数用于判断column_name字段的值是否为数字。如果是数字类型,则返回1;否则,返回0。


时间盲注

基于时间盲注的SQL注入是一种利用Web应用程序对SQL语句的响应时间来推测查询语句正确性的攻击方式。攻击者不停地尝试不同的SQL语句,观察程序的响应时间,从而判断SQL语句是否正确,进而获取数据库中的敏感信息。

例如,攻击者可以构造如下查询语句:


SELECT * FROM users WHERE username = 'admin' AND password = 'password' AND sleep(5) #'


#起作用后,语句变为:


SELECT * FROM users WHERE username = 'admin' AND password = 'password' AND sleep(5)

1

其中,sleep函数用于让数据库暂停执行5秒钟的时间,以便观察Web应用程序的响应时间。如果程序响应时间增长,则说明该漏洞存在时间盲注。


联合注入

基于联合查询的SQL注入是一种数据库查询语句中包含联合查询的攻击方式。攻击者将原始查询结果与构造的SQL查询语句的结果联合到一起,从而获取敏感信息或执行恶意操作。

举例如下:


SELECT * FROM users WHERE username='admin' UNION SELECT NULL,NULL,NULL FROM information_schema.tables --

1

首先,查询 users 表中 username 值为 ‘admin’ 的记录,这是一个正常的 SQL 查询语句。

然后,使用UNION将查询结果与另一个 SELECT 语句的结果合并。第二个SELECT语句中插入了三个NULL 值,来匹配前面查询的 users 表中的字段数目。

最后,利用 – 来注释掉原本的 SQL 查询语句,从而执行恶意代码。攻击者可查询到 information_schema.tables 中的所有表名信息。


实例如下:


SELECT * FROM users WHERE username='admin' UNION SELECT credit_card_number, expiration_date FROM credit_cards

攻击者将从 credit_cards 表中获取到信用卡号和过期日期等敏感信息

若回显成功,则说明该漏洞存在联合注入。


总结

以上为SQL注入常见原理及攻击方法简析。由于SQL语言的复杂性、灵活性及作者水平有限,本文仅供参考;具体姿势及其它注入原理、方法读者可自行探索。

后续会分享DVWA应用程序及SQLLABS测试平台相关注入知识、攻击姿势。


我是秋说,我们下次见。


目录
相关文章
|
8月前
|
存储 SQL 关系型数据库
mysql底层原理:索引、慢查询、 sql优化、事务、隔离级别、MVCC、redolog、undolog(图解+秒懂+史上最全)
mysql底层原理:索引、慢查询、 sql优化、事务、隔离级别、MVCC、redolog、undolog(图解+秒懂+史上最全)
mysql底层原理:索引、慢查询、 sql优化、事务、隔离级别、MVCC、redolog、undolog(图解+秒懂+史上最全)
|
11月前
|
SQL 安全 关系型数据库
SQL注入之万能密码:原理、实践与防御全解析
本文深入解析了“万能密码”攻击的运行机制及其危险性,通过实例展示了SQL注入的基本原理与变种形式。文章还提供了企业级防御方案,包括参数化查询、输入验证、权限控制及WAF规则配置等深度防御策略。同时,探讨了二阶注入和布尔盲注等新型攻击方式,并给出开发者自查清单。最后强调安全防护需持续改进,无绝对安全,建议使用成熟ORM框架并定期审计。技术内容仅供学习参考,严禁非法用途。
1705 0
|
10月前
|
SQL 存储 自然语言处理
SQL的解析和优化的原理:一条sql 执行过程是什么?
SQL的解析和优化的原理:一条sql 执行过程是什么?
SQL的解析和优化的原理:一条sql 执行过程是什么?
|
监控 安全 网络安全
深入解析PDCERF:网络安全应急响应的六阶段方法
PDCERF是网络安全应急响应的六阶段方法,涵盖准备、检测、抑制、根除、恢复和跟进。本文详细解析各阶段目标与操作步骤,并附图例,助读者理解与应用,提升组织应对安全事件的能力。
2126 89
|
SQL 安全 Java
除了Flask框架,还有哪些框架能防止SQL注入攻击?
这些框架都在安全方面有着较好的表现,通过它们的内置机制和安全特性,可以有效地降低 SQL 注入攻击的风险。然而,无论使用哪个框架,开发者都需要具备良好的安全意识,正确配置和使用框架提供的安全功能,以确保应用的安全可靠。同时,持续关注安全更新和漏洞修复也是非常重要的。
633 162
|
11月前
|
SQL 人工智能 自然语言处理
Text2SQL圣经:从0到1精通Text2Sql(Chat2Sql)的原理,以及Text2Sql开源项目的使用
Text2SQL圣经:从0到1精通Text2Sql(Chat2Sql)的原理,以及Text2Sql开源项目的使用
Text2SQL圣经:从0到1精通Text2Sql(Chat2Sql)的原理,以及Text2Sql开源项目的使用
|
机器学习/深度学习 数据采集 人工智能
GeneralDyG:南洋理工推出通用动态图异常检测方法,支持社交网络、电商和网络安全
GeneralDyG 是南洋理工大学推出的通用动态图异常检测方法,通过时间 ego-graph 采样、图神经网络和时间感知 Transformer 模块,有效应对数据多样性、动态特征捕捉和计算成本高等挑战。
408 18
GeneralDyG:南洋理工推出通用动态图异常检测方法,支持社交网络、电商和网络安全
|
SQL 缓存 Java
框架源码私享笔记(02)Mybatis核心框架原理 | 一条SQL透析核心组件功能特性
本文详细解构了MyBatis的工作机制,包括解析配置、创建连接、执行SQL、结果封装和关闭连接等步骤。文章还介绍了MyBatis的五大核心功能特性:支持动态SQL、缓存机制(一级和二级缓存)、插件扩展、延迟加载和SQL注解,帮助读者深入了解其高效灵活的设计理念。
|
SQL 存储 关系型数据库
MySQL进阶突击系列(01)一条简单SQL搞懂MySQL架构原理 | 含实用命令参数集
本文从MySQL的架构原理出发,详细介绍其SQL查询的全过程,涵盖客户端发起SQL查询、服务端SQL接口、解析器、优化器、存储引擎及日志数据等内容。同时提供了MySQL常用的管理命令参数集,帮助读者深入了解MySQL的技术细节和优化方法。