Subject: [Phrack] Watcher
---[ Phrack Magazine Volume 8, Issue 53 July 8, 1998, article 11 of 15
-------------------------[ Watcher
--------[ hyperion <hyperion@hacklab.com>
----[ INTRODUCTION
Do you know if your system has been hacked? If you found those funny user
accounts or that Trojaned program, its too late. You're owned. Chances are
that your systems were scanned for holes before your systems were cracked.
If you had just seen them coming you wouldn't be reloading that OS right now.
Programs like TCP Wrappers do some good, but they don't see the stealth scans
or DOS attacks. You could by a nice commercial network intrusion detector,
but your wallet screams in agony. What you need is a low cost (as in free)
fast, somewhat paranoid network monitor that watches all packets and uses
few resources. Watcher provides this.
----[ IMPLEMENTATION
Watcher examines all packets on the network interface and assumes they all are
potentially hostile. Watcher examines every packet within a 10 second window,
and, at the end of each window it will record any malicious activity it sees
using syslog. Watcher currently detects the following attacks:
- All TCP scans
- All UDP scans
- Synflood attacks
- Teardrop attacks
- Land attacks
- Smurf attacks
- Ping of death attacks
All parameters and thresholds are configurable through command line options.
You can also configure watcher to just look for scans or just look for DOS
attacks. Watcher assumes any TCP packet other than a RST (which elicits no
response) may be used to scan for services. If packets of any type are
received by more than 7 different ports within the window, an event is
logged. The same criteria are used for UDP scans. If watcher sees more than
8 SYN packets to the same port with no ACK's or FIN's associated with the
SYN's, a synflood event is logged. If a fragmented UDP packet with an IP id
of 242 is seen, it is assumed to be a teardrop attack since the published code
uses an id of 242. This is somewhat lame since anyone could change the
attacking code to use other id's. The code should track all fragmented IP's
and check for overlapping offsets. I may do this in a future version. Any
TCP SYN packets with source and destination address and ports the same is a
identified as a land attack. If more than 5 ICMP ECHO REPLIES are seen within
the window, Watcher assumes it may be a Smurf attack. Note that this is not a
certainty, since someone your watching may just be pinging the hell out of
someone. Watcher also assumes that any fragmented ICMP packet is bad, bad,
bad. This catches attacks such as the ping of death.
Watcher has three modes of monitoring. In the default mode, it just watches
for attacks against its own host. The second monitoring mode is to watch all
hosts on it's class C subnet. In the third mode, it watches all hosts whose
packets it sees. Watching multiple hosts is useful if you put Watcher on your
border to external networks, or to have hosts watch out for each other in case
one gets cracked before you can react. Even if log files are destroyed, the
other host has a record.
It must be noted that since Watcher treats every packet as potentially hostile,
it sometimes can report false positives. There are some checks in the code
to minimize this by increasing its tolerance for certain activity.
Unfortunately this also increases the rate at which scans can be done before
Watcher notices. The usual false positives are TCP scans and synfloods,
mostly resulting from WWW activity. Some web pages have many URL's to GIF
files and other pretty stuff. Each of these may cause the client to open a
separate TCP connection to download. Watcher sees these and treats them as
a TCP scan of the client. To minimize this, watcher will only log TCP scans
if more than 40 are received in the window AND the source port of the scan
was 80. This of course can be configured higher or lower as desired. As for
synfloods we will use the same WWW example above. If the client opens a lot
of connections to the server right before the 10 second window expires and
Watcher does not see the ACK's or FIN's for those SYN packets, Watcher will
think the client is synflooding port 80 on the server. This only happens
if watcher is watching the server, or if you are watching everyone. You
may also get occasional false UDP scans if the system being watched makes
lots of DNS queries within the window.
The output for Watcher is pretty simple. Every 10 seconds, any detected
attacks are logged to syslog. The source and target IP's are logged along
with the type of attack. Where appropriate, other information such as the
number of packets, or the port involved are logged. If the attack is normally
associated with false IP addresses, the MAC address is also logged. If the
attack is external, the MAC will be for the local router that handled the
packet. If it was from your LAN, you'll have the source machine and you can
thank the sender in an appropriate manner.
----[ PROGRAM EXECUTION
Watcher was written to run on Linux systems. Watcher has a variety of, most
of the self-explanatory. To execute watcher, simply run it in the background,
usually from the system startup script. The options are:
Usage: watcher [options]
-d device Use 'device' as the network interface device
The first non-loopback interface is the default
-f flood Assume a synflood attack occurred if more than
'flood' uncompleted connections are received
-h A little help here
-i icmplimit Assume we may be part of a smurf attack if more
than icmplimit ICMP ECHO REPLIES are seen
-m level Monitor more than just our own host.
A level of 'subnet' watches all addresses in our
subnet and 'all' watches all addresses
-p portlimit Logs a portscan alert if packets are received for
more than portlimit ports in the timeout period.
-r reporttype If reporttype is dos, only Denial Of Service
attacks are reported. If reporttype is scan
then only scanners are reported. Everything is
reported by default.
-t timeout Count packets and print potential attacks every
timeout seconds
-w webcount Assume we are being portscanned if more than
webcount packets are received from port 80
Hopefully, watcher will keep your systems a little better protected. But
remember that good security is multiple layers, and no single defense tool will
save you by itself. If you forget this, you'll be reloading that OS one day.
A network level monitoring tool to detect incoming packets indicative of
potential attacks.
This software detects low level packet scanners and several DOS attacks.
Its primary use is to detect low level packet scans, since these are usually
done first to identify active systems and services to mount further attacks.
The package assumes every incoming packet is potentially hostile. Some checks
are done to minimize false positives, but on occasion a site may be falsely
identified as having performed a packet scan or SYNFLOOD attack. This usually
occurs if a large number of connections are done in a brief time right before
the reporting timeout period (i.e. when browsing a WWW site with lots of
little GIF's, each requiring a connection to download). You can also get false
positives if you scan another site, since the targets responses will be viewed
as a potential scan of your system.
By default, alerts are printed to SYSLOG every 10 seconds.
***********************************************************************/
t = time((time_t *)0);
while(pkt = readdevice(netfd, &pktlen))
{
process_packet(pkt, pktlen);
if(time((time_t *)0) - t > Gtimer)
{
/* Times up. Print what we found and clean out old stuff. */
Purpose: sets values from environment or command line arguments.
**********************************************************************/
void doargs(argc, argv)
int argc;
char **argv;
{
char c;
Purpose: Display the usage of the program
**********************************************************************/
void usage()
{
printf("Usage: %s [options]n", Gprogramname);
printf(" -d device Use 'device' as the network interface devicen");
printf(" The first non-loopback interface is the defaultn");
printf(" -f flood Assume a synflood attack occurred if more thann");
printf(" 'flood' uncompleted connections are receivedn");
printf(" -h A little help heren");
printf(" -i icmplimit Assume we may be part of a smurf attack if moren");
printf(" than icmplimit ICMP ECHO REPLIES are seenn");
printf(" -m level Monitor more than just our own host.n");
printf(" A level of 'subnet' watches all addresses in ourn");
printf(" subnet and 'all' watches all addressesn");
printf(" -p portlimit Logs a portscan alert if packets are received forn");
printf(" more than portlimit ports in the timeout period.n");
printf(" -r reporttype If reporttype is dos, only Denial Of Servicen");
printf(" attacks are reported. If reporttype is scann");
printf(" then only scanners are reported. Everything isn");
printf(" reported by default.n");
printf(" -t timeout Count packets and print potential attacks everyn");
printf(" timeout secondsn");
printf(" -w webcount Assume we are being portscanned if more thann");
printf(" webcount packets are received from port 80n");
}
Purpose: Setup for monitoring of our host or entire subnet.
**********************************************************************/
void buildnet()
{
u_long addr;
u_char *p;
int i;
if(Gwatchlevel == MYSELFONLY) /* Just care about me */
{
(void) addtarget(Gmaddr);
}
else if(Gwatchlevel == MYSUBNET) /* Friends and neighbors */
{
addr = htonl(Gmaddr);
addr = addr & 0xffffff00;
for(i = 0; i < 256; i++)
(void) addtarget(ntohl(addr + i));
}
}
/**********************************************************************
Function: doicare
Purpose: See if we monitor this address
**********************************************************************/
struct scaninfo *doicare(addr)
u_long addr;
{
struct scaninfo *si;
int i;
for(si = Gsilist; si; si = si->next)
{
if(si->addr == addr)
return(si);
}
if(Gwatchlevel == HUMANITARIAN) /* Add a new address, we always care */
{
si = addtarget(addr);
return(si);
}
return(NULL);
}
Purpose: Adds a new IP address to the list of hosts to watch.
**********************************************************************/
struct scaninfo *addtarget(addr)
u_long addr;
{
struct scaninfo *si;
Purpose: Process raw packet and figure out what we need to to with it.
Pulls the packet apart and stores key data in global areas for reference
by other functions.
**********************************************************************/
void process_packet(pkt, pktlen)
u_char *pkt;
int pktlen;
{
struct ethhdr *ep;
struct iphdr *ip;
static struct align { struct iphdr ip; char buf[PKTLEN]; } a1;
u_short off;
Purpose: Process this TCP packet if it is important.
**********************************************************************/
void do_tcp(ep, pkt)
struct ethhdr *ep;
u_char *pkt;
{
struct tcphdr *thdr;
u_short sport, dport;
thdr = (struct tcphdr *) pkt;
if(thdr->th_flags & TH_RST) /* RST generates no response */
return; /* Therefore can't be used to scan. */
sport = ntohs(thdr->th_sport);
dport = ntohs(thdr->th_dport);
Currently teardrop and all its derivitives put 242 in the IP id field.
This could obviously be changed. The truly paranoid might want to flag all
fragmented UDP packets. The truly adventurous might enhance the code to
track fragments and check them for overlaping boundaries.
**********************************************************************/
void do_udp(ep, pkt)
struct ethhdr *ep;
u_char *pkt;
{
struct udphdr *uhdr;
u_short sport, dport;
We assume there is no valid reason to receive a fragmented ICMP packet.
**********************************************************************/
void do_icmp(ep, pkt)
struct ethhdr *ep;
u_char *pkt;
{
struct icmphdr *icmp;
Translates a MAC address into ascii. This function emulates
the ether_ntoa function that exists on Sun and Solaris, but not on Linux.
It could probably (almost certainly) be more efficent, but it will do.
*************************************************************************/
char *ether_ntoa(etheraddr)
u_char etheraddr[ETH_ALEN];
{
int i, j;
static char eout[32];
char tbuf[10];