SQL注入问题

SQL注入问题

在B/S应用中经常会有很多需要和用户直接进行交互处理的操作,在我们设计系统的时候往往会把用户想象成一个按照我们设定的情景去操作的角色。但是由于系统的开放性(界面直接由用户接触并操作),有可能会存在用户进行并不是那么“合法”的操作。这时候往往大多数页面都会给予一些提示或者示例,将用户操作规划在自己的可限定范围内。SQL注入也就属于用户不合法操作的一种,只是这种操作可能会相比于其他“不合法”操作来说更严重一点(其实可以称之为一种刻意的攻击)。本文将从以下几个环节以及自己的理解来说一下SQL注入问题,若有什么说的不对的地方还望各位大佬指出,谢谢~

SQL注入是什么?有什么危害?

SQL注入是什么

SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。(引用自百度百科)

根据上面的定义,其实就是“有备而来”的用户会根据sql语句执行的特性“去偷去骗”web程序,获得一些他本来不应该获得的权限,从而去做一些本来不属于他管理范畴的事情。这也就可见sql注入的危害,当用户获得了这些权限之后,最轻微的是获得对应的数据库数据,稍过分一点就是改数据,最过分的删你库还不用跑路!除此之外,例如web的登陆甚至也可以通过SQL注入跳过。

SQL注入的典型类型以及防治

1.提到SQL注入大家都会提及的登录时SQL执行语句:

select * from user where username = 'admin***' and password = '123456***'

在这个语句中正常情况下我们会根据前台用户传入的username以及password 去数据库里面查询对应符合的语句,从而判断是否登录成功。
执行结果

但是如果用户传入 【admin’ or 1 = 1 – 】,密码随便传入什么最后拼接出来的sql 就是

select * from user where username = 'admin' or 1 = 1 -- ' and password = '***'

执行结果

这时候在MySql中就会把这张表里的所有数据都查出来,因为 【–】 在MySql 相当于注释,后面的语句就都不会被执行,等于直接 【select * from user where 1 = 1】 。这也就变相泄露了我们用户表的所有信息。

这时候我们需要注意到 【–】 代表注释是针对MySql的特性,除此外在用户名的 【–】 著时候还要加上一个空格,单纯针对这种情况我们可以对用户的输入进行两端去空格的处理,这其实也是web段最基本的一些输入过滤。我们还可以增大我们的过滤范围,例如输入特殊的 【–】 在用户名里就被判断为有风险的,而且在数据库中存储的密码信息也一定要进行加密处理,不要直接使用明文存储的方式。除此之外,就是登录的验证用户输入用户名密码后不要直接拿着用户输入所有东西去数据库判断,我们要默认用户输入的值不一定都合法,可以选择根据用户名去查数据库,判断是否存在这个用户,如果存在的话直接取出其密码再和用户输入的密码加密后比对,如果正确跳转登陆即可。可以不需要就不要往用户界面返回数据库的数据。

2.使用SQL 注解修改或者删除表的信息。假设在一个页面中用户需要输入一些信息,并且根据用户的信息去和数据库进行一些增删改查的操作时,使用SQL注入可以修改甚至删除数据库里面的一些操作。假设设想的合规的sql语句如下:

select * from user where username = '***'; 

去查一下这个用户的一些信息,然后拼装好给前端返回展示。但是用户故意输入 【‘1’;drop table user;】 或者是在得知一些信息的情况下输入 【'1’;update user set password = ‘…’ where username = ‘…’;】 这样便可以一并执行两条sql 语句分别删除了user 表和改变了该用户的一些信息(如密码,地址等个人信息,一般大家在定义字段名称的时候都会取一些有意义的字段,也就比较好猜),这就影响了系统的正常运行。

想要处理这种方式我们其实可以采用上面的相同方法,不信任用户的任何输入,对用户的输入进行一些过滤操作,尤其是 drop update truncate 这种数据库层面比较危险的输入,更需要进行判断过滤,防止一些不合法的操作出现。还有一个比较特殊的地方在于,上面拼接的sql 中查询用到的内容完全是用户拼接的引号,这也是问题的一个原因。如果我们能够对用户将用户输入的东西都处理为字符串的内容,那后面的那些隐藏的sql 就无法被程序识别并执行了。此处我们可以看看MyBatis 中的一些处理方式。 下面是一个MyBatis的简单查询例子:

<select id=”findUser” resultType=”com.demo.mybatis.User”>
	select * from user
	where 1 = 1
	<if test=”name!= null and name!= ‘’”>
		and name = #{name}
	</if>
	<if test=”age!= null and age!= ‘’”>
    	and age = #{age}
    </if>
</select>

这里便是MyBatis的xml中select 的使用,通过name和age(或者其他表中有的字段)去查询最终的结果。这里需要注意的是#{}的这种写法,在MyBatis中这是一种预编译的模式,上面的这段查询在经过预编译后会变成

select * from user where 1=1 and name=? and age=?

(其中name和age都是满足条件的情况下),这个 【?】 可以理解为一个标记符,等到后续动态解析传入的值后便会解析为 【’…’】 ,这种情况下就不论你传入什么值都会被程序当成是查询的字符串也就避免了SQL注入的问题。但是看下面这种情况:

<if test="name!= null and name!= ''">
	and name like '%${name}%'
</if>

有时候我们需要进行模糊搜索使用 like 关键词,这里面的 ${} 正好和 #{} 是有很大区别的,当我们使用 ${} 的时候MyBatis不会进行预编译将其转换为标记符【?】,而是直接接收传入的变量,传入啥这边的 ${} 就是啥,因此是存在SQL注入风险的。但是如果使用 【’%#{name}%’】 这时候经过预编译就会变成 【’%’…’%’】,这就不满足我们的需求了。除此之外,在SQL中还有 in、动态表名等情况都需要使用字符串拼接,这就都存在SQL注入的风险。
如何避免? 1.在进行字符串拼接的时候,尤其是需要采用前端客户主动输入的数据的时候,需要进行 校验过滤一下有风险的数据,从数据层面就避免SQL注入;2.如果需要使用like进行模糊匹配,可以使用 【concat(’%’,#{name},’%’)】 或者 【"%"#{examTypeName}"%"】 这种写法,尽量使用#{}的形式;3.如果需要使用in的方式(其实不太建议sql中使用in,执行时候太费时间了),能优化sql就优化,实在不行就使用foreach 的方式进行遍历,使用方式如下

<foreach collection="list" item="name" open="(" close=")" separator=",">
      #{name}
</foreach>

尽量避免字符串的拼接才是避免SQL注入的最好方式。

最后总结,SQL注入只针对B/S应用的一种比较常见的攻击方式,但是找SQL注入点的过程还是比较难的。虽然别人可能不知道你SQL注入的位置,但是一旦被攻击了影响还是十分严重的,这就需要我们在编码中避免。尽量避免在SQL中进行字符串拼接,如果在service 中有拼接的话一定要对其进行校验去除危险操作,也可以在接收request的时候通过filter的方式过滤所有接收的参数。当然最好的方式是使用MyBatis提供的解决方案,使用预编译的模式从根源上避免SQL注入。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值