Windows 7 auto-elevation mistake lets malware elevate freely, easily
As you probably know by now, Windows 7 introduces some new in-between modes for User Account Control (UAC). By default, Windows 7 (beta thus far) ships with UAC configured at the “Notify me only when programs try to make changes to my computer.” level. As the UAC helper text indicates, “this setting does not prompt when you change Windows settings, such as control panel and administration tasks.”
But how does Windows determine if an application should not prompt the user and simply auto-elevate? As Long Zheng alluded to, Windows checks the process’ image on disk for an embedded digital certificate. But this alone isn’t enough, otherwise instances of any Microsoft application (e.g. calc.exe) would automatically elevate. Leo Davidson did some initial investigative work and uncovered a clue direct from Microsoft:
[…] The change we made in Windows 7 default UAC settings is that any operation that is necessary to manage windows will not require an elevation - which in technical terms translates into a white list of trusted action / binaries which the user can make perform without UAC prompting from an elevation. This list does include windows file operations.
Don’t get wrapped around the term “list”. Rather than implement a real list, that would potentially become a management nightmare, Microsoft chose to implement a new, currently undocumented, application manifest flag.
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
<autoElevate>true</autoElevate>
</asmv3:windowsSettings>
In every binary that Microsoft feels should have auto-elevation capabilities, a flag is added to its manifest and the executable (of which the manifest resides in) is digitally signed. I haven’t dug into the internals yet, but I’m hoping assuming that a) the manifest must be embedded (i.e. external manifests should not meet auto-elevation requirements) and b) the image must be signed by Microsoft and Microsoft alone. Evidence to support the latter can be found in the same newsgroup thread pointed out by Leo:
You see a prompt […] because your binary is not an inbox binary - i.e. not an executable which ships with Windows. Hope that explains and clarifies. For security considerations, Windows 7 does not allow any 3rd party binary to be in the Windows trusted list. […]
Now understanding how applications are “white-listed”, there’s a problem.
This auto-elevation flag was applied to rundll32.exe, an executable that has and still ships with Windows today. Rundll32 (the 32-bit version of original Rundll) was a small internal-only tool later introduced in Windows 95/NT for general use by the public. Its debug-oriented purpose is simple – allow a user to load a library of choosing and call a specific function with parameters.
By now, you should see where I’m going with this.
As Long also pointed out, malware authors can exploit the fact that rundll32.exe is allowed to automatically elevate by separating their malware into two pieces – a proxy application and a payload (in the form of a library). The proxy application’s job is to invoke rundll32.exe, with the payload library as a parameter in a way that “requests” elevation. Windows will intercept the request and automatically elevate the process to High Mandatory Level, executing your payload wearing an administrative hat.
As a proof of concept, I created two programs. The proxy application, Catapult.exe is a one-line C# application (code) that uses the Process.Start method to launch an instance of rundll32.exe, requesting elevation with the little-known “runas” verb. Cake.dll is a multi-line C++ library (code) and our payload with a single WhereAmI exported function. This function simply reads the current process token, requests Mandatory Level information and shows a message box on-screen. In the real world, this would be the entry point of our malware.
As of today, there has been no official word from Microsoft regarding this issue. Birdies, however, have told me this problem was fixed in later builds. We’ll just have to wait and see what Microsoft implemented. Removing of the auto-elevate flag from rundll32.exe would fix that process but what about mmc.exe that suffers from a similar problem?
Tomorrow I’ll post the list of auto-elevate-flagged applications.
Nitpicker’s corner: I understand rundll32 requires a specific function prototype/calling convention to not corrupt the stack upon completion of the invocation. This is merely a proof-of-concept. I frankly don’t care about rundll32.exe’s stack after I’m done.

AAHAHAHAHAH THE CAKE IS A LIE!
And good the “cheater” title for System Mandatory Level.
I hope that at default UAC will be set as highest level…
go get em raf. good job
Uh-oh! That’s seriously big deal. And what can be the solution? Embed manifest checking into rundll32? Replace all rundll32 calls with separate signed exes?
I think this whole signing concept is flawed.
Oh wow… just wow… This design is terrible.
I had been wondering how Win 7 verified that the elevation call was legitimate. I didn’t get around to testing it but I assumed — wrongly — that MS wouldn’t be stupid enough to let through any elevation request from any exe with a signature. I assumed — wrongly — that they would at least validate the call stack to confirm the call was from code within the exe module (or an MS DLL module) and not from a 3rd party module…
Since they don’t do this, and since Explorer.exe is whitelisted and loads all kinds of 3rd party DLLs (shell extensions), this problem would exist even without rundll32 being whitelisted. And since the Debug APIs do not require elevation you could, I presume, also inject code/threads from a non-elevated process into a whitelisted process and execute that code with elevation. Of course, with rundll32 being whitelisted there’s no need for anything that complex. What a disaster.
This doesn’t make UAC completely useless — it will still prevent some exploits which don’t explicitly target Win7 from working — but it makes it useless at preventing any new exploits written by anyone who wants to include Win7 users as their victims.
As I said on my page, Microsoft really, really need to give the USER, not Microsoft, control of which applications are on the whitelist. It’s a trade-off of security for convenience but users gain no convenience from mandatory whitelisting of programs they do not use (like I do not use Explorer). And while I won’t leave the whitelist enabled because it’s such a security flaw, people who do want it enabled — since it’s better than no UAC at all — should be able to add 3rd party apps to it. MS not allowing that is completely anti-competitive (whether intentional or not) on top of being stupid.
I don’t get how MS could mess up this bad. In Vista, doing ShellExecute(..”runas”,”rundll32.exe”,”foo.dll,bar”…) would display the UAC dialog with a “non safe” color, not the MS windows color at the top of the UAC dialog so they already knew they had to be careful with rundll32
The only way this is going to work is if there is a user controlled white list (with UAC popup to change this list ofcourse) In a fresh install, this list should only contain MS .cpl’s (excluding the one for configuring UAC)
Anti-competitive? WTF? UAC never prevented me from installing or running open-office. The White-list term is a simplification of what is happening in the deep bowels of the OS between fellow OS building blocks. CALC.EXE for example is not on the list. Let them do their job with this beta before you start tree-hugging the monopoly term.
@Dugbug
No-one’s saying that UAC will prevent you installing software such as Open Office. Leo Davidson’s point (I think!) is that given the user has no control over which components/applications are whitelisted, the playing field isn’t a level one. A 3rd party file manager will not be able to run in the same elevated/trusted fashion as Microsoft’s own file manager (Windows Explorer).
Well this is a big problem, but AppLocker is the way :D :
http://img152.imageshack.us/my.php?image=dlllocknt1.jpg
@Dugbug:
Windows never stopped anyone running Netscape either. That isn’t the only way things can be anti-competitive.
Having an operating system feature/API in place that gives features to multiple MS bundled applications but does not allow the same features (with the user’s permission where applicable) to 3rd party apps is anti-competitive, surely? How could it not be?
I am not arguing that MS should unbundle their apps or include other people’s. I’ve heard those arguments and I think they are silly. However, I do think that any OS feature with a bundled MS app can use should also be usable via 3rd party alternatives.
Does that not strike you as reasonable?
Although, as I say in my updated page, the anti-competitive nature of the whitelist doesn’t really matter as things are now because it’s so trivial for third party code to bypass UAC if the whitelist is enabled. The problem is that the user has no control over what is whitelisted if anything is whitelisted at all. So the security problem that Rafael has demonstrated so well is by far the greater issue. When (if) that is fixed the anti-competitive issue may still remain, unless MS do the right thing and let users control what is and isn’t whitelisted in addition to fixing the other security problems.
@Giulio: AppLocker could help with RunDll32. Looks useful for sure.
However, there are lots of other ways to get a whitelisted process like, say, Explorer.exe to run arbitrary code that will then be granted silent elevation. So only blocking the RunDll32 method will only stop some things.
(In particular, unless things have changed drastically in Win 7, there’s nothing to stop an unelevated process from using the debug APIs to inject code into Explorer.exe and that code can then gain silent elevation. The debug APIs are enabled by default and do not require elevation. The theory was that you can only debug processes running at the same level as yourself, and you had to be elevated to debug an elevated process. Using Explorer as an example, the problem is that Explorer.exe is *not* an elevated process — so anything can debug it and inject code/threads — but code running on behalf of Explorer.exe *can* then launch any other actions or arbitrary code as elevated because of the whitelist.
(As should go without saying, I am talking about a default Windows 7 beta install logged on as the default admin-with-UAC account. If you run as a non-admin account, or set UAC to always prompt, then the problem goes away. That isn’t the default, though, and the whitelist that is the default is of such questionable value given what we now know.)
@Leo Davidson: Have you tested this? A process can not change elevation level, so Explorer must be using a child process or a elevated COM object, so injecting code would not help unless you scan all its memory and somehow find this COM object. If its a child process, I don’t see how process injection could work (And I would assume this elevated instance does its fileoperation without loading shell exstensions)
Guys, the parent process is irrelevant. Any medium isolation-level application can launch a auto-elevate-flagged process by simply asking Windows to elevate it (e.g. runas verb). There’s no code injection into Explorer required.
@Rafael: Agreed, but I wanted to make the point that closing the RunDll32/runas hole isn’t enough to solve the problem.
There are other easy ways to get other whitelisted medium-level apps to launch elevated code. RunDll32/runas is certainly the best example because it’s explicitly intended for launching code and obviously should not allow arbitrary code to launch elevated. Fixing that alone would only mean you’d need 50 lines of code to gain elevation instead of 5 lines. (Very approximate line numbers, of course.)
@asf: Explorer.exe is just one example but I have checked that it is non-elevated (”medium” level) and creates elevated COM objects (IFileOperation at least on Vista; don’t have my Win7 VM booted at the moment). It is whitelisted so there are no prompts when it creates those objects.
AFAIK there’s no protection on which objects it creates elevated (there certainly isn’t in the case of RunDll32 as Rafael’s proof shows).
You can get your own code into any application running at the same level using the debug APIs. Essentially you copy the code into the other processes memory and then start a thread from that point. Your code is now running within a whitelisted process and can create elevated COM objects (or perform other UAC elevation actions) without prompting.
In theory, that is. I haven’t written a proof of concept for this like Rafael has done for the RunDll32/runas case. It’s possible there’s something I am missing but extrapolating from what I know about Vista and what Rafael has proven about Windows 7 I can’t see any flaws in my plan. It doesn’t seem worth proving when the RunDll32/runas case has already shown the system is deeply flawed as it is but I doubt it’d take more than a few hours of coding to implement, unless I am wrong.
@Leo: I see where you’re going. Sadly, the COM Elevation Moniker has more strict requirements when it comes to elevation. See http://msdn.microsoft.com/en-us/library/ms679687(VS.85).aspx.
@Rafael: You mean the restrictions on which objects can be created elevated, or something else I’ve missed? I think a lot could be done with the existing objects registered for elevation, plus the ones which third parties install to do whatever they need to. Now, unless I’ve missed something, any COM object intended for elevated use can be used, with elevation, by any program without any prompts. If that’s true we might as well disable UAC for any process timestamped post-2009. :-)
BTW, this story was picked up by Mary Jo Foley at ZDNet: http://blogs.zdnet.com/microsoft/?p=1898
She got a laughable reply from Microsoft which included this nonsense:
“The only way this could be changed without the user’s knowledge is by malicious code already running on the box.”
Here’s why I think that is nonsense. (I posted this in the comments over there as well.)
–>8–
Given that installers run with full admin rights, UAC has never been about preventing malicious code already on the box from doing things.
UAC is about reducing the risk from the scenario where non-malicious code on the box is exploited, usually through a buffer-overflow bug, into doing what someone outside the box wants it to.
UAC makes it easy to avoid running everything with full admin rights. That in turn means that when a non-malicious program is compromised it can do less damage.
But now, by default in Windows 7 unless Microsoft admit this is a problem and change things at the last minute, it is trivially easy for a compromised non-admin process to elevate arbitrary code to full admin rights.
The only thing UAC will prevent, by default on Win 7, is attacks that don’t bother to target Win 7. Any attack written with Win 7 in mind can use one of several trivial methods to bypass UAC unless the user has taken the time to change it to always prompt.
–>8–
@Leo: Good point, the already elevate-able COM objects are more than enough. I was referring to elevating your own COM objects but that’s pretty niche and unnecessary now that I think about it.
I’m very excited to see a small percentage of people actually understanding the issue here. Like I mentioned on ZDnet, I understand UAC was not designed to be an air-tight security barrier. I get it, really. The message we’re trying to send is that UAC’s weaknesses in Windows 7 make malware proliferation EASIER than its predecessor.
You can’t have it both ways. You either turn the slider up or down. It should be a personal choice (as they have made it).
How the heck that you get something like that is a vulnerability in this case is beyond me. If you don’t leave UAC up all the way it’s your choice. It’s important (like having sex with someone) that you are informed about your security practices.
The slider in Windows 7 gives you that option. If you hate the protection Vista gave you, and it slows you down too much turn it down.
If you are concerned leave it turned up all the way..
@Donald Burnett: Except its not personal choice, only MS gets to decide which apps/components gets to auto elevate
@Leo Davidson: Only COM interfaces in HKLM are loaded when elevated in explorer AFAIK, so the only thing I can think of is to overwrite a dll that is already registered in HKLM with your own for full code control (You would need to find a dll that’s not already loaded/locked, IIRC property sheet exstension dll’s are unloaded right after you close the prop sheet)
So, with auto elevated explorer, you would replace a dll that implements a property sheet handler (on my XP machine, docprop.dll is not normally loaded, only with open property sheet, I’m sure there are others) and you have replaced a system dll, then run explorer.exe /seperated c:\ and open a property sheet
The same thing can be done with MMC and anything that can be elevated and loads a dll (I’m assuming these dlls are not checked for missing MS cert)
* … run explorer.exe /seperated c:\ from elevated cmd prompt or whatever ….
Not sure what I am doing wrong but I can’t get this to work in standard user mode, only works in admin user mode. (x64 version).
If you are standard user then you are at a very safe position atleast on the UAC issue. If you have a default setting for a standard user, then you cannot decrease the UAC level from the default level. It says you need to login as an administrator to do this. Sadly 90% of the PC users are admin users and not standard users. Don’t know why people don’t educated anyone to be a standard user and not admin user.
Leo: Explorer does not run elevated and in fact is not designed to run elevated at all. AFAIK it elevated sub processes to perform specific tasks only when necessary, like moving files you need Administrator access to move. If explorer is elevated its run dialog contains the shield icon to warn you that anything launched from explorer will also be elevated (easy to do accidentally if you restart it from task manager).
However Open/Save dialogs in elevated processes may be another matter (and would apply to Vista too) but someone would need to test this, I have no idea if those dialogs are elevated with the rest of the process.
steve: Auto-elevation cannot function in standard user mode. It only works as an administrator. In standard user mode an administrator’s credentials are required to run anything elevated… obviously with an administrator already logged in the prompt can be silently bypassed with auto-elevated, but otherwise it needs credentials and is forced to ask for them.
asf: “* … run explorer.exe /seperated c:\ from elevated cmd prompt or whatever ….” If you’re already elevated there’s no need to replace shell extensions to elevate yourself, is there?
Tihiy: IMO it’s time MS marked rundll32 as a legacy component and stopped using it in their apps. They could easily build stubs for just the individual calls, and then just those stubs would be auto-elevated for those specific functions. But AFAIK in Vista they removed the need for rundll32 calls from their core stuff so I’m not sure why rundll32 is being unsecured now.
Giulio: Cool, but that would break nearly all third-party apps right out of the box. It’s really not an option for most users.
Giulio: Oh with that program files rule it might work, but some apps don’t get installed there because it’s not standard user-writable anymore (Google Chrome is one example). And some users may install programs on a separate drive, such as myself. Legacy apps also may require write access to their own app folders to function, for storing settings or whatnot.
Of course a user could 1) add their program folders to your whitelist there or 2) install their programs to Program Files and then make the program folder user-writable but then either way malware now has a place to drop dlls that will run.
This is all so stupid. Wasn’t this type of thing why CAS (code access security) was added to .Net? Don’t they even read their own docs? Morons!
@Dan: I know Exploder doesn’t run elevated. It doesn’t have to. It, or anything running inside of it, can *silently* elevate other code.
That’s the whole problem. (And it’s not just limited to Explorer.exe; I’m just using that as a well-known example other than RunDll32.exe.)
In the past elevated processes could create other elevated processes. That isn’t an issue because there’s nothing you can’t do in the original process that you can do in the ones it can spawn. If you’ve taken control of an elevated process you don’t need to spawn another one; you can do whatever you want in the process you already have.
Now, by default in Win7 beta, there are non-elevated processes like Explorer.exe which can create elevated processes without prompting. And since Explorer.exe (etc.) are non-elevated, *all* *other* non-elevated processes can take control of them and in turn elevate anything they want without prompting.
In other words, a non-elevated process which is not whitelisted for silent elevation can elevate things silently with very little effort. That’s the problem!
It’s getting frustrating explaining this again and again. :(
It does not work 4 me. I am running win 7 built 7000
@Dan: I was not sure if cmd.exe could be auto elevated. The point still stands, if explorer gives you full control, you can replace a dll that implements some shell extension with your own evil dll
If explorer will allow anyone to take advantage of elevated privilages, then what is the solution, to what I see as the most ridiculous security flaw ever? I was under the impression that Windows 7 was supposed to be supiriour to Vista in every sense. I have been running build 7000 for about a week and I’m very happy with it so far but if I have to get annoying confirm boxes every 30 seconds just to have a secure OS then I’ll probably start looking elsewhere for a new OS.
Although I’m currently at work and havent yet tried hack created by the author, I will try it when I get home and post my results.
http://blogs.zdnet.com/microsoft/?p=1914 there is an update where apparently they say they have fixed it. Mined you we may not see the fix untill final releace
This is one of the strangest proof of concept flaws I’ve ever seen. I totally understand how injecting a dll into a white listed app could exploit this. Would it not be better for the functions requiring admin privilledges to check if the invoker is white listed and if not, then prompt? That seems like an easier option.
Глубокоуважаемые, а нельзя оставлять комментарии по теме, а не разную глупость типа Автор молодец и т.д.