M-A's

technology blog

Monday 19 February 2007

Rationale behind UAC

I don't have any "insight" knowledge. Everything written in this post is directly coming from my head. This is what I think is the rationale behind UAC. All terms and acronyms have been explained in previous posts. It is not a pledge to Microsoft's design and implementation; it is simply an analysis of its behaviour and a deduction of the intended solutions.

Why MIC?
MIC permits a separation of access to object, either live or permanent. This comes in two parts.

First, the permanent objects with higher level will be protected from low level process, for a write-only perspective. You may say that it is not secure. It's true, except that it is at least enough secure for the protected audio process. Coupled with dual-token, MIC actually helps security. The reason is that it is an orthogonal layer of protection compared to token's SID. Think of it as a multiplicator for your SID privileges. Why didn't they leverage group SIDs to simply define a group SID for every level and use deny group SID for higher levels on DACL? In a way, it is actually explained this way: the SACL contains an SID with a variable end that is the IL. The only difference between the "variable" SID and defining specific IL group SID is that every higher level would have to be denied, not only setting a "level". MIC's design permits a much higher level of granularity that group SID; 6 levels are currently defined, but there are 0x6000 levels in total. Deny group SID wouldn't scale that well...

The second part is that permanent objects get an intrinsic IL too. This permits the "protection" that is necessary for registry/file system on Vista. The dual-token scheme (explained later) is non-persistent; ILs are. You can view it as a dynamic remapping of your access rights of the resources. On Windows, there's already some generic restriction that is done per-user. In Terminal Services (fast user switching), \??\ is remapped by session but there is no granularity per-process. MIC permits a more granular distinction even for one token with the same group SIDs in it and in the same session.

Why MIC does not cross computer boundary?
MIC can't cross computer boundary since I think SMB/NTLM does not implement it and I think it is not part of the token. (In fact, I'm not sure; it's maybe part of the token, TBV) It is part of the active process.
It's part of objects too, but since the re-created token on the server isn't the same as the client's token, the MIC can't be determined.

MIC can't cross computer boundary for a very simple reason. IL on the token (or active process, whatever) is set for this process and can only be lowered. When you access a remote resource, your token is not duplicated; you are network logged in on the remote computer so your token is actually different. Since there's no IL concept in the login procedure, that IL is inherited and lowered by the parent process, the network logon is always at high IL. Furthermore, network shares are entirely executed in kernel space, and if Process Explorer is right that ILs is a process property and not a token property, there's no MIC concept there either. (I'm not 100% sure about this, it needs verification. I finally think the IL is in fact a token's attribute even if documentation let think that it's a process' attribute.)

Why dual-token?
MIC is not a true security scheme. It is not sufficient alone to really protect from processes running as standard user. This is because it is an inheritance-only scheme. Dual token alone is not sufficient either because a process running as a standard user still have access to other process running as the same user (object ownership is the key here). The same apply to permanents objects too. Dual-token doesn't protect from shatter attacks. So the dual-token helps in having a personality that can be upgraded. It's not possible in MIC. IL can only be lowered, not increased. With dual-token, your level can be increased by gaining access to your original token. This original token is used to do the DACL verification when consent.exe has been executed.

The original token is really the normal token you'd get when UAC is off. The secondary token is a token with many privileges removed and with a Administrator Deny-only SID added. What it means is that if there is a resource that explicitly denies access to administrator, you won't be able to access resource denied to administrators even with your standard user equivalent token. This has been done to make sure administrators continue to be correctly denied resources they were already being denied (user's secrecy, I personally deny access to files for SYSTEM to make AVs stop bothering me, when I'm stuck with an AV, which doesn't happen often).

I talked about remapping in MIC. Well with dual-token, the global \??\ root is actually different for each token, like if they were on a different session. What it means in practice is that if you map a remote drive with the standard version of your token, you won't see it in the administrative version of your token. It's to complete the security of namespace. It will also bother people.

Why dual-token cross computer boundary?
Because of two things. Remember that when you access a network resource, you are actually network logged on. Since a logon is done, UAC still kicks in. UAC kicks in on the server, not on the client. So if UAC is disabled on the server, you will get your normal administrator token. Network logon could have been exempted from this scheme but it wasn't for a good reason. An old trick is the file:////localhost/c$ access (Note: I hate blogger's automatic reformating). If a user can chain thru local share to get back administrative access to the file system, there would be no point to dual token. This is another point where MIC couldn't have handled this alone.

Why UAC?
UAC is mainly the UI to make MIC and dual-token work. It's bothering, and the whole thing mainly done to make ISVs follow the "recommended" behaviour. In fact, this is a good thing; forcing ISV's hand, not bothering users.

Why virtualization?
That's a solution to the previous solutions' problems. Microsoft wanted to make legacy apps run better on Vista at the same time. If they wouldn't use virtualization, users would have been hammered with more popups that you can even imagine. Since virtualization may activates when you are on standard user token, the Admin-only resources look like they're allowed and UAC don't kick in. This behaviour will cause troubles to many people, but I think Microsoft felt obliged to do this because otherwise it would have been unmanageable for users running with the standard user token. Since Microsoft's goal is to force ISVs to make their application well behave in standard user environment, UAC was a must for them and virtualization was an obliged patch.

Note that applications with a correct manifest and x64 executable won't get virtualized. This is to stop virtualization somewhere. So what if virtualization is a problem for your app or you want to stop having virtualization for a specific third-party application? Simply place a correct manifest beside the executable, if the executable doesn't have a manifest already embedded in it. Otherwise, it will simply not work, i.e. you have to update the embedded manifest with some resource editing tool like VS2005. It is the trustInfo section that needs to be added, yes, the section that used to BSOD Windows XP. :)

I'd like to thank an anonymous friend for pointing out some errors before posting, but since he's not confident in what I'm saying, he'll remain anonymous. :)

Sunday 18 February 2007

Flash on Vista: an example of what will happen often with ActiveX

Adobe engineers did a simple error while implementing their out-of-process COM server. Nothing horrible, nothing that hinders security, it's just slight induced slowness.

When you create a COM server, you try to reuse it when different clients request it. It reduces the number of process start-up. The way it's done is that when the final Release() call is done on your last object, you wait a little before exiting the process just in case someone creates an object of the same type a few seconds later.

But on IE7 on Vista, each time you navigate on web pages that contains Flash objects, the process gets killed and started. There's nothing to do except using IE7 x64 so Flash objects don't load at all. :)

Since Microsoft wants ISVs to (finally) implement security with privilege separation by using different processes, many of them will have to create out-of-process COM server. I hope they'll do their homework.

---

I must not be too harsh, maybe they did this behaviour for some security reasons unknown to me.

Vista Recommendations

My recommendations are:

- You can't really disable UAC without problems until a nice way to add back the RunAs command exists and running IE7 in protected mode is available.

- Disabling UAC was my main point because there is no way for an administrator to remotely access sensitive resources on the computer otherwise. One thing to note is that the built-in administrator account is exempted by default from UAC (configurable through group policy). So my main recommendation is not to disable UAC, it is instead to enable back the built-in administrator account and set a strong password to it. Since the built-in administrator account is exempted from UAC, you don't get the dual-token scheme and you start at level 4000, but only for this account. You can use this account when you need to do administrative task, and keep running as a standard user the rest of the time. In case of emergency or anytime you want to browse c$, you can now remotely access the machine with this account. Otherwise, you're out of luck. Trust me.
To enable the built-in administrator account, start gpedit.msc, go in Computer Configuration, Windows Settings, Security Settings, Local Policies, Security Options. Set "Accounts: Administrator account status" to enabled. Restart the computer, login with the Administrator account (it will now be shown) and set a strong password. If you don't set a password, you won't have remote administrative access to the computer unless it's part of a domain.

- Disable virtualization. (See previous post) It's more trouble than solution. Do a RunAs instead when needed.

- Learn what is the integrity level stuff and dual token trick

- If you don't care about transparency, set Aero (desktop composition) off. You'll save a heck of memory. It's already automatically disabled in VMs and low-end laptops.

Like Mark Russinovich (A new marketing guy at Microsoft) said, UAC is mainly a temporary measure to make ISVs applications that runs correctly as a standard user. I don't think it'll stay as is more than a few years.

UAC Side effects

I finally started playing with UAC. The exploration has taken more time than I expected. I found out that disabling UAC has many side effects:

- It effectively disables protected IE7. I didn't expect it. In fact, it had to be expected but I think it's should not be the default behaviour. It gets disabled for a simple reason: iexplore.exe gets started at level 3000. When UAC is enabled, it gets a default level of 2000 instead. My observed behaviour is that when UAC is activated and IE7 is started at level 3000 it disables protected mode anyway. So the inner of IE7 disables protected mode because it has been started at level 3000, not because UAC is disabled. I'll have to try it myself one day (do a thunk that lowers the IL to start IE)
- It disables virtualization. It is normal for administrators but I didn't expect it for standard users.
- It renders "Run as admin" shell extension useless. It's the worst side-effect. The funny thing is that the menu item is still there, even when you are running as an administrator! For administrators and standard users, the result is that the process simply starts as if the user simply double-clicked the application. From my point of view this is a regression because the RunAs... is not there anymore. What if I want to start as a restricted user instead? There's no way in the UI.

So what to do? I'm not sure; probably the best bet is to enable back the old RunAs behaviour in Vista by fixing the registry a little bit. To be continued...

Friday 16 February 2007

Virtualization woes

A problem with virtualization that happens with legacy applications:

You start Explorer, you go in %ProgramFiles%\IDA\cfg to fix some configuration issues in ida.cfg. You double-click on ida.cfg file and edit it in your favorite text editor (let's say Notepad++). You save it. Start IDA. What? Why is the program still having the old behaviour? Did you mistype your last configuration change?

No!

Virtualization kicked in and your file was moved in a directory far far away. In fact, in %HOMEDRIVE%%HOMEPATH%\AppData\Local\VirtualStore\Program Files\IDA\cfg\. The problem was not IDA, it was Notepad++ that got virtualized. So be warned. If IDA had been virtualized too it would not be a problem.

Well at least I would not have noticed. However, imagine that IDA was virtualized. In addition, at first I used Notepad++ to modify the file, which created a virtual copy. Then I used standard Notepad to update it. I would have got an access denied. So I would have used the command "Run as admin". Then I'd get two different modifications from the base and IDA would continue to use the virtualized copy.

That is hypothetical, but it will happen. Just think about the registry virtualization. I hear all the weird problems support desks will face soon...

It should be noted that Microsoft knows this is a problem (1):

Although virtualization allows the overwhelming majority of pre-Windows Vista applications to run, it is a short-term fix and not a long-term solution.

For power users, I recommend disabling virtualization (1). That will reduce the number of surprises. Probably a lot of application will fail though, but only those that already needed administrative privilege anyway. If you were running as a user before, it should not affect you too much.

Watch out when disabling virtualization. If you've installed many programs where virtualization kicked in, you may get into troubles when disabling it. So you should disable it before installing third-party programs on your computer. I've warned you.

As the end note, don't get fooled, virtualization kicks in even when you are running as a standard user!

Reference
#1 "Understanding and Configuring User Account Control in Windows Vista"

http://technet2.microsoft.com/WindowsVista/en/library/00d04415-2b2f-422c-b70e-b18ff918c2811033.mspx
In you don't want to read the whole document, simply start gpedit.msc, go in Computer Configuration, Windows Settings, Security Settings, Local Policies, Security Options. There you'll see at the end the "User Account Control: ..." settings. (In French, it's "ContrĂ´le de compte d'utilisateur", de isn't there for every settings, the translators didn't verify their translations.)

The tale of associating .pl as an executable on Windows

First, I assume you installed ActivePerl 5.8+ installed. I also assume that you know how to modify safely the Windows Registry.

#1 In HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.pl
- Don't bother if the key doesn't exist.
- Remove Application value if there is one.

#2 In HKEY_CLASSES_ROOT\.pl
- Remove PerceivedType value if there is one.
- The (Default) value must be Perl.

#3 (x64-ONLY) Now do some verifications just in case. Verify HKEY_CLASSES_ROOT\Wow6432Node\.pl and make the value is the same than in its corresponding non-Wow6432Node key. Registry key reflection should kick in but if some 32 bits programs made modification to these keys, it could be different. Ahhh virtualization & reflection... :)

At this point, simply typing the name (including extension) of your Perl script will start it. For example, open a command prompt (64 or 32 bits as they should work fine for both) and type the (complete) name of your .pl script! Isn't it magical?

---

Now the true great trick is there:
If you want to have your .pl files searched through your %PATH% environment variable and to remove the need to type the extension at the same time, fix the %PATHEXT% variable by adding ";.PL" at the end (Or in the position you prefer for extension priority). Restart your command prompt and now you can simply type the name of your Perl script without extension. If you do not know how to modify environment variables, search in the System control panel. Note that this trick is applicable to any extension type that has a shell\open\command subkey. This fact is explained in online help of start (i.e. start /?).

Have fun!

---

Update: the following describe how to setup by using the cscript way. The problem with this method is that the command line arguments are not sent to the script for an unknown reason. I verified that cscript is indeed receiving the arguments. There must be a bug in ActiveState scripting engine. This section is kept for historical reasons.

#1 In HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.pl
- Don't bother if the key doesn't exist.
- Remove Application value if there is one.

#2 In HKEY_CLASSES_ROOT\.pl
- Remove PerceivedType value if there is one.
- The (Default) value must be PerlScriptFile. You may want to set the value to "Perl" instead. The difference is how the scripting engine is started. With Perl, c:\perl\bin\perl.exe is started; otherwise, cscript.exe is started and uses the ActiveState perl scripting engine. Why chose one to the other? Well the scripting engine permits you to have a nice property sheet on perl script files. :) I think it starts slightly faster. Maybe I'm just wrong. In theory, it'd add script debugging with VS2005 but for an unknown reason to me it doesn't work. Maybe the free version has been stripped down to remove this functionality. If you do so, step to #6 for the .pl verification only for x64 platforms, otherwise, you are finished but keep reading for second trick.

#3 In HKEY_CLASSES_ROOT\PerlScriptFile
- Set a nice description for (Default) value like "Perl Script File". What? You don't care? That's a very important step! :)

#4 In HKEY_CLASSES_ROOT\PerlScriptFile\Shell
Rename the Open subkey to OpenW and Open2 subkey to Open. By default, Open starts Wscript and Open2 starts Cscript. We want the reverse.

#5 In HKEY_CLASSES_ROOT\PerlScriptFile\Shell\Open\Command
- The (Default)'s value should be 'C:\WINDOWS\SysWow64\CScript.exe "%1" %*'. If it's wscript instead of cscript, you missing step #4.
- Change it to 'C:\WINDOWS\SysWow64\CScript.exe //Nologo "%1" %*'. This removes the copyright notice of cscript at start.

#6 (x64-ONLY) Now do some verifications just in case. Verify HKEY_CLASSES_ROOT\Wow6432Node\.pl and HKEY_CLASSES_ROOT\Wow6432Node\PerlScriptFile\Shell\Open\Command and make the value are the same than in their corresponding non-Wow6432Node key. Registry key reflection should kick in but if some 32 bits programs made modification to these keys, it could be different. Ahhh virtualization & reflection... :)

Thursday 15 February 2007

Using nVidia tools to rotate monitors easily

Great for wide-screen monitor when switching often to work in portrait and watch movies in landscape.

So here are my shortcut on my desktop (I have 2 monitors):
"Rotate 0° Monitor #1" = %windir%\system32\rundll32.exe nvcpl.dll,dtcfg rotate 1 0
"Rotate 90° Monitor #1" = %windir%\system32\rundll32.exe nvcpl.dll,dtcfg rotate 1 90
"Rotate 0° Monitor #2" = %windir%\system32\rundll32.exe nvcpl.dll,dtcfg rotate 2 0
"Rotate 90° Monitor #2" = %windir%\system32\rundll32.exe nvcpl.dll,dtcfg rotate 2 90

Anyway, you see the deal. Beside the rotate command, setgamma command is nice too (1). Personally, I use an old tool of NEC (2) (even if I now own Dell LCDs) but you cannot set different value for each monitor with this tool. If those method aren't precise enough, you can always resort to SetDeviceGammaRamp() function (3). Beware that trying to invert the colors or doing nasty thing like setting all colors to black won't work. I think the checks are that the colors must increase steadily and that the maximum color must be at least 75% but I am not sure.

At the same time I recommend to remove the nv* stuff in your registry HKLM\...\Run key.

---
Update June 9th, 20008. This trick doesn't work on Vista, the dll does a printf with "Error: API not supported on this version of Windows.". That's really sad.

Dual tokens: how to complexify a little more the security on Vista

On top of MIC (see previous post), there's the dual token scheme. Roughly, when you logon on Vista as an admin, your shell gets a standard user token and to access the normal admin token, a confirmation through secured desktop is necessary. At Microsoft, they call it Admin Approval Mode (AAM). The user interface calls it UAC. That's independent of MIC, which is a "local-only" technology in contrast to AAM which also impact your token on the network. The important part is that (1):

When authenticating to remote resources:
•If system is non-domain joined, user authenticates as standard user
•If domain-joined and an administrator of the remote resource, user authenticates as administrator

It killed me previously and will kill many home users because:
1. If you computer dies, you have no remote access to it unless RDP works, and RDP is disabled in Home Editions (2).
2. Shares need to be explicit to users and not just administrators.

I see the reason behind this; it is to protect from attacks that redirect to \\localhost\c$\. It creates a problem though; when you are unable to access your computer, let's say a filter driver that didn't uninstall correctly screwed your keyboard, like in the good old SoftIce days, you need some expensive recovery tools like ERD because you CAN'T use remote registry anymore. Well you can still use Safe Mode but I like to remotely fix dead computers. In addition, sharing is now a little more complex to set correctly.

Therefore, the only way to recover from this problem is to disable UAC and use a standard account, like everyone in the security field always recommended to. Adding to the fact that they improved the RunAs command in the shell, it shouldn't be a problem at all to run as a standard user.

Reference
#1 "Windows Vista User Account Control Internals", Mark Russinovich, powerpoint, page 46
http://microsofttech.fr.edgesuite.net/msexp/download/0370/0370_pres.zip

#2 Windows Vista Product Editions
http://www.winsupersite.com/showcase/winvista_editions_final.asp

Process Tree manipulation

The AppInfo service, which starts consent.exe, use a trick to fake the children process tree when calling CreateProcessAsUser() to make look like the creating process did indeed create the child process, which is false (1). That's well... "non-standard". I don't think that faking the process tree is the way to go, even for "user-friendliness".

So now the only thing we need to know is: How? :)

Reference
#1 "Windows Vista User Account Control Internals", Mark Russinovich
http://www.microsoft.com/emea/msdnshowtime/sessionh.aspx?videoid=360
The information is embeded in Mark's video around minute 37.

---

Update
It seems they pulled the plug of this presentation.

MIC : what they forgot to tell you

The Mandatory Integrity Control (which is implemented with Integrity Levels) is defined with 6 levels. The majority of the documentation only talks about 3 or 4 levels. At least, they are defined in winnt.h (1).

The "0" level is nice since it adds another blockage on anonymous tokens (furthermore that anonymous has been removed from everyone group in XP). The first place I heard about level 5000 is about an "installer" level (I've lost the reference). However, searching again I found true documentation about it (2). At least there, they tell upfront that it's about a protected process so it's most certainly used to implement Protected User Mode Audio (Protected Media Path or PMP).

Notice that in Process Explorer on Vista they never mention level 5000 (And they obfuscate the level with names, it's even worse on French Vista : "Niveau obligataire moyen" What?!? "3000" Ah now I understand! :) Since Process Explorer's author (Mark Russinovich) is now part of Microsoft, don't count on him anymore to reveal this kind of nice information. I think that protected processes are implemented as level 5000 is because it's an inherent ability given by MIC. Also, it is explicited that only "kernel mode CreateProcess()" can create a 5000-level process. (1) So talking about an "installer" mode is smoke. In Microsoft's document about protected processes, they tell the ISVs to forget about it (3):

Any application can attempt to create a protected process. However, due to the restrictions of running inside a protected process, the operating system requires that these processes be specially signed
Therefore, ISVs can't create protected processes that could touch the DRM audio process.

An underdocumented fact about MIC is that it's effective by default for "No-Write-Up"; it blocks write access but not read access to higher ILs. This is documented in Mark's presentation (4) at page 32. The other behaviors that can be configured through policies are No-Read-Up and No-Execute-Up. Look at the page 39 of Mark's presentation (4) to learn about the interactions of processes with different ILs.

Assuming that protected processes run at level 5000, I think that it is running with a No-Execute-Up policy. That implies that policies can change between different ILs? On the other hand, it is hardcoded only for level 5000? Who knows?

The values are stored in the SACL with a special SID to signal that it is not really an SACL entry. My first question is: how the IL propagates through containers? The icacls tool (6) has an interesting comment in its help: "Inheritance options for the integrity ACE may precede the level and are applied only to directories." Humm interesting, so the container's IL may precede the object's IL? Needs to be tested.

Finally for those who didn't know yet, the default integrity levels of objects without a specific integrity level is 3000. It is done to save space in the SECURITY_DESCRIPTOR and to implement a default security layer around objects from evil low-IL processes.

The conclusion is that there is a nebula around MIC and that the documentation is greatly deficient. I hoped that Microsoft would stop doing security by obfuscation but for MIC that's still the case.

---

References
#1 Winnt.h definitions concerning MIC
#define SECURITY_MANDATORY_LABEL_AUTHORITY {0,0,0,0,0,16}
#define SECURITY_MANDATORY_UNTRUSTED_RID (0x00000000L)
#define SECURITY_MANDATORY_LOW_RID (0x00001000L)
#define SECURITY_MANDATORY_MEDIUM_RID (0x00002000L)
#define SECURITY_MANDATORY_HIGH_RID (0x00003000L)
#define SECURITY_MANDATORY_SYSTEM_RID (0x00004000L)
#define SECURITY_MANDATORY_PROTECTED_PROCESS_RID (0x00005000L)
// SECURITY_MANDATORY_MAXIMUM_USER_RID is the highest RID that can be set by a usermode caller.
#define SECURITY_MANDATORY_MAXIMUM_USER_RID SECURITY_MANDATORY_SYSTEM_RID

#2 Well-known SIDs
http://msdn2.microsoft.com/en-us/library/aa379649.aspx

#3 Protected Processes (on Windows Vista)
http://www.microsoft.com/whdc/system/vista/process_Vista.mspx
Note: to people that had the chance to read a previous version of this document around 2006 summer can remark that the rights are slightly different in Vista's RTM.

#4 "Windows Vista User Account Control Internals", Mark Russinovich
http://www.microsoft.com/emea/itsshowtime/sessionh.aspx?videoid=360
Direct link to the powerpoint: http://microsofttech.fr.edgesuite.net/msexp/download/0370/0370_pres.zip
He is clear about a fact: Elevation is not a security boundary. But he had "the front" (place the right translation of "culot" in French) to say "There is 4 integrity levels", that's simply not true.

#5 "Windows Vista System Integrity Technologies", Steve Riley
http://www.microsoft.com/emea/itsshowtime/sessionh.aspx?videoid=223

#6 I recommend looking at the online help of those tools: icacls, accesschk, whoami.

Keywords: 100 200 300 400 500 1000 2000 3000 4000 5000

(Side note: the Blogger's HTML editor need to be redesigned, it's inefficient. Furthermore a 680x240 editor looks rather small on a 1200x1920 screen :( Blogger web site designers have some homeworks to do!)

Technical blog

This blog will contains some of the stuff I always wanted to put on a web site but that I never had/took the time to. I'd wanted to use a wiki so others can fix the blatant error I often make but I couldn't find any wiki web site that I liked. Therefore, I choose to be a little despot on my own island. :)

Be warned that I will often update the blog's entries to correct errors or add observations. On 7 entries so far I already did at least a dozen updates. Since Google does not indexed it yet, nobody will notice. :)

---

My first blog dates back from 1999 when I made a CGI script that generated an html file by parsing a text file. At least at the time, there was no hype about it and I quickly found that it was useless. ;)

I hope my second attempt eight years later be worth the trouble for the readers.

---

Syntactic and orthographic errors will happen since
- English is not my native language,
- The blog is about technology, so the content is more important and the container,
- Blogger's web editor doesn't have any spell checker.

I'll try to maintain an acceptable written level though.