2. Use the /robust Switch
If you create services that use remote procedure calls (RPC) on Windows 2000, make sure you use the /robust MIDL compiler switch. This will add more stringent integrity checking and mitigate many denial of service attacks, which rely on malformed RPC packets.
3. Use Negotiate Rather than NTLM—It's Free
If your application uses the Security Support Provider Interface (SSPI) or you use technologies that use SSPI indirectly, such as RPC and DCOM, request the Negotiate SSP rather than NTLM if your code runs on Windows 2000. Negotiate will use Kerberos authentication automatically if it is available, otherwise it will use NTLM. For example, if you use RPC and you call the RpcBindingSetAuthInfo[Ex] function, then set the AuthSvc argument to RPC_C_AUTHN_GSS_NEGOTIATE rather than RPC_C_AUTHN_WINNT or RPC_C_AUTHN_DEFAULT. The same applies to DCOM's use of CoSetProxyBlanket() or CoInitializeSecurity(), however the authentication level is set in the dwAuthnSvc variable and SOLE_AUTHENTICATION_INFO structure, respectively.
4. Use Packet Privacy and Integrity—It's Free
Both DCOM and RPC allow the channel between the client and server to be both encrypted and integrity checked. The performance impact is minimal unless you are transferring masses of data. In the case of DCOM, this feature may be enabled in the COM+ Explorer or programmatically by calling CoSetProxyBlanket with dwAuthnLevel set to RPC_C_AUTHN_LEVEL_PKT_PRIVACY. When using DCOM, call RpcBindingSetAuthInfo or RpcBindingSetAuthInfoEx with AuthLevel set to RPC_C_AUTHN_LEVEL_PKT_PRIVACY.
5. Keep Good ACLs—They're Your Friends
Bad access control lists (ACLs) on objects such as registry keys, files, named pipes, mutexes, and so on are a very common problem (see my second Note From the Trenches). They allow malicious users to view and/or change the resource. ACLs on objects should specify who is allowed to do what to a particular object. In fact, I have a little rule: someone on the development team has to vouch for every ACE in the ACL and everyone has to agree. Also, make these the default settings, don't expect your users to set ACLs correctly—because they won't.
When creating securable system objects such as named pipes and semaphores, using NULL as the default ACL is generally okay, this means inheriting the security descriptor of the process. However, explicitly setting an empty security descriptor is very bad, this means the object has no access control and anyone can manipulate it. ACLs are your friends, use them, and learn how to use the SetSecurityInfo() function.