如何通过DBMS_SQL获取DBA权限的

作者:安华金和 思成

数据库攻击的目的最终是为要获取数据库中有价值的数据,而获取数据最有效的方法就是直接获取DBA权限。本文通过Oracle数据库中的一个经典漏洞,演示从普通用户提权到DBA权限的过程,DBSec Labs数据库安全实验室给出针对性的防护建议。

Oracle漏洞分析

CTXSYS.driload.validate_stmt是一个Oracle的经典漏洞。出现在Oracle9i中,从10g开始被修复。这个漏洞是直接注入形漏洞的代表。漏洞发生在CTXSYS创建的driload包中的存储过程validate_stmt中。首先我们通过解压的方式打开validate_stmt观察源码。

validate_stmt结构如下:

CREATE OR REPLACE PACKAGE BODY DRILOAD IS

PROCEDURE VALIDATE_STMT( SQLSTMT IN VARCHAR2 )

IS

BEGIN

SRC := DBMS_SQL.OPEN_CURSOR;

DBMS_SQL.PARSE( SRC, SQLSTMT, DBMS_SQL.NATIVE );

RET := DBMS_SQL.EXECUTE_AND_FETCH( SRC );

DBMS_SQL.CLOSE_CURSOR( SRC );

END VALIDATE_STMT;

在源码中可以直观的看到存储过程中主要使用了DBMS_SQL包中的各种存储过程和函数。这说明validate_stmt的漏洞主要是DBMS_SQL的漏洞。

既然问题出在DBMS_SQL上,那么我们就有必要对它的功能和使用场景有一个初步的了解。DBMS_SQL主要被用来解决需要动态处理数据或表结构的问题。比如对一批表里的数据进行处理,或者批量创建表,索引,触发器等等,这时就可以通过DBMS_SQL包进行操作。下图来自Oracle官方揭示了DBMS_SQL运行时的整体逻辑。

通过对DBMS_SQL包中的存储过程和函数的分析得出结论,在函数中可以被注入超长参数的只有DBMS_SQL.PARSE。

在此函数中的参数STATEMENT应该是注入的突破点,这是因为此参数中的VARCHAR2类型可以容纳较长的字符串,这使在字符串中嵌入提权命令成为可能。

漏洞验证

笔者构造提权语句如下:

SYS.DBMS_SQL.PARSE( SRC, ‘GRANT DBA TO PUBLIC‘, DBMS_SQL.NATIVE

构造出提权语句,想要通过SYS.DBMS_SQL.PARSE去执行,还需要按照DBMS_SQL处理DLL的要求构造入侵函数块,示例如下:

DECLARE

SRC NUMBER;

RET NUMBER;

BEGIN

SRC := DBMS_SQL.OPEN_CURSOR;

SYS.DBMS_SQL.PARSE( SRC, ‘GRANT DBA TO PUBLIC‘, DBMS_SQL.NATIVE );

RET := DBMS_SQL.EXECUTE_AND_FETCH( SRC );

DBMS_SQL.CLOSE_CURSOR( SRC );

END;

实际攻击效果如下:

提权语句的SQL块在低权限用户上执行,提权显示失败。究其原因,因为Oracle特别设置DBMS_SQL.PARSE为AUTHID CURRENT_USER(调用者权限)。调用者权限决定DBMS_SQL.PARSE在执行之前会判断当前执行它的用户是否具有调用他的权限(DBA权限)。

但是这里Oracle只是单纯的降低了CTXSYS的权限,并未对DBMS_SQL.PARSE做有效的防护处理。虽然DBMS_SQL.PARSE被调用者权限保护,不能被直接注入。但如果某个DBA账号建立一个定义者权限的存储过程或是函数(暂且叫这个存储过程为A)中调用了DBMS_SQL.PARSE。并且把A的执行权限赋予PUBLIC。那么低权限用户则有机会通过A去调用DBMS_SQL.PARSE。

以下测试在Oracle 11.2上进行

首先检查DBA用户数量,为最后作为对照组用

在DBA账号SYS下建立存储过程A,A中间调用了DBMS_SQL.PARSE,并把存储过程A的执行权限赋予PUBLIC。使所有用户都可以执行A。

切到低权限SCOTT上执行SYS.A并把参数改为提权语句GRANT DBA TO PUBLIC。

虽然程序报错但其实已经执行了提权命令。切回SYS用户再次查询DBA用户,发现多了一个DBA用户PUBLIC。PUBLIC正式通过GRANT DBA TO PUBLIC这个命令获得提权的。

至此提权到DBA成功。

漏洞成因

以上Oracle调用者权限利用DBMS_SQL漏洞进行DBA提权的过程中存在四个关键点:

1. DBA用户创建定义者权限的函数或存储过程。(定义者权限可使任意用户可以在调用函数或存储过程的运行时中获得DBA权限。)例子中的存储过程A就是定义者权限。低权限用户SCOTT在调用A的运行时中具备了A的创建者SYS具有的DBA权限。致使DBMS_SQL的调用者权限保护机制失效。

2. DBA账号创建的函数或存储过程把执行权限赋予PUBLIC。如果A的执行权限不是PUBLIC,scott根本无法调用A,也不会出现后面的利用方式。

3. 对输入参数的限制和防守没有加强,使得某些非预计参数的执行。

4. 未对用户身份进行判断。加强对用户身份的识别可以在一定程度防止低权限用户进行非法提权操作。

漏洞防护建议

针对数据库漏洞的防护要做到以下几点:

1.自己不制造漏洞,使用安全性更高的函数或存储过程。可以使用DBMS_SYS_SQL代替DBMS_SQL。

笔者在实践中发现DBMS_SYS_SQL.PARSE_AS_USER这个存储过程可以代替DBMS_SQL.PARSE这个危险的存储过程。分析调用关系不难发现DBMS_SQL.PARSE和DBMS_SYS_SQL.PARSE_AS_USER其实调用的都是DBMS_SYS_SQL中的ICD_PARSE。但不同的是调用的ICD_PARSE有一位参数不同。
DBMS_SQL.PARSE调用的是:

ICD_PARSE( C, STATEMENT, LANGUAGE_FLAG MOD PARSE_AS_USER_FLAG, NULL );
而DBMS_SYS_SQL.PARSE_AS_USER调用的是:

ICD_PARSE( C, STATEMENT, LANGUAGE_FLAG MOD PARSE_AS_USER_FLAG + PARSE_AS_USER_FLAG, USERID );

仔细比较两者不难发现最后一位参数USERID不同。DBMS_SQL.PARSE对应的取的是null,而DBMS_SYS_SQL.PARSE_AS_USER对应的取的是当前用户的USERID。通过USERID来判断当前用户的权限是否能解析语句,而并非是运行时权限来判断是否能解析语句。

对比说明,存储过程Q采用DBMS_SYS_SQL.PARSE_AS_USER,存储过程P则采用DBMS_SQL.PARSE。存储过程P和Q唯一的区别就是分别采用DBMS_SYS_SQL.PARSE_AS_USER和DBMS_SQL.PARSE来解析SQL语句。

存储过程P成功实现了DBA提前操作。存储过程Q采用了DBMS_SYS_SQL.PARSE_AS_USER,成功阻止了低权限用户的提权操作。

2、使用第三方的数据库安全加固产品及解决方案

应对已知数据库安全问题最佳方案是升级数据库,但升级数据库存在很多风险和复杂的准备工作。即便做了升级测试、最小化测试、功能测试、集成测试、性能测试、容量与负载压力测试等一系列复杂的测试依旧可能导致某些应用或组件出现各种难以预计的问题。

在不对数据库本身进行升级操作的情况下,可以通过虚拟补丁(Vpatch)技术来完成对数据库系统漏洞的防护。数据库虚拟补丁技术一般是集成在数据库防火墙产品中,能够有效防止通过数据库本身漏洞对数据库的攻击行为。有效的解决了生产场景下数据库升级不及时可能给用户的数据库带来的潜在威胁。并在无需对数据库做深度操作的前提下,进行漏洞的修补与防护,以期达到数据库的安全标准要求。

时间: 2024-10-13 14:40:52

如何通过DBMS_SQL获取DBA权限的的相关文章

MSSQL DBA权限获取WEBSHELL的过程

前言 本文主要通过一个案例来演示一下当MSSQL是DBA权限,且不知道路径的时候如何去获取WEBSHELL.当然这种方式对站库分离的无效.我测试的环境是在Win7 64位下,数据库是SQLServer 2000,IIS版本是7.5,程序是采用风讯的CMS.后台登录后有多处注入,因为这里是演示用注入获取WEBSHELL,因此就不考虑后台上传的情况了,只是用注入来实现. 过程 首先找到一个如下的注入点: http://192.168.232.138:81/manage/news/Newslist.a

Android6.0使用BaiDu地图SDK动态获取定位权限

1.报错原因: 在集成百度地图SDK的时候在手机上无法定位,检查没有任何错误,最后通过搜索才知道是Android版本为6.0的问题,这是因为在Android6.0采用了运行时权限(RuntimePermissions),Android6.0的权限一般分为两种,一种时普通权限,可以直接获取,其它的运行时权限,需要提示用户手动同意之后,才能获取. 失败的原因就是,小米手机MIUI是Android6.0.1,如果不加动态获取权限的代码,是不会提示的,没有得到权限,当然无法定位. 2.解决代码: pri

三星Galaxy s4(i9505)完美获取root权限教程

三星Galaxy s4(i9505)完美获取root权限教程 论坛上贴吧上关于三星s4 i9505 root的介绍有很多,方法多种多样,今天小编来介绍一种使用root软件来实现三星i9505一键root的方法.这篇三星Galaxy s4(i9505)获取root教程仅仅三个步骤,借助完美ROOT工具来完成全部操作,方便快捷,废话不多说,请看i9505 root教程内容! 三星s4 i9505 root操作从准备工作开始,首先点击下载完美ROOT安装软件,其次检查手机保持开机,电量充足在50%以上

Genymotion刷入谷歌应用市场以及获取root权限

Genymotion刷入谷歌应用市场以及获取root权限 - 推酷http://www.tuicool.com/articles/rEV3aa6 刷入gapp, arm框架,supersu的包要注意,这些包所在的路径不能含有中文!!! 另外必须刷对的包 教程(包括我之前翻译的一篇 Genymotion简单教程及问题解决 ),但是大多数都已经没法用了.根据那些教程安装上的google play store,经常会弹出“已停止服务”的窗口. 其实最关键的点是,要刷对google apps packa

Android如何通过shareduserid获取系统权限

转载:http://my.oschina.net/zhoulc/blog/119282 android会为每个apk进程分配一个单独的空间(比如只能访问/data/data/自己包名下面的文件),一般情况下apk之间是禁止相互访问数据的.通 过Shared User id,拥有同一个User id的多个APK可以配置成运行在同一个进程中.所以默认就是可以互相访问任意数据. 也可以配置成运行成不同的进程, 同时可以访问其他APK的数据目录下的数据库和文件.就像访问本程序的数据一样(使用IPC机制,

获取管理员权限

获取管理员权限: void GainAdminPrivileges(UINT idd, BOOL bWait){ CString strCmd; CString strApp; strCmd.Format (_T("/adminoption %d"), idd); CSVPToolBox svpTool; strApp = svpTool.GetPlayerPath(); SHELLEXECUTEINFO execinfo; memset(&execinfo, 0, sizeo

【转】vc++MCF/C++/C中怎样让应用程序获得或以管理员权限运行 ,ShellExecuteEX编程 --- 获取管理员权限

ShellExecuteEX编程 --- 获取管理员权限:http://blog.csdn.net/jhui163/article/details/5873027 怎样让你的应用程序获得管理员权限:就是在运行开发工具如vc6.0 或vs2010时,要以管理员身份运行,这样你的应用程序才可以继承 http://bbs.csdn.NET/topics/390262991 解决:在vs2010等开发工具中虽然以管理员身份编译运行了程序,可以获得管理员权限,但是当单独点击Debug或release版时,

应用获取root权限分析及总结

ROM授权root权限,主要技术点在哪里?如何实现?带着这些问题,边实验边分析,并将过程和犯的错误记录如下. 1.rom支持root授权,需要包含su 简单点说,就是rom中支持su指令:必须包含su可执行程序,对应的代码/system/su目录下代码: 编译生成su程序后,再将其push到/system/xbin目录下:注意:此时需要修改该文件的执行权限, chmod 755 su 2.应用程序如何获取root权限? 关键点在于下面这句,通过执行su产生一个具有root权限的进程:Proces

[转载]如何使Android应用程序获取系统权限来修改系统时间

在 android 的API中有提供 SystemClock.setCurrentTimeMillis()函数来修改系统时间,可惜无论你怎么调用这个函数都是没用的,无论模拟器还是真机,在logcat中总会得到"Unable to open alarm driver: Permission denied ".这个函数需要root权限或者运行与系统进程中才可以用. 本来以为就没有办法在应用程序这一层改系统时间了,后来在网上搜了好久,知道这个目的还是可以达到的. 第一个方法简单点,不过需要在