怎么有效防止SQL注入攻击

77次阅读
没有评论

共计 3676 个字符,预计需要花费 10 分钟才能阅读完成。

这篇文章主要介绍“怎么有效防止 SQL 注入攻击”,在日常操作中,相信很多人在怎么有效防止 SQL 注入攻击问题上存在疑惑,丸趣 TV 小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么有效防止 SQL 注入攻击”的疑惑有所帮助!接下来,请跟着丸趣 TV 小编一起来学习吧!

SQL 注入攻击是黑客对数据库进行攻击常用的手段之一,随着 B / S 模式应用开发的发展,使用这种模式编写应用程序的程序员也越来越多。但是由于程序员的水平及经验参差不齐,相当大一部分程序员在编写代码的时候,没有对用户输入数据的合法性进行判断,使应用程序存在安全隐患。用户可以提交一段数据库查询代码,根据程序返回的结果,获得某些他想获取的数据,这就是所谓的 SQL  Injection,即 SQL 注入。

一 背景

假如某高校开发了一个网课系统,要求学生选课后完成学习,数据库中有一张表 course,这张表存放着每个学生的选课信息及完成情况,具体设计如下:

数据如下:

本系统采用 mysql 做为数据库,使用 Jdbc 来进行数据库的相关操作。系统提供了一个功能查询该学生的课程完成情况,代码如下。

@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,database(),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; } }

到此,关于“怎么有效防止 SQL 注入攻击”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注丸趣 TV 网站,丸趣 TV 小编会继续努力为大家带来更多实用的文章!

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-08-03发表,共计3676字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)