Show Changes Show Changes
Edit Edit
Print Print
Recent Changes Recent Changes
Subscriptions Subscriptions
Lost and Found Lost and Found
Find References Find References
Rename Rename
Search

History

7/27/2004 4:15:47 AM
List all versions List all versions
What Is Co Initialize Security
.

COM provides several process-level security settings, and CoInitializeSecurity is the documented Win32 API for choosing them. Now, in many cases you won't need to call this function because other infrastructure takes care of this housekeeping for you. For example, in a COM+ application, you specify your process-wide security settings via the COM+ catalog, and the COM+ surrogate (DLLHOST.EXE) takes care of wiring up these settings. The same goes with an ASP.NET worker process. On Windows 2000, you can specify your COM security settings via machine.config (see the <processModel> section), and some plumbing in ASP.NET configures COM security on your behalf. But what about a Windows Forms app or a lowly console app?

You might not think that a client app needs to configure COM security settings. It's not like they're serving up COM objects and need an access control infrastructure, right? Well, hold on. If a Windows Forms application makes calls to remote COM servers, it very likely receives callbacks and therefore does indeed act as a server. So it absolutely does need to have COM security settings because a bad guy can use a DCOM call as a way to attack the client application. Even if the app never receives callbacks, it's still important to choose client-side security settings to protect the client and, in some cases, to simply get the client working! And because the .NET Framework doesn't provide any plumbing to automate COM security configuration for client apps, you've got to call CoInitializeSecurity yourself, which can be a bit tricky, as I lay out in HowToConfigureSecurityForACOMClient.

Figure 52.1 AppIDs and the DCOM Config tool

There are a couple of ways of using this CoInitializeSecurity to specify your settings. If your application has registered an AppID for itself (this is a GUID under the registry key HKCR/AppID), you can use the Component Services MMC snap-in, which has a folder called DCOM Config (see Figure 52.1) to configure your settings. This tool shows a list of application names — these strings come from the default string value stored in the registry under the AppID. 1 And the way you tell COM what your AppID is (in other words, where to find your security settings) is to call CoInitializeSecurity. In fact, this is the easiest way to call this function because you only need to specify two things: a flag (EOAC_APPID) that says you're passing an AppID for the first argument of the function and the AppID itself. Here's some managed C++ code that does just that.

 // the simplest way I know to declare a GUID in VC++ ;-)
 struct __declspec(uuid("12341234-1234-1234-1234-123412341234"))
   MyAppID;


 void main() {
    CoInitializeEx(0, COINIT_MULTITHREADED);
    CoInitializeSecurity(&__uuidof(MyAppID),
    0, 0, 0, 0, 0, 0, EOAC_APPID, 0);
    // app code goes here...
    CoUninitialize();
 }

The benefits of using the method shown are twofold. First of all, it's incredibly simple to code. Second, Windows provides a tool for editing and persisting your security settings, and an administrator can use it to configure them. The drawbacks are twofold as well. First of all, you've got to create an AppID in the registry for your client program, and, because AppIDs for client apps aren't common, there isn't any infrastructure in the .NET Framework for doing this. So you'll have to have your setup application do it (it's not hard — you can use the registry classes in the Microsoft.Win32 namespace, but it's a step you can't forget). The second drawback is that in using this technique you don't have quite as much control. The GUI doesn't allow you to configure every single COM security setting, and some of those settings you want. You might prefer to manage these settings yourself and call CoInitializeSecurity, explicitly passing configuration parameters rather than simply referring to an AppID. I recommend this approach for new code.

       Here are the settings that the GUI allows you to control:

There are some other settings designed for base COM servers, including identity and launch permissions. But for client code that doesn't support activation, these aren't anything you need to worry about.

Here are some important additional settings that you can control if you call CoInitializeSecurity without using the EOAC_APPID hack I just described:

       There are a few other things you can do as well, but they're so esoteric that I won't mention them here. See Brown (2000b) for more details if you care.

For the remainder of this item, I'll walk you through what these various settings mean. First of all, I've devoted WhatIsTheCOMAuthenticationLevel and WhatIsTheCOMImpersonationLevel to the authentication and impersonation levels, so I'll start with the access control setting.

The first argument to CoInitializeSecurity is a pointer to a security descriptor (WhatIsASecurityDescriptor). This is where you specify your access control policy. There are a lot of really annoying restrictions on how this thing has to be built, which is why I provided some helper code in the accompanying library (samples can be found it HowToConfigureSecurityForACOMClient). 2 The only thing that really matters here is the DACL (WhatIsAnAccessControlList), which is where you specify the users and groups allowed to call into your process. The helper code in the accompanying library defaults to using a DACL with a single ACE that grants access to Authenticated Users. Whatever you choose, make sure that SYSTEM ends up being granted access or COM won't work properly. Fortunately, as of Windows 2000 SYSTEM has the Authenticated Users SID, so this DACL makes COM quite happy.

For a COM client, a great place to start with this first argument is to simply limit access control to Authenticated Users. This blocks the null session (WhatIsANullSession) and guest logons (WhatIsAGuestLogon), but allows the server to make callbacks to the client. Unfortunately, it also allows any other authenticated user to call your methods (fire events, etc.), but it's a heck of a lot better than not specifying an access control policy and allowing all calls in. If you happen to know (or can find out) a list of users and groups that should be allowed to make calls to your code, for example, if you know the server account name that will be firing events to your client, by all means be more specific in your access control policy.

For a COM server, use groups to grant permissions to any users who need to make COM calls into the server process. If you can't do this, at least follow my earlier advice and grant access to Authenticated Users to block anonymous callers. If you do want to allow anonymous callers, pass a null pointer for this argument.

Restricting custom marshalers is a good idea, and you should use this feature. You see, a bad guy can send you a COM request that includes a custom marshaler CLSID that effectively tells COM to create an instance of that class in your process, and COM happily obliges. But if you turn on this restriction, the only CLSIDs that COM trusts to act as custom marshalers are classes built into the operating system or classes that have been marked with a special category, CATID_MARSHALER. Turn this feature on, please; otherwise, you're providing an attacker a very easy way to force you to load DLLs into your process that you don't need (but that help the attacker in some way). To turn this feature on, specify the EOAC_NO_CUSTOM_MARSHAL flag in the penultimate argument to CoInitializeSecurity. My library turns this flag on by default for you (HowToConfigureSecurityForACOMClient).

Cloaking is a feature that you should turn on as well. It's already turned on automatically in COM+ and ASP.NET worker processes. You probably won't ever actually use this feature in a COM client, but then again you may. It has to do with impersonation (WhatIsImpersonation). By default, COM ignores any impersonation token you might have on your thread when you make an outgoing COM call. So if your process is running as Bob and your thread is impersonating Alice, outgoing COM calls ignore the thread token and go out using Bob's credentials, which is probably not what you intended. Turning on cloaking fixes this so Alice's credentials are used instead. This is a good example of the "principal of least surprise." Specify the EOAC_DYNAMIC_CLOAKING flag in the penultimate argument to CoInitializeSecurity to enable this feature. My library turns this flag on by default for you (HowToConfigureSecurityForACOMClient).

The last item, represented by yet another flag (EOAC_DISABLE_AAA), really doesn't make much sense for client code, but was designed for highly trusted COM servers, such as those that run as SYSTEM. If a highly trusted COM server made calls to an untrusted out-of-process COM server, it would be bad if that server were configured to run "as the launching user" because it would then be launched in the SYSTEM logon session, which is the most highly trusted logon on the machine! By default, then, you should turn this feature on for any COM servers that run with high privilege. It will prevent activation requests from being acknowledged by COM servers configured to run as "The launching user", or "As Activator". 3 For normal client code, you really don't want this feature because it breaks so many applications (most OLE automation apps like Microsoft Excel are configured to run as the launching user, which is quite natural). My library leaves this feature off by default.

Windows XP Service Pack 2

As this book is about to go to press, Windows XP service pack 2 is in beta. This service pack adds an additional layer of security for COM applications. There are two new machine-wide DACLs that can be edited via the computer property sheet accessible from the COM+ explorer. These control launch and access permissions for all COM servers on the machine, and any caller must pass these hurdles before COM even considers evaluating the individual server DACLs. As of this writing, it looks as though the default settings will prevent remote nonadministrators from launching COM servers on a Windows XP box. These settings won't place any further restrictions on calls into an already running process (callbacks into client applications, for example) by any authenticated user, but will by default block all anonymous calls that don't originate on the local machine.

Another likely change in Windows XP service pack 2 is the addition of fine-grained permissions that distinguish between local and remote calls. Traditionally COM servers have used only a single execute permission, which indicates whether a request will be allowed. This is being split into two permissions—let's call them LOCAL_EXECUTE and REMOTE_EXECUTE. You can grant these permissions individually to a user or group. For example, you can grant LOCAL_EXECUTE to Authenticated Users while granting REMOTE_EXECUTE to no one. This would allow a COM server to be used locally, but would prevent all remote access to that server.

Similarly, launch permissions are being split into local and remote flavors, and a new "activation" permission is being added. Whereas launch permissions dictate who can cause new COM server processes to start, activation permissions dicate who can create new COM objects (even in an already launched server). Activation permissions are also split into local and remote versions. 4

1 If you're a COM veteran and you know about AppIDs, you may be surprised to know that even a COM client can have one. Often they should, to control their security preferences.

2 The descriptor must be in absolute format, and the owner and primary group must be set, which makes the function a lot harder to call than it should be.

3 If you're wondering what the "AAA" stands for in the flag name, it's "As Activator Activation." Tell people this little tidbit at parties; it's a great way to get dates!

4 For more information on the implications of service pack 2, see http://msdn.microsoft.com/security/productinfo/xpsp2/default.aspx.

PortedBy Aldo Prinzi

PluralsightTraining

Keith's first book-in-a-wiki. If you would like to read the book online or order a physical copy to throw at annoying coworkers, surf to the HomePage. Please note that due to overwhelming wikispam, this particular wiki is no longer editable.

About FlexWiki.

Recent Topics