一、常见SQL注入
1、sql语句动态拼接
示例代码:
String id=request.getParameter("id");
res = st.executeQuery("SELECT * FROM \"IWEBSEC\".\"user\" WHERE \"id\"="+id);
while(res.next()){
int p = res.getInt("id");
String n = res.getString("username");
String s = res.getString("password");
}
上述代码通过request.getParameter方法获取id值,通过 SELECT * FROM \”IWEBSEC\”.\”user\” WHERE \”id\”=”+id 进行了sql语句的动态拼接。通过executeQuerry执行sql语句,会发现id的参数是可控的并且可以进行sql语句的拼接。
2、预编译错误
示例代码:
`String username="user%' or '1'='1'#";
String id ="2";
String sql = "SELECT * FROM user where id = ?";
if (!CommonUtils.isEmptyStr(username))
sql += " and username like '%" + username + "%'";
System.out.println(sql);
PreparedStatement preparedStatement = conn.prepareStatement(sql);
preparedStatement.setString(1, id);
rs = preparedStatement.executeQuery();`
上述代码虽然使用了preparestatement预编译,但是在后面的username使用了sql语句拼接的方式,这样会导致sql注入。
3、order by 注入
原理:使用prepareStatement时,order by 后面需要加字段名,字段名不能带引号,带引号会被认为这是一个字符串而不是字段名。PrepareStatement 是使用占位符传入参数的,传递的字符都会有单引号包裹,ps.setString(1, id)”会自动给值加上引号,这样就会导致 order by 子句失效。
示例代码:
```java
`String id ="2 or 1=1";
String sql = "SELECT * FROM user "+ " order by " + id;
System.out.println(sql);
PreparedStatement preparedStatement = conn.prepareStatement(sql);
rs = preparedStatement.executeQuery();`
```
上述代码中当使用“String sql = “SELECT * FROM user “+ “ order by “ + id”进行 id 参数拼接时,就出现了 SQL 注入漏洞。
4、%和模糊查询
原理:在 java 预编译查询中不会对%和进行转义处理,而%和_刚好是 like 查询的通配符,如果没有做好相关的过滤,就有可能导致恶意模糊查询。
传入的 username 为“”%user%””时,通过动态调试发现数据库在执行时并没有将%进行转义处理,而是作为通配符进行查询。
防范方法:直接将%进行过滤。
5、MyBatis SQL注入之order by
order by 子句不可以进行参数化查询,进而不能使用#{},只能使用${},如果在 MyBatis 的 order by
子句中使用#{},则 order by 子句会失效。
示例代码:
运行效果:
可见,其运行结果并没有排序,然后我们查看一下mybatis的日志发现,使用#{}参数化查询会将 age 进
行单引号包裹而导致 order by 失效。
5、like查询
MyBatis 的 like 子句中使用#{}程序会报错,所以为了避免报错,在开发的时候使用${},当使用like ‘#%{name}%’时,会报错。
而使用like ‘$%{name}%’,时会正常执行。
虽然使用${}可是使程序正常运行,但是${}属于字符串的拼接,存在SQL注入,如果 emp_Name 传
入的是“emp_Name’ union select 1,database(),3 #”就会造成 SQL 注入漏洞。
防范方法:过滤
6、in 参数
MyBatis 的 in 子句中使用#{}参数化查询,会将“select from users where name in
(#{user})”转变为“select from users where name like (‘’user1’,’user2’,’user3’,’user4’’)”。为避免这个问题只能用${}。
二、常规注入代码审计
1、找常见关键字,方便快速定位
Statement
createStatement
PrepareStatement
like ‘%${
in (${
select
update
insert
2、查找调用方法,弄清逻辑。
3、找到路径绑定关系,构造payload。
4、二次注入
前期与常规注入代码审计一样,找sql语句看是否存在字符串拼接,如果存在,通过查找参数的调用逻辑,理清逻辑,在构造payload时,先注册一个正常的用户名,但是用户名是带有sql语句的,比如 “ ‘union select user(),2.3# “,此时在登陆的时候就可以显示对应的信息。
三、SQL注入的修复
对于 SQL 注入漏洞,最有效的防御手段便是进行预编译处理,使用预编译处理不仅可以防范 SQL 注入攻击,而且能够提高执行速度。但是如果遇到order by,不能用预编译进行处理的时候,就需要对参数进行手动的过滤。
也可以使用强制类型转换来防止sql注入,比如我们已知id的参数是数字,那我们可以把id强制转换为int类型。有效的防止了SQL注入。
免费领取安全学习资料包!
渗透工具

技术文档、书籍


面试题
帮助你在面试中脱颖而出

视频
基础到进阶
环境搭建、HTML,PHP,MySQL基础学习,信息收集,SQL注入,XSS,CSRF,暴力破解等等


应急响应笔记

学习路线

Java代码审计:SQL注入防范与修复
本文探讨了Java中常见的SQL注入漏洞,包括动态拼接、预编译错误、order by注入、模糊查询等问题,并提供了防范方法。强调了预编译处理的重要性,以及在遇到order by等特殊场景时如何手动过滤参数。同时,提到了MyBatis中的SQL注入风险,如like查询和in参数的安全处理。文章最后讨论了SQL注入的修复策略和安全学习资源。
2836

被折叠的 条评论
为什么被折叠?



