一、 SQL概述

   1.SQL(SQL Injection)注入是这样一种漏洞,应用程序在像后台数据传递SQL查询时,如果为***者提供了影响该查询的能力,就会引发SQL注入。

 

 二、 理解Web应用的***原理

   1.数据驱动的Web应用通常包含三层:表示层(Web浏览器或呈现引擎),逻辑层(如:C#、Java、PHP等编程语言),和存储层(Mysql、Oracle等数据库)。

     下面看一个在售零售商店的例子。可以使用下列URL查看商店中所有价格低于$100的商品:http://www.victim.com/products.php?val=100.

     下列PHP脚步说明了如何将用户输入(val)传递给动态创建的SQL语句。当请求上述URL时,将会执行下列PHP代码段:

    wKiom1mNS1yxK6gIAAEXhaW7rUQ873.png

    

   2.一种简单的应用架构

    前面讲过的数据驱动的Web应用通常包含三层:表示层、逻辑层和存储层之间的交互,我们借助如下图来描述。

      wKiom1mNThDCAHOnAAG2qu-02q4563.png

   3.现在的应用架构

    在三层的基础上添加了一层中间件(通常称为应用服务器),如下图。


wKiom1mNUKbCg7QhAAGZHqjeDuU005.png

   


 三、理解SQL注入

   1.SQL注入是一种将SQL代码插入或添加到应用(用户)的输入参数中的***,之后再将这些参数传递给后台的SQL服务器加以解析并执行。SQL注入的主要方式是直接将代码插入参数中,这些参数会被置入SQL命令中加以执行。间接的***方式是将恶意代码插入字符串中,之后再将这些字符串保存到数据库的数据表中或将其当作元数据。当将存储的字符串置入动态SQL命令中时,恶意代码就将被执行。

    示例1:为展示该过程,我们回到之前那个简单的在线零售商店的例子。下面将尝试向该查询注入我们自己的SQL命令,并将其追加在输入参数val之后。可通过向URL添加字符串'OR '1'='1 来实现:http://www.victim.com/products.php?val=100 'OR '1'='1.

    这次,PHP脚步构造并执行的SQL语句将忽略价格而返回数据库中的所有商品。在查询的OR操作数中添加的语句永远返回真,即1永远等于1。下面是注入之后构造并执行的查询语句:

    wKioL1mRQVjymSkJAAApdkz1no0945.png

    

     示例2:CMS(内容管理系统)是一种Web应用,用于为Web站点创建、编辑、管理及发布内容。可使用下面的URL访问CMS应用:http://www.victim.com/cms/login.php?username=foo&password=bar。

     下面是login.php脚步的代码:

       wKiom1mRQleQRicKAAEPCpljE-A151.png

       这段代码的问题在于应用开发人员相信执行脚步时返回的记录数始终是0或1。在下面的URL添加字符串'OR '1'='1,这次,PHP脚本构造并执行的SQL语句将返回CMSUsers表中所有用户的userid。新的URL如下所示:http://www.victim.com/cms/login.php?username=foo&password=bar 'OR '1'='1。

       下面是注入之后构造并执行的查询语句:

        wKiom1mRQ4bShMtEAAArcs0ZCVM606.png


 四、理解SQL注入的产生过程

     SQL是访问Microsoft SQL Sever、Oracle、MySql、Sybase和Informix(以及其他)数据库服务器的标准语言。如果Web应用开发人员无法确保在将从Web表单、cookie及输入参数等收到的值传递个SQL查询之前已经对其进行验证,那么通常会出现SQL注入漏洞。

     1 构造动态字符串

         构造动态字符串是一种编程技术,它允许开发人员在运行过程中动态构造SQL语句。不过,如果使用参数化查询的话,开发人员可以以更安全的方式得到相同的结果。参数化查询是指SQL语句中包含一个或多个嵌入参数的查询。可以在运行过程中将参数传递给这些查询。包含的嵌入到用户输入中的参数不会被解析成命令而执行,而且代码不存在被注入的机会,更安全。

         下列PHP代码展示了某些开发人员如何根据用户输入来动态构造SQL字符串语句。

          wKioL1mSmB3wBxU2AABZLEtC8c8823.png

          下面是使用上述代码构造的SQL语句:

            wKiom1mSmaLzOeehAAAb8PQSSos512.png

   

         1.1 转义字符处理不当

            SQL数据库将单引号字符解析成代码与数据间的分界线:单引号外面的内容均是需要运行的代码,而用单引号括起来的内容均是数据。因此,只需要简单地在URL或Web页面(或应用)的字段中输入一个单引号,就能快速识别出是否会受到SQL注入***。如下SQL语句:

             wKioL1mSnFixbFhhAACXWuvDIIY876.png


             如果将一个单引号字符作为该程序的输入,那么可能会出现下列错误。

              wKiom1mSnLOwue3NAAAkKmQyoOA171.png

               wKioL1mSnNDS0uCxAAAyOVJeuzg715.png

             SQL数据库将单引号字符看作特殊字符(字符串分隔符)。在SQL注入***中,***者使用字符“转义”开发人员的查询以便构造自己的查询并加以执行。

             单引号并不是唯一的转义字符。比如在Oracle总,空格()、双竖线(||)、逗号(,)点号(.)、(*/)以及双引号字符(")均具有特殊含义。如:

             wKioL1mSn8uTfjzJAADP1CGIFNk343.png


        1.2 类型处理不当

            看不懂,先省略。。。


        1.3 查询语句组装不当

           以下例子讲的就是使用GET请求的方式,从表中查看相关字段的值:

           wKioL1mT5D2ApQ1kAACWeBX9Py4731.png

            如果***者操作HTTP请求并使用值uses替换表名,使用user、password和Super_pri字段替换应用产生的列名,那么便可以显示系统中数据库用户的用户名和口令。下面是URL:http://www.victim.com/user_details.php?table=users&column1=user&column2=password&column3=Super_priv 如果注入成功,便会返回以下数据:

             wKioL1mT5wLQMSqiAAB7en8X49Y028.png

              


          1.4 错误处理不当

             错误处理不当会为Web站点带来很多安全方面的问题。最常见的问题是将详细的内部错误消息(如数据库转储、错误代码等)显示给用户或***者。

             下面是一个简单的使用C#语言编写的ASP.NET示例。当用户从下拉列表中选择一个用户标识符时,脚本会动态产生并执行一条SQL语句:

               wKioL1mT6aWiXAryAAFkwJMh8lg960.png


              如果***者操作HTTP并输入自己的SQL语句,会获取非常大的SQL错误信息。

              wKioL1mT6jXzEjHKAAANt14-R48007.png


              第4章将详细介绍这种技术的过程及场景。

               wKioL1mT6mHhAGQCAAB73wL6iMc564.png

           

           1.5 多个提交处理不当

              大型Web开发项目会出现这样的问题:有些开发人员会遵循建议并对输入进行验证,而其他开发人员则不以为然,因为彼此独立工作的情形不少见,很难保证每个人都遵循相同的标准。例如,当用户已到达一些列表单中的第三个表单时,他们会期望用户肯定已完成第一个和第二个表单。但实际上,借助直接的URL乱序来请求资源,能够非常容易避开预期的数据流程。示例如下:

              wKioL1mT7oDwHk1uAAEzB2rWUtU823.png

              ***者直接调用第二个表单而不使用第一个表单,或是简单地向第一个表单提交有效数据,然后操纵向第二个表单提交数据。下面第一个URL会失败,因为需要验证参数。第二个URL则会引发成功的SQL注入***:

               wKioL1mT73zwrtyBAAA7It1kBh8595.png

               

 

           2 不安全的数据库配置

              保证应用代码的安全是首要任务,但也不能忽视数据库本身的安全。数据库带有很多默认的用户预安装内容。MySQL使用“root”和“anonymous”用户账户,Oracle则在创建数据库时通常默认会创建SYS、SYSTEM等账户。这些并非全部。

              每一种类型的数据库服务器都施加了自己的访问控制模型,它们为用户账户分配多重权限来禁止、拒绝、授权、支持数据库访问和执行内置存储过程、功能或特性。第4章到第7章将详细介绍利用这些功能和特性的***。

               应用开发人员在编写程序代码时,通常使用某个内置的权限账户来连接数据库,而不是根据程序需求来创建特定的用户账户。不过***者要实现目标,还需要了解可以获取哪些附加内容、目标及其安装了哪些其他数据、存在哪些其他的表及哪些有吸引力的字段!***者在利用SQL注入漏洞时,通常会尝试访问数据库的元数据。元数据是指数据库内部的数据,比如数据库或表的名称、列的数据类型或访问权限。有时也使用数据字典或系统目录等其他项来表示这些信息。MySQL服务器(5.0及之后的版本)的元数据位于INFORMATION_SCHEMA虚拟数据库中,可通过SHOW DATABASES 和SHOW TABLES命令访问。所有MySQL用户均有权访问访问该数据库中的表,但只能查看表中那些与该用户访问权限相对应的对象的行。

               更好的解决办法是对应用的数据库访问运行一个最低权限模型,并针对程序的功能性需求适当地分离授权角色。