热门搜索 :
考研考公
您的当前位置:首页正文

如何防御SQL注入

2023-11-09 来源:东饰资讯网

$uid = addslashes(uid);$sql = "SELECT uid,username FROM user WHERE uid=‘{$uid}‘";

以及

$uid = isset($_GET[‘uid‘]) ? $_GET[‘uid‘] : 0;$uid = addslashes(uid);$sql = "SELECT uid,username FROM user WHERE uid={$uid}";

上面两个查询语句都经过了php的addslashes函数过滤转义,但在安全性上却大不相同,在MySQL中,对于int类型字段的条件查询,上面个语句的查询效果完全一样,由于第一句SQL的变量被单引号包含起来,SQL注入的时候,黑客面临的首要问题是必须要先闭合前面的单引号,这样才能使后面的语句作为SQL执行,并且还要注释掉原SQL语句中的后面的单引号,这样才可以成功注入,由于代码里使用了addslashes函数,黑客的攻击会无从下手,但第二句没有用引号包含变量,那黑客也不用考虑去闭合、注释,所以即便同样采用addslashes转义,也还是存在SQL攻击漏洞。

对于PHP程序+MySQL构架的程序,在动态的SQL语句中,使用单引号把变量包含起来配合addslashes函数是应对SQL注入攻击的有效手段,但这做的还不够,像上面的2条SQL语句,根据「检查数据类型」的原则,uid都应该经过intval函数格式为int型,这样不仅能有效避免第二条语句的SQL注入漏洞,还能使得程序看起来更自然,尤其是在NoSQL(如MongoDB)中,变量类型一定要与字段类型相匹配才可以。

从上面可以看出,第二个SQL语句是有漏洞的,不过由于使用了addslashes函数,你会发现黑客的攻击语句也存在不能使用特殊符号的条件限制,类似where username=‘plhwin‘这样的攻击语句是没法执行的,但是黑客可以将字符串转为16进制编码数据或使用char函数进行转化,同样能达到相同的目的。而且由于SQL保留关键字,如「HAVING」、「ORDER BY」的存在,即使是基于黑白名单的过滤方法仍然会有或多或少问题,那么是否还有其他方法来防御SQL注入呢?

3、绑定变量,使用预编译语句

MySQL的mysqli驱动提供了预编译语句的支持,不同的程序语言,都分别有使用预编译语句的方法,我们这里仍然以PHP为例,编写userinfo2.php代码:

<?phpheader(‘Content-type:text/html; charset=UTF-8‘);$username = isset($_GET[‘username‘]) ? $_GET[‘username‘] : ‘‘;$userinfo = array();if($username){//使用mysqli驱动连接demo数据库$mysqli = new mysqli("localhost", "root", "root", ‘demo‘);//使用问号替代变量位置$sql = "SELECT uid,username FROM user WHERE username=?";$stmt = $mysqli->prepare($sql);//绑定变量$stmt->bind_param("s", $username);$stmt->execute();$stmt->bind_result($uid, $username);while ($stmt->fetch()) { $row = array(); $row[‘uid‘] = $uid; $row[‘username‘] = $username; $userinfo[] = $row;}}echo ‘<pre>‘,print_r($userinfo, 1),‘</pre>‘;

从上面的代码可以看到,我们程序里并没有使用addslashes函数,但是浏览器里运行 http://localhost/test/userinfo2.php?username=plhwin‘ AND 1=1-- hack 里得不到任何结果,说明SQL漏洞在这个程序里并不存在。

实际上,绑定变量使用预编译语句是预防SQL注入的最佳方式,使用预编译的SQL语句语义不会发生改变,在SQL语句中,变量用问号?表示,黑客即使本事再大,也无法改变SQL语句的结构,像上面例子中,username变量传递的plhwin‘ AND 1=1-- hack参数,也只会当作username字符串来解释查询,从根本上杜绝了SQL注入攻击的发生。

数据库信息加密安全

相信大家都还对2011年爆出的CSDN拖库事件记忆犹新,这件事情导致CSDN处在风口浪尖被大家痛骂的原因就在于他们竟然明文存储用户的密码,这引发了科技界对用户信息安全尤其是密码安全的强烈关注,我们在防范SQL注入的发生的同时,也应该未雨绸缪,说不定下一个被拖库的就是你,谁知道呢。

在Web开发中,传统的加解密大致可以分为三种:

1、对称加密:

即加密方和解密方都使用相同的加密算法和密钥,这种方案的密钥的保存非常关键,因为算法是公开的,而密钥是保密的,一旦密匙泄露,黑客仍然可以轻易解密。常见的对称加密算法有:AES、DES等。

2、非对称加密:

即使用不同的密钥来进行加解密,密钥被分为公钥和私钥,用私钥加密的数据必须使用公钥来解密,同样用公钥加密的数据必须用对应的私钥来解密,常见的非对称加密算法有:RSA等。

3、不可逆加密:

利用哈希算法使数据加密之后无法解密回原数据,这样的哈希算法常用的有:md5、SHA-1等。

在我们上面登录系统的示例代码中,$md5password = md5($password); 从这句代码可以看到采用了md5的不可逆加密算法来存储密码,这也是多年来业界常用的密码加密算法,但是这仍然不安全。为什么呢?

这是因为md5加密有一个特点:同样的字符串经过md5哈希计算之后生成的加密字符串也是相同的,由于业界采用这种加密的方式由来已久,黑客们也准备了自己强大的md5彩虹表来逆向匹配加密前的字符串,这种用于逆向反推MD5加密的彩虹表在互联网上随处可见,在Google里使用md5 解密作为关键词搜索,一下就能找到md5在线破解网站,把我们插入用户数据时候的MD5加密字符串e10adc3949ba59abbe56e057f20f883e填入进去,瞬间就能得到加密前的密码:123456。当然也并不是每一个都能成功,但可以肯定的是,这个彩虹表会越来越完善。

所以,我们有迫切的需求采用更好的方法对密码数据进行不可逆加密,通常的做法是为每个用户确定不同的密码加盐(salt)后,再混合用户的真实密码进行md5加密,如以下代码:

<?php//用户注册时候设置的password$password = $_POST[‘password‘];//md5加密,传统做法直接将加密后的字符串存入数据库,但这不够,我们继续改良$passwordmd5 = md5($password);//为用户生成不同的密码盐,算法可以根据自己业务的需要而不同$salt = substr(uniqid(rand()), -6);//新的加密字符串包含了密码盐$passwordmd5 = md5($passwordmd5.$salt);
小结

1、不要随意开启生产环境中Webserver的错误显示。2、永远不要信任来自用户端的变量输入,有固定格式的变量一定要严格检查对应的格式,没有固定格式的变量需要对引号等特殊字符进行必要的过滤转义。3、使用预编译绑定变量的SQL语句。4、做好数据库帐号权限管理。5、严格加密处理用户的机密信息。

如何防御SQL注入

标签:

小编还为您整理了以下内容,可能对您也有帮助:

如何对sql注入进行防护

对sql注入进行防护的方法有:分级管理、参数传值、基础过滤与二次过滤、使用安全参数、漏洞扫描。

1、分级管理:对用户进行分级管理,严格控制用户的权限,对于普通用户,禁止给予数据库建立、删除、修改等相关权限,只有系统管理员才具有增、删、改、查的权限。

2、参数传值:程序员在书写SQL语言时,禁止将变量直接写入到SQL语句,必须通过设置相应的参数来传递相关的变量。从而抑制SQL注入。数据输入不能直接嵌入到查询语句中。同时要过滤输入的内容,过滤掉不安全的输入数据。或者采用参数传值的方式传递输入变量,这样可以最大程度防范SQL注入攻击。

3、基础过滤与二次过滤:SQL注入攻击前,入侵者通过修改参数提交and等特殊字符,判断是否存在漏洞,然后通过select、update等各种字符编写SQL注入语句。因此防范SQL注入要对用户输入进行检查,确保数据输入的安全性,在具体检查输入或提交的变量时,对于单引号、双引号、冒号等字符进行转换或者过滤,从而有效防止SQL注入。

4、使用安全参数:SQL数据库为了有效抑制SQL注入攻击的影响。在进行SQLServer数据库设计时设置了专门的SQL安全参数。在程序编写时应尽量使用安全参数来杜绝注入式攻击,从而确保系统的安全性。

5、漏洞扫描:为了更有效地防范SQL注入攻击,作为系统管理除了设置有效的防范措施,更应该及时发现系统存在SQL攻击安全漏洞。系统管理员可以采购一些SQL漏洞扫描工具,通过专业的扫描工具,可以及时的扫描到系统存在的相应漏洞。

如何防范SQL注入攻击

如何防范SQL注入攻击?

如何防范SQL注入攻击?

SQL注入攻击是应用程序中最常见的安全漏洞之一。注入攻击者将恶意脚本注入到应用程序的SQL查询中,以获取敏感数据或者暴露系统的漏洞。如果您拥有一个包含用户输入的网站或应用程序,那么您需要采取一些措施来防范SQL注入攻击。以下是一些防止SQL注入攻击的最佳实践:

1.输入验证

输入验证是预防SQL注入攻击的最基本的方法。应用程序必须对所有的用户输入数据进行验证和检查,确保输入的内容符合应该的格式和类型。最常用的方法是使用正则表达式来验证数据。例如,如果用户要输入一个数字,则应该检查是否是数字,排除非数字的字符。如果应用程序期望收到文本,则应该验证输入的内容是否仅仅是纯文本。最好的方法是使用框架来处理输入验证,这些框架可以提供已经封装好的验证规则。

2.命令参数化

命令参数化是一种安全的SQL查询方式,能够有效地防范SQL注入攻击。当您使用命令参数化的方式将输入内容传递给数据库时,数据库会将输入数据当成参数来处理,而不是转换为SQL代码。这意味着如果有人试图注入恶意SQL代码,数据库会将恶意代码视为参数而不是代码,从而避免了漏洞。

3.减少错误信息的公开

避免将错误信息发送给客户端是预防SQL注入攻击的另一个重要步骤。通常,错误信息可能包含敏感数据,这些数据可以让攻击者更加了解应用程序和数据库的结构。由于攻击者了解了应用程序和数据库的结构,他们就可以更加轻易地导入SQL注入攻击。因此,您应该仅向管理员发送报错信息,以便检查系统错误。

4.权限控制

不同的用户需要访问不同的数据。因此,您应该采取措施来用户的访问权限。这意味着应该仅允许访问用户需要的数据,而不是整个数据库。同时,您应该仅允许用户的最低访问权限来保持安全。应用程序应该基于角色为用户分配权限。

5.安全维护

您应该定期检查应用程序的漏洞,并保持应用程序的安全更新。您还应该采取预防措施,例如升级软件版本和服务器硬件,以确保您的应用程序和数据库能够正常运行。此外,您应该采取保护措施,例如数据加密、数据备份和安全访问控制,以确保数据安全。

总之,SQL注入攻击是一种常见的网络攻击方式,而且对于大多数企业来说,它都是一个巨大的安全威胁。这篇文章列出了一些防范SQL注入攻击的最佳实践,您可以采取这些措施保护自己的应用程序。最后,减少应用程序中有效输入数据的公开,是防范SQL注入攻击的最基本、也是最重要的一点。

怎么样防止Sql注入?

(1)对于动态构造SQL查询的场合,可以使用下面的技术:

第一:替换单引号,即把所有单独出现的单引号改成两个单引号,防止攻击者修改SQL命令的含义。再来看前面的例子,“SELECT * from Users WHERE login = ''' or ''1''=''1' AND password = ''' or ''1''=''1'”显然会得到与“SELECT * from Users WHERE login = '' or '1'='1' AND password = '' or '1'='1'”不同的结果。

第二:删除用户输入内容中的所有连字符,防止攻击者构造出类如“SELECT * from Users WHERE login = 'mas' -- AND password =''”之类的查询,因为这类查询的后半部分已经被注释掉,不再有效,攻击者只要知道一个合法的用户登录名称,根本不需要知道用户的密码就可以顺利获得访问权限。

第三:对于用来执行查询的数据库帐户,其权限。用不同的用户帐户执行查询、插入、更新、删除操作。由于隔离了不同帐户可执行的操作,因而也就防止了原本用于执行SELECT命令的地方却被用于执行INSERT、UPDATE或DELETE命令。

⑵ 用存储过程来执行所有的查询。SQL参数的传递方式将防止攻击者利用单引号和连字符实施攻击。此外,它还使得数据库权限可以到只允许特定的存储过程执行,所有的用户输入必须遵从被调用的存储过程的安全上下文,这样就很难再发生注入式攻击了。

⑶ 表单或查询字符串输入的长度。如果用户的登录名字最多只有10个字符,那么不要认可表单中输入的10个以上的字符,这将大大增加攻击者在SQL命令中插入有害代码的难度。

⑷ 检查用户输入的合法性,确信输入的内容只包含合法的数据。数据检查应当在客户端和服务器端都执行——之所以要执行服务器端验证,是为了弥补客户端验证机制脆弱的安全性。

在客户端,攻击者完全有可能获得网页的源代码,修改验证合法性的脚本(或者直接删除脚本),然后将非法内容通过修改后的表单提交给服务器。因此,要保证验证操作确实已经执行,唯一的办法就是在服务器端也执行验证。你可以使用许多内建的验证对象,例如RegularExpressionValidator,它们能够自动生成验证用的客户端脚本,当然你也可以插入服务器端的方法调用。如果找不到现成的验证对象,你可以通过CustomValidator自己创建一个。

⑸ 将用户登录名称、密码等数据加密保存。加密用户输入的数据,然后再将它与数据库中保存的数据比较,这相当于对用户输入的数据进行了“消毒”处理,用户输入的数据不再对数据库有任何特殊的意义,从而也就防止了攻击者注入SQL命令。System.Web.Security.FormsAuthentication类有一个HashPasswordForStoringInConfigFile,非常适合于对输入数据进行消毒处理。

⑹ 检查提取数据的查询所返回的记录数量。如果程序只要求返回一个记录,但实际返回的记录却超过一行,那就当作出错处理。

---------------------------------------------------------------------------------------------------------------------------

关键是明白原理,其实防范很简单的,

1.过滤SQL需要的参数中的敏感字符(注意加入忽略大小写)

2.禁用数据库服务器的xp_cmdshell存储过程,删除相应用到的dll

3.屏蔽服务器异常信息

Top