大话数据库SQL注入的N种姿势

作者:安华金和 思成

一. 背景

数据库凭借其强大的数据存储能力和卓越的数据处理性能,在各行各业的信息化建设中发挥着关键的作用。随着数据库在各行业的大规模应用,数据泄露事件也频繁发生,这就使数据库安全问题也日益凸显,逐渐变成用户越来越担心的问题。虽然数据库厂商已经做了许多有效的措施来尽量解决数据库存在的安全问题,但至今为止数据库的安全漏洞仍然不断增加。下图为近5年数据库漏洞数量图。

大话数据库SQL注入的N种姿势_第1张图片

在数据库漏洞中最为常见的漏洞类型是SQL注入漏洞。安华金和数据库攻防实验室结合多年的实践结果总结出了数据库注入的分类分享给大家,以便大家对SQL注入型漏洞有一个更加全面的了解。

SQL注入漏洞不仅出现在WEB端,也出现在数据库的自定义或标准库的存储过程、函数、触发器中。数据库自身的SQL注入漏洞比WEB端的注入漏洞对数据库的威胁性更大。本文对SQL注入的分类是从数据库的角度来划分,不考虑WEB端的角度,这两者在分类上有着不同的角度。

首先在解释不同的数据库SQL注入漏洞之前先简要说明一下数据库攻击者能够进行SQL注入的主要原理:SQL注入漏洞是用户在输入中混入了程序命令。最直接的例子就是攻击者在正常的 Web 页面中把自己的 SQL 代码通过用户输入传输到相应的应用程序中,从而执行一些非授权的 SQL 代码,以达到修改、窃取或者破坏数据库信息的目的。SQL 注入攻击甚至可以帮组攻击者绕过用户认证机制,使其可以完全的操控远程服务器上的数据库。如果应用程序使用一些用户输入的数据来构造动态的SQL语句去访问数据库,将可能遭受到 SQL 注入攻击。同样的如果在代码中使用了存储过程,并且这些存储过程缺乏对用户输入的合理限制也很容易发生 SQL 注入。

二. SQL注入分类

1) 注入途径分类

SQL注入漏洞按照注入的物理途径可以分成两大类:通过WEB端对数据库进行注入攻击和直接访问数据库进行注入攻击。

直接访问数据库进行注入攻击是以数据库用户的身份直接连接数据库进行SQL注入攻击。在这种攻击方式中,攻击者可以通过SQL注入来执行SQL语句从而提高用户权限或者越权执行。而那些在PL/SQL程序中在给用户授权的时候没有使用authid current_user进行定义的存储过程、函数、触发器、程序块将更容易受到SQL注入攻击。

通过WEB应用程序的用户对数据库进行连接并进行SQL注入攻击。在这种类型的SQL注入攻击中,攻击者多采用拼接语句的方法来改变查询的内容。获取该账号权限下的全部信息。

一些高级的攻击手段往往结合这两种方式,先利用WEB应用程序上的SQL注入漏洞获取数据库和数据库所在服务器的基本信息。再利用数据库自身SQL注入漏洞对获取的数据库账号进行提权、越权等操作已达到对数据库进行破坏或者获取敏感信息的目的。

2) 注入方式分类

根据入侵方式,针对数据库的SQL注入攻击可以分为四种类型,分别是SQL Manipulation、Code Injection 、Function Call Injection以及Buffer Overflows 。前两种SQL注入攻击较为常见,多出现在WEB端的SQL注入上,而后两种攻击类型是直接针对数据库自身的攻击方式,所以对数据库的安全威胁更加致命。

1.针对 SQL 操作的注入攻击(SQL manipulation)是在所有的 SQL 注入攻击类型中最常见的一种类型。这种攻击的原理在于攻击者会试图在已经存在的SQL 语句中通过集合运算符(SET Operator)比如 UNION、INTERSECT 或者MINUS 来添加一些内容在 WHERE 子句中使其功能产生变化。当然还有可能会有其他的很多变化存在。最经典的 SQL manipulation 攻击就存在于登录验证过程中。一个简单的 Web 应用程序就可以通过执行以下的 SQL 语句来检查用户认证是否有返回值:

SELECT * FROM users WHERE username = 'admin' and PASSWORD = 'guess'而攻击者就可以尝试修改 SQL 语句使其变为:

SELECT * FROM users WHERE username = 'admin' and PASSWORD = 'xxxx'or 'a' = 'a'

通过以上对于 WHERE 子句的修改操作可以使用户登录的判定恒为真,这样攻击者便绕过了用户验证获得了进入后台的权利。集合运算符 UNION 也常常被用在 SQL 注入攻击中,其最主要的目的就是通过操作 SQL 语句来从另外一个表中返回某些行。一个WEB 窗体可以执行以下SQL 语句从一个存在的 product 表中返回一个需要的表单:

SELECT product_name FROM all_products WHERE product_name like '%ddd%'

而攻击者可以修改 SQL 语句使其变为:

SELECT product_name FROM all_products WHERE product_name like '%ddd%' UNION SELECT username,password FROM dba_users WHERE username like ‘%’

这种情况下在执行完这个SQL语句以后所返回的web表单中的结果就会包括

所有的产品名以及所有的数据库用户名和密码(当然需要链接账号具备查询表dba_users权限)。

2.代码注入攻击(CODE INJECTION)就是尝试在已经存在的 SQL 语句中添加额外的SQL语句或者命令。这种类型的攻击会经常的被应用在微软的SQLServer 应用程序里。在 SQL Server 中EXECUTE 语句经常会成为 这种SQL 注入攻击的目标。虽然Oracle 这类数据库中没有相应的语句,在 PL/SQL 和 Java中,也不支持单个数据库的多条SQL 语句的请求,但一些程序语言或者 API 可能允许多个 SQL 语句同时执行。PL/SQL 和Java 应用程序可以动态的执行那些容易受到代码注入攻击的匿名 PL/SQL 块。所以在特定情况下代码注入攻击对即便不支持多SQL请求的数据库依旧有效。

3.函数调用注入(FUNCTION CALL INJECTION)是因为在数据库函数或者自定义函数中存在某些漏洞,攻击者对问题函数进行 SQL 语句注入从而使此函数可以执行非预期功能而达到攻击者的目的。严格讲不光数据库中的函数可能存在这些漏洞存储过程、触发器等也存在类似漏洞。这些函数调用可以被用来在数据库中生成数据或者系统调用。

以Oracle为例,Oracle 数据库允许自定义函数或者包中的函数作为 SQL 语句的一部分来执行。同时 Oracle 数据库在 175 个标准数据库包中提供了 1000 多个函数,其中有一小部分有可能遭到 SQL 注入攻击,而那些用作网络通信的函数同样可以被攻击者利用。任何的自定义函数或者那些存在于自定义包中的函数都可以在 SQL语句中执行。当函数作为 SQL SELECT 语句中的一部分来执行的时候对于数据库 来 说 不 会 造 成 任 何 变 化 除 非 这 个 函 数 被 标 记 成 了 “PRAGMATRANSACTION”。只有极少数的标准数据库函数会被自动执行,而那些在插入、更新、删除语句中执行的函数会对数据库中的数据进行修改。当攻击者使用那些有漏洞的标准

Oracle 函数的时候就可以将数据库中的信息发送到远程计算机或者在其他的数据库服务器执行攻击。许多基于 Oracle 的应用程序都可能会使用那些有漏洞的数据库软件包,而这些自定义的软件包里就有可能会包括那些可以修改密码或执行那些敏感的应用程序的函数。

对于函数调用注入攻击来说,任何动态生成的 SQL 语句都是脆弱的,即使是最简单的 SQL 语句都可以被攻击者利用。
例如创建存储过程test说明

用DBA权限建立自定义存储过程

create or replace procedure test (putin varchar2) as

type c_type is ref cursor;

cv c_type;

buffer varchar2(200);

begin

dbms_output.enable(1000000);

open cv for ‘select object_name from all_objects where owner =’’’||putin||’’’and object_type=’’library’’’’;

close cv;

End;

/

这个 SQL 语句不容易遭到其它类型的注入攻击,但是却很容易遭受到函数注入攻击。这是因为在这个函数中缺乏对输入变量的约束。攻击者可能会输入的是一个想要执行的命令。例如 grant dba to public;

低权限用户构造一个含有想要执行的命令的函数

Create or replace function get_dba return varchar authid current_user is

Pragma autonomous_transaction;

Begin

Execute immediate ‘grant dba to scott’;

End;

/

在这个例子中本来存储过程test是用来查询用户所拥有的库的,但是为了方便其他用户使用test的执行,这一权限被赋予了所有用户,导致任何用户都可以执行test存储过程。但是函数中由于采用了定义者权限定义test,所以造成所有用户在执行test的时候都获得了DBA权限。

这一过程是低权限用户创建注入函数get_dba。通过test把任意低权限账号提权到DBA权限。

Exec sys.test(‘AAAA’||username.get_dba()―‘);

至此低权限用户通过漏洞把自身提权到DBA权限可以对整个数据库进行非法控制。数据库厂商的解决方案一般是通过删除存在漏洞函数的public执行权限来解决

4.许多的标准数据库函数都很容易受到缓冲区溢出(BUFFER OVER FLOWS)攻击,这是因为只需要对那些没有及时打补丁的数据库做 SQL 注入攻击就可以很容易利用到缓冲区溢出漏洞。缓冲区溢出漏洞危害很大,往往最终会造成攻击者直接控制数据库或数据库所在操作系统。

以Oracle为例,在某些版本的标准数据库软件包和标准数据库函数中

TZ_OFFSET,TO_TIMESTAMP_TZ, BFILENAME, FROM_TZ, NUMTOYMINTERVAL, andNUMTODSINTERVAL 等函数存在缓冲区溢出漏洞。而要使用这些存在缓冲区溢出漏洞的标准数据库包和函数来做缓冲区溢出漏洞攻击就需要利用到之前所介绍的函数注入的方法;当攻击者通过 SQL 注入攻击来利用缓冲区溢出漏洞的时候,就可以实现远程连接操作系统。此外,一些应用程序和 WEB 服务器都不能够正常处理由于缓冲区溢出所造成的数据库连接中断;通常,Web 进程将会被挂起,甚至导致发生拒绝服务攻击。

三. 防护SQL注入

数据库厂商针对SQL注入进行了大量的工作,其中以oracle为例在Oracle推出10G r2的时候开发了一个dbms_assert补丁包。这个补丁包主要被用来修复sql注入漏洞,加强对用户输入的信息的防守。修复了大量存在的数据库漏洞。但并不能呢彻底解决数据库自身的所有SQL注入漏洞。根据测试DBMS_ASSERT对二阶SQL注入和跨语言传参缺乏有效防守。

数据库厂商虽然一直在努力,但受限于数据库应用环境和场景。很多时候数据库不能及时进行补丁升级,所以很多时候数据库威胁依然存在。安华金和攻防实验室建议广大数据库用户,除了及时更新数据库补丁的同时,必要的时候采用第三方产品来加固数据库的安全。

这里安华金和攻防实验室给出两种数据库加固思路:

1.从信息的源头着手,对敏感信息进行加密。即便被攻击者获取到敏感信息,也保障信息是全密文,攻击者无法获得有价值的信息。

2.从数据库安全加固的角度。数据库防火墙可以有效防护来自外部的攻击行为。专业的数据库防火墙应该是基于数据库协议精确解析,通过对SQL语法/词法中存在的风险进行精确识别,拥有数据库虚拟补丁技术,能够进行细粒度权限管控,行为审计、监测分析等核心功能,以防止攻击者对数据库进行入侵。发挥保护数据库安全的作用。

相信以上无论哪种方式都会使用户数据库中的数据更加安全。


你可能感兴趣的:(数据库,信息安全,安华金和)