结合Mybatis聊聊对SQL注入的见解

目录
  • Mybatis聊聊对SQL注入的见解
    • 1.sql注入是什么
    • 2.sql注入实例
      • (1)特殊符号,如 ' 和 .等
      • (2)sql语句的注入
      • (3)通过sql语句的in和order by进行注入
    • 3.mybatis框架下如何解决sql注入问题
      • (1)用#{param}替换所有的${param}
      • (2)对用户输入的数据进行sql注入校验
      • (3)要对用户的权限进行区分
      • (4)更高级别的验证
  • 一种常见的Mybatis的SQL注入
    • 一、场景重现
    • 二、代码展示
    • 三、模拟请求&回应结果
    • 四、小结一下

Mybatis聊聊对SQL注入的见解

1.sql注入是什么

sql注入见名思意,是指一些非法用户通过将一些特殊字符或者sql语句插入到要提交的表单之中,从而让服务器在不知情的情况下执行恶意的sql命令,从而引发一系列的安全隐患。

讲的通俗一点就是说,用户利用sql语法将一些sql语句加在某些字段后面,提交表单的时候,服务器执行sql命令并未达到想要的结果反而引发异常和数据泄露。

这就是典型的系统漏洞,因此sql注入对系统的危害是非常大的,做好防止sql注入也是系统必须完善的。

2.sql注入实例

我写了个简单的登录程序,框架是Spring+SpringMVC+Mybatis。表结构如下:

(1)特殊符号,如 ' 和 .等

可以看到当我输入一个特殊符号,而后台未经过过滤的时候,便会抛出sql异常:

并且如果没有进行全局异常处理,用户便可以通过浏览器的开发者模式中获取到数据库和查询语句的相关信息。

而这个对系统来说是很危险的漏洞。

(2)sql语句的注入

当输入正确的账号密码的时候,可以看到执行时成功的。

但是如果加上这么一句sql语句在表单,我们可以看到结果依然可以执行成功

非法用户可以通过这个来测试数据库的表名字、该表的其他字段名、数据的量级等等。

举个例子:尝试获取到该表的其他字段名

只需要将刚才的表单中的“1=1”替换成测试sql语句即可,如果执行成功则代表该表中有这个字段存在。

看一下最后执行的sql语句:

就一目了然了。这通用是因为注入引起的。

类似的还有:'or''=' 不仅能执行成功,同时还有查询多全部的数据。

(3)通过sql语句的in和order by进行注入

以上的三点主要是因为在mybatis中使用了${}, sql语句没有执行预编译,无法防止sql注入。

3.mybatis框架下如何解决sql注入问题

mybatis框架本身就有防止sql注入的特性,这就要求我们必须在写sql语句时候遵循框架的书写规范。

(1)用#{param}替换所有的${param}

因为${}是拼接sql字符实现没有预编译的查询,因为是无法防御sql注入,而#{}则需要进行预编译,可以很大程度上防止sql注入。

在一些#{}使用时候会报错的地方,如like 查询、in 查询、order by排序等,

a) like:

select * from Users where username like '%${username}%'

替换成:

select * from Users where username like concat('%', #{username}, '%')

b) in

select * from Users where id in (${id})

替换成mybatis框架自带的foreach循环:

c) order by

不要直接使用:拼接排序

如:

select *from Users order by ${id}

而是在java层面做映射,然后用<if>来做判断

其他的类似的情况请按照相同的处理方式进行处理即可。

(2)对用户输入的数据进行sql注入校验

SqlServer本身的防sql注入机制,利用存储过程可以避免sql注入。应该禁止用户输入一些关键的特殊符号,如分号、分隔符、单引号等,同时对于一些关键位置进行sql关键字的屏蔽,如or、and等。必须对用户输入的内容的类型、长度、格式、范围进行校验。

(3)要对用户的权限进行区分

普通用户的权限和管理员的权限之间,必须严格区分开来,对管理员实现安全级别更高的验证,从而防止人为获取到更高权限时候的sql注入攻击。

(4)更高级别的验证

在后端代码和数据库中都开启对sql注入的验证,同时用专业的注入工具查找本系统的漏洞进行修复,也可以进行账号诱骗,将一些如“admin”之类的容易受到攻击的用户设置上千位的密码,让攻击者的软件因为解析量大而负载过大,从而耗尽资源而宕机。

一种常见的Mybatis的SQL注入

一、场景重现

现在有一张名为student的表,表结构如下:

其中id为自增主键,余下字段分别为英语成绩、数学成绩、美术成绩、学生的学号、学生的姓名、学生的电话。

目前表里面有6条数据:

二、代码展示

使用mybatis框架实现根据美术成绩查找相应的记录,在mapper.xml文件里,代码大概会这么写:

 <!--通过美术成绩作为筛选条件查询-->
    <select id="queryByArtGrade" resultMap="StudentMap">
        select
        id, english_grade, math_grade, art_grade, number, name, telephone
        from student
        <where>
            <if test="artGrade != null">
                and art_grade = #{artGrade}
            </if>
        </where>
    </select>

当然也可以这么写:

 <!--通过美术成绩作为筛选条件查询-->
    <select id="queryByArtGrade" resultMap="StudentMap">
        select
        id, english_grade, math_grade, art_grade, number, name, telephone
        from student
        <where>
            <if test="artGrade != null">
                and art_grade = ${artGrade}
            </if>
        </where>
    </select>

这两种写法的区别在于对传入参数的接收方式不同,前者是#{property},后者是${property}。

三、模拟请求&回应结果

想查询美术成绩为70的记录,使用postman进行请求,传入参数json为:

{

"artGrade":"70"

}

测试结果两者均为:

看起来好像是一样的结果,两种写法都正确。

但是我把参数改成下面的这个样子:

{

"artGrade":"'70' and id='4'"

}

结果就完全不同啦!

使用#{property}返回的结果为空:

通过日志,发现实际执行的SQL为:

select id, english_grade, math_grade, art_grade, number, name, telephone from classroom.student WHERE art_grade = "'70' and id='4'"

使用${property}返回的结果为一条:

通过日志,发现实际执行的SQL为:

select id, english_grade, math_grade, art_grade, number, name, telephone from classroom.student WHERE art_grade = '70' and id='4'

四、小结一下

这就是常见的sql注入了,因为后端接收传入参数的时候没有经过任何处理,直接到了mybatis层,而mybatis层接收参数的时候又使用了${property}这种方式,导致参数被直接拼接至预执行的SQL中,最后返回了一些恶意请求者需要的信息。

所以,mapper中尽量避免使用${property}来接收参数,因为你不知道上一层传进来的东西到底是什么。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • mybatis注解动态sql注入map和list方式(防sql注入攻击)

    目录 网上的教程 我的教程(防sql注入攻击) 注入Map 注入List 封装foreach mybatis防止sql注入的循环map写法 网上的教程 配置xml 注解中写xml脚本@Select() 使用Java类中的Java方法拼写sql语句(不防sql注入攻击的纯字符串拼接) 我的教程(防sql注入攻击) 注入Map Mapper层代码 @Repository public interface ManageMapper { @SelectProvider(type = ManageProv

  • java持久层框架mybatis防止sql注入的方法

    sql注入大家都不陌生,是一种常见的攻击方式,攻击者在界面的表单信息或url上输入一些奇怪的sql片段,例如"or '1'='1'"这样的语句,有可能入侵参数校验不足的应用程序.所以在我们的应用中需要做一些工作,来防备这样的攻击方式.在一些安全性很高的应用中,比如银行软件,经常使用将sql语句全部替换为存储过程这样的方式,来防止sql注入,这当然是一种很安全的方式,但我们平时开发中,可能不需要这种死板的方式. mybatis框架作为一款半自动化的持久层框架,其sql语句都要我们自己来手

  • MyBatis中防止SQL注入讲解

    SQL注入是一种代码注入技术,用于攻击数据驱动的应用,恶意的SQL语句被插入到执行的实体字段中(例如,为了转储数据库内容给攻击者). SQL注入,大家都不陌生,是一种常见的攻击方式.攻击者在界面的表单信息或URL上输入一些奇怪的SQL片段(例如"or '1'='1'"这样的语句),有可能入侵参数检验不足的应用程序.所以,在我们的应用中需要做一些工作,来防备这样的攻击方式.在一些安全性要求很高的应用中(比如银行软件),经常使用将SQL语句全部替换为存储过程这样的方式,来防止SQL注入.这

  • 实例讲解MyBatis如何防止SQL注入

     SQL注入是一种很简单的攻击手段,但直到今天仍然十分常见.究其原因不外乎:No patch for stupid.为什么这么说,下面就以JAVA为例进行说明: 假设数据库中存在这样的表: table user( id varchar(20) PRIMARY KEY , name varchar(20) , age varchar(20) ); 然后使用JDBC操作表: private String getNameByUserId(String userId) { Connection conn

  • Mybatis防止sql注入的实例

    sql注入大家都不陌生,是一种常见的攻击方式,攻击者在界面的表单信息或url上输入一些奇怪的sql片段,例如"or '1'='1'"这样的语句,有可能入侵参数校验不足的应用程序.所以在我们的应用中需要做一些工作,来防备这样的攻击方式.在一些安全性很高的应用中,比如银行软件,经常使用将sql语句全部替换为存储过程这样的方式,来防止sql注入,这当然是一种很安全的方式,但我们平时开发中,可能不需要这种死板的方式. mybatis框架作为一款半自动化的持久层框架,其sql语句都要我们自己来手

  • MyBatis下SQL注入攻击的3种方式

    目录 前言 Mybatis框架下易产生SQL注入漏洞的情况主要分为以下三种: 1.模糊查询 2.in 之后的多个参数 3.order by 之后 二.实战思路 三.总结 前言 SQL注入漏洞作为WEB安全的最常见的漏洞之一,在java中随着预编译与各种ORM框架的使用,注入问题也越来越少.新手代码审计者往往对Java Web应用的多个框架组合而心生畏惧,不知如何下手,希望通过Mybatis框架使用不当导致的SQL注入问题为例,能够抛砖引玉给新手一些思路. Mybatis的SQL语句可以基于注解的

  • Mybatis是这样防止sql注入的

    目录 1.首先看一下下面两个sql语句的区别: 2.什么是sql注入 3.mybatis是如何做到防止sql注入的 4.参考文章 1.首先看一下下面两个sql语句的区别: <select id="selectByNameAndPassword" parameterType="java.util.Map" resultMap="BaseResultMap"> select id, username, password, role fro

  • mybatis防止SQL注入的方法实例详解

    SQL注入是一种很简单的攻击手段,但直到今天仍然十分常见.究其原因不外乎:No patch for stupid.为什么这么说,下面就以JAVA为例进行说明: 假设数据库中存在这样的表: table user( id varchar(20) PRIMARY KEY , name varchar(20) , age varchar(20) ); 然后使用JDBC操作表: private String getNameByUserId(String userId) { Connection conn

  • 浅谈mybatis中的#和$的区别 以及防止sql注入的方法

    mybatis中的#和$的区别 1. #将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号.如:order by #user_id#,如果传入的值是111,那么解析成sql时的值为order by "111", 如果传入的值是id,则解析成的sql为order by "id". 2. $将传入的数据直接显示生成在sql中.如:order by $user_id$,如果传入的值是111,那么解析成sql时的值为order by user_id,  如果传入的

  • 结合Mybatis聊聊对SQL注入的见解

    目录 Mybatis聊聊对SQL注入的见解 1.sql注入是什么 2.sql注入实例 (1)特殊符号,如 ' 和 .等 (2)sql语句的注入 (3)通过sql语句的in和order by进行注入 3.mybatis框架下如何解决sql注入问题 (1)用#{param}替换所有的${param} (2)对用户输入的数据进行sql注入校验 (3)要对用户的权限进行区分 (4)更高级别的验证 一种常见的Mybatis的SQL注入 一.场景重现 二.代码展示 三.模拟请求&回应结果 四.小结一下 My

  • 关于mybatis使用${}时sql注入的问题

    目录 mybatis使用${}时sql注入的问题 区别 解决方法 mybatis sql注入问题之$与# 在mybatis中使用$符号 在mybatis中使用#符号 mybatis使用${}时sql注入的问题 最近在上线项目的时候,代码审查没有通过,提示有sql注入的风险. ORDER BY ${orderBy} 很简单的一个排序字段,但是因为使用 ${} 占位符的原因,有sql注入的风险,相信大家平时也经常会使用这个占位符,不知道有没有考虑sql注入的问题,下面简单介绍下 #{} 和 ${}

  • 详细聊聊关于sql注入的一些零散知识点

    目录 零.本文涉及知识点 一.sqlmap写一句马的过程(-- os-shell) 1.1 简述过程 1.2 一个小问题 二.堆叠注入: 2.1 什么是堆叠注入 2.2 如何判断存在堆叠注入? 2.3 局限性 三.union injection(联合注入) 3.1 原理 3.2 与堆叠注入的区别 四.常见的sql注入绕过姿势 4.1 Waf特性: 4.2 绕waf的核心思路: 4.3 常见的思路 五.Sql注入预编译与常见绕过姿势 5.1 概述 5.2 具体方式 5.2.1 ASC/DESC 5

  • 简单了解Mybatis如何实现SQL防注入

    这篇文章主要介绍了简单了解Mybatis如何实现SQL防注入,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Mybatis这个框架在日常开发中用的很多,比如面试中经常有一个问题:$和#的区别,它们的区别是使用#可以防止SQL注入,今天就来看一下它是如何实现SQL注入的. 什么是SQL注入 在讨论怎么实现之前,首先了解一下什么是SQL注入,我们有一个简单的查询操作:根据id查询一个用户信息.它的sql语句应该是这样:select * from u

  • Mybatis常用注解中的SQL注入实例详解

    目录 前言 常见注入场景 2.1普通注解 2.2 动态sql 2.2.1 使用< script> 2.2.2 使用Provider注解 总结 前言 MyBatis3提供了新的基于注解的配置.主要在MapperAnnotationBuilder中,定义了相关的注解: public MapperAnnotationBuilder(Configuration configuration, Class<?> type) { ... sqlAnnotationTypes.add(Select

  • 基于mybatis注解动态sql中foreach工具的方法

    目录 实现目标 工具类 测试 集成进spring后的使用方法 Mapper层 Provider层 Ognl问题 解决方案 创建一个DefaultMemberAccess.java文件 改造ForeachMybatisUtils.java类 实现目标 由于在注解版mybatis中手动循环拼接动态sql容易出错 请看mybatis注解动态sql注入map和list(防sql注入攻击),所以封装了这个类似于foreach标签的工具方法. 由于mybatis(3.5.6.3.5.7 or earlier

随机推荐