邪恶八进制信息安全团队技术讨论组's Archiver

sunwear 2006-1-4 09:14

[转载]Solaris Xsun heap溢出漏洞分析

信息来源:邪恶八进制信息安全团队([url]www.eviloctal.com[/url])
作者:warning3 <mailto:warning3@nsfocus.com>
整理:NSFocus Security Team
主页:[url]http://www.nsfocus.com[/url]
日期:2002-04-12

Xsun是Solaris 系统下的X11 Windows系统的服务器软件。在SPARC平台下,它缺省被
设置了setgid root属性。在x86平台下,它缺省被设置了setuid root权限。

既然Xsun设置了setuid/setgid属性,就有必要研究一下它的安全性。在着手测试之前,当然需要先看看它 以前有没有安全问题的历史。就像审查犯罪嫌疑人(现在都时兴这种称呼)之前先要看看有没有前科一 样,有案底在身的人肯定再次作案嫌疑要大一些。
:-) 其实应用程序的安全也是这样,往往有过一次安全漏洞的程序还会接二连三的出
现同样的问题。不看不知道,原来Xsun还真有过两次“前科”,而且都是缓冲区溢出
漏洞:

1. Solaris Xsun 本地缓冲区溢出漏洞
  [url]http://security.nsfocus.com/showQuery.asp?bugID=1362[/url]
2. Solaris Xsun 缓冲区溢出漏洞
  [url]http://security.nsfocus.com/showQuery.asp?bugID=474[/url]

第一个漏洞是eEye发现的,如果将HOME变量设置成一个超长的字符串,就会触发一个
基于堆栈的缓冲区溢出。第二个漏洞是DiGiT([email]teddi@linux.is[/email])发现的,这回溢出的部分又改在了对命令行 参数"-dev"的处理上。

第一个漏洞是一个堆栈缓冲区溢出,测试了一下,没什么特别。第二个漏洞据说也是
一个堆栈缓冲区溢出漏洞。但是我觉得有些奇怪的是,为什么DiGiT没有提供针对SPARC
平台的测试代码,按说应该并不难写。于是在Solaris 8(SPARC)下测试了一下,结果
出乎我的预料,在SPARC下竟然是一个heap溢出!怪不得DiGiT当时没有马上提供SPARC
下的测试代码。

下面是我测试的结果:
[w3@ /export/home/w3]> cp /usr/openwin/bin/Xsun .
[w3@ /export/home/w3]> gdb ./Xsun -q
(no debugging symbols found)...(gdb) r -dev `perl -e &#39;print "A"x5000&#39;`
Starting program: /export/home/w3/./Xsun -dev `perl -e &#39;print "A"x5000&#39;`
(no debugging symbols found)...(no debugging symbols found)...
(no debugging symbols found)...(no debugging symbols found)...
(no debugging symbols found)...(no debugging symbols found)...
(no debugging symbols found)...(no debugging symbols found)...
(no debugging symbols found)...(no debugging symbols found)...
(no debugging symbols found)...(no debugging symbols found)...
(no debugging symbols found)...(no debugging symbols found)...
(no debugging symbols found)...(no debugging symbols found)...
(no debugging symbols found)...(no debugging symbols found)...
(no debugging symbols found)...(no debugging symbols found)...
(no debugging symbols found)...(no debugging symbols found)...
Program received signal SIGSEGV, Segmentation fault.
[呵呵,SIGSEGV出现在_malloc_unlocked()中,看起来应该是我们熟悉的路数了。]
0xfecc0f4c in _malloc_unlocked () from /usr/lib/libc.so.1
(gdb) bt
#0  0xfecc0f4c in _malloc_unlocked () from /usr/lib/libc.so.1
#1  0xfecc0d44 in malloc () from /usr/lib/libc.so.1
#2  0x2f630 in Xalloc ()
#3  0xff2b105c in dupString () from /usr/openwin/lib/libowconfig.so.0
#4  0xff2b2ffc in OWconfigInit () from /usr/openwin/lib/libowconfig.so.0
#5  0xb4638 in ow_config_init ()
#6  0xb4664 in fa_config_read_local ()
#7  0xb4740 in fa_ow_config_file_font_path_set ()
#8  0x4e2b4 in ProcessCommandLine ()
#9  0x4ce98 in main ()
(gdb) x/i $pc
0xfffffffffecc0f4c:    ld  [ %o0 + 8 ], %o1
(gdb) i r $o0
o0         0x41599580     1096390016
(gdb) i r $o1
o1         0x185440 1594432
[看起来是一个典型的heap区溢出]
(gdb) x/20x $o1
0x185440:     0x41414140    0x41414141    0x41414141    0x41414141
0x185450:     0x41414141    0x41414141    0x41414141    0x41414141
0x185460:     0x41414141    0x41414141    0x41414141    0x41414141
0x185470:     0x41414141    0x41414141    0x41414141    0x41414141
0x185480:     0x41414141    0x41414141    0x41414141    0x41414141
(gdb)

写这个测试程序并不难,这里就不再赘述了。有兴趣的朋友可以自己验证一下。没想
到无意中发现了这么一个小秘密,也算是小有收获。看来Solaris中不是缺少heap溢出,而是缺少发现 heap溢出的眼睛。:-)

既然Xsun在处理环境变量和命令行参数时都曾经有过案底,那么是不是还有没有类似
的“案子”未曾被发现过呢?

OK,首先让我们来查一查命令行参数。

[w3@ /export/home/w3]> /usr/openwin/bin/Xsun -h
use: X [:<display>] [option]
-a #             mouse acceleration (pixels)
-ac              disable access control restrictions
-audit int         set audit trail level
-auth string        select authorization file
bc              enable bug compatibility
-bs              disable any backing store support
-c              turns off key-click
c #              key-click volume (0-100)
-cc int           default color visual class
-co string         color database file
-config string      read options from file
-core            generate core dump on fatal error
-dpi int          screen resolution in dots per inch
dpms             enables VESA DPMS monitor control
-dpms            disables VESA DPMS monitor control
-deferglyphs [none|all|16] defer loading of [no|all|16-bit] glyphs
-ep string         default encodings path
-f #             bell base (0-100)
-fc string         cursor font
-fn string         default font name
-fp string         default font path
-help            prints message with these options
-I              ignore all remaining arguments
The X Keyboard Extension adds the following arguments:
-kb              disable the X Keyboard Extension
+kb              enable the X Keyboard Extension
[+-]accessx [ timeout [ timeout_mask [ feedback [ options_mask] ] ] ]
                enable/disable accessx key sequences
-ar1             set XKB autorepeat delay
-ar2             set XKB autorepeat interval
-noloadxkb         don&#39;t load XKB keymap description
-xkbcomp          default keymap compiler
-xkbdb            file that contains default XKB keymaps
-xkbmap           XKB keyboard description to load on startup
-ld int           limit data space to N Kb
-lf int           limit number of open files to N
-ls int           limit stack space to N Kb
-logo            enable logo in screen saver
nologo            disable logo in screen saver
-p #             screen-saver pattern duration (minutes)
-pn              accept failure to listen on all ports
-r              turns off auto-repeat
r               turns on auto-repeat
-s #             screen-saver timeout (minutes)
-sp file          security policy file
-su              disable any save under support
-t #             mouse threshold (pixels)
-terminate         terminate at server reset
-to #            connection time out
-tst             disable testing extensions
ttyxx            server started from init on /dev/ttyxx
v               video blanking for screen-saver
-v              screen-saver without video blanking
-wm              WhenMapped default backing-store
+xinerama          Enable XINERAMA extension
-xinerama          Disable XINERAMA extension
-x string          loads named extension at init time
-query host-name     contact named host for XDMCP
-broadcast         broadcast for XDMCP
-indirect host-name   contact named host for indirect XDMCP
-port port-num      UDP port number to send messages to
-once            Terminate server after one session
-class display-class  specify display class to send in manage
-displayID display-id  manufacturer display ID for request
-XpFile           specifies an alternate `Xprinters&#39; file(Xprt only)
-accessX          enable accessx feature using shift key
-banner           enable Solaris banner
-dev framebuffer     name of device to open
  deviceoptions:
   [left | right |   orientation relative to previous screen
    top | bottom]
   dpix #         dpi in the x direction
   dpiy #         dpi in the y direction
   defclass [GrayScale |  visual to report as default
      StaticGray |
      PseudoColor |
      StaticColor |
      DirectColor |
      TrueColor]
   defdepth #      report visual of given depth as default
   grayvis        report only GrayScale and/or StaticGray visuals
-dpsfileops        enable DPS file operators
-dur             set bell duration
-flipPixels        reverse black and white pixel values
-mden            set pointer acceleration denominator
-nobanner          disable Solaris banner
-nominexp          disable minimized exposure
-pit             set bell pitch
-sharedretainedpath path  defines a file system path

呵呵,它支持的命令行参数还真是不少,究竟哪一个可能是有问题的呢?我们先排除
那些不允许带参数的命令行开关,这就剩下下面这些了:

-audit int         set audit trail level
-auth string        select authorization file
-cc int           default color visual class
-co string         color database file
-config string      read options from file
-dpi int          screen resolution in dots per inch
-deferglyphs [none|all|16] defer loading of [no|all|16-bit] glyphs
-ep string         default encodings path
-fc string         cursor font
-fn string         default font name
-fp string         default font path
-ld int           limit data space to N Kb
-lf int           limit number of open files to N
-ls int           limit stack space to N Kb
-sp file          security policy file
-x string          loads named extension at init time
-query host-name     contact named host for XDMCP
-indirect host-name   contact named host for indirect XDMCP
-port port-num      UDP port number to send messages to
-class display-class  specify display class to send in manage
-displayID display-id  manufacturer display ID for request
-dev framebuffer     name of device to open
-sharedretainedpath path  defines a file system path

我们注意到,有些开关要求参数是数字,因此我们很难利用,将这些开关也去掉,剩
下可能有问题的就少多了:

-auth string        select authorization file
-co string         color database file
-config string      read options from file
-ep string         default encodings path
-fc string         cursor font
-fn string         default font name
-fp string         default font path
-sp file          security policy file
-x string          loads named extension at init time
-query host-name     contact named host for XDMCP
-indirect host-name   contact named host for indirect XDMCP
-class display-class  specify display class to send in manage
-displayID display-id  manufacturer display ID for request
-dev framebuffer     name of device to open
-sharedretainedpath path  defines a file system path

让我们来依次测试一下这些参数,很快,我就发现"-co"开关在接受一个超长的参数
时发生了总线错误。

[w3@ /export/home/w3]> ./Xsun :1 -co `perl -e &#39;print "B"x10000&#39;`
Couldn&#39;t open RGB_DB &#39;BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
.....
BBBBBBBBBBBB&#39;
总线错误 (core dumped)
[w3@ /export/home/w3]> gdb ./Xsun core -q
(no debugging symbols found)...
Core was generated by `./Xsun :1 -co BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBB&#39;.
Program terminated with signal 10, Bus Error.
.......
......
#0  0xfecc1978 in t_splay () from /usr/lib/libc.so.1
(gdb) bt
#0  0xfecc1978 in t_splay () from /usr/lib/libc.so.1
#1  0xfecc17e4 in t_delete () from /usr/lib/libc.so.1
#2  0xfecc13f8 in realfree () from /usr/lib/libc.so.1
#3  0xfecc0f84 in _malloc_unlocked () from /usr/lib/libc.so.1
#4  0xfecc0d44 in malloc () from /usr/lib/libc.so.1
#5  0x2f630 in Xalloc ()
#6  0xb9fe0 in CreateServerOsPrivate ()
#7  0x4cf64 in main ()
(gdb) i r $pc
pc         0xfecc1978     -20178568
(gdb) x/i 0xfecc1978
0xfecc1978 <t_splay+24>:      ld  [ %o1 + 0x10 ], %g1
(gdb) i r $o1
o1         0x42424242     1111638594
(gdb) i r $g1
g1         0xfed140fc     -19840772
(gdb) x/20x $i0
0x186838:     0x42424242    0x42424242    0x42424242    0x42424242
0x186848:     0x42424242    0x42424242    0x42424242    0x42424242
0x186858:     0x42424242    0x42424242    0x42424242    0x42424242
0x186868:     0x42424242    0x42424242    0x42424242    0x42424242
0x186878:     0x42424242    0x42424242    0x42424242    0x42424242
(gdb)

从上面的结果可以看出,又是一个典型的heap溢出。上面测试用的字符串用了10000字节,这是为了保 证不漏掉对较大的buffer的溢出。经过测试,上面的参数只要大于5128
字节,就会发生溢出。这个程序的测试代码也很容易实现,参见“System V libc
malloc/free溢出技术分析”一文。

这个漏洞在x86平台下非常容易利用,覆盖t_delete/realfree/_malloc_unlocked/
malloc/Xalloc/CreateServerOsPrivate中任意一个函数的返回地址都可以。但是在
SPARC平台下则没有用,除非手工将断点设在t_delete函数中,才可以执行我们的代码。似乎有一种保护 机制,使得对堆栈中栈帧的修改失效了。这种情况我已经碰到过多次,令我非常迷惑,据说是由于寄存 器窗口没有刷新的缘故,但是还没有找到避免这种情况的方法。目前我发现的规律是,如果如果某个函 数与t_delete()函数之间间隔的函数调用比较多话,就有可能覆盖成功。如果能够解决这个问题,那么就 可以大大增加
SPARC下heap overflow成功的机会。有兴趣的朋友可以考虑一下,如果有什么发现,
记得通知我。:)

其他的命令行开关,经过测试都没有问题。至于环境变量,测试了一下也没有发现问题。
不过我的测试并不一定完全,可能还会有一些漏网之鱼等着你去发现.:-)

<完>

页: [1]
© 1999-2008 EvilOctal Security Team