Analysis of BGP on transport and application layer

In this post I will be explaining some observations in relation to BGP (Border Gateway Protocol) on layers 4 and 7 of the OSI reference model. While it's clear why we are discussing layer 7 (application layer of the BGP itself), it may not be clear why would transport layer be relevant. The answer lies in BGP peer authentication. Peer authentication is a mechanism that BGP deploys to prevent attackers to inject/delete routes or interfere with the protocol in an unauthorised manner. Nowadays we will rarely see BGP implementation that do not deploy authentication of peers. So, let us have a look at the mechanisms of authenticated BGP operations.
For this purpose, I installed quagga (1.2.4 is its most recent version as of time of the writing) from http://download.savannah.gnu.org/releases/quagga/. Quagga is a package that simulates various routing protocols as a Linux processes. I used only bgpd. Below is its relevant configuration.

BGP is configured with a single AS (Autonomous System) 7675 , and 192.168.56.104 and 110 are  neighbors that run our little application that simulates BGP speaker.  Before we dive into the technical details of the analysis, lets familiarise ourselves with the basic structure of a BGP message. BGP , unlike HTTP,SMTP , POP3 etc., is a binary protocol. This means you cannot simply telnet to port 179 and issue text-based commands. Wireshark intercept will reveal the BGP is a binary protocol, meaning it follows a strict structure of the attributes that need to be in place and which identify various BGP values such as Autonomous System, Length, type of message, Hold time etc.
To construct a valid BGP message, we will use a small custom made application that will contain a buffer that represents BGP message in a raw format, essentially mimicking the above message. It will then simply send this buffer to a connected socket to the destination BGP router.
Construction of a message is based on a binary analysis of a protocol that reveals the structure of the message and allows understanding of the protocol syntax and semantics. So let us start with an example where no BGP authentication takes place - no BGP peer authentication is configured. If we send the above message to a legitimate BGP peer, it will generate an answer similar to below.
Our application running on 192.168.56.110 connects to BGP socket (192.168.56.101, port 179) and issues an "OPEN" message. Notice that 2nd rectangle shows the response from a legitimate BGP peer (which is again an "OPEN" message). This response contains some information internal to BGP peer like its BGP Identifier (in our case IP of 192.168.46.3 , which is another interface that BGP speaker runs).
Another example will describe the BGP session that requires authentication of a BGP peer. First , you need to know a password to make the session return anything meaningful - if you do not know the password used for BGP peers, you will not be able to complete the 3 way handshake. Look at the session with wrong password - your peer will not even respond with SYN+ACK. You just see a retransmission sequence of SYNs from your application.
Note the rejection happens on the network/transport layer, not the application layer. This may seem strange at first. The explanation is that BGP peer authentication is done via TCP MD5 signatures that take place on the transport layer. Take a look at the attribute below - TCP MD5 Signature is part of the TCP header (not the BGP layer).
Now we will configure our application to use TCP MD5 signature to make the session run. TCP MD5 is a part of the tcp.h for Linux and allows us to manipulate it via setsockopt.
Of course, this is the crucial point in attacking BGP - to be able to simulate and interfere with legitimate BGP session, there are at least 3 details you need to know:
a) BGP peering password (tcpm_key)
b) AS number
c) IP address of allowed BGP peers
While b) can be found on the internet for public BGPs, c) could be brute-forced, but getting to know a) is indeed difficult. Sure, you may try to run password dictionary attack against TCP MD5 signature, but this is long and cumbersome approach. For the sake of protocol analysis, let us assume we know all three attributes and we equip our application with that data. We specify the server IP and port and client IP address and port, and of course, the preshared BGP peer key.
When we intercept this session, we can see the application responses are starting to arrive. Note that SYN packet already contains the packet MD5 signature and unless we are able to reply with the adequate response signed with MD5 signature , the 3way handshake will fail.
Immediately following the SYN/SYN+ACK/ACK, we see the BGP OPEN message arrives. At this moment, our application does nothing much - it just informs us that the response is received. But even though this information is irrelevant to BGP,we were able to provoke another BGP response informing us that the message we sent makes no sense to BGP. Note the BGP NOTIFICATION Message stating "Bad Message Type".
If we enhance the application just a little bit and add some more meaningful response to BGP message, we can make the session go a bit further. In order to do that, we will construct a BGP aware response , again as a raw binary response and embed it instead of "Server got your message".  Its binary representation is given in the 2nd screenshot from the top of the blog. This resulted in established BGP connection, successfully exchanged OPEN messages and proceeding to KEEPALIVE message.
This small demo proved that by capturing and understanding the structure of a binary protocol, we may be able to artificially construct a simple response and potentially retrieve some additional information from the BGP. The same approach can be used to attack other binary protocols - for example Windows SMB etc.

=============Appendix - bgpcrack utility bug in tcp-md5.c module=================

Recently I was playing with bgpcrack utility, very nice tools developed by ex-Cisco Critical Infrastructure Assurance Group and Eloy Paris. I want to point out one problematic point with tcp-md5.c module which works ok except for one small detail - it inaccurately parses BGP payload, in particular , the "TYPE" option.
This is the part of code that ran incorrectly in my environment - it was always displaying that bgp-type was zero, even though it correctly reads the attribute from tcp packets.
 I think the problem is "ntohs". Below is the output generated by compiled original code. Note that the execution reports "Invalid BGP message" due to "type" being 0.
The reason is, I believe,the following: There is no need to change network-to-host byte order as "TYPE" is only 1 byte, so I simply removed "ntohs".
I think it should work with ntohs as well as in case of just one byte, it should not do any change in byte order. But for reason it does something strange here...Anyway, the below is the correction I did - I simply removed "ntohs".
After recompilation it worked ok. I added some printfs just to display some additional BGP header attributes (BGP type, BGP length and BGP marker).
Not sure if Cisco still maintains this, though. It's a nice tool, helped me learn a good deal on BGP.
Sent this material to tac@cisco.com and their support, not sure if there's going to react given relative insignificance of this tool compared to their mainstream services and products.

Comments

Popular posts from this blog

Signature verification bypass vulnerability in some Huawei routers

Attacking encrypted VOIP (SIP) protocols

DNS insights - UDP vs TCP and EDNS