Local Procedure Call Elevates Privileges Reported January 14, 2000 by Bindview
VERSIONS AFFECTED
- Windows NT 4.0 Workstation
- Windows NT 4.0 Server
- Windows NT 4.0 Server, Enterprise Edition
- Windows NT 4.0 Server, Terminal Server Edition
DESCRIPTION
Due to a flaw in the NtImpersonateClientOfPort
Windows NT 4 system
call, any local user on a machine is able to impersonate any other
user on the machine, including LocalSystem. We have written a
demonstration exploit which allows any user to spawn a cmd.exe window as LocalSystem.
All Windows NT 4.0 systems up to and including SP6a are affected. Bindview tested their
exploit on W2K RC2 and found that it was not vulnerable.
All Windows NT 4.0 machines are subject to compromise by any user who can log in locally
and run arbitrary programs. This may lead to
Domain Admin access, if Domain Admin credentials are on the machine.
In the case of Terminal Server, it should also be possible
to use the
credentials of other users on the compromised machine to take actions across the network
as those other users. This has not been tested, however.
Windows NT includes a mostly undocumented feature called Lpc ports, which are used for
making Local Procedure Calls on a machine. One of the system apis used with Lpc ports is
NtImpersonateClientOfPort, which allows a server to act in the security context of the
client who is calling it. However, the interface to the call lets the server specify which
client to impersonate based on process and thread IDs.
The kernel does do some sanity checking of the parameters to verify that the call is
legitimate, but it"s possible to fake it. First it verifies that the port you"re trying to
impersonate on actually has an outstanding request. This is easy to satify by making a
request to it ourselves. Next, it checks that the message ID in the request matches the
outstanding message ID in the thread you"re asking to impersonate.
This is also easy to satisfy, because if a thread is _not_
making a request, it"s outstanding message ID will be zero. So, as the server, when the
request comes in, we just change the pid and tid to the ones we want, and change the
Message ID to 0. Once we"re impersonating we can do whatever we want as that user.
The pseudo-code for our exploit works like this. There are two
threads.
Server thread
|
Client thread |
NtCreatePort
NtReplyWaitReceivePort...
|
NtConnectPort... |
(returns)
NtAcceptConnectPort
NtCompleteConnectPort
NtReplyWaitReceivePort...
|
(returns)
NtRequestWaitReplyPort...
|
(returns)
modify the LpcMessage received in the request so that the process and thread ids point to
the thread we want, and change the message id to 0.
NtImpersonateClientOfPort |
|
|
|
|