‘Windows Local Security Authority Service Remote Buffer Overflow (MS04-011)’
‘eEye Digital Security has discovered a remote buffer overflow in the Windows LSA (Local Security Authority) Service (LSASRV.DLL). An unauthenticated attacker could exploit this vulnerability to execute arbitrary code with system-level privileges on Windows 2000 and Windows XP machines. The susceptible LSA functionality is accessible via the LSARPC named pipe over TCP ports 139 and 445.
This buffer overflow bug is within the Microsoft Active Directory service functions exposed by the LSASS DCE/RPC endpoint. These functions provide the ability to use Active Directory services both locally and remotely, and on default installations of Windows 2000 and Windows XP, no special privileges are required.
Some Active Directory service functions generate a debug log file in the ‘debug’ subdirectory located in the Windows directory. A logging function implemented in LSASRV.DLL is called to write entries to the log file. In this function, the vsprintf() routine is used to create a log entry. The string arguments for this logging function are supplied as parameters to vsprintf() without any bounds checking, so if we can pass a long string argument to the logging function, then a buffer overflow will occur.
We found some RPC functions that will accept a long string as a parameter, and will attempt to write it to the debug log file. If we specify a long string as a parameter to these RPC functions, a stack-based buffer overflow will happen in the Active Directory service functions on the remote system. Attackers who successfully leverage this vulnerability will be executing code under the SYSTEM context of the remote host.’
‘The information has been provided by Marc Maiffret.’
* Microsoft Windows NT? Workstation 4.0 Service Pack 6a – Download the update
* Microsoft Windows NT Server 4.0 Service Pack 6a – Download the update
* Microsoft Windows NT Server 4.0 Terminal Server Edition Service Pack 6 – Download the update
* Microsoft Windows 2000 Service Pack 2, Microsoft Windows 2000 Service Pack 3, and Microsoft Windows 2000 Service Pack 4 – Download the update
* Microsoft Windows XP and Microsoft Windows XP Service Pack 1 – Download the update
* Microsoft Windows XP 64-Bit Edition Service Pack 1 – Download the update
* Microsoft Windows XP 64-Bit Edition Version 2003 – Download the update
* Microsoft Windows Server 2003 – Download the update
* Microsoft Windows Server 2003 64-Bit Edition – Download the update
* Microsoft NetMeeting
* Microsoft Windows 98, Microsoft Windows 98 Second Edition (SE), and Microsoft Windows Millennium Edition (ME) – Review the FAQ section of this bulletin for details about these operating systems.
The buffer overflow bug is in a logging function which generates a string for the log file using vsprintf(). The name of the log file is ‘DCPROMO.LOG’, and it is located in the Windows ‘debug’ directory.
The Active Directory service functions implemented in LSASRV.DLL are as follows:
Function number – Function Name
In these functions, the DsRolepInitializeLog() API is called to create the log file ‘DCPROMO.LOG’ in the Windows ‘debug’ subdirectory. After calling this API, entries are written to the log file by invoking the DsRolepLogPrintRoutine() function. The following is an example of a log file that can be generated on the remote host using DsRolerDcAsDc() API:
09/25 21:49:22 [INFO] DsRolerDcAsDc: DnsDomainName aaaaa
09/25 21:49:22 [INFO] SiteName bbbbb
09/25 21:49:22 [INFO] SystemVolumeRootPath ccccc
09/25 21:49:22 [INFO] DsDatabasePath ddddd, DsLogPath eeeee
09/25 21:49:22 [INFO] ParentDnsDomainName fffff
09/25 21:49:22 [INFO] ParentServer ggggg
09/25 21:49:22 [INFO] Account hhhhh
09/25 21:49:22 [INFO] Options 1
The remote host can be specified as the first argument of the DsRolerDcAsDc() API. The parameters shown in this debug log file such as DnsDomainName ‘aaaaa’, SiteName ‘bbbbb’, and SystemVolumeRootPath ‘ccccc’ are string arguments for the DsRolerDcAsDc() API. These string parameters are logged using DsRolepLogPrintRoutine(), so, we can cause a buffer overflow condition by supplying a long DnsDomainName, SiteName, SystemVolumeRootPath, etc.
However, most of Active Directory service functions call RpcImpersonateClient() API, which changes the server thread’s security context to that of the client. Generally, the ‘debug’ subdirectory located in the Windows directory is not writeable by everyone if the drive is formatted as NTFS, meaning that we cannot append to the log using a null session. The RpcImpersonateClient() API is called before opening the log file, and if the connected client does not have the privilege to write to the log file, then CreateFile() will fail, and the vulnerable call to vsprintf() is not performed.
However, the DsRolerUpgradeDownlevelServer() function, which is supported by Windows 2000 and XP, does not use the RpcImpersonateClient() API — it calls DsRolepInitializeLog() API immediately. So, if we specify a long string parameter to this function, we can pass these parameters into vsprinf() in the DsRolepLogPrintRoutine() API, and a buffer overflow will occur.
The DsRoleUpgradeDownlevelServer() client API which issues the DCE/RPC request is implemented in NETAPI32.DLL. This is an undocumented API. If we specify a long szDomainName, LSASS.EXE — which provides the Active Directory service functions running on the local computer — will crash. This type of attack can be performed against the local machine for the purpose of privilege escalation.
There is no parameter to specify the remote host for the DsRoleUpgradeDownlevelServer() client API. The API specifies the host as NULL internally, so the DCE/RPC request will be sent to LSASS.EXE running on the local computer. However, the function called from LSASS.EXE does not check whether the request is sent from the local machine or a remote one, so it will also handle requests sent from remote hosts. So, if we craft this DCE/RPC packet by hand, or if we modify the client API to be able to specify remote host, then we can cause a buffer overflow on an arbitrary remote host running Windows 2000 or Windows XP.
Because the Active Directory services interface is registered on the LSASS named pipe RPC endpoint (ncacn_np:host[PIPELSARPC]), it is sufficient to use CreateFile() and ReadFile(), WriteFile(), and/or TransactNamedPipe() in order to communicate with LSASS.EXE on the vulnerable host. No SMB knowledge is necessary, just an RPC bind and a DsRoleUpgradeDownlevelServer() packet.
We also can craft this DCE/RPC packet if we modify the instructions of DsRoleUpgradeDownlevelServer() client API. The first argument for DsRolepEncryptPasswordStart() API which is used in DsRoleUpgradeDownlevelServer() API internally is the remote host. In this case, NULL is specified for the first argument. So, if we can change this to the pointer which is stored the remote host, we can send DCE/RPC request for DsRoleUpgradeDownlevelServer() function.
In order to modify the DsRoleUpgradeDownlevelServer() API, the protections on a region of this API implemented in NETAPI32.DLL must be changed to PAGE_EXECUTE_READWRITE using the VirtualProtect() API. The following code changes will allow the remote host to be specified as the 9th parameter (szUnknown2) of the DsRoleUpgradeDownlevelServer() API.
In case of Windows 2000, we should specify the DomainName as Unicode; on Windows XP, we should use ASCII. We can execute about 2KB of code on the remote host using this buffer overflow.
Microsoft has released a patch for this vulnerability. The patch is available at: