java之SQL注入

在java中,最常见的连接数据库方式有JDBC,Mybatis,和Hibernate。那我们只需要注意这些地方就可以判断是否存在sql注入即可

0x01、Mybatis下SQL注入

Mybatis的SQL语句可以基于注解的方式写在类方法上面,更多的是以xml的方式写到xml文件。Mybatis中SQL语句需要我们自己手动编写或者用generator自动生成。

编写xml文件时,Mybatis支持两种参数符号,一种是#,另一种是$。比如:

<select >
  SELECT * FROM NEWS WHERE ID = #{id}
</select>

而java开发的站点中大部分是预编译,也就是说存在的sql注入少了;但是,还是有些语句不能进行预编译,从而导致sql注入。为什么呢?因为预编译中获取参数从而执行sql语句使用的#号,然而$符是拼接的意思,像like,in这种使用不规范#符就会报错,所以就会使用$。那么这种就一定的几率存在注入,一切看开发是新手还是老司机

导入依赖

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.47</version>
</dependency>

<!--mybatis的依赖-->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.3</version>
</dependency>

1、like模糊查询注入

Select * from news where title like '%#{title}%'  //报错
Select * from news where title like '%${title}%'  //正常

在这种情况下使用#程序会报错,新手程序员就把#号改成了$,这样如果java代码层面没有对用户输入的内容做处理势必会产生SQL注入漏洞。

正确写法:

select * from news where tile like concat(‘%’,#{title}, ‘%’)

2、in 注入

in之后多个id查询时使用# 同样会报错,

Select * from news where id in (#{id})  //报错
Select * from news where id in (${id})  //正常

正确用法为使用foreach,而不是将#替换为$

id in
<foreach collection="id" item="item" open="("separatosr="," close=")">
#{id} 
</foreach>

3、order by 注入

这种场景应当在Java层面做映射,设置一个字段/表名数组,仅允许用户传入索引值。这样保证传入的字段或者表名都在白名单里面。需要注意的是在mybatis-generator自动生成的SQL语句中,order by使用的也是$,而like和in没有问题。

Select * from news where title ='#{titlename}' order by #{time} asc //报错
Select * from news where title ='#{titlename}' order by ${time} asc //正常

总结

总的来说,其实是新手程序员,因为使用#会报错,从而发现$符不会报错,进行使用$符;但是本身程序员自己不会用而导致的

java sql注入问题适合使用反推,先搜索xml查找可能存在注入的漏洞点→反推到DAO→再到实现类→再通过调用链找到前台URL,找到利用点