Service Best Practices

Service Best Practices

Analogous to UNIX daemons, services are the backbone of Microsoft Windows NT and beyond. They provide critical functionality to the operating system and the user without the need for user interaction. Issues you should be aware of if you create a service are described next.

Security, Services, and the Interactive Desktop

Services in Microsoft Windows are generally console applications designed to run unattended with no user interface. However, in some instances, the service may require interaction with the user. Services running in an elevated security context, such as SYSTEM, should not place windows directly on the desktop. A service that presents users with dialog boxes is known as an interactive service. In the user interface in Windows, the desktop is the security boundary; any application running on the interactive desktop can interact with any window on the interactive desktop, even if that window is invisible. This is true regardless of the security context of the application that creates the window and the security context of the application. The Windows message system does not allow an application to determine the source of a window message.

Because of these design features, any service that opens a window on the interactive desktop is exposing itself to applications executed by the logged-on user. If the service attempts to use window messages to control its functionality, the logged-on user can disrupt functionality by using malicious messages.

Services that run as SYSTEM and access the interactive desktop via calls to OpenWindowStation and GetThreadDesktop are also strongly discouraged.

NOTE
A future version of Windows might remove support for interactive services completely.

We recommend that the service writer use a client/server technology (such as RPC, sockets, named pipes or COM) to interact with the logged-on user from a service and use MessageBox with MB_SERVICE_NOTIFICATION for simple status displays. However, these methods can also expose your service interfaces over the network. If you don't intend to make these interfaces available over the network, make sure they are ACL'd appropriately, or if you choose to use sockets, bind to the loopback address (127.0.0.1).

Be wary if your service code has these properties:

  • Runs as any high-level user, including LocalSystem, AND

  • The service is marked in the Security Configuration Manager (Log on As\Allow Service to interact with desktop), or registry key HKLM\CCS\Services\MyService\Type & 0x0100 == 0x0100, OR

  • CreateService, and dwServiceType & SERVICE_INTERACTIVE_ PROCESS= SERVICE_INTERACTIVE_PROCESS, OR

  • The code calls MessageBox where uType & (MB_DEFAULT_DESKTOP_ ONLY MB_SERVICE_NOTIFICATION MB_SERVICE_NOTIFICATION_ NT3X) != 0, OR

  • Calls to OpenWindowStation("winsta0",...), SetProcessWindowStation, OpenDesktop("Default", ) and finally, SetThreatDesktop and create UI on that desktop, OR

  • You call LoadLibrary and GetProcAddress on the above functions.

CreateProcess is also dangerous when creating a new process in SYSTEM context, and the STARTUPINFO.lpDesktop field specifies the interactive user desktop ("Winsta0\Default"). If a new process is required in elevated context, the secure way to do this is to obtain a handle to the interactive user's token and use CreateProcessAsUser.

Service Account Guidelines

Services can be configured to run using many different types of accounts, and determining which type of account to use often requires some thought. Let's review the various types of accounts and take a look at the security implications.

LocalSystem

LocalSystem is the most powerful account possible. It has many sensitive privileges available by default. If you're targeting Windows 2000 and later and are part of a Windows 2000 (or later) domain, this account can also access resources across the network. It has the benefit that it will change its own password. Many services that run as LocalSystem don't really require this high level of access, especially if the target platform is Windows 2000 and later. Several of the API calls that previously needed high levels of access (e.g., LogonUser) no longer require these rights under Windows XP and later. If you think your service requires operating as LocalSystem, review your reasoning you may find that it is no longer required. The security implications of running as LocalSystem ought to be obvious: any flaw in your code will lead to complete compromise of the entire system. If you absolutely must run as LocalSystem, review your application design and implementation extremely carefully.

Network Service

Network Service is a new account introduced in Windows XP. This account doesn't have many privileges or high-level access but appears to resources across the network the same as the computer or LocalSystem account. Like LocalSystem, it has the benefit of changing its own password (because it is basically a stripped-down version of the LocalSystem account). One drawback to using this account is the fact that several services use this account. If your service gets breached, other services might also be breached.

LocalService

LocalService is much the same as Network Service, but this account has no access to network resources. Other than this, it shares all the same benefits and drawbacks as Network Service. Both of these accounts should be considered if your service previously ran as LocalSystem.

Domain Accounts

Using a domain account to run a service can lead to very serious problems, especially if the account has high levels of access to either the local computer, or worse yet, the domain. Services running under domain user accounts create some of the worst security problems I've encountered.

Here's a story. When I (David) first started working at Internet Security Systems, I bet my coworkers lunch that they couldn't hack my system. At the time, they were all a bunch of UNIX people and I had the lone Windows NT system on our network. I figured that if they managed to hack my system, the price of lunch would be worth the lessons I'd learn. Over a year went by and due to careful administration of my system, no one had hacked me not a small feat in a group of very sharp security programmers. One day I was scanning the network and found all the systems running a backup service under an account that had Domain Administrator credentials. I immediately went and chewed out our network administrator, who claimed that the boss required him to make the network insecure to get backups running. I told him it wouldn't be long until the domain was being run by everyone on the network, and he didn't believe me. The very next day, one of the people I liked least came and notified me that my system had been hacked! Just a few minutes of inspection revealed that the backup account had been used to compromise my system.

The problem with using a domain account to run a service is that anyone who either is or can become an administrator on a system where the service is installed can retrieve the password using the Lsadump2 utility by Todd Sabin of BindView. The first question people ask is whether this isn't a security hole. In reality, it isn't anyone who can obtain administrator-level access could also reconfigure the service to run a different binary, or they could even inject a thread into the running service and get it to perform tasks under the context of the service's user. In fact, this is how Lsadump2 operates it injects a thread into the lsass process. You should be aware of this fact when considering which account type to use. If your service gets rolled out in an enterprise, and the administrator uses the same account on all the systems, you can quickly get into a situation where you're unlikely to be able to secure all the systems at once. A compromise of any one system will result in a password reset on all the systems. Discourage your users from using the same account on all instances of your service, and if your service is meant to run on highly trusted systems like domain controllers, a different account should be used. This is especially true if your service requires high levels of access and runs as a member of the administrators group. If your service must run under a domain user account, try to ensure that it can run as an unprivileged user locally. If you provide enterprise management tools for your service, try to allow administrators to easily manage your service if there is a different user for each instance of the service. Remember that the password will need to be reset regularly.

Local Accounts

A local account is often a good choice. Even if the account has local administrator access, an attacker needs administrator-level access to obtain the credentials, and assuming that you've generated unique passwords for each system at installation time, the password won't be useful elsewhere. An even better choice is a local user account without a high level of access. If you can run your service as a low-level local user, then if your service gets compromised, you're not going to compromise other services on the same system and there's a much lower chance of leading to the compromise of the system. The biggest reasons you might not be able to run this way is if you require access to network resources or require high-level privileges. If you do run as a local user account, consider making provisions to change your own password. If the domain administrator pushes down a policy that nonexpiring passwords are not allowed, you'd prefer that your service keep running.

As you can see, there are several trade-offs with each choice. Consider your choices carefully, and try to run your service with the least privilege possible.



Writing Secure Code
Writing Secure Code, Second Edition
ISBN: 0735617228
EAN: 2147483647
Year: 2001
Pages: 286

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net