东莞

点击搜索

发布

服务器如何避免出现SQL注入漏洞

区域:
东莞 > 南城
类别:
IDC服务
地址:
南城高盛科技大厦
一、前言
本文将针对开发过程中依旧经常出现的SQL编码缺陷,讲解其背后原理及形成原因。不管是扬州高防服务器、还是杭州BGP机房等都一样,并以常见的几个漏洞存在形式,提醒,技术同学注意相关问题。后会根据原理,提供解决或缓解方案。

二、SQL注入漏洞的原理、形成原因
SQL注入漏洞,根本上讲,是由于错把外部输入当作SQL代码去执行。目前佳的解决方案就是预编译的方式。

SQL语句在执行过程中,需要经过以下三大基本步骤:

代码语义分析
制定执行计划
获得返回结果
而一个SQL语句是由代码和数据两部分,如:

SELECT id, name, phone FROM userTable WHERE name = 'xiaoming';  
SELECT id, name, phone FROM userTable WHERE name = 是代码,'xiaoming'是数据。

而预编译,以Mybatis为例,就是预先分析带有占位符的语义:

如SELECT id, name, phone FROM userTable WHERE id = #{name};

然后再将数据'xiaoming',传入到占位符。这样一来,错开来代码语义分析阶段,也就不会被误认为是代码的一部分了。

在早期,开发者显式使用JDBC来自己创建Connection,执行SQL语句。这种情况下,如果将外部可控数据拼接到SQL语句,且没有做充分过滤的话,就会产生漏洞。这种情况在正常的业务开发过程中已经很少了,按照公司规定,无特殊情况下,必须使用ORM框架来执行SQL。

但目前部分项目中,仍会使用JDBC来编写一些工具脚本,如DataMerge.java 、DatabaseClean.java,借用JDBC的灵活性,通过这些脚本来执行数据库批量操作。

此类代码不应该出现在线上版本中,以免因各种情况,被外部调用。

三、直接使用Mybatis1. 易错点
目前大部分的平台代码是基于Mybatis来处理持久层和数据库之间的交互的,Mybatis传入数据有两种占位符{}和#{}。{}和#{}。{}可以理解为语义分析前的字符串拼接,讲传入的参数,原封不动地传入。

比如说

SELECT id, name, phone FROM userTable WHERE name = '${name}';  
传入name=xiaoming后,相当于

SELECT id, name, phone FROM userTable WHERE name = 'xiaoming';  
实际应用中

SELECT id, name, phone FROM userTable WHERE ${col} = 'xiaoming';  
传入col = "name",相当于

SELECT id, name, phone FROM userTable WHERE name = 'xiaoming';  
就像预编译原理介绍里讲的一样,使用#{} 占位符就不存在注入问题了。但有些业务场景是不可以直接使用#{}的。

(1) 比如order by语法中

如果编写SELECT id, name, phone FROM userTable ORDER BY #{}; ,执行时是会报错的。因为order by后的内容,是一个列名,属于代码语义的一部分。如果在语义分析部分没有确定下来,就相当于执行SELECT id, name, phone FROM userTable ORDER BY 。肯定会有语法错误。

(2) 再比如like场景下

SELECT id, name, phone FROM userTable WHERE name like '%#{name}%';  
#{}不会被解析,从而导致报错。

in 语法和 between语法都是如此,那么如何解决这类问题呢?

2. 正确写法
(1) order by(group by)语句中使用${}

使用条件判断

<select id="getUserAndOrder" resultType="Emp" parameterType="Emp">
  select * from users where id < #{id}
  <choose>
    <when test="order == \"name\"">
        order by name
    </when>
    <when test="order != \"age\"">
        order by age
    </when>
    <otherwise>
        order by id
    </otherwise>
  </choose>
</select>
使用全局过滤机制,限制order by后的变量内容只能是数字、字母、下划线。

如使用正则过滤:

keywordkeyword = keyword.replaceAll("[^a-zA-Z0-9_\s+]", "");
这里需要注意,过滤需要使用白名单,不能使用黑名单,黑名单无法解决注入问题。

(2) LIKE语句

由于需要like中的关键词需要包裹在两个%符号中,因此可以使用CONCAT函数进行拼接。

<select id="selectStudentByFuzzyQuery" resultMap="studentMap">
  SELECT *
  FROM student
  WHERE student.stu_name
        LIKE CONCAT('%',#{stuName},'%')
</select>
注意不要用 CONCAT('%','${stuName}','%') ,这样仍然存在漏洞。也就是说,使用$符号是不对的,使用#符号才安全。

(3) IN语句

类似于like语句,直接使用#{}会报错,常见的错误写法为:

tenant_id in (${tenantIds})
正确的写法为:

select * from news where id in
<foreach collection="ids" item="item" open="("separator="," close=")">#{item}</foreach>
相关信息
其他-常平
3天前 刷新
其他-常平
3天前 刷新
其他-常平
3天前 刷新
其他-常平
11月20日 刷新
其他-塘厦
8月7日 刷新
其他-常平
8月7日 刷新
查看更多东莞网站/软件服务信息

免责声明:此信息系发布者(UID:725737)自行发布,本站是服务平台,仅提供信息存储空间服务,该信息内容的真实性及合法性由该发布者完全负责。

© lieju.com 联系我们