sql注入的原理是什么,怎么预防sql注入

为什么会产生sql注入:

  主要原因,对用户输入的绝对信任,相信所有用户的输入都是可信的,没有对用户输入的语句进行过滤或者筛选,直接放到sql语句中进行拼接,从而导致了sql注入的产生

  例如:

    <php?

      id = $_GET['id'];

      sql = "select * from tables where id=$id limit 0,1";

      .......

    ?>

  如果是正常的id等于数值之类,是没有问题的,但是id如果被恶意用户更改,我们原本的逻辑就会出现一系列的问题

  假如恶意用户输入的是 -1 union select version(),database()--+;

  直接将用户输入的id拼接上就会产生以下语句

  sql = "select * from tables where id=-1 union select version(),database()-- limit 0,1"(--表示的是数据库注释,+表示字符串的拼接)

  由于他将id设置为了-1,数据库中不存在负值的id,所以第一个查询会查询到一个空的表,这样数据库会将union联合查询查询到的sql结果,返回出来

  这样,恶意用户就会拿到我们数据库的版本和数据库的名字,要知道,在mysql5.0以上会存在一个information_schrma的数据库,这个数据库存放着所有的数据库名,表名,字段名,我们所有数据就会被泄露,严重的,还能对我们的数据进行修改和删除(堆叠查询,将原来的sql闭合,这样就可以直接对数据库进行危险操作 比如 insert drop  有的数据库或者中间件是不支持堆叠查询,具体堆叠查询(注入)就不再细说了)

sql注入的预防:

  sql注入的本质上还是对用户输入数据的绝对信任,当我们对用户输入的数据绝对不信任的时候,就可以预防sql注入

  1.输入数据长度的限制

  2.关键字过滤:

    对每个参数的传递进行检测,对其进行sql关键字过滤如(select insert where)          建议采用正则检测和递归过滤

  3.对参数携带的特殊字符进行转义和过滤:
    因为好多注入点都是在字符位置发生的,如果需要进行sql注入,就要先进性闭合的符号判断(id='$id' 如果不进行引号的闭合,数据库就会认为用户输入的所有参数为同一个字符串,这样sql注入的参数就会被认为是无效的)这也是我们的防护手段之一                建议采用正则检测和递归过滤

  4.预编译防注入:预编译防注入是目前最好的,最有效的防注入手段
    在数据库进行预编译的之后,sql语句已经会被数据库编译和优化了,并且运行数据库以参数化的形式进行查询,即使传递来的敏感字符也不会被执行,而是被当作参数处理

  5.不要直接显示出错误的原因,最好指定一个错误的页面,尤其是sql注入(即使存在注入,也要让他去盲注)

 

posted @ 2020-01-01 11:14  追得上的梦想  阅读(2544)  评论(0编辑  收藏  举报