sql注入及mybatis防止sql注入(六)

前言

1、回顾什么是sql注入

2、mybatis如何解决sql注入

一、sql注入

1.1Sql 注入产生原因及威胁

  当我们访问动态网页时, Web 服务器会向数据访问层发起 Sql 查询请求,如果权限验证通过就会执行 Sql 语句。这种网站内部直接发送的Sql请求一般不会有危险,但实际情况是很多时候需要结合用

户的输入数据动态构造 Sql 语句,如果用户输入的数据被构造成恶意 Sql 代码,Web 应用又未对动态构造的 Sql 语句使用的参数进行审查,则会带来意想不到的危险。

  Sql 注入带来的威胁主要有如下几点:

  • 猜解后台数据库,这是利用最多的方式,盗取网站的敏感信息。
  • 绕过认证,列如绕过验证登录网站后台。
  • 注入可以借助数据库的存储过程进行提权等操作。

二、mybatis${ } 和 #{ }区别

2.1Mybatis防止sql注入

  下面是MyBatis一个Dao配置

<select id="findRank" parameterType ="String" resultType="String">
    SELECT u.name FROM UserInfo u
        where 1=1 and u.UserID=#{userID} ;    
</select>

  打印出执行的SQL语句

 SELECT u.name FROM UserInfo u where 1=1 and u.UserID=?     

  这是因为MyBatis启用了预编译功能,在SQL执行前,会先将上面的SQL发送给数据库进行编译;执行时,直接使用编译好的SQL,替换占位符“?”就可以了。因为SQL注入只能对编译过程起作用,所以这样的方式就很好地避免了SQL注入的问题。

  • 底层实现原理

  MyBatis是如何做到SQL预编译的呢?其实在框架底层,是JDBC中的PreparedStatement类在起作用,PreparedStatement是我们很熟悉的Statement的子类,它的对象包含了编译好的SQL语句。这

种“准备好”的方式不仅能提高安全性,而且在多次执行同一个SQL时,能够提高效率。原因是SQL已编译好,再次执行时无需再编译。PreparedStatement只能用来为参数(如参数值)设置动态参数,即用?占位,不可用于表名、字段名等。

  话说回来,是否我们使用MyBatis就一定可以防止SQL注入呢?当然不是,请看下面的代码:

<select id="findRank" parameterType ="String" resultType="String">
    SELECT u.name FROM UserInfo u
        where 1=1
        and u.UserID=${userID} ;   
</select>

  假设userID=1,将SQL打印出来是这样的:

 SELECT u.name FROM UserInfo u where 1=1 and u.UserID=1

  显然${}这种方式直接参与sql编译,将传入的参数直接显示生成在sql中,不能避免注入攻击。

2.2mybatis${ } 和 #{ }区别

  • #方式能够很大程度防止sql注入。
  • $方式无法防止Sql注入。
  • $方式一般用于传入数据库对象,例如传入表名。

${xxx}

  • 缺点: 直接参与SQL编译,不能避免注入攻击。
  • 优点:及到动态表名和列名时,只能使用“${xxx}”这样的参数格式
  • 注意:这样的参数需要我们在代码中手工进行处理来防止注入。
  • ${}将传入的参数直接显示生成在sql中,不会添加引号

#{xxx}

  • 相当于JDBC中的PreparedStatement
  • #{}将传入的参数当成一个字符串,会给传入的参数加一个双引号
  • 优点:#{}是经过预编译的,是安全的;

三、MyBatis如何防止SQL注入

3.1、使用参数化查询

在SQL语句中使用参数可以有效地防止SQL注入攻击。参数化查询是一种将变量或参数(例如,查询条件)插入到SQL语句中的技术。在MyBatis中,可以使用“#{}”语法来表示参数,例如:

    <select id="getUserByName" resultType="User">
        SELECT *
        FROM users
        WHERE username = #{name}
    </select>

在上面的代码中,由于使用了“#{name}”来表示参数,MyBatis会在查询之前将参数转义,从而避免了SQL注入攻击。请注意,不要使用“${}”来表示参数,因为这可能会导致SQL注入攻击。

3.2、使用动态SQL

MyBatis的动态SQL可以帮助我们在运行时生成SQL语句,从而避免硬编码。然而,动态SQL也可能导致SQL注入攻击,因此我们需要采取一些措施来防止SQL注入。

1、使用if语句来过滤参数

使用if语句可以帮助我们在运行时动态生成SQL语句,并且可以防止SQL注入攻击。例如:

    <select id="getUserByAge" resultType="User">
        SELECT *
        FROM users
        WHERE 1=1
        <if test="age != null and age != ''">
            AND age = #{age}
        </if>
    </select>

在上面的代码中,我们使用了if语句来判断参数age是否为空。如果age不为空,MyBatis会将“AND age = #{age}”插入到SQL语句中。否则,MyBatis不会将“AND age = #{age}”插入到SQL语句中。

2、使用choose语句来过滤参数

choose语句可以帮助我们在不同的条件下生成不同的SQL语句:

<select id="getUserByCondition" resultType="User">
        SELECT *
        FROM users
        WHERE 1=1
        <choose>
            <when test="age != null and age != ''">
                AND age = #{age}
            </when>
            <when test="username != null and username != ''">
                AND username = #{username}
            </when>
            <otherwise>
                AND 1=1
            </otherwise>
        </choose>
    </select>

在上面的代码中,我们使用choose语句来判断在不同的条件下生成不同的SQL语句。如果age不为空,那么MyBatis会将“AND age = #{age}”插入到SQL语句中;如果username不为空,那么MyBatis会将“AND username = #{username}”插入到SQL语句中;否则,MyBatis会插入“AND 1=1”到SQL语句中。

3.3、使用SQL注入过滤器

即使我们已经使用了以上方法来保护我们的应用程序,SQL注入攻击仍然可能发生。因此,我们还需要使用SQL注入过滤器来增加应用程序的安全性。

SQL注入过滤器是一种自动检测和修复SQL注入漏洞的工具,可以通过检测和拦截SQL注入攻击来保护应用程序。MyBatis中的SQL注入过滤器可以帮助我们自动检测和拦截SQL注入攻击,例如:

    <configuration>
        <plugins>
            <plugin interceptor="org.mybatis.example.ExamplePlugin">
                <property name="someProperty" value="100"/>
            </plugin>
        </plugins>
    </configuration>

在上面的代码中,我们使用了MyBatis插件来添加一个SQL注入过滤器。插件需要实现Interceptor接口,并在调用时接受参数。在插件中,我们可以通过拦截StatementHandler来检测和拦截SQL注入攻击。

3.4、使用存储过程

存储过程是一种存储在数据库中的可执行程序,可以在应用程序中调用。使用存储过程可以有效地防止SQL注入攻击,因为存储过程的参数是确定的,并且可以在存储过程中进行处理。在MyBatis中,可以使用“call”语法来调用存储过程,例如:

    <select id="getUserById" statementType="CALLABLE">
        {call getUserById(#{id, mode=IN, jdbcType=NUMERIC})} 
    </select>

在上面的代码中,我们使用“CALLABLE”模式来调用存储过程getUserById,并通过参数“#{id, mode=IN, jdbcType=NUMERIC}”传递存储过程的输入参数。

3.5、总结

  SQL注入攻击是Web应用程序中最常见的安全漏洞之一。MyBatis提供了许多方法来防止SQL注入攻击,包括使用参数化查询、动态SQL、SQL注入过滤器和存储过程等。通过了解这些技术并实施它们,我们可以使我们的应用程序更加安全。

  mybatis防止sql注入的方法:1、使用预编译的sql语句;2、使用#{}占位符;3、使用{}占位符;4、使用动态sql;5、输入验证和清理;6、限制数据库权限;7、使用web应用防火墙;8、保持mybatis和数据库的安全更新。详细介绍:1、使用预编译的sql语句,mybatis通过预编译的sql语句来执行查询和更新操作,预编译的sql语句使用参数化查询等等。

  MyBatis 是一个优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。为了防止 SQL 注入,MyBatis 提供了多种机制来确保用户输入的安全性。以下是 MyBatis 防止 SQL 注入的主要方法:

1、使用预编译的SQL语句:MyBatis 通过预编译的 SQL 语句来执行查询和更新操作。预编译的 SQL 语句使用参数化查询,这意味着用户输入会被当作参数传递,而不是直接拼接到 SQL 语句中。这样可以有效防止 SQL 注入攻击,因为攻击者的输入不会被当作 SQL 代码执行。

2、使用#{}占位符:在 MyBatis 的 XML 映射文件中,可以使用 #{} 占位符来引用参数。这种方式会将参数值视为一个 JDBC 参数,而不是 SQL 语句的一部分。MyBatis 会自动将参数值进行转义,确保其安全性。

3、使用{}占位符:与 `#{}` 占位符不同,`{}占位符会将参数值直接替换到 SQL 语句中。这可能导致 SQL 注入的风险,因此应谨慎使用。只有当你完全信任传入的值并且确定它是安全的时,才可以使用${}` 占位符。

4、使用动态SQL:MyBatis 支持动态 SQL,可以根据条件动态生成 SQL 语句。然而,在使用动态 SQL 时要特别小心,确保不拼接用户输入到 SQL 语句中,以防止 SQL 注入。最好使用 if、choose、when、otherwise 等动态元素来控制 SQL 的生成。

5、输入验证和清理:在将用户输入传递给数据库之前,应该对输入进行验证和清理。确保输入符合预期的格式,并删除或转义任何可能的恶意字符。这可以通过 Java 的验证框架(如 Apache Commons Validator)或自定义的验证逻辑来实现。

6、限制数据库权限:为了防止 SQL 注入攻击,应该限制连接到数据库的帐号的权限。即使攻击者能够注入恶意代码,他们也无法执行不受限制的操作。只授予连接、查询和执行有限命令的权限,而不是授予管理员级别的权限。

7、使用Web应用防火墙:Web 应用防火墙可以检测和阻止常见的 Web 应用程序攻击,包括 SQL 注入。WAF 可以配置为监视请求并阻止任何可疑的输入模式。虽然 WAF 不能替代其他安全措施,但它可以作为一种额外的防御层来减少潜在的攻击风险。

8、保持MyBatis和数据库的安全更新:及时更新 MyBatis 和数据库管理系统的安全补丁是非常重要的。开发人员应关注官方发布的安全公告,并尽快应用相关的修复程序和补丁,以确保系统的安全性。

  综上所述,MyBatis 通过多种机制来防止 SQL 注入攻击,包括预编译的 SQL 语句、参数化查询、输入验证和清理以及限制数据库权限等。同时,开发者还应该注意安全最佳实践,并采取其他额外的防御措施来提高系统的安全性。

参看链接:

https://blog.csdn.net/cristianoxm/article/details/123726070

https://www.python100.com/html/120956.html

https://www.php.cn/faq/654224.html

https://blog.csdn.net/weixin_43702295/article/details/135517483

https://blog.csdn.net/m0_62381101/article/details/132913821

 

posted @ 2023-12-27 16:52  慎终若始  阅读(3331)  评论(0编辑  收藏  举报