SQL注入之百密一疏
Posted 网安前哨
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SQL注入之百密一疏相关的知识,希望对你有一定的参考价值。
赵少海,中国金融认证中心信息安全工程师。
首先我们先了解一下什么是SQL?
那真实的计算机网络环境中SQL是怎么体现的呢?各位请往下看:
比如登录百度:
select * from s_users where username=‘adminchen’ and password=‘!fzycSQL@’;
一但这条语句成功查询出来的结果,就会将此成功返回到你的计算机设备中。然后我们看到的就是我们登录成功的样子。
SQL讲完了,我们说说Mybatis,Mybatis是个什么玩意呢?
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生类型、接口和 Java 的 POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。另附美图一张:
讲这么深奥其实就一句话:可以方便优化程序员工作……
常识普及到此结束,接下来开始探讨SQL注入及Mybatis易出现漏洞。
SQL注入解释
比如此功能:
输入标题“你好”,交易类别“通过”点搜索:
执行SQL语句:
select * from user_verify where userid=‘765369876532145’ and title=‘你好’and trans_no=‘通过’;
执行此SQL语句就可以查询当前用户名下标题为“你好”,状态为“通过”的审批记录。常规用户会输入正常字段进行查询,但是“有想法的用户”就会输入一些特殊的东西,比如:把“你好”换为“1’ or 1=1 or ‘1’=’1”这样真正的SQL就会变成:
select * from user_verify where userid=‘765369876532145’ and title=‘1’ or 1=1 or ‘1’=’1’and trans_no=‘通过’;
约等于:
select * from user_verify;
这样数据库中相关的审批记录就会被全部查询出来,你的,我的,他的,大家的……都能看到。
那存在如此大的风险,有没有什么手段可以避免呢?答案是肯定的,“参数化查询”为您解决燃眉之急。
title=’你好’
trans_no=’通过’
PreparedStatement pstmt = con.prepareStatement("select * from user_verify where userid=‘765369876532145’ and title=‘?’and trans_no=‘?’");
pstmt.setvalue(‘你好’)
pstmt.setvalue(‘通过’)
通过这种先编译再传参的方式可以有效避免此类风险,至于为什么?请参考SQL解析器处理规则。那如果使用Mybatis又将发生什么情况呢?
Like情景:
设置场景新闻查询:按照新闻标题对新闻进行模糊查询,如果考虑安全编码规范问题,其对应的SQL语句如下:
Select * from news where title like ‘%#{title}%’,
但由于这样写程序会报错,研发人员将SQL查询语句修改如下:
Select * from news where title like ‘%${title}%’,
在这种情况下我们发现程序不再报错,但是此时产生了SQL语句拼接问题,如果java代码层面没有对用户输入的内容做处理势必会产生SQL注入漏洞。
In 情景:
在对新闻进行同条件多值查询的时候,如当用户输入1001,1002,1003…100N时,如果考虑安全编码规范问题,其对应的SQL语句如下:
Select * from news where id in (#{id}),
但由于这样写程序会报错,研发人员将SQL查询语句修改如下:
Select * from news where id in (${id}),
修改SQL语句之后,程序停止报错,但是却引入了SQL语句拼接的问题,如果研发人员没有对用户输入的内容做过滤,势必会产生SQL注入漏洞。
Order by 情景:
当根据发布时间、点击量等信息对新闻进行排序的时候,如果考虑安全编码规范问题,其对应的SQL语句如下:
Select * from news where title =‘京东’ order by #{time} asc,
但由于发布时间time不是用户输入的参数,无法使用预编译。研发人员将SQL查询语句修改如下:
Select * from news where title =‘京东’ order by ${time} asc,
修改之后,程序通过预编译,但是产生了SQL语句拼接问题,极有可能引发SQL注入漏洞。
那对于以上三个特例我们需要如何处理呢?听我慢慢道来:
1.like查询
按照新闻标题对新闻进行模糊查询,可将SQL查询语句设计如下:
select * from news where tile like concat(‘%’,#{title}, ‘%’),
采用预编译机制,避免了SQL语句拼接的问题,从根源上防止了SQL注入漏洞的产生。
2. in之后的参数SQL注入修复建议
在对新闻进行同条件多值查询的时候,可使用Mybatis自带循环指令解决SQL语句动态拼接的问题:
select * from news where id in #{item}
3. order by SQL注入修复建议--在Java层面做映射
预编译机制只能处理查询参数,其他地方还需要研发人员根据具体情况来解决。如前面提到的排序情景:
Select * from news where title =‘京东’ order by #{time} asc,
这里time不是查询参数,无法使用预编译机制,只能这样拼接:
Select * from news where title =‘京东’ order by ${time} asc
针对这种情况研发人员可以在java层面做映射来进行解决。如当存在发布时间time和点击量click两种排序选择时,我们可以限制用户只能输入1和2。当用户输入1时,我们在代码层面将其映射为time,当用户输入2时,将其映射为click。而当用户输入1和2之外的其他内容时,我们可以将其转换为默认排序选择time(或者click)。
以上为在下对SQL注入一点点浅薄的认识,希望大家共勉。
作者邮箱:zhaoshaohai@cfca.com.cn
欢迎大家提出宝贵的建议!
校对:牛 菁
排版:牛 菁
审核:谢宗晓
以上是关于SQL注入之百密一疏的主要内容,如果未能解决你的问题,请参考以下文章
安全测试 web安全测试 常规安全漏洞 可能存在SQL和JS注入漏洞场景分析。为什么自己没有找到漏洞,哪么可能存在漏洞场景是?SQL注入漏洞修复 JS注入漏洞修复 漏洞存在场景分析和修复示例(代码片段