@restcontroller public class controller { @autowired sqlinject sqlinject; @getmapping("list") public list courselist(@requestparam("studentid") string studentid){ list orders = sqlinject.orderlist(studentid); return orders; } }
@service public class sqlinject { @autowired private jdbctemplate jdbctemplate; public list 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
public list 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 = 0) { return true; } } return false; } }