Dubious security vulnerability: Attacking the application directory in order to fool yourself?


A security vulnerability report arrived that went something like this:

There is a vulnerability in the XYZ.EXE program. If you place a hacked copy of the file CABINET.DLL in the same directory as XYZ.EXE, then when the user runs the XYZ.EXE program, it loads the hacked CABINET.DLL instead of the real one. When XYZ.EXE prompts for elevation, the user will allow it, and now the rogue CABINET.DLL is running code as administrator.

Um, okay.

First of all, this is an application directory attack, and the application directory is considered a trusted location. If you let somebody write to your application directory, then you are giving them control over what the application does. So don't do that.

This particular variation tries to disguise the matter by throwing in an elevation prompt, but the underlying issue is the same. Let's look at it another way: Who is the attacker, and who is the victim?

The attacker is the user who creates a trap in the application directory. The victim is the person who runs the application and gets caught in the trap. But how do you get the victim to wander into the yucky hot tub? Whatever technique you used to get them to run a program from your hot tub, you can use that technique to get them to run a rogue app directly; no need for fancy application directory attacks.

The other possibility of a victim is the user himself, who runs the XYZ.EXE application, and discovers that he just fell into his own trap. It's not really considered elevation if you manage to fool yourself.

Comments (48)
  1. Mark (The other Mark) says:

    There is a vulnerability in the XYZ.EXE program. If you place a hacked copy of the file XYZ.EXE in the same directory as XYZ.EXE, then when the user runs the XYZ.EXE program, it loads the hacked XYZ.EXE instead of the real one. When XYZ.EXE prompts for elevation, the user will allow it, and now the rogue XYZ.EXE is running code as administrator.

    1. Brian_EE says:

      There is vulnerability in Windows Explorer. If a user has administrator privileges, she can put any file into the XYZ application directory.

    2. DWalker07 says:

      @Mark, that was my first thought. If you can place a hacked DLL in the same folder as the executable, then surely you can place a hacked executable in the same directory. Sheesh.

      1. DWalker07 says:

        I just realized, that’s what Raymond said with “Whatever technique you used to get them to run a program from your hot tub, you can use that technique to get them to run a rogue app directly… “

    3. Antonio Rodríguez says:

      There is a vulnerability in Windows. Windows allows to run arbitrary programs, and arbitrary programs include malware. So Windows is designed specifically to run malware. Move on to other OS that doesn’t let you run malware, like eh… ummm… other OS :-P .

      1. alegr1 says:

        You’re kidding, but the execution model of running any arbitrary programs with full privileges of the user is a serious weakness of Windows, which continues to cause grief to many users. Even UAC is little help.

        1. morlamweb says:

          @alegr1: you’re kidding, because since 2009, Windows clients have not run applications with full admin privileges by default. I know that it depends a lot on whether users log on as the local admin account and the group policy settings in effect, but in most cases, users do not run EXEs with full admin rights (source: my experience in tech support since 2009). I’ve worked on countless support cases where a user tried to install a program or write to a trusted location, only to be blocked by permissions. “But my account is an admin!” they cry. Doesn’t matter in the default case: accounts in the admin group run programs with standard user permissions by default. Ditto, of course, for user accounts in the Users group.

          1. alegr1 says:

            I’m not talking about admin privileges. Every user process has full access to all files and registry. UWP was a step to the right direction, but it’s too little, too late.

            Operating system should be out of bounds even for the “administrator”. Applications should not be able to install arbitrary programs as services, even when they run as administrators. Service binaries should be required to bear MS signature, like kernel drivers are.

          2. Darran Rowe says:

            @alegr1:
            And we saw how popular completely locked down systems like Windows RT were.
            The thing to also remember is that hiding things behind a high cost wall is also not a good option. It deters the wrong kinds of people you want developing for your platform, and the driver related signing has already pushed small independent hardware devs to go to Linux. If they did the same with software then they would be pushing even more people away to an OS like Linux which has the same kind of full access to the system as Windows, except they won’t have to pay for it. Plus, even with the driver signing requirements, I could still manage to convince an undereducated user to install any driver I want them to.
            So right now, unless you have a time machine, trying to convince people to go to the super locked down approach won’t work.

          3. zboot says:

            @alegr1 Actually, you can set a security policy so that even when logged on as an administrator, programs are not elevated by default.

        2. Darran Rowe says:

          That was the whole point of annoying people like crazy starting with Windows Vista.
          If you are running an application that requires administrative privileges these days then it is normally in one of three categories.
          First, a network game that uses driver based anti cheat protection. These suck.
          Second, a legacy application that was written to assume full administrative rights.
          Third, a modern application whose programmers suck.
          The third one is the major problem, but due to guidelines becoming more well known these are going down but probably will never go away.
          Anyway, the point here is the need for blindly running things with full administrative rights has gone down like crazy and any decent modern application should be following good development practices and using the user profile to save settings. For the application to actually be a threat with an administrative account these days the user must be doing stupid things like turning off UAC (which is on by default), linking the tokens or running untrusted executables without setting UAC to maximum.
          For the second class of applications above, the need for an administrative account can be mitigated if you can change permissions on directories/registry keys. Of course, you have to be really careful about this (like changing permissions on sub directories or sub keys if possible).
          As one final note, even though I still have some issues with it, the UWP/WinRT model doesn’t run with more privileges than you need, so “any arbitrary application” is wrong here.

        3. Integrity Levels help with this- I just finished up tracking down an issue where, under certain circumstances, a document storage location would be created under medium integrity level instead of low, which caused a problem with the process running under low integrity levels.

          To the best of my knowledge, all POSIX-style OSes have very similar issues, when the user is logged in as root. However, it’s much more common that people who run POSIX know to never use root for day to day usage, while many Windows user blithely log in as a Local Admin.

        4. Antonio Rodríguez says:

          Alegr1, you are ten years late. Since October 2006, every version of Windows runs every process as limited user by default. Under that level of privileges, processes can only write to the current user’s home folder, have no access to other users’ homes, and have read only access to almost everywhere else (including Windows and Program files). The Registry is similarly secured (yes, ACLs are used to regulate access to different areas of the Registry).

          This is pretty similar to what Unix does: every user has read permissions on /bin/ (equivalent to C:\Windows\) and /usr/bin/ (equivalent to C:\Program files\), for example.

          In any case, in a properly secured open system (as both Windows and Linux are), it is easier to trick the user than the system. And if you are going to trick a user, would you target an OS with a 90% of share (Windows) or one with only 1% (Linux)? Which one do you think would be more desirable to malware writers?

          1. Jonathan Gilbert says:

            Even better, developers are encouraged to make new apps using the Windows Store model where possible, the principle being to lock down the app, not the user. If each app lives in its own isolated sandbox, then a vulnerability in an app only affects the files and settings written by *that app*. Nothing else on the system is exposed. :-) (Of course, the Windows Store app model is blatantly ripped off of Android and iOS, but that doesn’t make it a bad idea.)

        5. Josh B says:

          Possibly the only thing worse than any process having access to all of your documents is everything being silo’d away, invisible to everything but the app that made it. Of course, now that Windows runs both apps and regular programs, you can run apps of things you don’t want touching your files, strictly managing their permissions, and regular programs when you want to be able to use synergy to do interesting things.

    4. Neil says:

      Well, they might just notice that the application’s signature has changed…

  2. Brian_EE says:

    The standard answer to these researchers should be “Call us back when you can demonstrate how an untrusted process put the rogue file into the application directory in the first place.”

  3. Joshua says:

    The vulnerability is real but I don’t care for political reasons.

    Some people lock down their systems so that only binaries signed by certain entities may run.

  4. Pietro Gagliardi (andlabs) says:

    I’m starting to wonder if this specific set of security reports come from people who think Windows should never allow you to load a non-system DLL with the same name as a system DLL. That is, the LoadLibrary() heuristics become “Is this DLL a system DLL like dwmapi.dll? If so, **always** load the system version, no matter what.”.

    I admittedly don’t know why either option is better than the other. The best I could come up with is: Had a dwmapi.dll in your third-party Windows XP app but need to upgrade to Vista? (For instance, that app may have been developed by a fictional “DWM Corporation” and they named their utility library dwmapi.dll.) Too bad, Windows now gets to keep that DLL name all to itself!

    1. Brian says:

      The .NET Framework kinda-sorta behaves like that. Strongly named “assemblies” (DLLs) are signed. If an app has a dependency on a strongly named assembly, only the properly signed one will load. All Framework assemblies are strongly named. If I create an app that will be installed on a user box, I can strongly name my assemblies as well. That way, only the DLLs I expect will ever be loaded into my process.

      1. ranta says:

        The CLR used to verify all strong-name signatures like you say, but nowadays the “strong-name bypass feature” usually skips this verification for DLLs loaded from the application directory.

      2. Goran says:

        WinSXS behaves like .net, but for native code, and is far more strict. For example, you need a real certificate to sign your executable etc.

    2. Antonio Rodríguez says:

      If you specify in the documentation (the “contract”) of LoadLibrary(), it can work well and solve a lot of hassle. But LoadLibrary() has been around for more than 30 years (it was introduced in Windows 1.0, back in 1985), way before DLL injection and privilege escalation were worrying in personal computers. Locking it now would break many legit apps and utilities who rely on this behavior.

      .NET, on the other side, was designed with this in mind, and thus, it favors signed strong assemblies from day zero.

    3. Klimax says:

      Problem with such lock is that it prevents useful tools fixing up old games or improving them. (Gedosato or modifications for Final Fantasy VIII)

      1. cheong00 says:

        Did you know that sn.exe can run with self-signed certs, so if you generate your own self-signed cert and use it to sign those binaries, it’ll work for you?

        https://blogs.msdn.microsoft.com/shawnfa/2006/02/14/sn-v2-0-works-with-pfx-files/

        Now you just need to redistribute those files with delay-signing option, and include a tool that automates the process with the package.

  5. skSdnW says:

    “the application directory is considered a trusted location” the exception to this is the Downloads folder. This is the default save location for most browsers so people often end up with a bunch of unrelated programs and installers there. Combine that with the default “feature” of downloading without asking where to save in some browsers and some evil JavaScript on a page and suddenly your application directory is full of evil .DLLs just waiting for the user to run something they downloaded.

    1. Neshram says:

      Would it be prudent, problematic, or useless, to set a “low integrity” ACE on such a folder?

      1. skSdnW says:

        It would mostly just be problematic. Most applications are not designed to run at Low IL and even if they could handle it, it really restricts their usefulness since they would not be able to write anywhere. The default Low IL behavior is no-write-up so something evil could read all the files in your profile and upload all your files somewhere. The bigger concern is that some of the programs are going to ask for elevation and then the ACE becomes moot?

        A better solution would be for the Downloads folder to deny execute rights on files. ShellExecute could detect this and ask you if you want to enable execution of just this file.

        1. Neshram says:

          I have a vague memory of a program that needed elevation that was flat failing with some Windows error, instead of prompting. We eventually figured out it had gotten marked with low integrity by accident. Removing the ACE resulting in running and normal prompting for elevation. But maybe that was just something about that particular program.

        2. Jonathan Gilbert says:

          Even simpler: Create a separate subdirectory for each download, or for each download source. C:\Downloads\microsoft.com\ProcExp.exe isn’t going to accidentally load C:\Downloads\haxx0r.ru\kernel32.dll. :-)

  6. pc says:

    Is there some way (a manifest-type thing, or API call, or whatnot) for an application to designate itself as “I don’t rely on other DLLs in my directory; I should only be loading system DLLs? It seems that installer applications and the like should have that kind of flag set, to indicate that it shouldn’t be considered part of the “bundle” with whatever else is in the Downloads directory. Or perhaps all web browsers should default to downloading all files into individual subdirectories.

    1. ranta says:

      Your program could call SetDefaultDllDirectories without LOAD_LIBRARY_SEARCH_APPLICATION_DIR, and then SetDllDirectory(TEXT(“”)) so that LoadLibrary won’t search the current directory either.

      Windows 10 apparently has also PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_PREFER_SYSTEM32_ALWAYS_ON for UpdateProcThreadAttribute, and PROCESS_MITIGATION_IMAGE_LOAD_POLICY::PreferSystem32Images for SetProcessMitigationPolicy. I don’t know if it possible to put those in the manifest somehow.

      1. Joshua says:

        Does not help in the case of static binding (the default).

  7. heto says:

    > Whatever technique you used to get them to run a program from your hot tub, you can use that technique to get them to run a rogue app directly; no need for fancy application directory attacks.

    But this is not the attacker’s hot tub: the directory may have been created and XYZ.EXE was placed there by the administrator or by someone whom the administrator trusts. Just because the administrator might run XYZ.EXE on request, periodically, or even automatically (e.g. as a scheduled task), does not mean the administrator is willing to run any arbitrary program.

    For example, say XYZ.EXE is a user account management tool (of course, not provided by the attacker, instead in place and trusted before the attacker is involved at all). You can come up with a legitimate-sounding reason for the administrator to run that tool, but it would be much harder for you to convince the administrator to run an arbitrary EXE provided by you.

    The real vulnerability here is only that whoever owns the tub, granted too many permissions to the tub to the attacker. I.e. write permissions to the directory are the problem, not that administrators sometimes run programs.

  8. Phylyp says:

    How come this entry doesn’t have Raymond’s standard phrase “this side of the airtight hatch”? :-) I thought this was that class of attack.

    1. James says:

      Of course there are scenarios where this _is_ a vulnerability, well not specifically the DLL loading itself but the scenario where you could drop a DLL next to an executable another user would run without being able to replace the EXE itself. It happens that there’s an annoying number of applications which like to drop files to the system temporary directory (which for back-compat a normal user can create files in) or into a folder in %PROGRAMDATA%. Both these locations have default DACLs which mean only the owner can modify the files they create but allow another user to come along later and drop arbitrary files next to them. Of course the bug here is these applications shouldn’t be dropping and running executables in these locations in the first place, or at least without securing the DACL, but if you give people enough rope, yada yada.

  9. I wonder how the recent plague of “installing” programs in the users app data folder is seen.
    Doesn’t it basically undermine the security lockdown of the program files folder? It’s done to simply avoid having a UAC popup, which brings with itself the “feature” that the UAC won’t even pop up if it really should.
    Maybe disallowing running applications from the users app data would be a solution?

    1. cheong00 says:

      Or just don’t load DLLs in the same folder when the DLL is not in one of the %SystemRoot%/%ProgramFiles%/%ProgramFiles(x86)% folders of the system.

      Or make a whitelist entry in GPO to define location of DLLs (folders and their subfolders) that can be used.

      1. cheong00 says:

        On the second thought, those programs installs to ProgramData usually because they don’t need admin right to run in the first place, and they don’t want elevation prompt to show up in order to update. In other words, the EXEs in these folder usually do not need admin right to run so no security program is created.

        The ones with problem are those inhouse applications created to run on file server shares. They often DO require admin right to run because of various things they need to perform.

        1. Darran Rowe says:

          He does actually mean installing the programs into %USERPROFILE%\AppData\Local, not %ALLUSERSPROFILE%.

    2. Darran Rowe says:

      I would say the answer to this is it depends.
      First of all, if the user has administrative rights enabled all the time (UAC disabled), then it wouldn’t make much of a difference. If the user is using a UAC limited administrator account, or better yet, a limited user account and a separate administrator account to use to elevate then the biggest question is whether the application that ends up in the user profile requires elevation.
      My opinion on that is only an application that will never need administrative rights can be installed in the user’s profile. This way, you can only end up in the situation that you will only get the same privileges from there as the user currently has.

    3. ranta says:

      In Windows 7, Microsoft added FOLDERID_UserProgramFiles, which points to the user’s %LOCALAPPDATA%\Programs. Windows Installer can automatically use that in per-user installations. If Microsoft now turned around and decided to block execution of files from within that directory, I’d be surprised.

      Strangely though, “Certification requirements for Windows Desktop Apps” version 10 requirement 10.1 seems to forbid installing apps to that directory by default. I wonder if it was allowed in “Windows 7 Client Software Logo Program Technical Requirements”.

    4. DWalker07 says:

      Right; don’t many browsers install themselves into the AppData folder (partly so they can update themselves every day without asking the user for consent)?

      Which means that the program’s executable could probably be overwritten somehow without asking the user’s consent, and then the next open of that browser… you are sunk. Well, whatever program overwrote the browser’s executable file is, itself, a bad program and could probably do bad things without replacing the browser’s executable.

  10. Ray Koopa says:

    I think the subtitles you can now add to the articles on the blog’s main page are a win for this blog, they’re quite funny.

    1. Jonathan Gilbert says:

      They were always there from the very beginning, actually, and only got lost temporarily when Microsoft migrated their entire suite of blogs to this new platform. I’m glad Raymond was able to get them working again — or, should I say, able to convince the blogs team to get them working again. :-)

      1. Klimax says:

        The only problem with them is, RSS readers like me don’t see them.

  11. Dave Bacher says:

    The application directory generally should not be a trusted location all the time.

    Here’s the problem. You have an on-by-default install technology that ships with the operating system, as a must-install component of the operating system. That on-by-default install technology creates folders under %USERPROFILE%\AppData\Local\Apps\2.0\Random\Random

    Users installing are prompted “do you want to install this,” and the experience is very similar to UAC. Most users could not tell you why sometimes the screen goes dark before it asks them yes / no and other times it doesn’t.

    Microsoft’s package manager is verifying it is OK to install the package, and then downloading and installing the package — making shortcuts, etc. If something else running in the user’s space can copy a library into that folder — without any prompting at all (which is the case for the Apps folder) — that is actively dangerous to the user’s computer and data.

    Note: changing the technology to off-by-default and requiring a redistributable won’t materially impact the problem given a ton of Windows software won’t run correctly without the technology being installed.

  12. Reelix says:

    If you’re wondering, this is mainly an issue where browsers prompt you to “Run” something you have downloaded. If you can get a malicious DLL with a commonly used name into their downloads folder, the majority of the applications the user runs will use said malicious DLL instead of the native Windows one.

Comments are closed.

Skip to main content