Sql注入
示例
为了说明项目中的sql注入,此处以mybatis为例
package com.fiberhome.base;
import com.fiberhome.base.dao.TUserMapper;
import com.fiberhome.base.model.User;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import javax.annotation.Resource;
import java.util.List;
/**
* @description:
* @author: pp_lan
* @date: 2021/8/29 9:17
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
"classpath:spring/spring-content.xml",
"classpath:spring/spring-mvc.xml"
})
@WebAppConfiguration
public class UserTest {
@Resource
private TUserMapper tUserMapper;
// @Test
public void test() {
for (int i = 1; i < 101; i++) {
tUserMapper.insertUserInfo(new User(i, 20, "li" + i));
}
}
/**
* 有sql注入危险示例
*/
@Test
public void test02() {
List<User> users = tUserMapper.selectByName("' or '1'='1");
System.out.println("期望: 系统没有该用户时候,查询不到");
Assert.assertEquals(0, users.size());
}
/**
* 优化后方案
*/
@Test
public void test03() {
List<User> users = tUserMapper.searchByName("' or '1'='1");
System.out.println("期望: 系统没有该用户时候,查询不到");
Assert.assertEquals(0, users.size());
}
}
Mapper
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org/DTD Mapper 3.0" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.fiberhome.base.dao.TUserMapper">
<insert id="insertUserInfo">
INSERT INTO t_user ("id", "age", "name") VALUES (#{user.id}, #{user.age}, #{user.name});
</insert>
<select id="selectByName" resultType="com.fiberhome.base.model.User">
select * from t_user where "name" like '%${name}%';
</select>
<select id="searchByName" resultType="com.fiberhome.base.model.User">
select * from t_user where "name" like concat('%', #{name}, '%');
</select>
</mapper>
单元测试用例执行日志
test02
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@ce9b9a9] was not registered for synchronization because synchronization is not active
JDBC Connection [jdbc:postgresql://localhost:5432/test?characterEncoding=utf-8, UserName=postgres, PostgreSQL JDBC Driver] will not be managed by Spring
==> Preparing: select * from t_user where "name" like '%' or '1'='1%';
==> Parameters:
<== Columns: id, age, name
<== Row: 1, 20, li1
<== Row: 2, 20, li2
<== Row: 3, 20, li3
<== Row: 4, 20, li4
<== Row: 5, 20, li5
<== Row: 6, 20, li6
<== Row: 7, 20, li7
<== Row: 8, 20, li8
<== Row: 9, 20, li9
<== Row: 10, 20, li10
<== Row: 11, 20, li11
<== Row: 12, 20, li12
<== Row: 13, 20, li13
<== Row: 14, 20, li14
<== Row: 15, 20, li15
<== Row: 16, 20, li16
<== Row: 17, 20, li17
<== Row: 18, 20, li18
<== Row: 19, 20, li19
<== Row: 20, 20, li20
<== Row: 21, 20, li21
<== Row: 22, 20, li22
<== Row: 23, 20, li23
<== Row: 24, 20, li24
<== Row: 25, 20, li25
<== Row: 26, 20, li26
<== Row: 27, 20, li27
<== Row: 28, 20, li28
<== Row: 29, 20, li29
<== Row: 30, 20, li30
<== Row: 31, 20, li31
<== Row: 32, 20, li32
<== Row: 33, 20, li33
<== Row: 34, 20, li34
<== Row: 35, 20, li35
<== Row: 36, 20, li36
<== Row: 37, 20, li37
<== Row: 38, 20, li38
<== Row: 39, 20, li39
<== Row: 40, 20, li40
<== Row: 41, 20, li41
<== Row: 42, 20, li42
<== Row: 43, 20, li43
<== Row: 44, 20, li44
<== Row: 45, 20, li45
<== Row: 46, 20, li46
<== Row: 47, 20, li47
<== Row: 48, 20, li48
<== Row: 49, 20, li49
<== Row: 50, 20, li50
<== Row: 51, 20, li51
<== Row: 52, 20, li52
<== Row: 53, 20, li53
<== Row: 54, 20, li54
<== Row: 55, 20, li55
<== Row: 56, 20, li56
<== Row: 57, 20, li57
<== Row: 58, 20, li58
<== Row: 59, 20, li59
<== Row: 60, 20, li60
<== Row: 61, 20, li61
<== Row: 62, 20, li62
<== Row: 63, 20, li63
<== Row: 64, 20, li64
<== Row: 65, 20, li65
<== Row: 66, 20, li66
<== Row: 67, 20, li67
<== Row: 68, 20, li68
<== Row: 69, 20, li69
<== Row: 70, 20, li70
<== Row: 71, 20, li71
<== Row: 72, 20, li72
<== Row: 73, 20, li73
<== Row: 74, 20, li74
<== Row: 75, 20, li75
<== Row: 76, 20, li76
<== Row: 77, 20, li77
<== Row: 78, 20, li78
<== Row: 79, 20, li79
<== Row: 80, 20, li80
<== Row: 81, 20, li81
<== Row: 82, 20, li82
<== Row: 83, 20, li83
<== Row: 84, 20, li84
<== Row: 85, 20, li85
<== Row: 86, 20, li86
<== Row: 87, 20, li87
<== Row: 88, 20, li88
<== Row: 89, 20, li89
<== Row: 90, 20, li90
<== Row: 91, 20, li91
<== Row: 92, 20, li92
<== Row: 93, 20, li93
<== Row: 94, 20, li94
<== Row: 95, 20, li95
<== Row: 96, 20, li96
<== Row: 97, 20, li97
<== Row: 98, 20, li98
<== Row: 99, 20, li99
<== Row: 100, 20, li100
<== Total: 100
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@ce9b9a9]
期望: 系统没有该用户时候,查询不到
java.lang.AssertionError:
Expected :0
Actual :100
<Click to see difference>
at org.junit.Assert.fail(Assert.java:88)
at org.junit.Assert.failNotEquals(Assert.java:834)
at org.junit.Assert.assertEquals(Assert.java:645)
at org.junit.Assert.assertEquals(Assert.java:631)
at com.fiberhome.base.UserTest.test02(UserTest.java:45)
日志说明
查询出了全部数据,不满足测试期望(查询错误返回[],实际却返回100条),存在数据泄露风险
test03
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2b10ace9] was not registered for synchronization because synchronization is not active
JDBC Connection [jdbc:postgresql://localhost:5432/test?characterEncoding=utf-8, UserName=postgres, PostgreSQL JDBC Driver] will not be managed by Spring
==> Preparing: select * from t_user where "name" like concat('%', ?, '%');
==> Parameters: ' or '1'='1(String)
<== Total: 0
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2b10ace9]
期望: 系统没有该用户时候,查询不到
日志说明
优化解决sql注入问题手段(mybatis为例)
- 用$替换# ,预编译
- 用 concat(’%’, ‘zhangsan’, ‘%’) 替换 ’%zhangsan%‘