Module: KernelBase.dll
Functions: PathCanonicalize() and PathCchCanonicalize()

PathCanonicalize (which is now deprecated) and PathCchCanonicalize are responsible for converting an attacker controlled path into a canonicalized form, so that the path could be sanitized to prevent a possible Path Traversal attack. However, it seems that all of the tested versions of these functions are only aware of the Back Slash (‘\’) char as a path separator, and ignore the Forward Slash (‘/’) char which can be used for the exact same purpose.

A programmer is supposed to perform the following operations for sanitizing a given path:

  1. Concatenate all different parts
  2. Canonicalize the path
  3. Check that the canonical path starts with the wanted prefix

Intended Behavior:

  1. Base\Inner\ + ..\Evil.bat ==> Base\Inner\..\Evil.bat
  2. Base\Inner\..\Evil.bat ==> Base\Evil.bat
  3. Verdict: Reject.
    Reason: Base\Evil.bat doesn’t start with Base\Inner

Same test, now with ‘/’:

  1. Base\Inner\ + ../Evil.bat ==> Base\Inner\../Evil.bat
  2. Base\Inner\../Evil.bat ==> Base\Inner\../Evil.bat (nothing changed)
  3. Verdict: Approve.
    Reason: Base\Inner\../Evil.bat starts with Base\Inner

This vulnerability caused the patch for CVE-2019-0887 (Remote Desktop Services Remote Code Execution Vulnerability) to be partial, and we managed to bypass it by using ‘/’ instead of ‘\’ in our exploit path.

Microsoft refers to their improper fix of CVE-2019-0887 as CVE-2020-0655.
Microsoft added a workaround for their RDP client (inside mstscax.dll), while PathCchCanonicalize() could still be bypassed if used in other cases.