Since the private key is not password-protected, an attacker can use the private key of the account’s owner at will for as long as they are logged on. Additionally, an attacker could export the key to a floppy disk (password-protecting it with a password that the attacker chooses) and then use tools like Gutmann’s or our modified version of OpenSSL to retrieve the key offline. The second vulnerability comes from the format in which the private key is stored on a disk once it has been exported (in a .pwl or .pfx file). Gutmann’s breaks tool performs a dictionary attack to discover the password used to protect the file and outputs the private key. The third vulnerability involves the CryptEx portKey function found in the CryptoAPI, which Gutmann raised concerns about back in 1998. Specifically, with the default key generation (i.e., no password protection) and an exportable key, any program running under the user’s privileges may call the CryptExportKey function and silently obtain a copy of the user’s private key. In the Microsoft ‘‘low-security’’ model of client-side PKI, it seems that one has to trust the entire system (OS, IE, the CSP, etc.) for the client-side vision to work. If an attacker compromises one piece of the system (e.g., an executable with a user’s privileges), then because of tight coupling, the attacker can violate other parts of the system (e.g., the user’s private key).


Wondered if, with its new security emphasis, Microsoft had fixed some of these vulnerabilities, either directly or perhaps as a result of decoupling IE and the OS. Began experiments with the low-security key, a key that can be used by any application running with the user’s privileges without warning the user that the key is in use. It is noticed that generating low-security keys is still the Microsoft CSP’s default behavior. Curious to see if the latest versions of the CryptoAPI and CSP have remedied the CryptExportKey issue, perhaps by warning the user when their private key is being exported. Conclusion: ‘‘no’’. Experiment able to construct a small executable which, when run on a low-security (default) key, quietly exports the user’s private key with no warning.


The Windows CryptoAPI does permit users to import keypairs at medium or high-security levels. With both of these levels, the use of the private key will trigger a warning window; in the high-security option, the warning window requests a password. Consequently, the previous attack may not work; when the executable asks the API to export the key, the user may notice an unexpected warning window. So our attack strategy had to improve.


Before it is to be discussed the specifics of stealing medium and high-security keys, a brief introduction to the general method of API hijacking is in order. The goal of API hijacking is to intercept (hijack) calls from some process (such as IE) to system APIs (such as the CryptoAPI).


API hijacking uses a feature of Microsoft’s linker called ‘‘delay loading’’. Typically, when a process calls a function from an imported Dynamically Link Library (DLL), the linker adds information about the DLL into the process. When a process is loaded, the Windows loader reads the imports section of the process, and dynamically loads each DLL required. As each DLL is loaded, the loader finds the address of each function in the DLL and writes this information into a data structure maintained in the process’s imports section known as the Import Address Table (IAT). As the name suggests, the IAT is essentially a table of function pointers. When a DLL has the ‘‘delay load’’ feature enabled, the linker generates a small stub containing the DLL and function name. This stub (instead of the function’s address) is placed into the ‘‘imports’’ section of the calling process. Now, when a function in the DLL is called by a process for the first time, the stub in the process’s IAT dynamically loads the DLL (using  LoadLibrary and GetProcAddress). This way, the DLL is not loaded until a function it provides is actually called i.e. its loading is delayed until it is needed. For delay loading to be used, the application must specify which DLLs it would like to delay load via a linker option during the build phase of the application.


So, how does an attacker use delay loading on a program for which he cannot build (possibly because he does not have the source code i.e. IE)? The answer is to redirect the IAT of the victim process (e.g. IE) to point to a stub that implements the delay loading while the process is running. The strategy is to get the stub code as well as the IAT redirection code into an attack DLL and inject this DLL into the address space of the victim process. Once the attack DLL is in the process, the IAT redirection code changes the victim’s IAT to point to the stub code. At that point, all of the victim process’s calls to certain imported DLLs will pass through the attack DLL (which imported DLLs are targeted and which functions within those DLLs are specified by the attack DLLdi.e. the attacker gets to choose which DLLs to intercept). This implements a software man-in-the-middle attack between an application and certain DLLs on which it depends. The Windows OS provides a number of methods for injecting a DLL into a process’s address space (a technique commonly referred to as ‘‘DLL injection’’). The preferred method is via a ‘‘Windows Hook’’, which is a point in the Windows message handling system where an application can install a routine that intercepts messages to a window.


Using the techniques above, the web ables us to construct a couple of programs that, running at user privileges only, allowed us to intercept function calls from IE to the CryptoAPI. This is particularly useful for stealing medium or high-security private keys which display warning messages when used (in a client-side SSL negotiation, for example). The idea is to wait for IE to use the key (hence, displaying the warning or prompting for a password), and then get a copy of the private key for ourselves without triggering an extra window that might alert the user.


Essentially, the attack code is two programs: the parasite an attack DLL with the IAT redirection code and the delay loading stubs, and the grappling hook an executable to register a hook that is used to inject the attack DLL into IE’s address space.

Implemented attack as follows.

  • Get the parasite and grappling hook onto the victim’s machine (perhaps through a virus or a remote code execution vulnerability in IE).
  • Get the grappling hook running with the user’s privileges. This installs a Windows hook which gets the parasite injected into IE’s address space.
  • The parasite changes IE’s IAT so that calls to desired functions in the CryptoAPI (crypt32.dll and advapi32.dll) are redirected to the parasite.
  • At this point, the web has complete control and is aware of what IE is trying to do. For example, if the web specifies CryptSignMessage to be redirected in our parasite, then every time IE calls this function (e.g. to do an SSL client-side authentication), control will pass to our code.

The web knows that the user is expecting to see a warning, in this case, so we take advantage of the opportunity to do something nefarious like export the private key. In our current demo, the adversarial code exports the private key, so the warning window will say ‘‘exporting’’ instead of ‘‘signing’’ at the top. This could be remedied by hijacking the call which displays the warning.


The bottom line is that with a DLL and small executable running with the victim’s privileges, the private key even with medium-security or high-security protections can be stolen if it is exportable. The obvious solution is to make keys non-exportable, and the web verified that this countermeasure prevents the attack.  We stress that this is different from full-blown cross-site scripting. SA is not using a subtle bug to inject code into pages that are (or appear to be from) other servers. Rather, SA is using the standard rules of HTML to ask the browser to itself load another page.


The divine scriptures are God’s beacons to the world. Surely God offered His trust to the heavens and the earth, and the hills, but they shrank from bearing it and were afraid of it. And man undertook it.
Back to top button