Freigeben über


Impersonation isn't dangerous

I was called to task because in Writing Secure Code for Windows Vista, I asserted that from the standpoint of a service, the impersonation privilege isn't dangerous. SeImpersonate is one of the newer privileges in Windows, and has only been put there since Windows 2003 (and is in XP SP2). Basically, the attack it is trying to prevent is one where you can get a higher-level process to connect to some resource you have, impersonate them, and escalate privilege. This can happen in a number of ways:

  1. The higher-level process might be tricked into opening some arbitrary file, and while unlike UNIX, not everything is a file, a fair number of things can be opened with CreateFile - for example, \\.\pipe\mypipe is a fairly sure attack. In Office, we have a whole lot of APIs wrapped to do the right thing, so CreateFile becomes MsoCreateFile, which correctly sets the security quality of service bits to prevent impersonation.
  2. COM sources and sinks can be a nasty security hole - in this scenario, the server becomes a client when it executes the callback. If the server is running as local system and hasn't set the security settings correctly, then the client becomes localsystem, and away we go. Since COM is really only a wrapper over RPC for the most part, the same issues also apply to RPC.
  3. It's now possible to impersonate socket clients, so the same sort of things apply.

So it's starting to sound as if impersonation was enemy #2 (just behind buffer overruns) - why would I say it's benign? Here's the deal - by default, local system, local service, and network service are allowed to impersonate callers. To get to be running as any of these user accounts, you've got to have a service installed by an admin (or a hideously misconfigured service ACL), and if you're being attacked by the admin, just give up - it's game over. The second way you get to be one of these services, is by finding some sort of ghastly flaw in the service, taking it over, and causing it to do your bidding. Sounds like a plausible attack, so let's think about how that might work. If you've manged to own up a local system service, game over, and you win. Next, work on taking over the rest of the network (which you of course have permission from the owner to conduct pen testing on, or you risk serious consequences, like a new, unfriendly roommate in a very bad, long-stay facility). So let's say you've managed to take over a service running as the local service account - surely you can trick something running as local system to connect to you, and do rotten things. If you can, then there's a flaw in the local system service - the local system service should NEVER assume that any less privileged process is doing anything other than running malicious code. Whether the service running as local service has SeImpersonate or not, if the higher level process trusts them, they're making a mistake.

But what if an unwary admin connects to a service? Sorry - same rules apply. If you're running as admin, you're equivalent to local system (since you can install new drivers and services). If you put trust in anything running with less privileges that's on the system, it's your mistake - or the person writing the software has made a mistake.

The point here is that the service that has SeImpersonate isn't what is at risk here. The users connecting to the service are at risk, if they allow themselves to be fully impersonated.

Now let's look at the flip side - if a service ought to be impersonating, and is not, then we have an opportunity for what's called a luring attack. In a luring attack, one user tricks another into doing something on their behalf that ought not happen. Impersonation prevents luring attacks, because the action is being performed as the calling user. If you're doing something on behalf of another user, _not_ impersonating is very likely to be a problem. We can't say that impersonation is really just scary and ought not be used - then we'd have luring attacks all over the place.

Impersonation is a complex issue, and using it really correctly is something that ought to be covered much more thoroughly than what we did in either WSC2 or WSCV. Here's the bottom line:

  • If you're writing a high level service, or a tool typically used by admins, understand how impersonation could be mis-used to attack your user or app. Take proper measures to only allow identification.
  • If you're writing a lower level service (in terms of privilege - I don't mean drivers), you're probably doing something on behalf of other users. If you are, you may need to maintain an audit trail, and you do want to avoid luring attacks. If so, impersonation is probably a good idea.
  • If you decide your service doesn't need to impersonate anything, drop the privilege. Using least privilege never hurt anything. Even if it is just a speed-bump, and an attacker with full knowledge of everything on the system could hop over to some other process, and gain the privilege, the more complex the attack, the less likely it is to work. And sometimes the attacker doesn't know everything and will trip the alarm system.
  • If you do use impersonation, remember that you need to maintain correct seperation between the various users. Even hopping from one user to another can be an EoP in effect - you and your boss are probably both plain users with respect to the domain controller, but if you can run code as your boss, all sorts of interesting possibilities spring to mind (including getting sacked when caught). The thing to think about here is something called "least common mechanism" - one of the Saltzer and Schroeder design principles, which basically says that the fewer resources two users have to share, the less chances for one to usurp the privileges of the other.

The whole topic is fairly complicated, so I might spend some time on it in the future. Another wrinkle worth a future post is how you manage when you can't impersonate, but you can identify the caller. There's a bunch of relatively new functionality that makes this problem a lot easier.

Comments

  • Anonymous
    March 25, 2007
    Impersonation could be dangerous enough. http://www.gentlesecurity.com/adv04302006.html By default Windows has at least one service (RPC) run as 'Netwrok Service' that accepts and impersonate LocalSystem clients. That means any other service that run as 'Netwrok Service' can easily elevate up to LocalSystem. And if such service (any that run as Network Service) is hacked, then an attacker gets LocalSystem. As a result Network Service is neraly the same as LocalSystem, due to:
  1. impersonation
  2. unreasonable defaults, configuration where RPC service would run as LocalSystem is more secure in fact. That is impersonation paradox. No need admin connection, you have LocalSystem already who connects and impersonated. Network Service is just a most obvious case. There are other conditions when impersonation is dangerous. Impersonation poses a sufficient risk, and the risk must be clearly understood/communicated  not mitigated.
  • Anonymous
    March 26, 2007
    As I was saying, the flaw would be in the local system service for allowing a less privileged server to impersonate it. The ideal way for a service to handle such things would be to first try to impersonate, then drop to identify, and for the higher level service not to allow impersonation. Let's also examine the alternative - if you confine impersonation to local system, then you have all the services that need it running with most privilege, not least. Another note - it's true that having all the services running under the same 3 accounts is a problem. This offers a lot of opportunity for services to work against one another, but there's some cool new stuff in Vista that helps a lot. More on that later, or you can read it in detail in WSCV. I also don't completely agree with the analysis in the URL above, but there's not time this morning to go into detail, except that to say again that if a localsystem service allows itself to be impersonated, it has a problem. SQL 2000 had such a problem, and IIRC, it has been fixed for quite a while.

  • Anonymous
    March 26, 2007
    OK, but what about particular example of rpcss? It is used by many privileged services and still run as Network Service account. Mircosoft actively suggest to use Network Service as a replacement for LocalSystem. Indeed it makes sense as an additional measure, but the value of this measure is misleading at least in official description. There is a note that Network Service is an ordinal unprivileged user account which is true. However, there is no any note that Network Service is used to run critical service such as rpcss. I assume it would be quite difficult to run such service “unprivileged” due to its nature. And for the rpcss it really weakened overall configuration. An alternative to run rpcss as LocalSystem is more secure because of two reasons:

  • Rpcss services many privileged requests and if an attacker managed to break into it then Network Service will not help anyway. So it doesn’t provide claimed attack surface reduction if a target is rpcss.
  • Those who follow using Network Service advice would not be vulnerable to privilege elevation to LocalSystem. Why not to fix this problem for rcpss? Regarding the SQL server, no need to agree.  You may try a demo for this provided by the advisory authors. I can confirm it works on w2k3 R2, SQL2000 SP4. The same issue is present for IIS6 as runs ‘Worker Process’ as Network Service by default.
  • Anonymous
    March 26, 2007
    David, just to clarify the problem is not in SQL/ISS etc. there is nothing to fix there. The problem is that they use Network Service which can be easily elevated up to LocalSystem. The path: Open rpcss process -> Break into impersonation negotiations/get tokens handles/etc. ->token handle of LocalSystem -> impersonate to LocalSyetm rpcss must impersonate LocalSystem and impersonation makes it useless to run as unprivileged account. In this case makes it even worth as there are other services run as this unprivileged account.

  • Anonymous
    March 26, 2007
    You'd prefer that rpcss be running with reduced privileges, even if imperfect - it's listening directly to the network. It is also typically doing enough stuff that trying to have a very controlled exploit that could sit around and wait until a localsystem process connected would likely be unreliable. Something else that I'm honestly not sure about is whether that service is normally doing the impersonation, or hands that off to the processes that actually serve up the RPC endpoint. Reviewing the services as shipped with Vista, it looks like network service is used much less often than local service, and it is used for some fairly sensitive services - for example, if you could compromise the terminal services service, you could swipe credentials without any further ado. That's assuming that the exploit didn't corrupt it to the point it would fail to run properly. Because of this, and the fact network service can authenticate as that system across the network, don't write services to run as that account unless you have a need to do so. Stuff like this always gets fixed in stages - up until XP, we had local system or plain users, with the accompanying password managment issues. People had to do a ton of work to get things to run as network service or local service, and while this isn't perfect, it's a lot better than having everything running as localsystem. It also allows you to get to the next level. In Vista, there's a new thing called a service SID that allows you to ACL resources directly to your service, and keeps other services from being able to access your stuff. Something else - it's not nearly as easy to hop from one service to another in Vista as it was previously - check out the process ACL - the service has a unique logon ID SID, and access is granted to that logon ID and administrators. But what about the service configuration - seems that's locked down, too. So if you could take over rpcss and do so in a way that kept it stable, you could probably eventually EoP. This is still better than the alternative, which is running as full localsystem. But what you can't do, that you could do before is to easily hop from one network service process to another. That's a significant level of hardening. The other thing to check out in Vista is the SID type configuration - this is complicated and took a couple pages to explain, so I'll blog about that soon. Does this get us as far as I'd like? No - even with all the great new stuff, it isn't perfect, only a lot better. I can say we are thinking about ways to improve this in future releases, but obviously can't go into details, especially since it hasn't even been coded yet. Anyway, thanks for the feedback - you've given me some more things to blog about!

  • Anonymous
    March 26, 2007
    AFAIC, the exploit is quite simple and reliable in this case, no hooks or waiting for LocalSystem are required. Rpcss always has a number of LocalSystem token handles with impersonation level = SecurityImpersonation (not just SecurityIdentification). You can check it by ProcessExplorer for example. What is required is enumeration of the handles, selecting those with LocalSystem token handles and duplicating them. Vista indeed fixes the issue by making unique ID as token’s owner. That is good step forward, just waiting when we get it available in server platform. BTW, would Longhorn Server have some additional measures in this area (I mean least privileges) in comparison to Vista? I hope, I have inspired a topic on Vista’s “least privileges” options :-) Thanks, please keep posting!

  • Anonymous
    March 26, 2007
    The comment has been removed

  • Anonymous
    March 28, 2007
    You might want to look at http://www.microsoft.com/whdc/system/vista/Vista_Services.mspx to get an overview of the Service SID support in Vista.

  • Anonymous
    August 21, 2007
    The comment has been removed

  • Anonymous
    September 21, 2007
    I wrote this piece up for our group as we entered the most recent round of threat models. I've cleaned

  • Anonymous
    September 21, 2007
    I wrote this piece up for our group as we entered the most recent round of threat models. I've cleaned