Sunday, January 20, 2008

Namedpipe Impersonation Attack

Privilege escalation through namedpipe impersonation attack was a real issue back in 2000 when a flaw in the service control manager allowed any user logged onto a machine to steal the identify of SYSTEM. We haven't heard a lot about this topic since then, is it still an issue?

First of all, let's talk about the problem.

When a process creates a namedpipe server, and a client connects to it, the server can impersonate the client. This is not really a problem, and is really useful when dealing with IPC. The problem arises when the client has more rights than the server. This scenario would create a privilege escalation. It turns out that it was pretty easy to accomplish.
For example, let's assume that we have 3 processes: server.exe, client.exe and attacker.exe. Server.exe and client.exe have more privileges than attacker.exe. Client.exe communicates with server.exe using a namedpipe. If attacker.exe manages to create the pipe server before server.exe does, then, as soon as client.exe connects to the pipe, attacker.exe can impersonate it and the game is over.

Fortunately, Microsoft implemented and recently documented some restrictions and tools to help you manage the risk.

First of all there are some flags buried in the CreateFile documentation to give control to the pipe client over what level of impersonation a server can perform. They are called the "Security Quality Of Service".

There are 4 flags to define the impersonation level allowed.

The server process cannot obtain identification information about the client, and it cannot impersonate the client.

The server process can obtain information about the client, such as security identifiers and privileges, but it cannot impersonate the client. ImpersonateNamedpipeClient will succeed, but no resources can be acquired while impersonating the client. The token can be opened and the information it contains can be read.

SECURITY_IMPERSONATION - This is the default
The server process can impersonate the client's security context on its local system. The server cannot impersonate the client on remote systems.

The server process can impersonate the client's security context on remote systems.

There are also 2 other flags:

Specifies that any changes a client makes to its security context is reflected in a server that is impersonating it. If this option isn't specified, the server adopts the context of the client at the time of the impersonation and doesn't receive any changes. This option is honored only when the client and server process are on the same system.

Prevents a server from enabling or disabling a client's privilege or group while the server is impersonating.

Note: Since the MSDN documentation for these flags is really weak, I used the definition that can be found in the book "Microsoft® Windows® Internals, Fourth Edition" by Mark Russinovich and David Solomon.

Every time you create a pipe in client mode, you need to find out what the server needs to know about you and pass the right flags to CreateFile. And if you do, don't forget to also pass SECURITY_SQOS_PRESENT, otherwise the other flags will be ignored.

Unfortunately, you don't have access to the source code of all the software running on your machine. I bet there are dozen of software running on my machine right now opening pipes without using the SQOS flags. To "fix" that, Microsoft implemented some restrictions about who a server can impersonate in order to minimize the chances of being exploited.

A server can impersonate a client only if one of the following is true.
  1. The caller has the SeImpersonatePrivilege privilege.

  2. The requested impersonation level is SecurityIdentification or SecurityAnonymous.

  3. The identity of the client is the same as the server.

  4. The token of the client was created using LogonUser from inside the same logon session as the server.

Only Administrators/System/SERVICES have the SeImpersonatePrivilege privilege. If the attacker is a member of these groups, you have much bigger problems.

The requested impersonation level in our case is SecurityImpersonation, so the second point does not apply.

That leaves us with the last two conditions. Should we worry about them? I think so. Here are some examples:

I'm on XP. I want to run an untrusted application. Since I read my old posts, I know that I can run the process using a stripped down version of my token. Unfortunately, my restricted token has the same identity as the normal token. It can then try to exploit all applications running on my desktop. This is bad.

My main account is not administrator on the machine. When I want to install software, I use RunAs. This brings up a new problem. RunAs uses LogonUser, and it is called from the same logon session! That means that my untrusted application using a restricted token derived from a standard user token can now try to exploit and impersonate a process running with administrator rights! This is worse.

But how real is all this?

This is hard to say. I don't have an idea about the percentage of applications using the SQOS flags. We must not forget that allowing impersonation is also required and desired in certain cases.

For fun I took the first application using namedpipes that came to my mind: Windbg. There is an option in Windbg to do kernel debugging and if the OS you are debugging is inside vmware, you can specify the namedpipe corresponding the COM1 port of the vmware image. By default it is "com_1". My untrusted application running with the restricted token was now listening on com_1, and, easy enough, as soon as I started windbg, the untrusted application was able to steal its token.

To be fair I have to say that vmware displayed an error message telling me that the com_1 port was "not configured as expected". I should not have started windbg knowing that. But, eh, who reads error messages? :)

What should we do now?

Well, it turns out that Microsoft implemented two new restrictions in windows Vista to fix these problems. I don't think they are documented yet.

  1. If the token of a server is restricted, it can impersonate only clients also running with a restricted token.

  2. The server cannot impersonate a client running at a higher integrity level.

These new restrictions are fixing both my issues. First of all my untrusted application can't be running with a restricted token anymore. Then, even if the untrusted application is running with my standard token, it won't be able to impersonate the processes that I start with the "Run As Administrator" elevation prompt because they are running with a High Integrity Level.

Now it is time to come back to the main question: Is it still an issue?

My answer is yes. Windows XP is still the most popular Windows version out there and there is no sign that Vista is going to catch up soon. But I have to admit that I'm relieved to see the light at the end of the tunnel!


Some technical details:
When you call ImpersonateNamedPipeClient and none of the conditions is met, the function still succeeds, but the impersonation level of the token is SecurityIdentification.

If you want to try for yourself, you can find the code to create a server pipe and a client pipe on my code page.

Related link:
Impersonation isn't dangerous by David Leblanc


Iron Guts Morla said...

Here is a fun puzzle:

This client sequence:

1- h = ::CreateFile(..,no_qos,);
2- ::ImpersonateAnonymousToken();
3- SendReceiveStuff(h)
4- ::RevertToSelf()

Is it better, same or worse?

nsylvain said...

This is better.

ImpersonateNamedPipeClient takes the thread token of the client.

The token has the impersonation level "SecurityImpersonation", but the token identify is "Anonymous", so you can't do much with it.

Nima said...

Nice blog! I just added your url to my blogroll :)

Nima said...

Oops I forgot to leave my blog address in case you would like to check it out :)

mat and die said...

Thank you, really useful article.