April 20th, 2020

It rather involved being on the other side of this airtight hatchway: Planting files onto a custom PATH

For some reason, we get lots of reports about DLL planting that basically boil down to this:

Program X is susceptible to a DLL planting attack because it loads the DLL TOTALLYSAFE.DLL without a full path. If I put a rogue TOTALLYSAFE.DLL on the system PATH ahead of its actual location, then the rogue copy is loaded into the service, and I have gained elevation of privilege.

When we dig into the report, we find that the directory into which TOTALLYSAFE.DLL was planted is not one of the directories that are on the PATH by default. It’s some custom directory that was added by a third-party program’s installer. And that third-party program added a directory that granted write access to non-administrators.

So what we have here is a case of creating an insecure system and then being surprised that it’s insecure.

Creating this insecure system was done by editing the global PATH, which requires administrator permission. Therefore, we are already on the other side of the airtight hatchway. There is no elevation of privilege, because you need to have administrator privileges to create the insecure system in the first place.

The third-party program decided to install itself into a directory directly off the root of the C: drive. If you create your own subdirectory as a direct child of the root, the default security grants Modify access to all authenticated users, and that’s dangerous if you’re going to add that directory to the PATH.

This is one of the reasons why the long-standing recommendation has been to install programs into a subdirectory of %ProgramFiles%. The security for %ProgramFiles% is set so that only administrators have write access, which means that if you install into a subdirectory of %ProgramFiles%, you will get a directory that by default grants write access only to administrators. You can then safely add that directory to the PATH.

In many of the cases I’ve seen, the rogue unsafe directory on the PATH belongs to a variety of popular developer tools. My guess is that the finders install these programs by habit into all of their systems, and when they find an issue, it never occurs to them that it was their insecure customizations that was the source of the vulnerability.

Bonus chatter: In one of the cases, the developer tool indeed protects its directories by limiting write access only to administrators. That didn’t stop the finder from “planting” a DLL in that protected directory and then “discovering” a vulnerability. So not only did they require elevation to install the developer tool, they also required elevation in order to “plant” the DLL into the protected directory. I guess that puts them on the other side of two airtight hatchways.

 

Topics
Other

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

26 comments

Discussion is closed. Login to edit/delete existing comments.

  • cheong00

    I think this is pretty common for Games that do self update to do so, to update it’s copy of payload in ProgramData.

    Still pretty unsure what is the correct way to do self-updates. We could use a service that runs in higher privilege, but we don’t want to have bazillion updater services installed.

  • Antonio Rodríguez

    The very first versions of Google Chrome installed themselves into the Program Data directory, no doubt to work around the unpopular elevation prompts of Windows Vista. Even worse, the installers didn't even allow you to select a target directory. Many friends of mine had a hard time understanding why placing an executable in a well-kown, fixed, world-writable directory was a big security risk. How easy was it to create a simple worm that silently replaced...

    Read more
    • Kalle Niemitalo

      The ACLs of C:\ProgramData and C:\Users\Public allow interactive users to create subdirectories. I see several subdirectories under those have more restrictive ACLs and have presumably been created and restricted by some installer software. A user might be able to create the subdirectory and plant a file there before the installer is run.

      How am I supposed to defend against that if I am implementing such an installer?

      Can a user also create a file in a directory...

      Read more
      • Stefan Kanthak

        The user can add a reparse point (junction) to the directory he created. Unless the installer removes the reparse point, it performs all operations on the target of the junction. After it has finished, the user can remove the reparse point and create rogue files with the same name as the installer created files.

      • Stefan Kanthak

        @Kalle
        Junctions and symlinks have the same semantics: reparse points are evaluated by the filesystem (filter) driver, ie. on the SMB (or NFS, FTP, HTTP) server in case of remote access.
        The difference: while junctions are always evaluated, symlinks are per default only evaluated for local accesses, to local and remote targets, and they are per default not evaluated for remote accesses.
        This behaviour is controlled by 4 registry entries, here shown with their default...

        Read more
      • Paradice .

        Yeah, but the user requires administrator (or developer) access to create the junction. And if you have administrator access, you’ve already won. You don’t need to continue playing ‘tricks’ with same-named files. Just do whatever you want.

      • Joshua Hudson

        Our world is changing.

        I can, today, without admin rights and without an elevated command prompt, create symbolic links.

        Microsoft still refuses vulnerability reports involving symbolic link racing, but that's not forever. Soon there will be a killer app that wants the switch thrown for all users to be able to create symbolic links. Oh wait, we already have it. It's npm. Soon there will be a killer app for ordinary users that wants that switch thrown...

        Read more
      • Kalle Niemitalo

        Creating a directory junction (MKLINK /J) does not require the same privilege as creating a directory symbolic link (MKLINK /D). This may be justified by the difference in semantics when accessed over SMB.

      • Paradice .

        There is no reply button for Stefan's incorrect comment. AFAIK creating symlinks requires either Administrator access (on every version of Windows and including Windows 10 up until the Creator's Update) or Developer Mode to be enabled (on Windows 10 Creator's Update onwards). Or, I suppose, editing the "Create symbolic links" group policy setting. Since the latter options both require Administrator access to perform anyway, effectively the requirement boils down to "have Administrator access".

        Here you...

        Read more
      • Stefan Kanthak

        OUCH: kids which are even unable to write their name are clueless!
        Creating a junction requires NO privilege, every user can do this!

  • Flux

    Isn’t there a user-local PATH variable?

    • Stefan Kanthak

      Of course, and it is appended to the system-global PATH variable during user logon, when the initial environment block is built.
      There's also an application-specific PATH, which is appended or prepended when an application is started via ShellExecute().
      BUT: unprivileged users can only set their own environment variables, they can't set them for other users, or for applications run by other users.

      Every user can but add user environment variables windir, SystemDrive, SystemRoot, ProgramData, ProgramFiles, ProgramFiles(x86),...

      Read more
      • Jernej Simončič

        Keep in mind that while clean Windows installs will always have their %SYSTEMDRIVE% as C:, upgrades won’t. My own Windows 10 install boots off W:, and my C: is currently a card reader slot.

      • Gacel Perfinian

        Is this just Windows messing up an upgrade or you intentionally coax it? Also, are there programs simply not working due to this?

      • Stefan Kanthak

        Before Windows 2000, drive letters ware assigned at every boot (using the well-known algoritm), so adding/removing a drice or partition could result in a system which booted, but failed at user logon.
        Before Windows Vista, the drive letters ware assigned during setup, again using the well-known algorithm.
        See https://support.microsoft.com/en-us/kb/51978, https://support.microsoft.com/en-us/kb/101703 and https://support.microsoft.com/en-us/kb/234048, plus https://support.microsoft.com/en-us/kb/223188 and https://support.microsoft.com/en-us/kb/249321
        The "Windows" drive (which hosts the "Windows" and the "Program Files" directories) could therefore get an arbitrary letter.
        Programs...

        Read more
      • Raymond ChenMicrosoft employee Author

        If you modify an environment variable, you’re just attacking yourself. It’s not a security vulnerability that you can make your own life miserable.

      • Stefan Kanthak

        That's WAY to simple!
        For which good reason do (at least some of the) applications and DLLs shipped with Windows depend on the environment variables named above?
        There's absolutely NO technical necessity to refer environment variables; implemented properly, they use the functions provided by the Windows API to retrieve the various paths or names!
        Denial of service is a well-known vulnerability: would you like the Windows-powered medical gear in any hospital to fail due to...

        Read more
      • Flux

        I appreciate your enthusiasm, Stefan. I’m sure you’ll become a great developer once you grow up.

        But things are much more complex than you imagined today. Developers have to deal with not just code logic, but also office politics. And they don’t always develop with a full-fledged programming language.

      • Flux

        If only things were that simple, Mr. Chen. Alas.

        Rest assured, however, that I won’t be attacking myself.

      • Joshua Hudson

        We build paths from the environment variables because localization. We don’t know if the path names will change again on foreign-language builds, but the environment variable names won’t. But if you can manage to change the definition of an environment variable of a windows service, then the game is already over.

      • Stefan Kanthak

        This is acceptable only in batch scripts, since there's no other way to evaluate paths like %USERPROFILE%, %ALLUSERSPROFILE%, %windir%, %SystemRoot%, %TEMP% etc., or names like %USERNAME%, %COMPUTERNAME%, ...
        This is but NOT ACCEPTABLE in applications, since you can get all these values from functions of the Windows API.

        Continued, since the blog software fails to offer a reply beyond depth 5

        OUCH!
        Please ask Raymond to explain that these environment variables DON'T control the locations/paths (with the...

        Read more
      • Joshua Hudson

        On the other hand, I get really annoyed when I discover certain applications won’t honor it when I change the paths in environment variables. Changing %USERNAME% and %USERPROFILE% is a decent way to do the application-initialization step for a batch-job user. Changing %TEMP% comes up a lot. Changing %SystemRoot% is pretty useless though.

  • Nathan Williams

    *cough* C:\Python27 *cough*

    • Zander

      *cough* pythonclock.org *cough*

  • Marek Słowikowski

    All of your posts have no sense. Why do you write them? Please, do not do this. Write your own blog but here should be presented words about MS Technology, not your mental problems.

    • Jan Ringoš

      Your comment has no sense. Please don’t write any more comments and let the rest of us enjoy Raymond’s ruminations.