thicknet: starting wars and funny hats

Man-in-the-middle attacks are old. Really, really old. Maybe even as old as ancient times, when messengers ran between cities. Beat up a messenger, steal his funny hat, and change his scroll to say, "King Sam is really pissed at you guys". Who knows, maybe start a war, or at least a trade disruption. Beats the heck out of banging rocks with a stick, which was pretty much the cool thing to do before TV.

The LAN version of this attack caught on in full force with the advent of switches. Hubs send all packets to all connected hosts, whereas switches are smart enough to only send each packet to its intended destination. We used to get everyone's usernames and passwords simply by listening to the wire. Now we had to get a little smarter. This time we beat up Address Resolution Protocol (ARP), steal its funny hat, and read all the great stuff going over port 110.

ARP is easy stuff, it just maps IP address to MAC address. IP address is assigned by you, or a box with blinky lights. MAC address is "burned-in" at the factory, which means that the card just comes with it, and that every single one is different. Like snowflakes, no two network cards are exactly the same. Unlike snowflakes, you can cut yourself on network cards because they have sharp edges. ARP bridges the gap between these two by specifying how to discover MAC from IP. If the printer is at 192.168.1.20, you say "Who has 192.168.1.20?" in ARP-speak, and it replies with its MAC address. Easy stuff.

Now what if we start telling people that we're the printer? There's nothing to stop us from saying "192.168.1.20 is me". Then when people send us their print jobs, we change them to "King Sam is really pissed at you guys", send it along to the printer, and the cycle of history repeats itself. That's what thicknet is about: starting wars, and funny hats.

Modification

Actually thicknet started because of a penetration test, like most things in life. I was doing the usual ARP poisoning thing, using the venerable MITM tool ettercap, and happened to get ahold of a connection between an Oracle server and a DB admin. The goal of the test was to get cardholder data, so I grabbed some popcorn and watched the network trace, hoping that the admin would issue some commands that pulled CHD so I could go home. But he didn't. I started to realize that, despite being "in the middle", I was still kind of powerless. Oracle Net8 is a complex and undocumented protocol, if I put something about King Sam in there, it would barf on the admin and me and ruin everything.

That's when I called my good friend and co-worker Wendel G. Henrique, who had done some Oracle hacking, and who told me about this great way to get your own queries in there. He mentioned that there were "keepalive" packets that you could modify on-the-fly, and make them do what you want. I'd seen these packets before, they took the form of:

 

/** TESTING CONNECTION IS ALIVE */ SELECT 1 FROM DUAL

 

This can vary depending on the DB application, but this one in particular was really usable thanks to the long comment at the front. Using an etterfilter plugin to ettercap, I was able to change these commands to:

 

create user sl identified by sl1111

 

The thing is, we can't just switch one for the other because the protocol specifies the size of the data. We need to make our new text as large as the previous one. Comments are great for this.

 

/*I-LIKE-CATS--*/ create user sl identified by sl1111

 

The actual etterfilter looks like this:

 

if (tcp.dst == 1521) {
    if (replace("/** TESTING CONNECTION IS ALIVE */ SELECT 1 FROM DUAL", "/*I-LIKE-CATS--*/ create user sl identified by sl1111")) {
        msg("WIN");
    }
}

 

So this is pretty great, using predictable keepalive packets, we can make our own queries using an already-authenticated account. We don't even need to know the username and password.

But it's never enough, is it? I'm kind of impatient, and the whole idea of waiting for a keepalive, and being constrained to the size of the actual data, still chafed on my delusions of grandeur. If anything, this whole episode proved that Oracle doesn't use hashing or any other methods of validating the data. Using our ancient example, the scroll doesn't have a seal, so we can make it say whatever we want.

Now Wendel and I started thinking about asynchronous injection. We're in the middle, after all, and the session is running right through us. Why can't we just put our own stuff in there whenever we want? Well turns out that we can, if we put on big-boy TCP pants.

The Sled (Rosebud...)

I started looking at current tools like ettercap and The Middler for this. ettercap actually has an injection feature, but I started running into segfaults and had varying levels of success with it. From looking at the wire, it looks like ettercap creates its own TCP packets using a "stock" format, which can trigger oddness on the far end. I'm not sure that this was the problem, but the forums had almost no reference to this, and I started getting that "I am the only person in the world who has ever used this feature" feeling.

The Middler is another interesting tool, but at the time it was focused on L7 middling – i.e. stealing session cookies. It didn't seem to have hooks to do "middling" at L4, which is where this sick animal was going to live. I also kept thinking about stupid things like "Bette Middler", "The Middler on the Roof" and whatnot, which was very distracting. There was just something very unwholesome about the whole episode.

So it was all about perl and pcap from there on out, stuff I'd done for ackack extended and even more perverse, until I had something that would work long enough to get through a Black Hat demo. Wendel did some great work on downgrading Oracle crypto during this time, which made it into thicknet as well. It also takes advantage of a really cool/efficient eventloop by Marc Lehmann called libev. I highly recommend considering the libev/pcap combo if you're looking for an alternative to threads.

Our main struggle with the injection side of things, though, was learning how to speak enough Oracle Net8 to be dangerous. Net8 is undocumented, and any inquiries on the forums about it end up with "You have to pay lots of money and sign an NDA" which is a pretty wet blanket. We didn't understand Net8 when we used ettercap to modify packets, it seemed like we could take this concept farther. Indeed, the injection logic in thicknet uses "sleds" to accomplish this.

Sled-based injection works like this. We see something during the session that can be modified to suit our needs – a SELECT query, for example. Then we capture it, mess with it, and inject it into the stream. The tricky part is figuring out which fields need to change. This requires that identify dynamic fields, as opposed to fields that remain static. Remember that we are talking about session-static fields here. Many fields will change between sessions, but we don't need to build a fully working session, we're going to get on board with this "going green" business and recycle someone else's. The only fields that matter to us are ones that change based on the size, sequence, or content of the packet.

One of the things that makes Net8 injection easier is that, by default, no validation is performed on the data. Guessing at checksum algorithms is fun and all, but it's time consuming and might be really tough if something like encrypted hashes are in use. This leaves length and sequence fields. As you stare at the thicknet code, pounding on the table and laughing hysterically, you'll see these items called out. Now that these things are identified, we can capture a sled packet, modify it, and… injection time.

Pardon the injection

Remember the comment about big-boy TCP pants? Well the thing is, if we just inject into the stream, we won't be full of win yet. For one, we have to make the packets look like the client as much as possible. The sled helps us here too – we simply capture the entire packet, including TCP options. The TCP headers also need to be changed to reflect our new packet size. More tricky than that, we now own the session because the sequence numbers are going to change. This is where we kind of turn into a jerk. Unless you write some crazy fake session multiplexer, it's time to tell the other guy to get lost. Kind of the school dance equivalent of "may I cut in?" except without the resulting bruises. That's right, we're going to steal the homecoming queen from the football captain. With TECHNOLOGY.

So it all comes down to this:

  • Get in the middle (you can use arpspoof, or the included vamp.pl for this)
  • Watch for a sled
  • Perform injection based on sled
  • Takeover TCP session and issue whatever queries we want, whenever we want

I was a little worried about cutting off the client, until I realized that many of these database "studio" apps will reconnect transparently if the connection goes down. The whole thing really is win-win, in the truest "sharing is caring" sense.

It's important to note that while thicknet was developed as a proof-of-concept with Oracle Net8 in mind, it was created with some thought to adding other protocols. MSSQL is a possibility, as well as many other protocols that aren't even DB-related. As long as you can inject arbitrary data into a session, you can make a thicknet module for it. And for those of you developing protocols, strongly consider implementing encrypted hashes and/or strong encryption before sending something out the door. These are things that should be included by default instead of add-ons or options that may be overlooked.

As I mentioned earlier, there's a lot of other great stuff going on in thicknet, thanks to Wendel's research into Oracle protocol downgrading. For more details on this side of the tool, take a look at the whitepaper and presentation at Black Hat Europe 2010.

thicknet can be found on github at the following URL: http://www.github.com/SpiderLabs/thicknet

Trustwave reserves the right to review all comments in the discussion below. Please note that for security and other reasons, we may not approve comments containing links.