Status: NEW → RESOLVED
Last Resolved: 20 years ago
Resolution: --- → INVALID
lpSecurityDescriptor is set to NULL by the ZeroMemory call on line 549.
There is a recently discovered technique in which NT processes can be hijacked to allow a user on an NT machine to get higher privileges on that machine. This is often due to NT calls which have a SECURITYATTRIBUTE, which is set as NULL, which gives it the default security. In PR_CreatePipe there is a call to CreatePipe, in which portions of the SECURITYATTRIBUTE struct are set, but not the lpSecurityDescriptor, which means this process is still given the default (bad) security.
Here is some additional reading on the recent NT object security exploitation technique. L0pht Security Advisory Release date: February 18, 1999 Application: Microsoft Windows NT 4.0 Severity: any local user can gain administator privileges and/or take full control over the system Author: email@example.com URL: http://www.l0pht.com/advisories.html --- Overview : --- Microsoft Windows NT 4.0 implements a system-wide cache of file-mapping objects for the purpose of loading system dynamic link libraries (DLLs) as quickly as possible. These cache objects, located in the system's internal object namespace, are created with permissions such that the 'Everyone' group has full control over them. Hence, it is possible to delete these cache objects and replace them with others that point to different DLLs. When processes are created, the loader maps/loads the loading executable's imported DLLs into the process space. If there is a DLL cache object available, it is simply mapped into the process space, rather than going to the disk. Hence, there is an exploitable condition, when a low-privilege user replaces a DLL in the cache with a trojan DLL, followed by a high-privelege account launching a process. The high priveleged process will map in the trojan DLL and execute code on behalf of the low privelege user. --- Affected systems: --- Windows NT 4.0 Server SP4 Windows NT 4.0 Workstation SP4 Other service packs are likely to be vulnerable, but the exploit has not been tested on them, neither has the fix presented below. --- Description : --- The Windows NT object namespace is the place where the kernel keeps the names of mutexes, semaphores, filemapping objects, and other kernel objects. It is organized hierarchically, like a directory structure. Amongst the directories are: \Device \BaseNamedObjects \Driver \KnownDlls ... The NT object namespace is browsable with a tool called 'WinObj 2.0' from System Internals (their website is http://www.sysinternals.com). You may wish to look around this namespace and browse the default permissions of objects. It is quiet entertaining, really. The "\Knowndlls" directory contains a list of DLLs in the c:\winnt\system32 directory, like: \KnownDlls\COMCTL32.dll \KnownDlls\MPR.dll \KnownDlls\advapi32.dll \KnownDlls\kernel32.dll .. All of these objects are created at boot time, and are 'permanent shared objects'. Normally, users can not create permanent shared objects (it's an advanced user right, and it is normally not assigned to any group, even Administrators). But the system preloads this cache for you. Permanent shared objects differ from regular shared objects only in the fact that they have a flag set, and an incremented reference count, such that if you create one, and then terminate the creating process or close all handles to the object, it does not disappear from the object space. To exploit the poor permissions on this cache, one first needs to delete one of the shared objects by name, in order to later replace it. So we make a call to the NTDLL.DLL native function "OpenSection()", getting a handle to the object. Then we call the NTOSKRNL.EXE native function "ZwMakeTemporaryObject()" which removes the 'permanent' flag and decrements the reference counter from the object. Now we just call NTDLL.DLL:NtClose() on the handle and it is destroyed. To create a section, one calls NTDLL.DLL:CreateSection(), which is undocumented. There are other calls one needs to make in order to set up the object and open the KnownDlls directory, but they are trivial and will not be discussed here. Feel free to browse the source code presented at the end of this advisory to see what you need to do though. Anyway, you create a section (aka file-mapping) object that points to a trojan DLL. A good candidate for DLL trojan is KERNEL32.DLL, since it is loaded by pretty much every executable you're going to run. Note that any DLL cache objects you create as a user can not be 'permanent', hence, when you log out, the cache object _will_ disappear. So how can we get a higher privelege process to run while we're logged in? There are many ways. We can wait for an 'At' job to go off, or we can set up the DLL hack as an 'At' job that goes off when someone else is logged in. But more reliable is this: When a new Windows NT subsystem is started, it creates a subsystem process to handle various system details. Examples of these processes are LSASS.EXE and PSXSS.EXE. The PSXSS.EXE is the POSIX subsystem. But since no one ever really uses the POSIX subsystem under NT. So, chances are, it won't be loaded into memory yet. Once it is, though, it's loaded until the machine reboots. If it loaded, reboot the machine, and it won't be :P. So, we launch our DLL cache hack, and then run a POSIX subsystem command, thus launching PSXSS.EXE (which runs as 'NT AUTHORITY\SYSTEM', the system account), and running our DLL with local administrator privileges. Incidentally, other subsystems have the same effect, such as the OS/2 subsystem (the only other one that probably isn't started yet). --- Workarounds/Fixes: --- I developed a patch for this security problem in the form of a Win32 Service program that can be installed by the Administrator of the system. It sets itself to run every time the system is started, and before the user has the opportunity to start a program, it adjusts the permissions of the DLL cache to something much safer. The source code for this service is also provided, along with a compiled version. Links to the programs can be found at http://www.l0pht.com/advisories.html. One can verify the validity of the patch by downloading the WinObj v2.0 tool from System Internals (www.sysinternals.com) and inspecting the permissions of the KnownDlls directory, and the section objects within it. Microsoft has been sent a copy of this advisory, and I would expect a hotfix from them at some point in the near future. --- Example: --- I wrote up a trojan to test exploitability, and it was a simple 'forwarder' DLL that had the same exported names as KERNEL32.DLL, but a different 'DllMain()' function, to be called when the DLL is loaded. The function calls in my trojan, simply forward off to the real KERNEL32.DLL calls located in a copy of the kernel that you make in 'REALKERN.DLL' in the c:\temp directory. To try out this vulnerability, obtain an account as a low-privilege guest user (referred to as 'Dick') and do the following: 1. Log in as Dick at the console. 2. Start up two "cmd.exe" shells. Do the following in one of them. 3. Copy c:\winnt\system32\kernel32.dll to c:\temp\realkern.dll (The egg dll is hard coded to use the c:\temp directory to find this file. If you can't put it in c:\temp, then modify the source '.def' file to point to a different location and recompile eggdll.dll) 4. Copy the provided hackdll.exe and eggdll.dll to c:\temp 5. Ensure that there is no file named c:\lockout. If there is, delete it. The exploit uses this file as a lockfile. 6. Delete the KERNEL32.DLL file-mapping object from the system cache: c:\> cd\temp c:\temp> hackdll -d kernel32.dll 7. Insert the new file-mapping object with: c:\temp> hackdll -a kernel32.dll c:\temp\eggdll.dll Don't hit a key in this window after hitting enter. 8. Now move to the other cmd.exe window that you started. 9. Run a POSIX subsystem command. A good way to start it is: c:\temp> posix /c calc (if you have calculator installed. If not, pick some other program) 10. Now the EGGDLL.DLL will prompt you with a few message boxes: Say no to the "User is DOMAIN\DICK, Spawn Shell?" box. Say no to the "User is \[garbage], Spawn Shell?" box. Say YES to the "User is NT AUTHORITY\SYSTEM, Spawn Shell?" box. Say YES to the "Winsta0" window station message box. Say YES to the "Desktop" window desktop message box. You will now see a "System Console" command.com shell open up. (saying yes to the next 'winlogon' box will give you something funny when you log out, btw :P) 11. Now go back to your first cmd.exe window and hit a key to unpoison the DLL cache 12. In the System Console window, run the User Manager program, and modify Dick's account (or anyone else's for that matter) to your hearts content. (NT Server) c:\winnt\system32> usrmgr (NT Workstation) c:\winnt\system32> musrmgr --- Source and Compiled Code: --- Exploit code can be downloaded from L0pht's website at http://www.l0pht.com/advisories.html. It is available in compiled form, and in pure source form as two zipfiles. The L0pht patch for this advisory is also available in both source form and compiled form from the same URL. firstname.lastname@example.org --------------- For more L0pht (that's L - zero - P - H - T) advisories check out: http://www.l0pht.com/advisories.html ---------------
(Assigned the bug to the module owner.) NSPR passes NULL as the lpSecurityAttributes argument to many Win32 functions (e.g., CreateFile). Should we be concerned? What is a good security attributes or security descriptor structure like?
I am confused. There is no mention of the security attributes or security descriptor structure in the L0pht Security Advisory that you posted. How is this DLL cache security hole related to this bug?
An ACL (access control list) should be created, with a single user ACE (access control entry) and disallow everything else. The single user ACE being that of the currently logged in user that started the netscape process. There should be a section of code that grabs the sid from the current process token and makes an allow security descriptor for it. I'll try to dig up some example of good security attribute handling. Meanwhile, here is the pointer to MSDN stuff on the securitydescriptor, which has links at the bottom, which deal with the other API's for secure object handling in NT. http://msdn.microsoft.com/library/sdkdoc/winbase/accctrl_6i5u.htm The L0pht advisory is an example of a technique to exploit NT objects that have incorrect permissions.
Yes, other areas where the SECURITYATTRIBUTE has been set to NULL, like in the CreateFile calls, are areas of concern. Perhaps even better examples than the CreatePipe call. I'll wait for feedback concerning this bug, before entering bugs on the other areas of NULL set sec. attributes.
I read the L0pht advisory thoroughly but still don't see how one can exploit file or pipe handles with the default security. I even downloaded the WinObj 2.0 tool (mentioned in the L0pht advisory) and it doesn't show any file or pipe handles. I think this security hole is only applicable to *named* objects, which are kept in the Windows NT object namespace.
ASSIGNED::INVALID makes no sense to me. clearing the resolution.
Taking this bug out of the Netscape Confidential group, so that experts on the NT SECURITY DESCRIPTOR add their comments.
The problem with not specifying a non-null security descriptor on objects isn't just one of security, but also of decreasing unknowns. When specifying a NULL security descriptor, one of two things happen: 1) NT will apply the ACEs with the inherit bit set in the parent object's ACL to the new child object if the object is named 2) if the object is unnamed, it will apply the DACL from the user's token Because these are uncontrolled variables, there is possibility that if a user has secured their machine properly (or even improperly), your functionality will break. You are relying on the operating environment to properly deal with these issues when there is no guaruntee of such a thing happening (and no error checking to make sure it is). To avoid issues like this, all object creation API calls should be setting a non-null security descriptor. Unless any of the threads launched form the clinet run under a different user context, CREATOR/OWNER Full Control and SYSTEM Full Control should work just fine. Comments?
NSPR now has its own Bugzilla product. Moving this bug to the NSPR product.
phillip gone, removing him from qa contact, sorry for spam
Ignore the previous attachment; it was meant for bug 23815.
A new API is being added to NSPR for specifying security attributes when creating files; see bug 24461. Marking this bug as a duplicate of 24461. *** This bug has been marked as a duplicate of 24461 ***
Status: ASSIGNED → RESOLVED
Last Resolved: 20 years ago → 19 years ago
Resolution: --- → DUPLICATE
Cleaning up a bit VERIFY dupe, sorry for spam
Status: RESOLVED → VERIFIED
You need to log in before you can comment on or make changes to this bug.