SQL注入之百密一疏

Posted 网安前哨

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SQL注入之百密一疏相关的知识,希望对你有一定的参考价值。


赵少海,中国金融认证中心信息安全工程师。


首先我们先了解一下什么是SQL?

结构化查询语言(Structured Query Language)简称SQL,是一种特殊目的的编程语言,是一种数据库查询和 程序设计语言 用于存取数据以及查询、更新和管理 关系数据库系统
结构化查询语言是高级的非过程化编程语言,允许用户在高层 数据结构 上工作。它不要求用户指定对数据的存放方法,也不需要用户了解具体的数据存放方式,所以具有完全不同底层结构的不同 数据库系统 , 可以使用相同的结构化查询语言作为数据输入与管理的接口。结构化查询语言语句可以嵌套,这使它具有极大的灵活性和强大的功能。
SQL语句本质就是在数据存储的仓库里,经过一系列复杂运算,然后把数据合理的展现给用户的一种手段。

那真实的计算机网络环境中SQL是怎么体现的呢?各位请往下看:

比如登录百度:

我们输入用户“adminchen”和密码“!fzycSQL@”,点击登录。 这时候,两个字段adminchen和!fzycSQL@就会从你的手机、电脑、pad……等设备通过互联网传送百度阳泉机房中的某台主机,执行一条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注入之百密一疏

讲这么深奥其实就一句话:可以方便优化程序员工作……

常识普及到此结束,接下来开始探讨SQL注入及Mybatis易出现漏洞。


SQL注入解释

比如此功能:

输入标题“你好”,交易类别“通过”点搜索:

执行SQL语句:

select * from user_verify where userid=‘765369876532145and title=‘你好’and trans_no=‘通过’;

执行此SQL语句就可以查询当前用户名下标题为“你好”,状态为“通过”的审批记录。常规用户会输入正常字段进行查询,但是“有想法的用户”就会输入一些特殊的东西,比如:把“你好”换为“1’ or 1=1 or ‘1’=’1”这样真正的SQL就会变成:

select * from user_verify where userid=‘765369876532145and title=‘1or 1=1 or1’=’1and 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注入漏洞修复 漏洞存在场景分析和修复示例(代码片段

代码审计之SQL注入

Java代码审计之SQL注入

PHP 代码审计之死磕 SQL 注入

JAVA代码审计之WebGoat靶场SQL注入

MyBatis如何防止SQL注入