天天看点

SQL注入攻击与防御一、概念:二、攻击条件:三、攻击示例:四、防御措施:

一、概念:

        SQL注入:针对程序本身的逻辑,输入一些特别的字符串,构造出符合SQL语法的SQL语句,使该SQL语句能执行出本不希望的结果,达到攻击服务器的目的。按输入参数的类型,注入方式可分为:数字型注入和字符型注入。不管是数字型注入还是字符型注入,都是程序本来期望输入的一个参数对应的是一个查询条件,但恶意攻击者通过构造字符串,将一个参数中包含了多个查询条件甚至多条语句,最终构造成的SQL字符串在数据库执行,达到攻击的目的。

二、攻击条件:

        1、能够通过前端输入一些参数,并且这些参数作为SQL语句的一部分进行执行;

        2、这些参数通过程序代码组成的SQL语句符合SQL语法,执行时可以执行成功;

三、攻击示例:

        攻击不仅仅指破坏数据库对象(修改、甚至删除数据库对象,比如表,视图等)、修改库中的数据(新增、修改、删除数据),还包括可以任意获取不希望用户获取到的数据(比如用户的私密信息如密码等)。

        1、数字型注入:

        如果需要用户输入编号$no(整型),这个$no经过服务端代码处理后,最终会拼成SQL语句(实际上就是字符串的拼接)并执行,比如:

SELECT id,no,name,passwd FROM userinfo where no = $no;
           

        因为是数字,所以$no不需要用单引号''包围。如果传入的编号$no是数值:1,构造成的SQL最终是这样:

SELECT id,no,name,passwd FROM userinfo where no = 1;
           

        但如果编号$no没有校验必须是数字,那么如果传入的编号$no是字符串:"1 OR 1 = 1",构造成的SQL最终是这样:

SELECT id,no,name,passwd FROM userinfo where no = 1 OR 1 = 1;
           

        可以看出,实际上传入的编号$no并不是一个查询条件,而是多增加了条件: OR 1 = 1,使userinfo表中所有记录的where条件都成立,可以查出userinfo表中的所有记录,近而达到攻击的目的,如果是update语句或delete语句后果更严重。

        2、字符型注入:

        如果需要用户输入姓名$name(字符串),这个$name经过服务端代码处理后,最终会拼成SQL语句(实际上就是字符串的拼接)并执行,比如:

SELECT id,no,name,passwd FROM userinfo where name = '$name';
           

        因为是字符串,所以$name需要用单引号''或双引号""包围。如果传入的姓名$name是字符串:"张三",构造成的SQL最终是这样:

SELECT id,no,name,passwd FROM userinfo where name = '张三';
           

        但如果姓名$name没有校验是否含单引号''或双引号"",那么如果传入的姓名$name是字符串" ' OR 1 = 1 OR ' ",构造成的SQL最终是这样(字符串的开始和结束位置都有单个单引号用以与原来准备包围字符串的单引号配对,避免SQL执行报错):

SELECT id,no,name,passwd FROM userinfo where name = '' OR 1 = 1 OR '';
           

        可以看出,实际上传入的姓名$name并不是一个查询条件,而是多个条件: OR 1 = 1 OR '',使userinfo表中所有记录的where条件都成立,可以查出userinfo表中的所有记录,近而达到攻击的目的,如果是update语句或delete语句后果更严重。

  • 不管是数字型注入还是字符串注入,除了构造OR条件外,还可以利用--(--后面一定要有空格)、# 等注释字符,可以使本来可以拼接到字符串后面的SQL子串失效,比如需要输入账号和密码判断用户是否登录:
SELECT id,no,name,passwd FROM userinfo where name = '$name' AND passwd = '$passwd';
           

        通过是否能查到数据判断用户是否注册,如果$name中有注释字符,构造成的SQL最终是这样:

SELECT id,no,name,passwd FROM userinfo where name = '张三' -- ' AND passwd = 'passwd$';
           

        可以看出不需要输入密码就可以伪造成已登录。

  • 不管是数字型注入还是字符串注入,还可以利用结束符:分号;,这样就可以在分号之后追加任意的SQL语句,比如DROP语句等;
SELECT id,no,name,passwd FROM userinfo where name = '张三'; DROP DATABASE mydb;''
           

四、防御措施:

        1、对输入的参数进行类型检查、长度检查和格式检查,对于数字类型的入参,要先转成数值类型,如果入参不是数字而是字母或符号,转成数字的过程中就会报错;对于字符串类型的入参,根据实际情况酌情决定是否需要检查长度是否超长,利用正则等手段检查字符串的格式是否符合要求;

        2、对于字符串类型的入参,检查其中是否包含引号(单引号'、双引号"),是否包含注释字符(-- 、#),是否包含结束字符(分号;),如果有这些字符,直接报错,或者将这些字符过滤或转译;

        3、尽量使用编程语言提供的的SQL预编译及占位符?进行SQL执行,因为在入参与占位符绑定时,会对入参进行处理(比如:如果含单引号则进行转译\',并将整个参数当成一个用单引号''包围起来的字符串等处理);

继续阅读