Our previous blog post analyzed CVE-2015-0016 to determine the origins of the vulnerability. However, that blog post only looked into the vulnerability on a Windows 7 system.
The analysis for Windows 7 and Windows 8 is different. On the former, before CreateProcessW is called it does not check the lpApplicationName. On the latter, it will call the IsValidMstscLocation function to check lpApplicationName. This post looks into how the vulnerability works on a Windows 8.1 system.
My initial analysis of this vulnerability already covered TSWbPryx.exe on Windows 7 32-bit systems. A commenter, MJ0011, pointed out that the behavior is different on Windows 8.1 systems.
To analyze this vulnerability, I used a Windows 8.1 32-bit system with the unpatched TSWbPrxy.exe at version 6.3.9600.16421, and KernelBase.dll at version 6.3.9600.16656.
The Unpatched Code
Below is the code for the unpatched version of the function StartRemoteDesktop:
Figure 1. Code for StartRemoteDesktop
Before CreateProcessW is called, there is a call for IsValidMstscLocation. Let’s check what this particular function does.
Figure 2. Code for IsValidMstscLocation
This function performs the following routines:
- Check the length of lpApplicationName. It this is bigger than 0x104, return with the error 0x80075007.
- Call PathContainsEnvironmentStrings to check lpApplicationName whether contains environment strings. If these strings are found, return with the error 0x80075007.
- Format lpApplicationName by converting all slashes (‘/’) to backslashes (‘\’) and save the result to var_canonicalizeStr.
- Call PathCanonicalizeW to canonicalize var_pszPath and save the results into var_canonicalizeStr.
- Call PathFindFileNameW with the parameter var_pszPath, and compare the returned string with mstsc.exe, if these are not equal return with the error 0x80075007.
- Call SHGetKnownFolderPath to get the FOLDERID_SYSTEM path. Afte this, call CompareStringW to compare FOLDERID_SYSTEM with var_canonicalizeStr, with the compare length of length(FOLDERID_SYSTEM). If these not equal, return with the error 0x80075007.
- Call SHGetKnownFolderPath to get the FOLDERID_SystemX86 path. After this, call CompareStringW to compare FOLDERID_SystemX86 with var_ canonicalizeStr, with the compare length of length(FOLDERID_SystemX86). If these are not equal, return with the error 0x80075007.
There is a flaw in PathCanonicalizeW, which can eventually lead to code being executed. We can look at what this function does.
The function PathCanonicalizeW is found in the kernelbase.dll module. This function simplifies a path by removing navigation elements like “.” and “..” to produce a clean, well-formed path. It calls PathCchCanonicalizeEx to do this; however when dealing with the “\\..” string the code has an error which can eventually lead to an exploit.
Because this function is quite complex, instead of showing the problematic code we will only show pseudocode and focus on how “\\..” strings are handled.
The following are the definitions of the variables used in the pseudocode:
- dstStr: the array used to save the canonicalized string
- originalStr: the original, uncanonicalized string
- pBeginDstStr: pointer to the beginning of dstStr
- pTempDstStr: pointer to the dstStr array after it has been canonicalized
- pTempOriginalStr: point to the originalStr array during canonicalization.
- pNextOriginalStr: point to the originalStr array during canonicalization.
The pseudocode would read:
Figure 3. Pseudocode of PathCchCanonicalizeEx
The process can also be shown (in a streamlined fashion) in the following flow chart:
Figure 4. Flow chart of function
So, for example, if the uncanonicalized string C:\windows\system32\\..\\..\mstsc.exe is processed with this function, the resulting string is C:\windows\system32\mstsc.exe. If the uncanonicalized string is processed with the CreateProcess procedure, it would treat the string as C:\mstsc.exe.
In certain conditions, this function can be bypassed, with the associated error checking bypassed in effect. This can be used in further attacks that attempt to run arbitrary code.
Root causes of the vulnerability, and solution
The method the PathCanonicalizeW function processes the “\\..” string is incorrect, which allows the it and the CreateProcess function to handle the same path, but get different results. An attacker can construct a special path to escape the IsValidMstscLocation check, and use CreateProcess to launch a specially created file of their choosing.
As we noted earlier, Microsoft has patched this vulnerability on both Windows 7 and Windows 8. However, it is worth nothing that this was done by not using the problematic PathCanonicalizeW function anymore. Other portions of code that use this function may still be at risk, but we cannot be sure.