OK, the last entry was a teaser for a blog entry or two on what developers can and IMHO should do regarding least privilege and least privileged user access (LUA) on Windows. A lot of this information can be already found scattered around but I wanted to target developers specifically and also be reasonably concise with links to furhter information.

Principle of Least Privilege (from Writing Secure Code): “All apps should execute with the least privilege to get the job done and no more”

The idea of least privilege is to limit the damage done by accident, error or attack. It’s quite simple: the more privileges a process has the more havoc it can wreak on your machine.

During Mark Russinovich’s entertaining and insightful malware talk at TechEd EMEA he admitted to accidentally downloading some spyware (which proved remarkably obstinate to remove). When Mark asked the audience who personally had been infected by malware, almost the entire room (~700 people) raised their hand. I have to admit I was surprised. If someone as smart as Mark Russinovich gets infected then what hope is there for the rest of us? The numbers in the room provided ample evidence: not a lot!

Given that we all make mistakes, all software has bugs, and that there is no shortage of hackers and malware, we’d be foolish not to apply the principle of least privilege to our PCs and to our code, right? What’s more, if we can do this with little or no inconvenience to either ourselves or our users then we’d have to be truly barking mad not to do something.

I am talking about developers here, not sysadmins, not knowledge workers (anyone else detest that term?), not home users. Developers are – of course – special and need special powers. They are continually installing tools and software, modifying registry entries, debugging, playing with COM and web apps and doing other fun stuff. What’s more, they have not only themselves to consider but also their software – and their users. Developers have the reputation of being anti-social but sandals and unwashed armpits and are nowhere near as offensive in my eyes as software which insists on running as SYSTEM when it doesn’t need to!

Let’s cover personal computer hygiene first and tackle code later. Here are the main choices, each making a different trade-off between security and usability:

The Developer as User choices
1) Log in as admin
2) Log in as admin but do risky things as LUA
3) Log in as LUA with a few extra privileges for added comfort
4) Login as LUA and escalate privileges when required
5) Login as LUA and stay there

Personally, I believe option 1 is indefensible and option 5 is impractical – at least until Windows Vista (née Longhorn)ships, where even admins log in as normal users – so let’s take a look at the other three.

Logging in as admin but doing risky things as LUA

The purists will pour scorn on this technique but given the large number of developers who admit to running as admin this can benefit a lot of people for minimal effort. You may resist all attempts to convert you to a non-admin logon but there’s really no excuse for not adopting this simple method of reducing risk, especially when you consider that much of today’s malware (rightly) assumes it will be running in an admin context and promptly fails otherwise. 

You log in (as usual) as admin on your XP or W2K3 box but when it comes to running a browser, email, IM or any other app you deem risky, you cut the privileges using Software Restriction Policy (aka SRP or SAFER). There are two ways to do this:

1) You use a simple program which crufts up a restricted token using the SAFER APIs and then launches your chosen app using that token, or
2) You take the phone off the hook, put your feet on the desk and make like a sysadmin, running secpol.msc and using group policy

These approaches are documented by Michael Howard in Browsing the Web and Reading E-mail Safely as an Administrator, Part 1 and Part 2 respectively.

Part 1 has a simple app, DropMyRights, which you download, and then use as follows

DropMyRights {application path} [N|C|U]

N runs the app as a normal user
C runs the app as a constrained user (less rights than N)
U runs the app as an untrusted user (less rights than C)

N is the recommended setting and usually works. I find C sometimes works but U rarely does (eg. notepad doesn’t lauch!). Your mileage may vary depending on the apps you use so experiment and see what is best for you.

The obvious thing to do with DropMyRights is to set up some shortcuts for IE, IM and Outlook with a target such as

DropMyRights "c:\program files\internet explorer\iexplore.exe" N

To make it pretty, add a name like “IE (nonadmin)”, start the thing minimized and select an icon which entices you to click on it. Once you’ve replaced your old shortcuts with the shiny new ones you need never give it another thought. You are no longer running your risky apps as admin.

At this point, if you are a cynical old goat like me, then you will want to check that DropYourRights is doing what it says on the tin. To do this, download Process Explorer from Sysinternals.com and check it out: in the tool, double click the relevant process and in the Security tab you should see (at least) a Deny flag on the Administrators group and additional constraints for the C and U options.

Part 2 uses a magical DWORD registry key, Levels, set to 0x20000 under

HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\Safer\CodeIdentifiers

Once you have added this, you can run secpol.msc, go to “Software Restriction Policies” (it may ask you to create them via the action menu) and you will notice “Basic User” under Security Levels. You are then able to go to “Additional Rules” and add a new path rule, forcing an app to run as Basic User.

The advantage to this approach is that all shortcuts to that target path will launch as Basic User. Note you can use group policy to disallow certain apps from running. This can be extremely useful if there are certain pieces of software you don’t want running on your machine.

The ever-helpful kiwi, Michael Howard, provides an app, SetSAFER, which you can download and compile against a version of Visual Studio 2005. I’ve tried it with beta 2 and it works perfectly. SetSAFER provides a simple UI and an XML config file allowing you to avoid secpol.msc and manipulate the registry directly.

The observant amongst you may notice that when you add the Levels registry key some extra options appear for runas, namely /showtrustlevels and /trustlevel. This enables you to do the following:

runas /trustlevel:"Basic User" "c:\program files\internet explorer\iexplore.exe"

However, I’ve not had as much success with this (i.e. IE hangs) and I would advise you to use the other methods. This is a timely reminder that until the MSDN articles were published much of this stuff was undocumented so, as always, be careful.

Also please bear in mind the weaknesses of this whole approach (logging in as admin and running risky apps as least privilege). Malware running as LUA could send Windows messages to other apps running with higher privilege. However, you are raising the bar for the malware writers and contributing to a strategy of defense in depth.

Logging in as LUA but adding a few extra privileges

With this approach you make your everyday account a member of the Users group and then customize it by adding privileges that you need. You do this by running secpol.msc and going to Local Policies -> User Rights Assignment. You could, for example, give yourself the powerful SeSystemtimePrivilege which enables you to see a calendar by double clicking the clock in the toolbar (oops, I’m in danger of breaking the old journalist’s rule: never use sarcasm in writing). Actually, there is some method in the madness: you might not want end users to change the time on their machine as they could subvert auditing.

Personally, I don’t like this approach. Micromanaging your privileges is a labour-intensive PITA. The operating system is supposed to provide abstractions to avoid this kind of crap. Anyway, if you can keep the number of extra privileges low and it works for you then more power to you - but always remember that malware running as you can do everything you can.

Logging in as LUA and escalating privileges when required

This is the preferred approach from the LUA purists. You log on as a normal user (i.e. your user account is in the Users group not the administrators group) but when you need to you escalate your privileges. Ideally you should take only those privileges you need and relinquish them as soon as possible but to avoid faffing it is normal to escalate to admin and back again. There are a number of ways you can do this: using the secondary logon service (Runas/MakeMeAdmin), Terminal Services/Remote Desktop and Fast User Switching.

You’ve probably noticed that when you give yourself new privileges the changes don’t manifest themselves until the next logon. As the name implies, the secondary logon service (check it out in your list of services) enables you to start a process under alternate credentials using the runas command. It also pops up as the runas option in context menus and in the CreateProcessWithLogonW API.

At its simplest, you can do something like

runas /u:machinename\administrator cmd

and, after being prompted for a password, a command prompt will pop up running as admin (helpfully labeled as such on my XPSP2 box). Or you can get fancy with

runas /u:machinename\administrator "runas /netonly /u:domainname\username \"%comspec% /K""

I’ve had success with Keith Brown’s approach of having a red-coloured admin command prompt running with my domain credentials for network connections (see here for details). You can use it to launch Control Panel applets, run mmc, and install apps (see here for a list of applets and mmc files). This is a nice approach if you enjoy working in command windows.

I like an easy life so I tend to just set up some shortcuts for apps that need to run as admin with the runas flag on. Then when I double click on the shortcut I automatically get prompted to see whether I want to use alternate credentials. To enable this you just need to click the advanced button on a shortcut’s properties context menu and select “Run with different credentials”. By the way, the “Protect my computer and data from unauthorized program activity” option in XP runs the app with a restricted SID, somewhat similar to the C option on DropMyRights.

The disadvantages to the secondary logon approach are that malware can send Windows messages to the admin command prompt window (think Sendkeys). Also if you install an app that is so brain-dead that it takes user information at install time rather than at run time then you end up with your admin profile rather than your user profile.

Another thing to watch out for is programs that, once running, resist all attempts to launch additional instances of themselves. By default, if you try to run another instance of Explorer it laughs in your face and instead opens a new window from the existing process. Unfortunately, this prevents you from launching a separate instance of Explorer running as admin. This issue, with workarounds, is covered in more detail in Aaron’s Margosis’ blog here. The easiest thing to do is to launch IE instead although there are some refresh issues.

Aaron has evolved Keith Brown’s humble batch file to a minor art form in the shape of MakeMeAdmin. Rather than bring up a command prompt running as admin, MakeMeAdmin leaps through some hoops to add your user account to the administrators group and launch a command prompt using those credentials – before promptly removing you from the admins group again. You can read the details here and here.

The advantage of this approach is that the high privilege command window is running as you with administrator privileges. Brain-dead install programs pick up your profile correctly. Any objects you create will be marked either with your SID or the Administrators SID depending on the “Default Owner” setting which Aaron describes in detail here. Read this carefully to understand the ownership issues. The general disadvantage with MakeMeAdmin is again the possibility of a SendKeys attack.

The solution to this mixed desktop context issue is to either use a Remote Desktop to yourself (!) on Windows Server or to use Fast User Switching (FUS) on Windows XP. Both of these use Terminal Services technology to provide a separate desktop and you can switch between them as required.

Unfortunately, most developers’ main machine is not running W2K3 and you can only use Fast User Switching if you are not connected to a domain (there is also no offline folder support with FUS). This rules out a lot of us. Naturally, Windows Vista fixes this but in the meantime, FUS is incredibly useful for your home PC(s) where you can set up a separate admin account for games (which often need admin access) and low privilege accounts for browsing.

Using Visual Studio when logged as LUA

Versions of Visual Studio prior to VS 2005 can be painful to use as a non-admin – which is a shame seeing as most of the time you are just typing code. There is an MSDN article on how to work around all the issues. From a pragmatic point of view, if you can run as Visual Studio as LUA then fantastic but if you can’t then it’s still better to log in as a non-admin and set up a shortcut with VS running as admin than to log in as admin from the start.

This is probably as good a place as any to ask a question about privileges: is the cunningly named SeDebugPrivilege necessary in order to debug? The answer, perhaps surprisingly, is not in the majority of cases. By default, you can debug any process running as the currently logged in user. The time you need SeDebugPrivilege is when you have to debug a process running as another user. This normally happens when you want to debug a server process which, more often than not, is with an IIS web app.

So if you’re just hitting F5 in Visual Studio there shouldn’t be a problem. You will need to be in the “Debugger users” group for Visual Studio 2003 but this is a VS03 thing not a Windows thing. This group is created when VS is installed and allows access to the Visual Studio Machine Debug Manager component.

Note things are a bit different in Visual Studio 2005 – there is no Debugger users group (nor the VS Developers group for creating web sites) and the whole LUA experience is much, much better.

Well, when I’ve recovered from writing this post I’ll try another post talking about writing code that runs as least privilege. In fact, this is much more important than you personally logging in as admin. How you write your code can affect the experience and the security of many people and, what’s more, they are your customers. Be nice to them.

Some resources

1) Keith Brown’s .NET Developer’s Guide to Windows Security
2) Aaron Margosis’ blog
3) Peter Torr on non-admin
4) Larry Osterman on non-admin
5) Non-Admin Wiki
6) Least Privilege in Longhorn
7) How to develop code as a Non-Admin
8) The Challenge of Least Privilege
9) Browsing the Web and Reading E-mail Safely as an Administrator (Part 1)
10) Browsing the Web and Reading E-mail Safely as an Administrator (Part 2) 
11) Developing Software in Visual Studio .NET with Non-Administrative Privileges
12) Using Software Restriction Policies to Protect Against Unauthorized Software