Uninformed: Informative Information for the Uninformed

Vol 7» 2007.May

External Cookie Generation

An alternative solution that could combine the effects of the first two solutions would be to change the GS implementation to generate the cookie external to the binary itself. One of the most dangerous aspects of the GS implementation is that it is statically linked and therefore would require a recompilation of all affected binaries in the event that a weakness is found. This fact alone should be scary. To help address both this problem and the problem of weak entropy sources, it makes sense to consider a more dynamic approach.

One example of a dynamic approach would be to have the GS implementation issue a call into a kernel-mode routine that is responsible for generating GS cookies. One place that this support could be added is in NtQuerySystemInformation, though it's likely that a better place may exist. Regardless of the specific routine, this approach would have the benefit of moving the code used to generate the cookie out of the statically linked stub that is inserted by the compiler. If any weakness were to be found in the kernel-mode routine that generates the cookie, Microsoft could issue a patch that would immediately affect all applications compiled to use GS. This would solve some of the concerns relating to the static nature of GS.

Perhaps even better, this approach would grant greater flexibility to the entropy sources that could be used in the generation of the cookie. Since the routine would exist in kernel-mode, it would have the benefit of being able to access additional sources of entropy that may be challenging or clumsy to interact with from user-mode (though the counterpoint could certainly be made as well). The kernel-mode routine could also accumulate entropy over time and feed that back into the cookie, whereas the statically linked implementation has no context with which to accumulate entropy. The accumulation of state can also do more harm than good. It would be disingenuous to not admit that this approach could also have its own set of problems. A poorly implemented version of this solution might make it possible for a user to eliminate all entropy by issuing a non-trivial number of calls to the kernel-mode routine. There may be additional consequences that have not yet been perceived.

The impact on performance is also a big point of concern for any potential change to the cookie generation path. At a high-level, a transition into kernel-mode would seem concerning in terms of the amount of overhead that might be added. However, it's important to note that the current implementation of GS already transitions into kernel-mode to obtain some of it's information. Specifically, performance counter information is obtained through the system call NtQueryPerformanceCounter. Even more, this system call results in an in operation on an I/O port that is used to query the current performance counter.

Another important consideration is backward compatibility. If Microsoft were to implement this solution, it would be necessary for applications compiled with the new support to still be able benefit from GS on older platforms that don't support the new kernel interface. To allow for backward compatibility, Microsoft could implement a combination of all three solutions, whereby better entropy sources and seeding of high order bits are used as a fallback in the event that the kernel-mode interface is not present.

As it turns out, Microsoft does indeed have a mechanism that could allow them to create a patch that would affect the majority of the binaries compiled with recent versions of GS. This functionality is provided by exposing the address of an image file's security cookie in its the load config data directory. When the dynamic loader (ntdll) loads an image file, it checks to see if the security cookie address in the load config data directory is non-NULL. If it's not NULL, the loader proceeds to store the process-wide GS cookie in the module-specific's GS cookie location. In this way, the __security_init_cookie routine that's called by the image file's entry point effectively becomes a no-operation because the cookie will have already been initialized. This manner of setting the GS cookie for image files provides Microsoft with much more flexibility. Rather than having to update all binaries compiled with GS, Microsoft can simply update a single binary (ntdll.dll) if improvements need to be made to the cookie generation algorithm. The following output shows a sample of dumpbin /loadconfig on kernel32.dll:

Microsoft (R) COFF/PE Dumper Version 8.00.50727.42
Copyright (C) Microsoft Corporation.  All rights reserved.

Dump of file c:\windows\system32\kernel32.dll

File Type: DLL

  Section contains the following load config:

            00000048 size
                   0 time date stamp
            7C8836CC Security Cookie