« Back to home

SQL Server Authentication With Metasploit and MITM

While exploring the depths of Metasploit capture modules, I came across auxiliary/server/capture/mssql which can be found here. The module can be used to capture Microsoft SQL Server logon credentials if a user or client authenticates with the module. What caught my attention is just how effective this module can be in retrieving plain text credentials.

First a bit of background on SQL server authentication. Usually authentication is done using one of two methods, SQL Server Authentication or Windows Authentication. Windows Authentication allows you to access SQL Server using existing Windows credentials (such as local windows users or domain users), whereas SQL Server Authentication requires user credentials to be added and managed on SQL server directly. The specifics of each authentication method are out of this scope for this post, but today we will be focusing on a SQL Server Authentication weaknesses that this metasploit module exploits.

First looking through the source of capture/mssql, we come across this Ruby method:

def mssql_tds_decrypt(pass)   
    Rex::Text.to_ascii(pass.unpack("C*").map {|c| ((( c ^ 0xa5 ) & 0x0F) > 4) }.pack("C*"))

That single word, ‘decode’ should send shivers down any security researchers spine. So what is actually happening here? Well each character of the password goes through the following process:

  1. Each nibble of the byte is XOR’ed with 0xa5, and then swapped
  2. That’s it…

After a bit of searching we come across CVE-2002-1872 which confirms that the vulnerability affects SQL Server up to and including SQL Server 2000. So as long as we have a version of SQL Server Management Studio to communicate with a server version later than SQL Server 2000, we’re OK right? Wrong… lets look at another method in the module:

def on_client_data(c):
  # no errors, and the packet was a prelogin
  # if we just close the connection here, it seems that the client:
  # SQL Server Management Studio 2008R2, falls back to the weaker encoded
  # password authentication.

So it seems that SQL Server Management Studio 2008 r2 will fall back to the vulnerable SQL Server 2000 authentication method if required, which combined with the above decoding method means that passwords can be retrieved in plain text when SQL Authentication is used. Simple as that!

So now we have the vulnerability, but how do we get our user to authenticate against our metasploit module? Well that’s where good old social engineering comes into play. Lets imagine asking our DBA “hey, we’ve just spotted this SQL server on the network which we want to check for [Insert Generic Reason Here], any chance you could see if you have access?”. There is no way he/she is going to pass up this opportunity to be helpful right? OK I know, your team are all savvy with security practices and wouldn’t fall for such a obvious social engineering attempt, so what else can we do? Well we could use a MITM attack to put ourselves between the client and the server and force traffic to our metasploit module.

We are going to use Kali Linux to do this, but the tools we use are available for most Linux distributions. First we need to enable IP forwarding to ensure that we are forwarding traffic being passed to us:

echo 1 > /proc/sys/net/ipv4/ip_forward

Next we start our MITM arp spoofing attempt between out client and SQL server:

arpspoof -i eth0 -t [sql server address] [client address]
arpspoof -i eth0 -t [client address] [sql server address]

We kick off our metasploit module:

use auxiliary/server/capture/mssql
set SRVPORT 1433

And finally we use iptables to add a NAT rule redirecting traffic attempting to reach port 1433 (MSSQL) to our metasploit module running on localhost:

iptables -t nat -A PREROUTING -p tcp -d [sql server address] —dport 1433 -j REDIRECT —to-ports 1433

Now each time the victim tries to authenticate to SQL Server with SQL Server Authentication using SQL Management Studio, their traffic will be redirected to our metasplot module:

Nice! It’s worth noting that SQL Management Studio will be told that authentication has failed with the server, so caution needs to be used when testing this:

So now that we have a way to capture SSMS credentials, let’s consider another common source of SQL Server traffic, a web application. More specifically a ASP.NET web application. In this scenario we have a .NET application attempting to communicate with SQL Server using SqlConnection to make the connection between the web server and SQL Server using SQL Authentication. Does the same issue occur?

Our test client is pretty basic, we use a SqlConnection with a connection string containing our authentication details (the test code used can be found on github here). Again we start up Kali and use the above configuration to MITM traffic between us and the web application. What happens when the .NET application tries to connect to SQL Server?

That’s right, .NET SqlConnection also suffers from the same backwards compatibility issue as SQL Management Studio, authentication will fall back to SQL Server 2000 authentication mode with its switch nibble and XOR encoding.