Developing Software in Visual Studio .NET with Non-Administrative Privileges
Visual Studio Core Team
Summary: Members of the local Administrators group have privileges to perform any action on a machine. This causes both a risk to the user performing actions in that environment and to the software that they develop. This article explains how to productively develop software while logged on with non-administrative privileges. (14 printed pages)
- Microsoft® Windows® XP and the Microsoft Windows Server 2003 family
- Disk drives with NTFS file system
- Microsoft Visual Studio® .NET
Security is important. No one argues with this and everyone spends a lot of time thinking about security issues, security bugs, and malicious users. However, very few people are willing make the effort to eradicate the largest single reason that e-mail viruses and cracks in general are so dangerous: everyone logs in as a user who is a member of the local Administrators group, and most services run as Administrators. The principle of "least privilege" states that running with the minimal set of rights needed to perform an action minimizes the damage done when something bad happens, whether it is a corrupt attachment in an e-mail received from Outlook, or a service that has a security risk. By running programs without Administrative privileges whenever possible, you ensure a more secure environment.
Currently available software often requires elevated privileges in order to run correctly. To end this situation, developers must take the first step and stop running as administrators. Then, if we all consistently log in, develop, and test applications as non-administrative users, the software we produce is more likely to be executable without artificial requirements of elevated privileges. Until developers fix the software they are writing and shipping, users will never be able to run in a secure environment, too!
Tasks such as global registration, installation of new software applications, and reconfiguring devices require administrative privileges. Unless a full-time administrator manages your machine, you will need to keep one administrative account to do these tasks.
From now on, it is assumed that this user account is named 'Administrator' and is on the local machine, as opposed to a domain account. However, the user could equally well be named 'root' as long as it is a member of the local machine's Administrators group. It is also assumed that you are working in a Windows domain, and your primary login is an account in that domain of the form DOMAIN\username; however, this is not a requirement and both accounts could be on the local machine.
Changing your account status
After confirming that you still have access to an administrative account, go to the User Manager, remove your user account from the Administrators group, and then add it to the Users group and any other less-privileged groups that are appropriate. To add your user account to the Users group, you must first load the Microsoft Management Console (MMC) and the User Management snap-in.
Note In most network setups, the domain's Domain Users group is already a member of the local Users group, so your domain account will already be in the local Users group.
Using the Microsoft Management Console
- Right-click My Computer and choose Manage.
- On the Start menu, choose Run, and then type lusrmgr.msc.
You are now ready to add your account to the Users group.
Adding your account to less-privileged groups
- Confirm that the account that will be your primary login in the future is not a member of the Power Users group.
The Power Users group is effectively the Administrators group, because it has write access to all of HKLM\Software and the Program Files directory, by default.
- Under the Local Users and Groups node, choose the Groups folder.
- Double-click the Power Users group.
- If your account or a group containing your account is listed in the Members list box, select that entry.
- Choose Remove.
- Add the account to the Users group.
- Add the account to the Debugger Users group.
- Remove the account from the Administrators group.
- Add the account to any other appropriate group, according to the following chart:
If you: Add your account to: Use Terminal Services to connect to the machine remotely Remote Desktop Users group Develop and debug local Web applications and you are using Windows Server 2003 IIS_WPG group
Note If you develop and debug local Web application using Windows XP Professional, use the following procedure to add the Log on as Batch Job privilege to your account.
Logging on as a batch job
- On the Start menu, choose Run, and then type gpedit.msc.
The Group Policy Object Editor appears.
- Expand the Computer Configuration node to display the Windows Settings, Security Settings, Local Policies, and User Rights Assignment nodes.
- Add the DOMAIN\username restricted account to the Log on as a batch job group.
- Log off and log back on as that user so that your changes will take effect.
Ensuring access to files and shares
While you were logged on as a member of the local Administrators group, you might have created directories for your personal use. You might have also created network shares that you wanted your user account to access, but those network shares were created with access granted only to the local Administrators group. You should ensure that the directories you have created on the local drive outside of your profile directory are still available to you and are owned by your user account.
To verify ownership of a private file or directory
- Right-click on the file or folder and choose Properties.
- On the Security tab, choose Advanced.
- On the Owner tab, verify that your user account is listed. If not, take ownership.
To verify access to file shares
- Right-click on My Computer and choose Manage.
- Expand the Shared Folders node and then the Shares node.
- For each user-created share to verify access to, right-click on the share and choose Properties.
- The Share Permissions tab and the Security tab correspond to the access to the share and the underlying file system permissions, respectively. The user account must have access through both lists in order to perform any operations with that share.
If you do not have access, add your user account in both places.
When you log in, you will notice that many of the UI widgets no longer work. Double-clicking the clock in the taskbar, for example, no longer displays the calendar, because the calendar is able to change the date, and that functionality is only available to users with elevated privileges.
Running an application as another user
Windows XP includes facilities to easily run an application as another user without logging out and back in as that user. Note, however, that these applications will terminate when you end your primary interactive logon session. You can do this in one of three ways.
Running a shortcut with different credentials
- Right-click a shortcut.
The Properties menu appears.
- Choose Run As.
This allows you to provide a different username and password to run the application with.
If you are always going to run an application as a different user, you can also allow Windows to automatically prompt you.
Running an application command line with different credentials
- On the Start menu, choose Run, and then type runas /user:Administrator program.exe.
— or —
- In the command shell window, type runas /user:Administrator program.exe.
Runas.exe will prompt for a password and execute whatever command line you passed in a new login session. This is convenient for running programs like regedit, iexplore, or even just opening a new command window, all of whose child processes will be running as that user as well. Because it is a new login, it does not inherit handles, environment variables, or the current working directory from its point of invocation; if you want to run programs that are not on the other user's path, you need to provide a full path to them.
Prompting for different username automatically
- Windows XP and later versions also allow the user to change the properties of shortcuts so that every time they are activated the user is asked to enter a different username and password.
- Right-click the shortcut and choose Properties.
- On the Shortcut tab, choose Advanced.
- Select Run with different credentials.
Running specialized administrative tools with different credentials
The next logical question is: How do you run the tools that are normally launched from the control panel? Should you right-click My Computer and select Manage, or should you go through other UI widgets that do not have intuitive shortcuts or obvious command line equivalents? Fortunately, all of the administrative tools are available either by running the control panel applets or directly through the Microsoft Management Console (MMC). The following tables list the common administrative tools (control panel applets and Microsoft Management Console files) and how they can be launched (either from a command prompt or by starting the control.exe or mmc.exe applications directly with the RunAs command). All of them are stored in the Windows System32 folder, though some are available exclusively on either the Windows Server 2003 family or Windows XP. Those entries are called out in the table below.
|Administrative action||Control Panel applet|
|SCSI, PCMCIA, and Tape Devices||DEVAPPS.cpl 1|
|Add New Hardware Wizard||hdwwiz.cpl|
|Mouse, Font, Keyboard, Printers||main.cpl|
|Multimedia and Sounds||MMSYS.cpl|
|Logon Management for XP||nusrmgr.cpl (XP)|
|Devices, Services, Server||srvmgr.cpl 1|
1 Uses the Windows Server 2003 family of operating systems
|Administrative action||Microsoft Management Console file|
|Current user certificates||certmgr.msc|
|Certificate authority||certsrv.msc 1|
|Certificate templates||certtmpl.msc 1|
|Group policy object editor||dcpol.msc 1|
|Distributed file system||dfsgui.msc 1|
|Active directory domains and trust||domain.msc 1|
|Default domain security settings||dompol.msc 1|
|Active directory users and computers||dsa.msc 1|
|Active directory sites and services||dssite.msc 1|
|File server||filesvr.msc 1|
|Group policy object editor||gpedit.msc|
|Internet authentication service||ias.msc 1|
|Local users and groups||lusrmgr.msc|
|Removable storage operator requests||ntmsoprq.msc|
|Routing and remote access||rrasmgmt.msc 1|
|Resultant set of policy||rsop.msc|
|Local security settings||secpol.msc|
|Terminal services configuration and connections||tscc.msc 1|
|Remote desktops||tsmmc.msc 1|
|Windows management infrastructure||wmimgmt.msc|
1 Uses the Windows Server 2003 family of operating systems
When a window or logon session is open as the administrator, the default network credentials are not that of the domain account that is normally used to log on. Because most networks expose critical resources such as file shares only to domain accounts, it is necessary to establish alternative network credentials.
There are two ways to do this. You can open a new command window and then set up alternative default credentials for use over the network. Another option is to allow individual servers or shares to be accessed with another username and password.
When you are running a command prompt, it can be helpful to change your environment to clearly indicate that this is a window with administrative privileges. Many people use one of the following methods:
- Set the prompt at which commands are entered to be unique, such as
PROMPT ADMIN $P$G
- Set the prompt to have a different color, such as a bright red background with black text, by using the command
- Set the title bar to unique text by using a command such as
title Admin Window
Opening a new command window with alternative network credentials
- To open the window, use runas /user:administrator "runas /netonly /user:DOMAIN\username cmd.exe"
- In the first command window that appears, enter the administrator password when prompted.
- In the second command window that appears, enter the password for the alternate username whose credentials are to be used when accessing resources over the network.
Opening a new command window for accessing individual server shares
- Open a new command widow with the runas /user:administrator cmd.exe command.
- For each network server that requires an alternate set of credentials, use the net use /user:DOMAIN\username \\server command in that shell window.
Other forms of the net use command allow you to either map a network drive to a persistent letter or provide the domain credentials for authenticating access requests coming from this machine. The following table lists some net use commands. After you have completed these commands, applications can be installed from the remote shares, as they would normally have been.
|net use command||Action|
|net use||List connections|
|net use * /persistent:no /user:DOMAIN\username \\server\share||Open a connection mapped to a local drive letter with alternate credentials, but do not reconnect to the drive on the next logon|
|net use /user:DOMAIN\username \\server\share||Connect to network share with alternate user credentials|
Installing software when you do not have administrative privileges can be complicated. For example, inserting an installation disc launches setup as the user who is currently logged in, who probably does not have permissions to install the application. To avoid this, you can:
- Run the setup program (usually Setup.msi) using the RunAs command.
— or —
- Use the runas /user:administrator "control appwiz.cpl" command.
This creates an instance of the Add/Remove programs application running as the Administrator user. Choose to install for all users of this machine if the application offers the option, or the Administrator user might be the only person able to run it when the installation completes.
Many Web sites — especially those on corporate intranets — often require administrative access to install their ActiveX controls, and do not support restricted user installation. The easiest way to launch Internet Explorer as Administrator is to do the following:
- Right-click the icon.
The icon can be in the Quick Launch bar, on the Desktop, or on the Start Menu.
- Choose Run As from the Properties list, and run it as Administrator.
The Windows Installer package
If it is a Windows Installer package (.MSI file), then the MSIEXEC.exe application is helpful to install or uninstall applications.
- To install, run msiexec /I msifile.msi.
Note This is exactly what Windows does when you double-click an .MSI file.
- To uninstall, run msiexec /x msifile.msi.
Note Arguments to the msiexec.exe program are located in ms-help://MS.VSCC/MS.MSDNVS/msi/app_73eb.htm.
Running programs that assume administrative access
Unfortunately, many programs are not Windows Logo compliant, and many of those programs that are compliant seem to be less so than others. The Windows Logo program states that an application needs to function reasonably under a less-privileged account, whenever possible. Occasionally, a program requires write access for user accounts to its Program Files installation directory or even a key in HKLM\Software. If you can easily determine the directory, files, or registry keys access to which access is required, you can edit them to help the program run. The following procedures explain how to do this.
Editing registry permissions
- Open regedit as Administrator by typing runas /user:Administrator regedit.
- Right-click the registry key you want to edit.
- Choose Permissions.
- Either add the appropriate user to the set of those users who are allowed Full Control or give them a custom set of access privileges on that key.
Editing file system permissions
For files or directories, the cacls.exe program is useful for resetting permissions from the command line. Help for using Cacls.exe usage is available by two different methods:
- on the command line, by passing the /? flag
- in Windows Help
Example: running the cacls.exe program to add permissions for a user to a directory
Run cacls.exe with the flags to recursively add a grant of the write privilege
runas /user:Administrator "cacls.exe directory /t /e /g domain\username:w"
- On Windows Server 2003, fully qualify the directory parameter with a trailing slash.
- On Windows XP Professional, you might need to omit the final quotation mark due to differences in the cacls.exe program between versions of the operating system. Check the output from the runas.exe command, and if it contains an extra quote (as called out below), remove the terminating one from the command line above.
Attempting to start cacls.exe c:\foo\ /t /e /g domain\username:w" as user "MACHINE\Administrator" ...
As a last resort, you can use runas.exe to launch the program as the local Administrator user; however, do so with care — after all, if the program is not well-behaved enough to degrade gracefully in a less-privileged environment, how much should it be trusted to behave safely in a highly-privileged environment? Unfortunately, many programs were not tested to be run as a user other than the one who installed it, much less in a less-privileged account; you might find that you need to run the program as the local Administrator in order to get work done. This is still a better environment than running all software and logging in as a member of the local Administrators group, but you should try to contact the company who developed the software about their bug so that they can fix it in their next release. The only way end users will ever be able to run in a safer login environment and still be as productive as they are today is for every developer to fix their software.
Visual Studio .NET is Windows Logo compliant, so you would expect that it runs as a restricted user. However, even though the vast majority of all functionality works in constrained permissions, there are a few tasks that are slightly more difficult in this model, either because of operating system limitations or the fundamental nature of the tasks being performed. The following sections provide simple workarounds for all of the difficult tasks in a development process; in future versions of the integrated development environment (IDE) we hope to build this functionality directly into the shell and reduce the requirements wherever possible. We are working hard in future versions of both the operating system and development tools to make it easier to perform these actions in equivalent ways that do not require administrative privileges.
Doing post-build steps (registration)
In classic Visual C++, it is regsvr32.exe. In the Visual Basic .NET and the Visual C# .NET world, it is registering assemblies for interop. Whatever the project system forcing it, there are many tools that require write access to HKLM\Software\Classes in order to register COM components and type libraries. If your application is currently performing registration steps that require write access to secured portions of the registry, you should first determine if you really need to do be doing them. Remember that:
- HKCU\Software\Classes is writeable by any user, and shows up in HKCR just as well as HKLM\Software\Classes does, although only for your user.
Note Details on the composition of HKEY_CLASSES_ROOT are found at ms-help://MS.VSCC/MS.MSDNVS/sysinfo/regapi_0htl.htm
- You should not be relying on regsvr32.exe as your method of end-user installation for classic COM components. Changing your application registration to be per-user is acceptable, because the DllRegisterServer method should be used only for debugging and private development purposes. When deploying applications to end users, you are required to author all of your registry requirements into Windows Installer .MSI file tables so that it can handle issues such as multiple programs writing the same registry keys and being installed or uninstalled in various orders.
Unfortunately, many of the tools and operating system APIs allow registration only to HKLM\Software\Classes; type library registration is a prime example of this. In these cases, the most feasible options are either to use runas /user:administrator cmd.exe, change directory to the output directory, and then run the registration steps by hand, or to eliminate the dependency altogether. Unfortunately, elimination of the dependency on global registration is complicated enough to be worthy of its own article. An alternative is to create custom manifest files to circumvent the registration steps altogether, but that too is beyond the scope of this article and more information is available at ms-help://MS.VSCC/MS.MSDNVS/sbscs/sidebysideref_03ol.htm. The most uncomplicated way to work around the global registration limitations is to perform registration steps with your administrative account.
The following table shows common post-build registration tasks and their registration. Do them the first time and you should be able to build and run as normal afterward. Remember, though, that you might need to re-do the registration step any time you switch between Debug and Release configurations, and when you make changes to your application that impact the items being registered.
|Post-Build Registration Type||Registration Action|
|COM Executable registration||output.exe /RegServer|
|COM DLL registration||regsvr32 output.dll|
|.NET assembly registration for COM interoperability||regasm output.dll|
|Installation of a .NET assembly into the Global Assembly Cache||gacutil /if output.dll|
|.NET Services installation registration||regsvcs output.dll|
Debugging normal applications
When you log on as a non-administrator, there is one feature you will lose: Windows does not allow debugging of native applications that are running as a different user unless you have the special user right allowing it (SeDebugPrivilege), and the .NET Framework does not allow debugging other users' applications unless you are in the local Administrators group. You will still be able to debug native and managed applications that you have launched from the development environment or which are already running as your non-administrative user. If you need to debug services or other programs that run in other security contexts, you will need to either grant yourself that OS privilege for native applications, add your account to the local Administrators group, or use RunAs to launch Visual Studio .NET as the local Administrator user. That said, there are many methods to launch your application as your own user, both enabling debugging and helping ensure that your application correctly runs in a privilege-constrained environment.
Native and managed apps
Wherever possible, simply launch the application as your non-administrative user and everything will work. By default, Start from the Debug menu on normal executables works, as does attaching (Attach to Process from the Debug menu) to any of the applications you have launched yourself on that machine. You must be a member of the Debugger Users group in order to attach to any process with the default Visual Studio .NET mechanisms. Membership in this group does not give you access to debug other users' programs, but simply allows you to use the service that attaches the debugger to the process being debugged.
Remote machines (native/managed)
There are two acceptable ways to do remote debugging: through the Machine Debug Manager service or msvcmon.exe. The machine debug manager is a service that recognizes your network credentials, understands who you are, checks to see if you are a member of the target machine's Debugger Users group, and then allows you to connect to your own applications if you are. The Machine Debug Manager is also the only way to debug remote managed applications, including Web applications. You will not be able to connect to other users' applications on remote machines simply by being in the Debugger Users group. For native programs running on a remote machine, you would need the SeDebugPrivilege user right on the target machine as well. For managed applications on a remote machine, you are required to be a member of the Administrators group.
As an alternative method for debugging native applications, the msvcmon.exe program allows a way to connect over TCP/IP to managed applications on a remote machine. In this scenario, login credentials from the debugging machine are not replicated on the remote machine. For example, if msvcmon.exe is launched on the remote machine as that machine's local Administrator, but with the "-anyuser" flag, then anyone can connect to the service and attach to and debug any native application on that machine, even if they didn't originally have rights to do so.
Creating Web applications
There are two options for creating new Web applications. The first is to add the user account to which you are logged to the VS Developers groups, allowing that account to write anywhere in the IIS WebRoot. The alternative is to create the directory as that user and then add a Virtual Root. In either case, after you have completed one of those options, you can create the new application from the Visual Studio .NET Create New Project dialog as the restricted user.
To add an IIS Virtual Root
- Run the Management Console compmgmt.msc as an administrative user.
- Expand the Services and Applications node to display the Internet Information Services, and Web Sites nodes.
- Right-click the Default Web Site node, choose New, and then choose Virtual Directory.
- Click Next, enter the name for the virtual root, and click Next again.
- Enter the directory name to expose and click Next.
- Leave the default access permissions, and click Next.
- Click Finish to establish the Virtual Root.
Debugging Web Applications
There are two conditions for debugging of Web applications: running ASP.NET as your restricted login account and directory permissions. For the set of directories you will need to add read or write access to, refer to the following table.
|Directory||Permissions needed in the directory and all of its children|
|%WINDIR%\Temp||Read and Write|
|%INSTALLROOT%\ASP.NET Temporary Files||Read and Write|
Note %INSTALLROOT% is of the form D:\WINDOWS\Microsoft.NET\Framework\v1.0.3705 and %WINDIR% is of the form D:\WINDOWS.
By default, with a restricted user login, you cannot debug Web applications because the user running the debugger is not a member of the proper group to debug other users' programs (Administrators), and the Web server started ASP.NET as the NETWORK_SERVICE account.
If you do not want to grant this login membership in the local Administrators group or run the debugger as the local Administrator, you need to change the account that ASP.NET is running as. On Windows XP Professional, edit machine.config as shown below and put in your username and password in clear text. This has the potential disadvantage of requiring all ASP.NET applications on the machine to run as your user account, but is the best method for IIS 5, and allows you to debug and build Web apps the same way you did in the past.
Security Note The machine.config file must be on an NTFS drive and have a restrictive ACL set if you do this, or anyone who logs on to the machine will be able to see your password. Even if you do, all users in the Administrators group will be able to read it, regardless of the ACL set.
Enabling ASP.NET to run as another user on Windows XP Professional
As an Administrator, edit the attributes of the file"%INSTALLROOT%\Config\machine.config" 'on the processModel tag, as shown:
<processModel enable="true" userName="DOMAIN\username" password="MyPswd2" ... / >
Note %INSTALLROOT% is of the form D:\WINDOWS\Microsoft.NET\Framework\v1.0.3705
Enabling ASP.NET to run as another user on Windows Server 2003
With Windows Server 2003 and IIS 6, there is a new feature named application pools. Each pool can be configured to run as a different user, provided that user has membership in the IIS_WPG group. Virtual roots can be added to an application pool, and the debugger will then be able to attach to it if the pool is running as the same user that launched the debugger. This mechanism provides an easy way to set up an alternate execution environment, safely protect user credentials, and set up additional virtual roots.
Adding and Configuring an Application Pool
- Run the Management Console compmgmt.msc as an administrative user.
- Expand the Services and Applications node to display the Internet Information Services, and Application Pools nodes.
- Right-click the Application Pools node, choose New, and then choose Application Pool.
- Type the name for the Application Pool and click OK.
- Right-click on the new Application Pool and choose Properties.
- Under the Identity tab, choose the Configurable option.
- In the corresponding boxes, enter the User name and Password that you will be running the debugger with and click OK.
Note This account must be a member of the IIS_WPG group and have the access permissions listed above in order to run ASP.NET applications.
Setting a Virtual Root to run in an Application Pool
- Run the Management Console compmgmt.msc as an administrative user
- Expand the Services and Applications node to display the Internet Information Services, Web Sites, and Default Web Site nodes.
- Expand the Default Web Sites node to display all of the virtual roots available.
- Right-click on the virtual root to configure and choose Properties.
- On the Virtual Directory tab, change the Application Pool drop-down to select the application pool running with the appropriate user identity and click OK.
Installing deployment project output
Installing the output from a deployment project has the same restrictions as installing an application from the network, as previously mentioned with the RunAs.exe and MSIEXEC tools. Install it as a normal application, for all users, or it might be difficult to launch or to debug.
The cost of developing secure applications and having a secure environment in which to work is a little bit of inconvenience when you need to perform a task that requires a higher level of privilege. However, the rewards are both a safer work environment and safer programs. There is no excuse not to do it.
Remember that the lower the set of privileges your application requires when it runs, the less damage it can do when it is compromised. It is a simple fact that your application will ship with at least one security vulnerability — it is up to you how much it should ruin your users' machines and your company's image if someone else finds it and exploits it.