sql注入攻击的原理以及防范措施

sql注入攻击的原理以及防范措施

我是艾西,从业多年的IDC服务器机房行业总是会遇到各种各样的网络漏洞以及斗智斗勇的过程,今天和大家聊聊sql注入的方法以及如何防止sql注入

SQL 注入(SQL Injection)是发生在 Web 程序中数据库层的安全漏洞,是网站存在最多也是最简单的漏洞。主要原因是程序对用户输入数据的合法性没有判断和处理,导致攻击者可以在 Web 应用程序中事先定义好的 SQL 语句中添加额外的 SQL 语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步获取到数据信息。

简而言之,SQL 注入就是在用户输入的字符串中加入 SQL 语句,如果在设计不良的程序中忽略了检查,那么这些注入进去的 SQL 语句就会被数据库服务器误认为是正常的 SQL 语句而运行,攻击者就可以执行计划外的命令或访问未被授权的数据。

SQL 注入已经成为互联网世界 Web 应用程序的最大风险,我们有必要从开发、测试、上线等各个环节对其进行防范。下面介绍 SQL 注入的原理及避免 SQL 注入的一些方法。

SQL注入的原理

SQL 注入的原理主要有以下 4 点:

1)恶意拼接查询

我们知道,SQL 语句可以查询、插入、更新和删除数据,且使用分号来分隔不同的命令。例如:

SELECT * FROM users WHERE user_id = $user_id

其中,user_id 是传入的参数,如果传入的参数值为“1234; DELETE FROM users”,那么最终的查询语句会变为:

SELECT * FROM users WHERE user_id = 1234; DELETE FROM users

如果以上语句执行,则会删除 users 表中的所有数据。

2)利用注释执行非法命令。

SQL 语句中可以插入注释。例如:

SELECT COUNT(*) AS 'num' FROM game_score WHERE game_id=24411 AND version=$version

如果 version 包含了恶意的字符串'-1' OR 3 AND SLEEP(500)--,那么最终查询语句会变为:

SELECT COUNT(*) AS 'num' FROM game_score WHERE game_id=24411 AND version='-1' OR 3 AND SLEEP(500)--

以上恶意查询只是想耗尽系统资源,SLEEP(500) 将导致 SQL 语句一直运行。如果其中添加了修改、删除数据的恶意指令,那么将会造成更大的破坏。

3)传入非法参数

SQL 语句中传入的字符串参数是用单引号引起来的,如果字符串本身包含单引号而没有被处理,那么可能会篡改原本 SQL 语句的作用。 例如:

SELECT * FROM user_name WHERE user_name = $user_name

如果 user_name 传入参数值为 G'chen,那么最终的查询语句会变为:

SELECT * FROM user_name WHERE user_name ='G'chen'

一般情况下,以上语句会执行出错,这样的语句风险比较小。虽然没有语法错误,但可能会恶意产生 SQL 语句,并且以一种你不期望的方式运行。

4)添加额外条件

在 SQL 语句中添加一些额外条件,以此来改变执行行为。条件一般为真值表达式。例如:

UPDATE users SET userpass='$userpass' WHERE user_id=$user_id;

如果 user_id 被传入恶意的字符串“1234 OR TRUE”,那么最终的 SQL 语句会变为:

UPDATE users SET userpass= '123456' WHERE user_id=1234 OR TRUE;

这将更改所有用户的密码。

SQL注入:通过在Web表单中插入SQL命令提交或输入域名或页面请求的查询字符串来欺骗服务器执行恶意SQL命令。

具体来说,就是利用现有应用程序将(恶意)SQL命令注入到后台数据库引擎执行中的能力,可以通过在Web表单中输入(恶意)SQL语句来获取安全漏洞网站上的数据库,而不是按照设计者的意图执行 SQL 语句。例如,以往的很多影视网站泄露VIP会员密码的方式大多是通过WEB表单提交查询字符

网站页面包含与数据库交互的部分(如新闻网站的搜索功能),当在网站上输入数据信息时,将数据信息编程并传递给执行的数据库。对传入数据库的相应数据进行安全处理(如过滤特殊字符、编码等),使黑客可以通过网站并在数据库中执行它们。这些以黑客为目的的SQL语句会导致数据库信息的泄露和破坏。

1、数字注入点

很多网页链接都有类似的结构 http://www.XXX.com/123456.php?id=1 基于这种形式的注入,一般称为数字注入点,因为它的注入点 id 类型是一个数字。在大部分网页中,比如查看用户个人信息、查看文章等,大多采用这种结构形式来传递id等信息,交给后端,在数据库中查询相应的信息,然后返回到前台。这类SQL语句的原型大概是select * from table name where id=1 如果有注入,我们可以构造类似下面的SQL注入语句进行爆破: select * from table name where id=1 and 1= 1

2、字符注入点

网页链接结构类似 http://www.XXX.com/users.php?user=admin 在这种形式中,注入点的用户类型是字符类型,所以称为字符注入观点。这类 SQL 语句的原型大概是 select * from table name where user='admin'。值得注意的是,这里的引号比数值注入类型的SQL语句原型要多,可以是单引号,也可以是双引号。如果有注入,我们可以构造类似如下的sql注入语句进行爆破: select * from table name where user='admin' and 1=1 ' 我们需要处理这些烦人的引号。

3、搜索注入点

这是一种特殊类型的注入。这类注入主要是指在数据搜索时不过滤搜索参数。一般链接地址中有“keyword=keyword”,有的链接地址不显示,而是直接通过搜索框表单提交。此类注入点提交的SQL语句的原始形式大致为:select * from table name where field like '%keyword%' 如果有注入,我们可以构造类似如下的SQL注入语句进行爆破:select * 来自表名称,其中字段如 '%test%' 和 '%1%'='%1%'

只要所有输入都与数据库交互,就可能触发 SQL 注入。 SQL注入可分为:按数据提交方式:

(1)GET注入:提交数据的方法是GET,注入点的位置在GET参数部分。比如有这样一个链接http://xxx.com/ news.php?id=1 ,id为注入点。

(2)POST注入:使用POST方式提交数据,注入点位于POST数据部分,经常出现在表单中。

(3)Cookie注入:客户端的cookie会包含在HTTP请求中,注入点存在于cookie中的某个字段中。

(4)HTTP头注入:注入点在HTTP请求头中的一个字段中。例如存在于User-Agent字段中。严格来说cookies也应该被认为是一种header注入.form.因为在HTTP请求中,Cookie是header中的一个字段。

按照提交方式分类后,你会发现SQL注入最长出现在链接地址、数据参数、cookie信息和HTTP请求头中。

了解SQL注入的可能位置,然后我们需要判断这些位置是否可以触发SQL注入。最简单的方法是在对应的位置输入and 1=1(和and 1=1的变换形式)来判断。对于不同的注入点类型,比如字符类型,需要适当加单引号,而对于数字类型的注入点,则不需要。

SQL注入高级分类(按执行效果分类)

1、基于布尔的盲注:即可以根据返回的页面判断条件真假的注入。

2、基于时间的盲注:即不能根据页面返回的内容判断任何信息,使用条件语句检查是否执行了延时语句(即页面返回时间是否增加)。

3、基于错误注入:即页面会返回错误信息,或者注入语句的结果直接返回给页面。

4、联合查询注入:联合可用时注入。

5、堆查询注入:可以同时执行多条语句的注入。

6、宽字节注入:使用gbk是多字节编码,两个字节代表一个汉字

避免SQL注入

对于 SQL 注入,我们可以采取适当的预防措施来保护数据安全。下面是避免 SQL 注入的一些方法。

1. 过滤输入内容,校验字符串

过滤输入内容就是在数据提交到数据库之前,就把用户输入中的不合法字符剔除掉。可以使用编程语言提供的处理函数或自己的处理函数来进行过滤,还可以使用正则表达式匹配安全的字符串。

如果值属于特定的类型或有具体的格式,那么在拼接 SQL 语句之前就要进行校验,验证其有效性。比如对于某个传入的值,如果可以确定是整型,则要判断它是否为整型,在浏览器端(客户端)和服务器端都需要进行验证。

2. 参数化查询

参数化查询目前被视作是预防 SQL 注入攻击最有效的方法。参数化查询是指在设计与数据库连接并访问数据时,在需要填入数值或数据的地方,使用参数(Parameter)来给值。

MySQL 的参数格式是以“?”字符加上参数名称而成,如下所示:

UPDATE myTable SET c1 = ?c1, c2 = ?c2, c3 = ?c3 WHERE c4 = ?c4

在使用参数化查询的情况下,数据库服务器不会将参数的内容视为 SQL 语句的一部分来进行处理,而是在数据库完成 SQL 语句的编译之后,才套用参数运行。因此就算参数中含有破坏性的指令,也不会被数据库所运行。

3. 安全测试、安全审计

除了开发规范,还需要合适的工具来确保代码的安全。我们应该在开发过程中应对代码进行审查,在测试环节使用工具进行扫描,上线后定期扫描安全漏洞。通过多个环节的检查,一般是可以避免 SQL 注入的。

有些人认为存储过程可以避免 SQL 注入,存储过程在传统行业里用得比较多,对于权限的控制是有一定用处的,但如果存储过程用到了动态查询,拼接 SQL,一样会存在安全隐患。

下面是在开发过程中可以避免 SQL 注入的一些方法。

1. 避免使用动态SQL

避免将用户的输入数据直接放入 SQL 语句中,最好使用准备好的语句和参数化查询,这样更安全。

2. 不要将敏感数据保留在纯文本中

加密存储在数据库中的私有/机密数据,这样可以提供了另一级保护,以防攻击者成功地排出敏感数据。

3. 限制数据库权限和特权

将数据库用户的功能设置为最低要求;这将限制攻击者在设法获取访问权限时可以执行的操作。

4. 避免直接向用户显示数据库错误

攻击者可以使用这些错误消息来获取有关数据库的信息。

一些编程框架对于写出更安全的代码也有一定的帮助,因为它提供了一些处理字符串的函数和使用查询参数的方法。但同样,你仍然可以编写出不安全的 SQL 语句。所以归根到底,我们需要有良好的编码规范,并能充分利用参数化查询、字符串处理和参数校验等多种办法来保护数据库和程序的安全。

1.严格区分用户权限

在权限设计中,针对软件用户,没有必要给予数据库的创建、删除等管理权限。这样即便在用户输入的SQL语句种含有内嵌式的恶意程序,因为其权限的限定,也不可能执行。所以程序在权限设计时,最好把管理员与用户区别起来。这样能够最大限度的降低注入式攻击对数据库产生的损害。

2、强制使用参数化语句。

如果用户输入的变量在编写SQL语句时没有直接嵌入到SQL语句中。如果将此变量通过参数传递,则可以有效防止 SQL 注入攻击。也就是说,用户的输入不能直接嵌入到 SQL 语句中。相反,必须过滤用户输入,或者必须使用参数化语句来传递用户输入变量。参数化语句使用参数而不是将用户输入变量嵌入到 SQL 语句中。使用这种措施可以防止大部分的 SQL 注入攻击。不幸的是,支持参数化语句的数据库引擎并不多。但是,数据库工程师在开发产品时应该尽量使用参数化语句。

3、使用 SQL Server 数据库附带的安全参数。

为了减少注入攻击对SQL Server数据库的不利影响,在SQL Server数据库中专门设计了相对安全的SQL参数。在数据库设计过程中,工程师应该尽量利用这些参数来防止恶意SQL注入攻击。

Parameters 集合在 SQL Server 数据库中提供。此集合提供类型检查和长度验证。如果管理员使用Parameters集合,用户输入将被视为字符值而不是可执行代码。即使用户输入包含可执行代码,数据库也会将其过滤掉。因为此时数据库只将其视为普通字符。使用Parameters集合的另一个好处是可以强制执行类型和长度检查,超出范围的值会触发异常。如果用户输入的值不满足指定的类型和长度限制,则会引发异常并报告给管理员。如上例,如果员工编号定义的数据类型为字符串,则长度为10个字符。用户输入的内容也是字符型数据,但长度达到20个字符。此时会抛出异常,因为用户输入的内容长度超过了数据库字段长度的限制。

4、增强的用户输入验证。

一般来说,可以使用两种方法来防止 SQL 注入攻击。一是加强对用户输入内容的检查和验证;另一种是强制使用参数化语句来传递用户输入的内容。在 SQL Server 数据库中,有很多用户输入内容验证工具,可以帮助管理员应对 SQL 注入攻击。测试字符串变量的内容,只接受所需的值。拒绝包含二进制数据、转义序列和注释字符的输入。这有助于防止脚本注入,防止一些缓冲区溢出攻击。测试用户输入的大小和数据类型,实施适当的限制和转换。这有助于防止故意的缓冲区溢出,对防止注入攻击有比较明显的效果。

例如,存储过程可用于验证用户输入。使用存储过程可以过滤用户输入的变量,比如拒绝一些特殊的符号。比如上面的恶意代码,只要存储过程过滤掉分号,恶意代码就没用了。在执行 SQL 语句之前,可以通过数据库的存储过程拒绝接受一些特殊符号。在不影响数据库应用的前提下,应使数据库拒绝包含以下字符的输入。和分号分隔符一样,是SQL注入攻击的主要帮凶。例如注释分隔符。注释仅在数据设计期间使用。一般用户的查询语句中没有必要的注释内容,直接拒绝即可。通常,这样做不会有意外损失。如果这些特殊符号被拒绝,即使 SQL 语句中嵌入了恶意代码,它们也不会做任何事情。

因此,请始终通过测试类型、长度、格式和范围来验证用户输入,并过滤用户输入。这是防止 SQL 注入攻击的常用且行之有效的措施。

5、如何防范多层环境下的SQL注入攻击?

在多层应用环境中,用户输入的所有数据在被允许进入可信区域之前都应该经过身份验证。验证过程失败的数据应被数据库拒绝,并向上层返回错误消息。实施多层身份验证。对没有目的的恶意用户采取的预防措施可能对坚定的攻击者无效。更好的做法是在用户界面和跨信任边界的所有后续点验证输入。例如,验证客户端应用程序中的数据可以防止简单的脚本注入。但是,如果下一层认为其输入已经过验证,则任何可以绕过客户端的恶意用户都可以不受限制地访问系统。因此,对于多层应用环境,在防范注入攻击时,需要各层协同工作,客户端和数据库端都必须采取相应的措施来防范SQL语句注入攻击。

5.利用陷阱账户

可以设定两个账户,即管理员账户和防注入账户。将防注入的账户伪装成管理员账户,如将名称设置为admin,让检测软件产生错觉,在密码方面,可以设置成超长的中文字符(几千字),让攻击者的漏洞检测软件达到高负荷状态直至资源耗尽。

我是艾西,今天的分享就到这里啦。

携手驰网为您网络的道路上保驾护航

猜你喜欢

转载自blog.csdn.net/V13807970340/article/details/129818587