本文很水,纯属个人笔记,有些小点主要是为了怕忘记,也方便以后教一些入门的朋友。

1、常出现的点

快速审计,我们需要快速搜索
String query
executeQuery
execute
executeUpdate
createStatement

order by group by
(“Select

这种原生的sql查询基本上使用prepareStatement(预编译)方法来进行防护就好了。
demo代码

  1. pstm = con.getMssqlConn().prepareStatement("select * from xxxx where id = ?");

java参数化预编译之所以能防御住SQL注入,只要是基于以下2点:

  1. setString(): WEB程序接收字符串的场景
    将用户输入的参数全部强制转换为字符串,并进行适当的转义,防止了闭合的产生
  2. setInt(): WEB程序接收整型的场景
    将用户输入的非整型参数强制转换为整型,并去除潜在的”非整型注入字符”,类似与PHP中的intVal()防御思路

并不是说使用了参数化预编译方法执行SQL,就不会有注入的发生了,当WEB系统和DataBase系统的字符集配置不当,可能会导致宽字节注入的发生

2、mybatis(现在比较常用)

mybatis的sql语句可以写在xml配置文件里,也可以写在注解里
xml配置文件

  1. <select id="getById" resultType = "org.example.User" >
  2. SELECT * FROM user WHERE id = #{id}
  3. </select>

注解

  1. @Select("select * from user where id=#{id}")

mybatis 提供了两种方式 #{} 和 ${}
select from user where ${id} select from user where #{id}
#{} 在预处理时,会把参数部分用一个占位符 ? 替代,能有效解决 SQL 注入问题,相对比较安全
${} 表示使用拼接字符,将接受到参数的内容不加任何修饰符拼接在 SQL 中,使用${}拼接 sql,是不安全的

但是在${}在面对like、in 、order by、group by这类关键字时,${}就不起作用了
like正确写法

  1. select * from user where username like concat('%',#{username},'%')

in正确写法

  1. select * from user where username in
  2. <foreach collection="list" index="index" item="item" open="("
  3. separator="," close=")">
  4. #{username}

order by
手动写过滤。

那么我们看下面xml配置,可以看到是存在sql注入漏洞的,那么我们需要找的就是搜索id——getById

  1. <select id="getById" resultType = "org.example.User" >
  2. SELECT * FROM user WHERE id = ${id}
  3. </select>

3、Hibernate(以前比较常用)

相关jar包
image.png
Hibernate的SQLi我们叫他HQL注入
HQL查询并不直接发送给数据库,而是由hibernate引擎对查询进行解析并解释,然后将其转换为SQL
HQL大多数利用都是直接拼接字段获取当前表中的数据,或者盲注,报错注入案例少的可怜

一般存在的地方
session.createQuery

代码demo

  1. Query query=session.createQuery("from User user where user.name=? and user:userage=? ");
  2. query.setString(0,username);
  3. query.setInteger(1,age);

除了使用问号来映射,同样支持 :
例如要从商品数据库中取出第一个大于25元的商品的Sql语句写法如下。

  1. String hql = "from Product where price>25.0";
  2. Query query = session.createQuery(hql);
  3. query.setMaxResults(1);
  4. Product product = (Product) query.uniqueResult();

案例
根据别人的案例可知需要直接拼接字段盲猜,利用盲注直接去找到相关字段
image.png

防护的话:
基本上就是看有没有这两个方法,setString和setInt
query.setString(“username”,username);
query.setInteger(“userage”,age);
以及 setParameter和setParameterList可以产生预编译

相关资料:
https://mp.weixin.qq.com/s/-jz3v1L8f7ZDUMeXc2xWyg

总结:

sql正则

  1. Select|insert|update|delete|java.sql.Connection|Statement|.execute|.executeQuery|jdbcTemplate|queryForInt|queryForObject|queryForMap|getConnection|PreparedStatement|Statement|execute|jdbcTemplate|queryForInt|queryForObject|queryForMap|executeQuery|getConnection

sql修复方式

1、预编译。
2、对于不能使用预编译的方式对这些语句的传入进行过滤。
3、对于明确传入数字型的参数做int类型的强制转换。
4、包括可以在全局做一些过滤,直接过滤掉诸如注释 ,分号,select,xp_xxx,单引号双引号这样的字符。

order by 注入

并无太大差异,可以直接使用盲注或者强行报错的方式来进行判断,
可能就是利用传统的and 1=1 and 1=2判断不出来而已。
强行报错就不多说了,就是报错注入
然后还要就是盲注,可以使用异或的方式来进行。

那么为什么Mybits order by 后面不能使用预编译呢?
原因是使用预编译后会增加了’’ 引号这个东西,加了引号order by 原本的作用就消失了,因此框架就默认禁止了这种写法,因此使用预编译就会报错,那么可能就会有程序员就怕麻烦就直接拼接了。

不只order by,凡是字符串但又不能加引号的位置都不能参数化;包括sql关键字、库名表名字段名函数
所以在代码审计的时候,可以多找找order by 或者group by出现的地方