• 售前

  • 售后

热门帖子
入门百科

怎样有用防止sql注入的方法

[复制链接]
飘渺九月 显示全部楼层 发表于 2021-8-14 14:31:46 |阅读模式 打印 上一主题 下一主题
SQL注入攻击是黑客对数据库举行攻击常用的手段之一,随着B/S模式应用开辟的发展,使用这种模式编写应用程序的程序员也越来越多。但是由于程序员的程度及经验乱七八糟,相称大一部分程序员在编写代码的时间,没有对用户输入数据的正当性举行判定,使应用程序存在安全隐患。用户可以提交一段数据库查询代码,根据程序返回的结果,得到某些他想获取的数据,这就是所谓的SQL Injection,即SQL注入。
一 配景

如果某高校开辟了一个网课体系,要修业生选课后完成学习,数据库中有一张表
  1. course
复制代码
,这张表存放着每个学生的选课信息及完成情况,详细设计如下:

数据如下:

本体系接纳mysql做为数据库,使用Jdbc来举行数据库的相干操纵。体系提供了一个功能查询该学生的课程完成情况,代码如下。
  1. @RestController
  2. public class Controller {
  3.    
  4.     @Autowired
  5.     SqlInject sqlInject;
  6.    
  7.     @GetMapping("list")
  8.     public List<Course> courseList(@RequestParam("studentId") String studentId){
  9.         List<Course> orders = sqlInject.orderList(studentId);
  10.         return orders;
  11.     }
  12. }
复制代码
  1. @Service
  2. public class SqlInject {
  3.     @Autowired
  4.     private JdbcTemplate jdbcTemplate;
  5.    
  6.     public List<Course> orderList(String studentId){
  7.         String sql = "select id,course_id,student_id,status
  8. from course where student_id = "+ studentId;
  9.         return jdbcTemplate.query(sql,new BeanPropertyRowMapper(Course.class));
  10.     }
  11. }
复制代码
二 注入攻击演示

1. 正常情况下查询一个学生所选课程及完成情况只需要传入
  1. student_id
复制代码
,便可以查到相干数据。

根据响应结果,我们很快便能写出对应的sql,如下:
  1. select id,course_id,student_id,status
  2. from course
  3. where student_id = 4
复制代码
2. 如果我们想要获取这张表的所有数据,只需要保证上面这个sql的where条件恒真就可以了。
  1. select id,course_id,student_id,status
  2. from course
  3. where student_id = 4 or 1 = 1
复制代码
请求接口的时间将
  1. studendId
复制代码
设置为4 or 1 = 1,这样这条sql的where条件就恒真了。sql也就等同于下面这样
  1. select id,course_id,student_id,status
  2. from course
复制代码
请求结果如下,我们拿到了这张表的所有数据

3. 查询mysql版本号,使用
  1. union
复制代码
拼接sql
  1. union select 1,1,version(),1
复制代码

4. 查询数据库名
  1. union select 1,1,database(),1
复制代码

5. 查询mysql当前用户的所有库
  1. union select 1,1, (SELECT GROUP_CONCAT(schema_name) FROM information_schema.schemata) schemaName,1
复制代码

看完上面这些演示后,你畏惧了吗?你所有的数据设置都完全暴袒露来了,除此之外,还可以完成许多操纵,更新数据、删库、删表等等。
三 怎样防止sql注入

1. 代码层防止sql注入攻击的最佳方案就是sql预编译
  1. public List<Course> orderList(String studentId){    String sql = "select id,course_id,student_id,status
  2. from course where student_id = ?";    return jdbcTemplate.query(sql,new Object[]{studentId},new BeanPropertyRowMapper(Course.class));}
复制代码
这样我们传进来的参数
  1. 4 or 1 = 1
复制代码
就会被看成是一个
  1. student_id
复制代码
,以是就不会出现sql注入了。
2. 确认每种数据的范例,好比是数字,数据库则必须使用int范例来存储
3. 规定命据长度,能在肯定程度上防止sql注入
4. 严格限制数据库权限,能最大程度镌汰sql注入的危害
5. 制止直接响应一些sql异常信息,sql发生异常后,自定义异常举行响应
6. 过滤参数中含有的一些数据库关键词
  1. @Component
  2. public class SqlInjectionFilter implements Filter {
  3.     @Override
  4.     public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
  5.         HttpServletRequest req=(HttpServletRequest)servletRequest;
  6.         HttpServletRequest res=(HttpServletRequest)servletResponse;
  7.         //获得所有请求参数名
  8.         Enumeration params = req.getParameterNames();
  9.         String sql = "";
  10.         while (params.hasMoreElements()) {
  11.             // 得到参数名
  12.             String name = params.nextElement().toString();
  13.             // 得到参数对应值
  14.             String[] value = req.getParameterValues(name);
  15.             for (int i = 0; i < value.length; i++) {
  16.                 sql = sql + value[i];
  17.             }
  18.         }
  19.         if (sqlValidate(sql)) {
  20.             throw new IOException("您发送请求中的参数中含有非法字符");
  21.         } else {
  22.             chain.doFilter(servletRequest,servletResponse);
  23.         }
  24.     }
  25.     /**
  26.      * 关键词校验
  27.      * @param str
  28.      * @return
  29.      */
  30.     protected static boolean sqlValidate(String str) {
  31.         // 统一转为小写
  32.         str = str.toLowerCase();
  33.         // 过滤掉的sql关键字,可以手动添加
  34.         String badStr = "'|and|exec|execute|insert|select|delete|update|count|drop|*|%|chr|mid|master|truncate|" +
  35.                 "char|declare|sitename|net user|xp_cmdshell|;|or|-|+|,|like'|and|exec|execute|insert|create|drop|" +
  36.                 "table|from|grant|use|group_concat|column_name|" +
  37.                 "information_schema.columns|table_schema|union|where|select|delete|update|order|by|count|*|" +
  38.                 "chr|mid|master|truncate|char|declare|or|;|-|--|+|,|like|//|/|%|#";
  39.         String[] badStrs = badStr.split("\\|");
  40.         for (int i = 0; i < badStrs.length; i++) {
  41.             if (str.indexOf(badStrs[i]) >= 0) {
  42.                 return true;
  43.             }
  44.         }
  45.         return false;
  46.     }
  47. }
复制代码
到此这篇关于怎样有用防止sql注入的方法的文章就介绍到这了,更多相干sql防止注入内容请搜索草根技术分享从前的文章或继续浏览下面的相干文章盼望各人以后多多支持草根技术分享!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

帖子地址: 

回复

使用道具 举报

分享
推广
火星云矿 | 预约S19Pro,享500抵1000!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

草根技术分享(草根吧)是全球知名中文IT技术交流平台,创建于2021年,包含原创博客、精品问答、职业培训、技术社区、资源下载等产品服务,提供原创、优质、完整内容的专业IT技术开发社区。
  • 官方手机版

  • 微信公众号

  • 商务合作