共计 3262 个字符,预计需要花费 9 分钟才能阅读完成。
自动写代码机器人,免费开通
如何有效防止 sql 注入?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面丸趣 TV 小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。
@RestController
public class Controller {
@Autowired
SqlInject sqlInject;
@GetMapping(list)
public List Course courseList(@RequestParam( studentId) String studentId){ List Course orders = sqlInject.orderList(studentId);
return orders;
}
}
@Service
public class SqlInject {
@Autowired
private JdbcTemplate jdbcTemplate;
public List Course orderList(String studentId){
String sql = select id,course_id,student_id,status from course where student_id = + studentId;
return jdbcTemplate.query(sql,new BeanPropertyRowMapper(Course.class));
}
}
二 注入攻击演示
1. 正常情况下查询一个学生所选课程及完成情况只需要传入 student_id,便可以查到相关数据。
根据响应结果,我们很快便能写出对应的 sql,如下:
select id,course_id,student_id,status
from course
where student_id = 4
2. 如果我们想要获取这张表的所有数据,只需要保证上面这个 sql 的 where 条件恒真就可以了。
select id,course_id,student_id,status
from course
where student_id = 4
or 1 = 1
请求接口的时候将 studendId 设置为 4 or 1 = 1,这样这条 sql 的 where 条件就恒真了。sql 也就等同于下面这样
select id,course_id,student_id,status
from course
请求结果如下,我们拿到了这张表的所有数据
3. 查询 mysql 版本号,使用 union 拼接 sql
union select 1,1,version(),1
4. 查询数据库名
union select 1,1,database(),1
5. 查询 mysql 当前用户的所有库
union select 1,1, (SELECT GROUP_CONCAT(schema_name) FROM information_schema.schemata) schemaName,1
看完上面这些演示后,你害怕了吗?你所有的数据配置都完全暴露出来了,除此之外,还可以完成很多操作,更新数据、删库、删表等等。
三 如何防止 sql 注入
1. 代码层防止 sql 注入攻击的最佳方案就是 sql 预编译
public List Course orderList(String studentId){
String sql = select id,course_id,student_id,status from course where student_id = ?
return jdbcTemplate.query(sql,new Object[]{studentId},new BeanPropertyRowMapper(Course.class));
}
这样我们传进来的参数 4 or 1 = 1 就会被当作是一个 student_id,所以就不会出现 sql 注入了。
2. 确认每种数据的类型,比如是数字,数据库则必须使用 int 类型来存储
3. 规定数据长度,能在一定程度上防止 sql 注入
4. 严格限制数据库权限,能最大程度减少 sql 注入的危害
5. 避免直接响应一些 sql 异常信息,sql 发生异常后,自定义异常进行响应
6. 过滤参数中含有的一些数据库关键词
@Component
public class SqlInjectionFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException { HttpServletRequest req=(HttpServletRequest)servletRequest;
HttpServletRequest res=(HttpServletRequest)servletResponse;
// 获得所有请求参数名
Enumeration params = req.getParameterNames();
String sql =
while (params.hasMoreElements()) {
// 得到参数名
String name = params.nextElement().toString();
// 得到参数对应值
String[] value = req.getParameterValues(name);
for (int i = 0; i value.length; i++) { sql = sql + value[i];
}
}
if (sqlValidate(sql)) {
throw new IOException( 您发送请求中的参数中含有非法字符
} else { chain.doFilter(servletRequest,servletResponse);
}
}
/**
* 关键词校验
* @param str
* @return
*/
protected static boolean sqlValidate(String str) {
// 统一转为小写
str = str.toLowerCase();
// 过滤掉的 sql 关键字,可以手动添加
String badStr = |and|exec|execute|insert|select|delete|update|count|drop|*|%|chr|mid|master|truncate| +
char|declare|sitename|net user|xp_cmdshell|;|or|-|+|,|like |and|exec|execute|insert|create|drop| +
table|from|grant|use|group_concat|column_name| +
information_schema.columns|table_schema|union|where|select|delete|update|order|by|count|*| +
chr|mid|master|truncate|char|declare|or|;|-|--|+|,|like|//|/|%|#
String[] badStrs = badStr.split( \\|
for (int i = 0; i badStrs.length; i++) { if (str.indexOf(badStrs[i]) = 0) {
return true;
}
}
return false;
}
}
看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注丸趣 TV 行业资讯频道,感谢您对丸趣 TV 的支持。
向 AI 问一下细节