Today’s post is a bit boring.
I’ve got a bunch of security-related articles that I’d like to write up, but I’ve realized that doing this requires that I define some terms up front to give a common framework for the articles. I’ll be using this post as a reference for these posts in the future.
So please bear with me while I define some commonly used terms that show up a lot in discussions about security.
First off, there’s “authentication”. This is the process of knowing that the guy at the other end of the pipe (or keyboard) is really who she says she is. Authentication is hard. REALLY hard. So hard that any company that thinks it can design its own authentication scheme might as well be putting out a sign saying “Hack Me!” There are lots of examples of this, Google for NTLMv1 vulnerability sometime for some horror stories about when Microsoft tried it. Or, my personal favorite: Dark Age of Camelot, a MMRPG put out by Mythic. As this post to Bugtraq points out, they made some slight errors in their authentication protocol (like sending the encryption key from the server to the client, then transmitting all the customer’s billing information to the client (including credit card number and expiration date) J.
When you authenticate a user, you establish the user’s “security principal”. A “security principal” isn’t the head of the security school; instead a security principal uses the 2nd definition of principal: “A main participant in a situation”. In NT, a principal is identified by their SID, or Security IDentifier. A security principal doesn’t have to be a user; it can also be a group (a collection of users). Again, because groups are principals, they have SIDs.
When you authenticate a user, one of the byproducts of that authentication (in NT) is the “token” of the user. The token of the user contains the user’s SID, and the SID for all the security groups of which the user is a member (there are other types of groups that don’t participate in security like Distribution Groups).
The next thing to consider is “authorization”. This is the process of knowing if the principal you just authenticated has the rights to access a particular piece of data. People often confuse authentication and authorization, but it’s important to keep them straight. In NT, the principal mechanism used for authorization is the AccessCheck API.
When you’re doing an access check, all the SIDs in the user’s token are considered during the access check. If a principal in the token (a SID in the token) is present, then the principal is considered to be “active” in the user’s token. It is also possible to create a “restricted” token from an existing token. When you create the restricted token, you can specify principals in the token to be disabled. When principals are disabled in a token, they are only considered for deny access in an access check.
In order to perform authorization, it is often useful to “impersonate” the client. To impersonate a client, the server’s process takes on the identity of the client. This is done via the ImpersonateLoggedOnUser (or the RpcImpersonateClient or the CoImpersonateClient) API. More on impersonation later in this post.
Ok, those are the biggies, now for some more terms.
First off, there’s “Quality of Service”, or QoS. When you’re dealing with networking, QoS typically means a guaranteed throughput, which is useful for multimedia. When you’re talking about security, QoS means the quality of the security information sent from the client to the server. RPC exposes this as the RPC_SECURITY_QOS structure. For COM, the CoInitializeSecurity API can be used to set these fields.
In the RPC structure, there are basically 3 fields of interest. The first sets up the capabilities of the connection. This determines which authentication package should be used, and whether or not the connection should be encrypted.
The second defines the impersonation level – this controls the level of the authentication.
The third indicates whether the security is dynamic or static.
Let me take all these in turn.
First the capabilities of the connection. This determines if the connection will be authenticated with a security package that supports mutual authentication (so the client can trust the server or not), etc.
Next, the impersonation level – the impersonation level determines what can be done once the server’s authenticated the user.
There are four levels of impersonation:
1) Anonymous – there’s no authentication of the user at all. If you use Anonymous QoS to identify the user, the server authenticates the client, but the RPC server can’t use that information. This is usually counter-intuitive, so it’s not recommended. If you want to see what the Anonymous user can access, then you can use ImpersonateAnonymousToken to impersonate the anonymous user, and then do your access checks.
2) Identify – The server validates the user. The server can call AccessCheck to verify the user’s access to resource, but it cannot access resources outside the process space (like files, registry keys, shared memory regions, etc).
3) Impersonate – The server has validated the user. In addition, the server can act on the user’s behalf to access local resources. For many security providers, there is no difference between Identify and Impersonate.
4) Delegate – The server has validated the user. In addition, the server can act on the user’s behalf to access both local AND remote resources.
And finally, there’s static or dynamic QoS. Static QoS indicates that the security token of the user is fixed at the time of connection. Dynamic QoS indicates that changes to the token on the client will be reflected in the client’s token on the server. Similarly, if the client application is impersonating a user on the client machine, then that impersonation will be reflected on the server. If the client then reverts to his own identity, the token that server is using will also revert to the client’s original identity.
Thanks go to Richard Ward for his review.