Session objects, which track actual TCP conversations. Session objects are in charge of things like injection, and ACK-ing packets when we go into injection mode.
Now when the main script wants to inject, we can simply tell the session to do so:
Cooter would be proud indeed.
So now that the college profs are off our back, it's time to play with TDS, the official fuzzy protocol mascot of Microsoft SQL. There's a really great document here that explains the whole thing:
Other than some header info, it's almost like taking what you type on the command line and shoving it into a packet. Here's an example of a simple query (taken from Microsoft SQL Server 2008):
Starting at 0x0020, the play-by-play details:
01 – Type = SQL Batch. Generic construct for sending SQL messages.
01 – Status = End of Message. This is the last packet in this request.
0056 – Length. Size of the packet including 8 byte packet header.
0000 – SPID / Server Process ID. Can be specified by client, but not required or common to do so.
01 – Packet ID. Just set this to 01, it's for future functionality to track a sequence of TDS packets but is currently ignored according to the spec.
00 – Window. Also reserved for future use, set to 00.
And now we get into the data headers:
16 00 00 00 – Total Length of Data Headers. Bytes from here to SQL command.
12 00 00 00 – Header Length. Bytes from here to SQL command. We only have one header so it's a little redundant with the "Total Length".
02 00 – Header Type. 01 is Query Notifications, 02 is a Transaction Descriptor, which we're using to do the query.
00 00 00 00 00 00 00 01 – MARS Transaction Descriptor. Multiple Active Result Sets has been around since Microsoft SQL 2005, and is a way to feed multiple requests into a session without waiting for the results. We can set this to 01 for now (but should probably make a non-MARS version for older versions of the database)
00 00 00 – Outstanding request count. How many outstanding MARS requests we have, in this case none. (Oddly, in the spec this is 4 bytes, but I've been seeing 3 in actual MSSQL traffic)
Then we have the actual payload, which is encoded using UCS-2 Little-Endian. That's a fancy way of saying multi-byte encoding with the little number in the front, which is also a fancy way of saying that you put a 00 after your ASCII characters. It's a bit more complex than that if you want to use international symbols, or Funny Letters as they like to say where I grew up. (In my neighborhood you could get punched in the face for saying things like "umlaut")
The great thing about this whole setup is that we don't have any session-specific blobs of data. Unlike Oracle Net8, where we had a bunch of stuff going on that we didn't understand, we can pretty much build these payloads from scratch and sit them on top of our L3-L4 sled. It's also nice to have the actual spec in front of us, but even if we didn't, we could just fake it using a sled like we did in Net8 land.
So now, using the Session class as a base, we can create our own injection logic that creates the payload and adds our text accordingly. Here's the code from thicknet/session/MSSQL.pm:
my $str = encode("UCS-2LE", $cmd);
my $len = length($str) + 30;
my $data = pack('C*',0x01,0x01,0x00,$len,0x00,0x00,0x01,0x00,0x16,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00);
$data = $data . $str;
Don't freak out about the hex, you have the cheat sheet a few paragraphs up. Both the TDS header and the data header can be completely static except for the data length, which we populate with $len. Once created, we call pcap_sendpacket, and it's off to the races. We also have to own the TCP session at this point, but that's old hat since last time.
Here's the new MSSQL module in action. Notice that we don't see any visible disruption in SQL Management Studio. Database "studio" apps like this one frequently maintain a connection pool to speed the process of performing queries. Sometimes the database times out these connections, so it's a common occurrence for the application to open another connection without thinking twice. This design aspect is great for us, since it allows us to grab a connection without freaking out the user.
The overarching moral of the story remains the same as always: encrypt your database communications. thicknet will fall flat on its smug face if it tries to inject into an encrypted stream. Microsoft offers good options here, so it's definitely worth a look:
But enough of this cautionary stuff, there's a whole world outside of Hazzard County just waiting for you. You, with your object-oriented thicknet and your crazy sleds with the doors welded shut. The cipher might get you, but the creds never will.