Dan Griffin's Blog
Comments on security, PKI, smart cards, cryptography, and entrepreneurship.
Comments on CNG article in this month’s MSDN Mag
June 15, 2007
There’s a nice survey of programming with "Crypto API: Next Generation," aka CNG, in the July 2007 issue of MSDN Magazine - http://msdn.microsoft.com/msdnmag/issues/07/07/Security/default.aspx. Kenny Kerr wrote the piece.
My favorite quote is near the end of the article, when he’s discussing interoperability between Microsoft’s native and managed crypto APIs. He observes, "working with CNG is quite a bit simpler than working with the managed cryptography classes as there are fewer abstractions and inherited defaults to think about. Effective cryptography relies on programmers being explicit about every single detail."
That’s an interesting statement on a couple of levels. It initially resonated with me, since working on the legacy (native) Crypto API was one of my first responsibilities at Microsoft, right out of college. So CAPI made a big impression on me in my formative years
From that background, when the managed (System.Security.Cryptography) interfaces were released, they seemed a little bit unnatural. Case in point - the "RSAOAEPKeyExchangeFormatter" class. I had always assumed that the intent of the CLR is to provide a careful balance between power and usability, in contrast to Win32, which is all about full power. But if you’re going to be using something called RSAOAEPKeyExchangeFormatter, then you had better really understand crypto. In other words, where’s the usability (I’ll come back to that)?
On the other hand, if you have to really understand crypto to safely use managed CAPI, why, as Kenny Kerr asks, do the higher level classes offer so many defaults? "Default behavior" is bad news in many aspects of system-level programming, but it’s especially dangerous in crypto. For example, what happens when the chosen default behavior is no longer secure? You either fix it and break apps, or leave it and perpetuate an insecure system. Better to force application programmers to make explicit choices (about crypto algorithm, key size, cipher chaining mode, etc) from the outset about handling versioning and configuration.
Herein lies the betrayal of crypto APIs in general: there is no way for the layman to use them safely (regardless of default vs explicit behavior). Applications should be built on top of existing, proven security protocols. This generally implies that application programmers won’t be calling the low level crypto interfaces directly. And this brings me to my second point regarding this month’s CNG article - any overview-level guide for a cryptographic interface should include such a disclaimer.
Examples of existing, proven security protocols follow. All provide integrity as well as confidentiality (encryption) features.
* Authentication: Kerberos (http://en.wikipedia.org/wiki/Kerberos_%28protocol%29)
* Data: DPAPI (http://en.wikipedia.org/wiki/Data_protection_application_programming_interface)
* File: EFS (http://en.wikipedia.org/wiki/Encrypting_File_System)
* Network: IPsec (http://en.wikipedia.org/wiki/IPsec)
* Socket: TLS (http://en.wikipedia.org/wiki/Secure_Sockets_Layer)
Permalink | Comments (0)
More information about the IPsecPing sample code
June 6, 2007
First, the version of the IPsecPing client code available above makes a call to WSASetSocketPeerTargetName with a Service Principal Name (SPN) based on the DNS name (specified via the command-line) of the target peer. Using an SPN forces the identity of the server to be verified by the underlying authentication protocol, e.g. Kerberos. However, between peers that lack trust (i.e. non-domain joined; or joined to domains that don’t share trust), Kerberos isn’t available. This was the case in my TechEd demo environment. Anticipating this, I configured shared-password-based IPsec policies. But I’d forgotten that the code was written to require checking the SPN.
Note - I’m told that certificate-based IPsec authentication also supports verification of an SPN (presumably via something resembling schannel name mapping), and that in that situation a Kerberos environment isn’t required. I haven’t confirmed that.
Anyway, to allow IPsecPing to work in my demo environment, I modified the code to only conditionally call WSASetSocketPeerTargetName (based on the presence of a command-line argument). Now I’m able to confirm IPsec-protected IPv4 connectivity between the un-trusted peers.
But IPsec-protected IPv6 connectivity wasn’t working! Why? Well, this one was easy - I was using an IPsec policy that only specified v4 addresses. Actually, I’d followed the directions on p. 1144 of the Vista Resource Kit book (http://download.microsoft.com/download/f/c/7/fc7d048b-b7a5-4add-be2c-baaee38091e3/9780735622838_WindowsVistaRK_ch27.pdf) and created a Connection Security rule via Windows Firewall. However, when creating an address-specific rule that way, it appears that the only way to provide an v6-compatible policy is to type in the v6 addresses. I’m just too lazy for that
So I disabled my WF Connection Security rule and instead created a new IPsec policy via the IP Security Policies snap-in. That approach is arguably more time-consuming than the above, but it allows policies to be specified via DNS name (which - note - can probably be spoofed). The resulting filter ruleset seems to apply to both v4 and v6 traffic. Running IPsecPing with the -6 switch confirmed this (I used "stcpserver.exe -v6", from the Vista SDK sample code, on the test peer in this case; note that the latter listens on port 27015).
Security panel discussion this morning at TechEd
June 5, 2007
First topic (although I arrived a little late and may have missed something earlier) - computers on the internet are now being compromised more for the sake of criminal activity than for hacker street cred. Attacks are becoming less visible. Attacks are also becoming more targetted against specific companies. Hackers and criminals follow the money, and so much the better if the target is poorly defended (TJX comes to mind).
Next came the inevitable discussion of the User Account Control (UAC) feature in Vista. I was listening to a talk yesterday by Rafal Lukawiecki at TechEd. His advice to the audience is to leave on UAC and run as a regular user. That way, every elevation prompt requires admin password entry. That’s sensible advice, but there’s a flip side: most Windows users will continue to run as admins, and hence will see UAC prompts, but won’t be required to enter a password in order to elevate. The net result is that, over time, users become trained to always click Continue (just like the Firewall prompt trains users to always click Allow).
What to do about the UAC prompting issue? One suggestion was to continue to push application authors toward digital signing, thereby allowing application identity to be tracked. The theory is that, if the application has been vetted and signed by a trusted authority (i.e. which I suppose means Microsoft :)), don’t prompt for elevation; just do it. If the application isn’t signed or trusted, prompt when elevation is required. However, I don’t see how validating and signing even a representative set of PC based applications could scale in the consumer (non-managed machines) environment.
Returning to the topic of network attacks, the observation was made that DDoS attacks continue to become nastier and more disruptive, as more compromised machines (bots) are brought to bear. What to do about this? Answer: get IPv6 widely deployed on the internet. This is primarily because the huge (and non-contiguously allocated) address space makes scanning ineffective. How soon is IPv6 going to widely deployed, given the infrastructure upgrade requirements? Probably not very. An interim solution exists in IPsec via IPv4, but IPsec is too hard to configure and manage in general. Software companies could certainly do a better job at making technologies such as IPsec easier to deploy.
Security education for software developers at the University level was the next topic. Do widely used languages such as Java and C# make secure programming techniques easier to teach? Maybe, although they don’t seem to be having that affect. And, in the absence of such training, those languages are no more likely to result in secure code than C/C++.
The final topic discussed was spam. Spam has become so pervasive that client-side filters now tend to catch a noticeable amount of legitimate email. This is especially a problem for small & medium-sized businesses, who tend to have a smaller percentage of email sent between internal accounts. Depending on the number and type of business partners involved, setting up trusted/federated messaging beween them can either be challenging or impossible. One technology could play an alleviating role here: S/MIME (or PGP), but getting all parties is still a challenge.
I wanted to provide clearer instructions for the one of the Vista security sample code projects we recently did. I’m referring to the Windows Filtering Platform demo which can be downloaded here (http://download.microsoft.com/download/f/1/2/f12dbbb5-d164-4e7c-b42d-aaca3efb85dc/WFPSample.EXE). In summary, it shows how to build a packet inspection driver which uses context information passed from user mode.
1. Building the demo requires the latest Windows Driver Kit (formerly known as the DDK). It’s a big download, available two ways (that I’m aware of): either via an MSDN subscription or via http://connect.microsoft.com.
For the latter, the connection is called "Windows Logo Kit (WLK), Windows Driver Kit (WDK), and Windows Driver Framework (WDF)".
Once you’re registered, the current download link is (https://connect.microsoft.com/Downloads/DownloadDetails.aspx?SiteID=148&DownloadID=4606). Once you’ve got the Driver Kit installed, run Start | All Programs | Windows Driver Kits | WDK 6000 | Build Environments | Windows Vista and Windows Server | Windows Vista and Windows Server Longhorn x86 Checked Build Environment. In that command window, change to the WfpDemo directory from the extracted demo download package and type build.exe.
2. I recommend deploying the driver on a test x86fre Vista machine. To do so, copy the following files to a temporary directory on the target machine: msnmed.sys, medit.exe, msnmed.inf. On the target machine, open Explorer, right click on msnmed.inf, and select Install. That will copy and register the driver. Then run net start msnmed; the driver should then be loaded (if it wasn’t already).
3. On the test Vista machine, install version 7.5 of MSN Messenger. If you use a different version, you’ll need to double-check that the messenger application binary path isn’t different. Otherwise, the custom filter installed by the demo won’t apply (it’s configured to be specific to a certain path/binary name).
4. To run the demo, you’ll need access to two different Messenger accounts: one to send messages (IMs) from the test machine, and one to receive the messages and view the changes made by the filter driver to the outbound data stream.
On the test machine, in a command window, run medit.exe oldstring newstring. What the demo will show is that, any time oldstring is typed into the messenger window where the driver is installed, it will be changed to newstring, which is what the recipient will see. ‘Oldstring’ and ‘newstring’ can be anything, but they need to be the same length (otherwise, medit.exe will immediately return an error).
After running the above, don’t close medit - the filters it installs are dynamic, and will be cleaned up when the medit process terminates.
Now open the messenger client on the test machine and send a test chat to the other messenger account. Use ‘oldstring’ in the messege. Check the recipient’s messenger window and you should see the sender’s message, with ‘newstring’ instead of ‘oldstring’. That’s the demo
5. Regarding debugging the driver, if medit.exe succeeds in running the command above, and doesn’t terminate immediately with an error, then things should generally be working. Aside from running a kernel debugger (which you should be doing anyway if you plan on digging into the driver in any detail), deeper debugging is available via WMI tracing.
Copy \WinDDK\6000\tools\tracing\i386\TraceView.exe (and the chm help file …) from your Driver Kit installation to the test machine where the filter driver is installed. You’ll need the current msnmed.pdb on the test machine as well. Run TraceView.exe on the test machine, File | Create New Log Session | Add Provider | PDB. Enter the full path of msnmed.pdb. Click OK, then Next, then Set Flags and Level. Double-click on Level and select Information. Click OK, then Finish. Now the TraceView window should show the full driver debug output when running scenarios as the test machine. Unfortunately, we didn’t add any specific WMI tracing output for the new filter we added in this demo (i.e. above and beyond what the original DDK sample already implemented).
Permalink | Comments (0)Where to find me at TechEd
June 4, 2007
Also, I’ll be signed in as a Subject Matter Expert to answer questions online during Rafal Lukawiecki’s "Windows Security for Developers" session Monday morning, which is also being made available as an MSDN webcast - http://tinyurl.com/2fo874.
Permalink | Comments (0)