Avast, me hearties! When a swashbucklin’ pirate sights land whilst sailin’ uncharted waters, the first thing he be doin’ is makin’ a map. Ye can’t be burying ye treasure if ye don’t have a map, yarrr!

PUBLIC SERVICE ANNOUNCEMENT For everyone’s sanity, the pirate speak ends now. Save it for TLAP day!

When searching for booty on a network, it’s often useful to have a map. If you’ve got a foothold during a pentest, for example, how far does your conquered domain stretch? Is it a single-subnet site behind a SOHO router, or a tiny outpost of a corporate empire spanning several countries?

To get the answer, the best thing to do is ask one of the locals. In this case, we’re going to try to convince a helpful router to give up the goods and tell us what the network looks like. The control plane within the enterprise’s routers contains the routing table, which is essentially a list of destination prefixes (i.e., IP networks) and the next-hop to be used to get there (i.e., which neighbouring router to pass traffic on to in order to reach a destination).

The routing table is populated by a routing protocol (such as BGP, OSPF, EIGRP, RIP, etc), which may in turn have many internal tables and data structures of its own. Interior routing protocols (like OSPF) are concerned with finding the “best” route from A to B within the enterprise using a “technical” perspective; they’re concerned with automatically finding the “shortest” and “fastest” route, as opposed to exterior routing protocols like BGP which are more interested in implementing human-written traffic forwarding policies between different organisations.

The key word above automatic. Interior routing protocols like to discover new neighbouring routers without intervention – it can therefore cater for failed routers that come back online, and allow the network to grow and have the “best” paths recomputed automatically.

So, how are we going to get our treasure map so that we know how far we can explore? We’re going to call in Cap’n Quagga!

Quagga is a software implementation of a handful of routing protocols. We’re going to use it to convince the local router that we’re a new member of the pirate fleet, upon which the router will form a neighbour relationship with us. After this has happened we’ll end up with our pirate treasure map, namely the enterprise’s routing table. Finally, we’ll look at ways in which the corporate privateers can detect Cap’n Quagga, and ways to prevent his buckle from swashing in the first place.

For the purposes of this article we’re going to use OSPF, but the principles hold for other protocols too. OSPF is quite a beast, and full discussion of the protocol is well beyond the scope of this article – interested parties should pick up a book.

Step One – Installing and configuring Quagga

I’m using Debian, so ‘apt-get install quagga’ will do the job quite nicely. Once installed, we need to tweak a few files:

/etc/quagga/daemons

This file controls which routing protocols will run. We’re interested only in OSPF for this example, so we can edit it as follows:

zebra=yes

bgpd=no

ospfd=yes

ospf6d=no

ripd=no

ripngd=no

As shown above, we need to turn on the zebra daemon too – ospfd can’t stand alone.

Next, we need to set up some basic config files for zebra and ospfd:

/etc/quagga/zebra.conf

hostname pentest-zebra

password quagga

enable password quagga



/etc/quagga/ospfd.conf

hostname pentest

password quagga

enable password quagga

log stdout



Now we can force a restart of Quagga with ‘/etc/init.d/quagga restart’.

For more information, the Quagga documentation is here, the wiki is here, and there’s a great tutorial here.

Step Two – Climb the rigging to the crow’s nest and get out ye spyglass

We need to work out if there’s a router on the local subnet that’s running OSPF. This step is straightforward, as OSPF sends out multicast “Hello” packets by default every ten seconds – all we have to do is listen for it. As far as capturing this traffic goes, it has a few distinguishing features:

The destination IP address is 224.0.0.5, the reserved AllSPFRouters multicast address

The IP datagrams have a TTL of one, ensuring that the multicast scope is link local only

OSPF does not ride inside TCP or UDP – it has its own IP Protocol number, 89.

The easiest capture filter for tshark/tethereal or their GUI equivalents is simply “ip proto 89”; this will capture OSPF hellos in short order:

Apart from confirming the presence of a local OSPF router, this information is critical in establishing the next step on our journey to plunderville – we need Quagga’s simulated router to form a special kind of neighbour relationship with the real router called an “adjacency”. Only once an adjacency has formed will routing information be exchanged. Fortunately, everything we need to know is in the hello packet:

For a text only environment, “tshark -i eth0 -f ‘ip proto 89’ -V” provides similar output.

Step Three – configure Quagga’s OSPF daemon

For an adjacency to form (which will allow the exchange of LSAs, which will allow us to populate the OSPF database, which will allow us to run the SPF algorithm, which will allow us to populate the local IP routing table…), we need to configure Quagga so that all of the highlighted parameters above match. The command syntax is very Cisco-esque, and supports context sensitive help, abbreviated commands and tab completion. I’m showing the full commands here, but you can abbreviate as necessary:

# telnet localhost ospfd

Trying 127.0.0.1…

Connected to localhost.

Escape character is ‘^]’.

Hello, this is Quagga (version 0.99.17).

Copyright 1996-2005 Kunihiro Ishiguro, et al.

User Access Verification

Password:

pentest> enable

Password:

pentest# configure terminal

pentest(config)# interface eth0

! Make the hello and dead intervals match what we’ve captured

pentest(config-if)# ospf hello-interval 10

pentest(config-if)# ospf dead-interval 40

pentest(config-if)# exit

pentest(config)# router ospf

! eth0 on this machine was given 192.168.88.49 by DHCP

! The command below will put any interfaces in

! 192.168.88.0/24 into area 0.0.0.4, effectively

! therefore “turning on” OSPF on eth0

! The area id can be specified as an integer (4) or

! as a dotted quad (0.0.0.4)

pentest(config-router)# network 192.168.88.0/24 area 0.0.0.4

pentest(config-router)# exit

pentest(config)# exit

We can check our work by looking at the running-config:

pentest# show running-config

Current configuration:

!

hostname pentest

password quagga

enable password quagga

log stdout

!

!

!

interface eth0

!

interface lo

!

router ospf

network 192.168.88.0/24 area 0.0.0.4

!

line vty

!

end

The Hello and Dead intervals of 10 and 40 are the defaults, which is why they don’t show in the running-config under ‘interface eth0’.

Step Four – Start diggin’, matey!

With a bit of luck, we’ll have formed an OSPF adjacency with the local router:

pentest# show ip ospf neighbor

Neighbor ID Pri State Dead Time Address Interface

172.16.7.6 1 Full/DR 32.051s 192.168.88.1 eth0:192.168.88.49

If we exit from Quagga’s OSPF daemon and connect to zebra instead, we can look at our shiny new routing table. Routes learned via OSPF are prefixed with O:

# telnet localhost zebra

Trying 127.0.0.1…

Connected to localhost.

Escape character is ‘^]’.

Hello, this is Quagga (version 0.99.17).

Copyright 1996-2005 Kunihiro Ishiguro, et al.

User Access Verification

Password:

pentest-zebra> show ip route

Codes: K – kernel route, C – connected, S – static, R – RIP, O – OSPF,

I – ISIS, B – BGP, > – selected route, * – FIB route

O 0.0.0.0/0 [110/1] via 192.168.88.1, eth0, 00:04:45

K>* 0.0.0.0/0 via 192.168.88.1, eth0

O>* 10.4.0.0/26 [110/1012] via 192.168.88.1, eth0, 00:04:46

O>* 10.4.0.64/26 [110/1012] via 192.168.88.1, eth0, 00:04:46

O>* 10.4.0.128/26 [110/1012] via 192.168.88.1, eth0, 00:04:46

O>* 10.4.0.192/26 [110/1012] via 192.168.88.1, eth0, 00:04:46

O>* 10.4.2.0/26 [110/1012] via 192.168.88.1, eth0, 00:04:46

O>* 10.4.3.0/26 [110/1012] via 192.168.88.1, eth0, 00:04:46

O>* 172.16.6.0/30 [110/15] via 192.168.88.1, eth0, 00:04:46

O>* 172.16.6.4/30 [110/16] via 192.168.88.1, eth0, 00:04:46

O>* 172.16.6.8/30 [110/11] via 192.168.88.1, eth0, 00:04:46

O>* 172.16.6.12/30 [110/110] via 192.168.88.1, eth0, 00:04:46

O>* 172.16.7.1/32 [110/12] via 192.168.88.1, eth0, 00:04:46

O>* 172.16.7.2/32 [110/13] via 192.168.88.1, eth0, 00:04:46

O>* 172.16.7.3/32 [110/16] via 192.168.88.1, eth0, 00:04:46

O>* 172.16.7.4/32 [110/1012] via 192.168.88.1, eth0, 00:04:46

O>* 172.16.7.5/32 [110/1012] via 192.168.88.1, eth0, 00:04:46

We clearly are not just sitting on a single-subnet LAN! Here are some of the things we can learn from the routing table:

Firstly, we’ve got a few more subnets than merely the local one to enumerate with nmap etc!

We can make some kind of estimation on how far away the subnets are by looking at the route metrics. An example above is the ‘1012’ part of ‘[110/1012]’. 1012 is the metric for the route, with the precise meaning of “metric” varying from routing protocol to routing protocol. In the case of OSPF, by default this is the sum of the interface costs between here and the destination, where the interface cost is derived from the interface’s speed. The 110 part denotes the OSPF protocol’s “administrative distance“, which is a measure of trustworthiness of a route offered for inclusion in the routing table by a given routing protocol. If two protocols offer the routing table exactly the same prefix (10.4.3.0/26, for example), the routing protocol with the lowest AD will “win”.

A good number of these routes have a prefix length of /26 (i.e., a subnet mask of 255.255.255.192), meaning that they represent 64 IP addresses. These are likely to be host subnets with new victims on them.

The /30 routes (4 IP addresses) are likely to be point-to-point links between routers or even WAN or VPN links between sites.

The /32 routes (just one IP address) are going to be loopback addresses on individual routers. If you want to target infrastructure directly, these are the ones to go for.

If you want to start digging really deeply, you can look at the OSPF database (show ip ospf database), but that’s waaay out of scope for now.

Step Five – Prepare a broadside!

If we’ve got to this point, we are in a position not only to conduct reconnaissance, but we could also start injecting routes into their routing table or manipulate the prefixes already present in an effort to redirect traffic to us (or to a blackhole). Originating a default route is always fun, since it will take precedence over legitimate static default routes that have been redistributed into OSPF (redistributed routes are “External” in OSPF terminology, and are less preferable to “internal” routes such as our fraudulent default). If we had a working default route of our own, this approach could potentially redirect Internet traffic for the entire enterprise through our Quagga node where we can capture it. Either that or you’ll bring the network to a screaming halt.

Anyway, it’s all moot, since we’re nice pirates and would never consider doing anything like that!

Privateers off the starboard bow, Cap’n!

How can we detect such naughtiness, and even better, prevent it?

The first step is to use the OSPF command ‘log-adjacency-changes’ on all the enterprise’s OSPF routers. This will leave log messages like this:

Nov 23 15:11:24.666 UTC: %OSPF-5-ADJCHG: Process 2, Nbr 192.168.88.49 on Gi­gabitEthernet0/0.2 from LOADING to FULL, Loading Done

Keeping track of adjacency changes is an excellent idea – it’s a metric of the stability of the network, and also offers clues when rogue devices form adjacencies.

Stopping rogue adjacencies altogether can be accomplished in two ways. The first is to make OSPF interfaces on host-only subnets “passive“, which permits them to participate in OSPF without allowing adjacencies to form.

The second method is to use OSPF authentication, whereby a hash of a preshared key is required before an adjacency can be established. Either method is strongly recommended!

As always, keep yer eyes to the horizon, mateys! 🙂



Alec Waters is responsible for all things security at Dataline Software, and can be emailed at alec.waters@dataline.co.uk



Share this: Twitter

Reddit

Facebook

LinkedIn

Like this: Like Loading... Related