SQL注入的危害:
1、数据库被拖库(把数据从数据库拉取出来);
2、重要信息被泄露等;
注入攻击的本质,是把用户输入的数据当做有效代码执行;
举例:
当用户发送GET请求:
https://ke.qq.com/course.jsp?id=1
这是一个课程详情页面,会显示出课程的title和content,程序会接收id参数传递给SQL语句,SQL如下:
SELECT title, content FROM course WHERE id = 1
这是SQL的原义,也是程序员想要得到的结果,但是如果用户改变了id的内容,改为:
https://ke.qq.com/course.jsp?id=1 and 1=2 UNION SELECT username, password FROM admin
此时内部程序执行的SQL语句为:
SELECT title, content FROM course WHERE id = 1 and 1=2 UNION SELECT username, password FROM admin
密码被查询了出来;
Mybatis框架作为一款半自动化的持久层框架,其SQL语句都需要我们自己手动编写,此时就需要我们按照安全编码规范进行开发,以防止SQL注入的产生。
Mybatis框架SQL语句安全的写法(即JDBC预编译模式),可以写为:
select * from course where id=#{id}
这即可避免SQL注入漏洞的产生;
1.SQL注入的例子
案例一:
Select * from course where title like ‘%#{title}%’
由于这样写程序会报错,开发人员会将SQL改为:
Select * from news where title like ‘%${title}%’,
此时程序不再报错,但会产生了SQL语句拼接问题,如果Java代码未对用户输入的内容做处理可能产生SQL注入漏洞。
如果用户输入:%’ AND 1=1AND ‘%’=’
可将SQL查询语句设计如下:
select * from news where tile like concat(‘%’, #{title}, ‘%’)
采用预编译机制,避免SQL语句拼接问题,从根源上防止SQL注入漏洞的产生。
案例二:
select * from news where id in (#{id})
由于这样写程序会报错,开发人员将SQL查询语句修改如下:
Select * from news where id in (${id})
此时便引入了SQL语句拼接的问题,如果研发人员未对用户输入的内容做过滤,容易产生SQL注入漏洞。
uUserInfoMapper.selectByIn(“select user_name from u_user_info”);
where user_name in (${userName})
可使用MyBatis自带循环标签解决SQL语句动态拼接的问题:
select * from news where id in
<foreach collection=“ids” item=“item” open="(“separator=”," close=")">
#{item}
案例三:
Select * from news where title =‘动力节点’ order by ${time} asc,
产生了SQL语句拼接问题,有可能引发SQL注入漏洞。
案例四:
select * from user where ${column} = #{value}
其中 ${column} 会被直接替换,而 #{value} 会被使用 ? 预处理。
User userOfId1 = userMapper.findByColumn(“id”, 1L);
User userOfNameKid = userMapper.findByColumn(“name”, “kid”);
User userOfEmail = userMapper.findByColumn(“email”, “noone@nowhere.com”);
应该怎么做? 制定安全编码规范,不要出现SQL直接替换/拼接的问题,要采用预编译模式;
#{xxx},使用的是PreparedStatement,会有类型转换,所以比较安全;
${xxx},使用字符串拼接,可以SQL注入;
like查询不小心会有漏动,正确写法如下:
Mysql: select * from t_user where name like concat('%', #{name}, '%')
Oracle: select * from t_user where name like '%' || #{name} || '%'
SQLServer: select * from t_user where name like '%' + #{name} + '%'
2.MyBatis动态SQL
根据不同条件拼接 SQL 语句是非常痛苦的,拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号,利用动态 SQL 这一特性可以彻底摆脱这种痛苦;
if --判断标签
choose (when, otherwise) --多项选择 ,与页面的 jstl 标签非常类似
trim (where, set) --修剪、格式化,添加前后缀的一个标签
foreach --循环