java之SQL注入
前言
在java中,最常见的连接数据库方式有JDBC,Mybatis,和Hibernate。那我们只需要注意这些地方就可以判断是否存在sql注入即可
0x01、Mybatis下SQL注入
Mybatis的SQL语句可以基于注解的方式写在类方法上面,更多的是以xml的方式写到xml文件。Mybatis中SQL语句需要我们自己手动编写或者用generator自动生成。
编写xml文件时,Mybatis支持两种参数符号,一种是#,另一种是$。比如:
<select id="queryAll" resultMap="resultMap">
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,找到利用点