一、SQL注入原理

  SQL注入出现的原因是开发人员过于信任从前端输入的数据,没有经过校验就直接插入到SQL语句中执行,导致执行了开发人员预料之外的SQL语句,从而对Web应用乃至整个服务器造成危害。

  在开发的登录验证模块中,如果开发人员写出了这样的代码:

 1 <?php
 2 $username = $_GET['username'];
 3 $password = $_GET['password'];
 4 
 5 $sql = "select * from User where username = '" . $username . "' and password = '" . $password . "'";
 6 
 7 /**
 8 ……连接数据库并执行SQL语句……
 9 */
10 ?>

   直接将从前端获取的数据拼接到SQL语句中查询,则会造成SQL注入漏洞。攻击者可以构造以下恶意输入:

    username = ' or 1=1 -- 

  这样的恶意输入拼接到SQL语句中,就会形成这样的语句:

1 select * from User where username = '' or 1=1 -- ' and password = '';

  恶意输入的第一个单引号闭合了前面的单引号,后面的“or 1=1”构成了永真的判断条件,“-- ”注释掉了后半部分的SQL语句,导致这个SQL语句的实际效果等于:

1 select * from User;

  数据库会返回User表中的所有数据,虽然能否全部在前端显示出来还得看后端代码对数据是怎么处理的,但这已经使得数据库执行了开发人员意料之外的语句,具有巨大的危害。

  以上虽然展示的是对select语句的注入,实际上,不管是什么SQL语句,不管是在SQL语句的哪个部分进行拼接,只要没有做好防护,就会产生SQL注入漏洞。

二、SQL注入分类

  针对SQL注入漏洞的利用方式,其大致可以分为以下几类:

1、一般注入

  这一类的注入,即类似于上面所举的例子,是一类最简单最普通的因为SQL语句的直接拼接而导致的漏洞。后端并没有做任何验证,且任何回显都会被展示在前端页面上。攻击者只需稍加思考,猜测出后端SQL语句并构造恶意输入即可完成一次SQL注入攻击。

2、报错注入

  有时,有些注入漏洞所在的页面并不会显示从数据库中查询到的数据,这和后端代码的逻辑有关。但我们又希望获得数据库中的数据,这可怎么办呢?如果开发人员没有将数据库的报错回显关闭的话,这又会给攻击者提供一种攻击的方式,即报错注入。

  在各个厂商提供的数据库产品中,存在着厂商提供的各种各样的函数。有的函数可以被攻击者利用,在里面注入查询语句并使这个函数报错,使得查询到的数据夹杂在报错信息中返回,导致攻击者获得数据库中的数据。比如MySQL中的extractvalue()函数就可以被攻击者进行如下构造:

1 select 1 and (extractvalue(1,concat(0x7e,(select user()),0x7e)));

   该SQL语句被MySQL数据库执行之后会产生如下效果:

  函数中的SQL语句被成功执行并返回。报错注入有时还可以被用来绕过某些安全过滤。

3、延时注入

  当注入漏洞所在的页面不产生任何回显时,攻击者也有办法获得其中的数据。

  在各个厂商的数据库产品中,都存在类似于sleep(time)这样的函数,它的作用是使SQL语句的执行暂停参数“time”所表示的时间。攻击者可以利用此函数,根据数据库的响应时间的变化来逐字猜解数据库中的数据,即延时注入。

  在MySQL中,如果攻击者构造出了如下语句:

1 select 1 and sleep(5*(select ascii(substr(user(),1,1)) = 114));

   这个语句我们从里向外理解,首先user()查询登录MySQL的用户,这里得到的是“root@localhost”。接着用substr()函数对获得的用户名进行截取得到第一个字符“r”,再通过ascii()函数将其转化成ASCII码114,接着与最后的数字相比较,如果相等,则会返回数字“1”;如果不等,则会返回“0”。这里“114”与“114”相等,因此会返回“1”,“1”与“5”相乘得到“5”,所以最后该语句等价于:

1 select 1 and sleep(5);

  执行效果如下:

  数据库将会延时5秒才会返回结果。根据这样的信息,攻击者得知MySQL用户名的第一个字符的ASCII码为114,即字符“r”,接着攻击者可以继续构造下一条语句:

1 select 1 and sleep(5*(select ascii(substr(user(),2,1)) = 114));

  该语句会将MySQL用户名的第二个字符转化成ASCII码与“114”进行比较,这里不相等,因此该语句等价于:

1 select 1 and sleep(0);

  执行效果如下:

  数据库不会延时,因此攻击者可以知道MySQL用户名的第二个字符的ASCII码不是“114”。

  依此类推,攻击者只需修改substr()函数的第二个参数和最后的数字,根据页面的响应时间,就可以达到对数据进行逐个字符猜解的目的。

  由于延时注入是逐字符猜解,因此需要编写脚本来自动化执行,且猜解所有数据需要的时间比较长。

  这里不直接用字符进行比较,而转换成ASCII码进行比较,是为了便于使用二分法来加快猜解速度。

4、布尔注入

  这一类的注入指的是注入漏洞所在的页面只有两种状态,比如登录成功或失败,有响应或无响应、修改成功或失败等等。这两种状态根据你输入的SQL语句的变化而相互交替出现,分别对应SQL语句执行成功或失败,即true或false,因此被称为布尔注入。简单的布尔注入SQL语句如下:

1 select 1 and (select ascii(substr(user(),1,1)) = 114);

  该语句利用了逻辑符“and”,“and”之后的语句如果正确,则查询得到“1”,否则因条件不成立而查不到数据。

  乍一看,跟延时注入的语句很像是不是?其实布尔注入的思想和延时注入是一样的,都是对数据进行逐字符的猜解,通过响应的不同来判断猜解的内容是正确的还是错误的。只是延时注入利用的是响应时间的不同,而布尔注入利用的是响应页面的不同。

5、二次注入

  有时,应用程序对从外界输入的数据做了严密的防护,但却疏于对内部比如数据库查询出来的数据进行防护,从而造成二次注入漏洞。

  比如,在一个网站的注册页面,攻击者注册了一个用户名为“' union select user() -- ”的用户。假设网站对外部输入的数据做好了防护,那么该用户名会被当成一整个字符串被插入到数据库中而不会造成危害,数据库将会存在以下数据:

  接下来,在网站的某个页面比如个人信息页面上,如果网站进行了如下操作:

    1、从数据库中查询用户名

    2、将查询到的用户名直接拼接到SQL语句中进行其他信息的查询

  就会形成如下拼接后的SQL语句:

1 select * from test where username = '' union select user() -- ';

  前面的单引号闭合了后台SQL语句中前面的单引号,后面的“-- ”注释掉了后面的单引号,在数据库中的执行效果如下:

  可见,数据库执行了攻击者的SQL语句,产生了注入。因此,不管是从哪里来的数据,只要跟数据库发生交互,都应该做好防护。

6、false注入

  在MySQL中,如果输入下面的查询语句:

1 select * from user where username = 0;
1 select * from user where username = false;

  会产生如下效果:

  为什么会返回所有的数据?这跟MySQL的隐式类型转换有关。在MySQL中,当字符串和数字比较时,会把字符串转为浮点数,而字符串转换时会产生一个warning,转换的结果为0。但如果字符串开头是数字话,则会从数字部分截断,转换为数字。false原理也是类似。

  除了上面举例的这两个,MySQL还有很多因为隐式类型转换而产生的神奇的情况,这里就不再一一举例。利用这一点,可以绕过一些过滤,或产生一些意想不到的结果。

三、SQL注入的危害

  1、获取、篡改数据。虽然上面举例时用的是查询语句,但SQL注入可以发生在任何语句比如update、delete、insert中,只要拼接到SQL语句中的参数可控,就有可能发生SQL注入。

  2、绕过验证。通过构造永真条件,可以绕过登录等身份验证,造成越权访问。

  3、读取、修改、写入文件。数据库包含了一些操作文件的函数,通过注入漏洞调用函数,可以实现文件的读写修改。

  4、提权。如果应用后台使用的是高权限用户连接数据库的话,比如MySQL的root用户、MsSQL的sa用户,则可以通过提权来获取整个服务器的访问权限。

  5、命令执行。数据库中还包含了一些可以执行系统命令的函数,只要有足够的权限,就可以执行系统命令。

四、SQL注入的终极解决方案——使用预编译语句

  从本质上讲,SQL注入是攻击者通过对SQL语句的准备过程进行干扰破坏,从而使数据库执行受到污染的SQL语句。而预编译语句是已经准备好了SQL语句,在执行阶段只是把输入的数据作为字符串处理,而不再对SQL语句进行解析,因此避免了SQL注入问题。

内容来源于网络如有侵权请私信删除
你还没有登录,请先登录注册
  • 还没有人评论,欢迎说说您的想法!