4

I have a situation where malicious files are being copied to the installation directory of some software and the software will load those files when making a call to LoadLibrary or DllImport (in .NET land).

If your software runs with administrator privileges, a P/Invoke on a malicious DLL can essentially run any code in an elevated fashion, using your application as a vehicle to do so on it's behalf.

Many of these techniques can be found in this question: Ways to inject malicious DLLs to exe file and run it

What I'm asking is how, as a software developer, can you prevent this type of attack? If I want to import user32.dll into my application and make a call, how do I know it's loading the right one?

In the LoadLibrary documentation they do hint at this problem existing but don't exactly explain what you are supposed to do to avoid it at all costs.

Do not use the SearchPath function to retrieve a path to a DLL for a subsequent LoadLibrary call. The SearchPath function uses a different search order than LoadLibrary and it does not use safe process search mode unless this is explicitly enabled by calling SetSearchPathMode with BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE. Therefore, SearchPath is likely to first search the user’s current working directory for the specified DLL. If an attacker has copied a malicious version of a DLL into the current working directory, the path retrieved by SearchPath will point to the malicious DLL, which LoadLibrary will then load.

A simple solution like checking if the file is in a search path you don't expect (such as side-by-side with your executable) doesn't work very well because the assembly name can be changed and a redirect put in place.

UPDATE: This article on Dynamic-Link Library Security explains things well, however, all these techniques can easily be bypassed by the same process copying the malicious files. I've seen DLL Redirection used to redirect to the malicious files as well. I fear even programmatic approaches can fail because your applications can be modified anyway to still load the malicious files.

Are all Windows applications doomed to have this security flaw in them?

BrutalDev
  • 202
  • 2
  • 9
  • `I have a situation where malicious files are being copied`, `the software will load those files` -> can you actually start working on prevent that in the first place? – usr-local-ΕΨΗΕΛΩΝ Oct 11 '19 at 22:34
  • @usr-local-ΕΨΗΕΛΩΝ - You actually can to some extent, we added internal signature checks to ensure the files being loaded are the correct ones, if that gets modified you can also do internal self-checks on the digital signature and close the app, those can be bypassed as well but it just gets more and more difficult to accomplish but not impossible. – BrutalDev Oct 13 '19 at 08:10

3 Answers3

3

DLLs and other binaries could be signed (see here for how to check signature).

If they are not, or if you don't want to go that way, but you know what library you are supposed to load, then you can verify the library's checksum before loading. Acquire a read lock on the library and release it only after successfully loading it; this way, you avoid the small chance of a race attack (replacing the DLL after the checksumming but before the loading).

But yes, you need to load the library using the explicit full path, otherwise an attacker can just place a the DLL with the same name in any directory that's checked before the right one. So:

  • get the full path
  • lock the file
  • verify its signature
  • load the file
  • unlock the file
  • lather, rinse, repeat for the other DLLs

One possibility to verify whether Authenticode is trustworthy or not is to supply a tampered library of your own. Try loading it and verify that Authenticode check fails. If it does not fail, you will know that the system has been tampered with, and is not to be relied upon.

Just to be sneaky, you can try loading the tampered library and set a flag, do a bunch of other things, then acquire a lock on wintrust.dll and generate a checksum. Whatever the checksum says, if the flag has been raised, refuse to go on and act as if the checksum was invalid (you could inject the flag's contents into the algorithm to ensure the check will fail).

LSerni
  • 22,521
  • 4
  • 51
  • 60
  • Thanks for the answer. All files are signed (authenticode), but that means wintrust.dll just gets cracked (which is exactly what happens) meaning all tampering of signed files and internal checks to verify them goes unnoticed. I think there may be too many different checksums of things like kernel32.dll to make that check viable. Checksum checks can also be easily removed, which invalidates the signatures, but as mentioned before wintrust.dll just gets loaded in the same way always responding with "Valid" to internal checks. – BrutalDev Oct 24 '16 at 17:44
  • 1
    I was going to point out that these checks assume the attacker doesn't already completely own the system and there's some meaningful escalation of privilege intended here - which is apparently not what @BrutalDev has in mind - but I guess the comment above mine does that well enough already. Obviously if the attacker (excuse me, "software written with malicious intent") already has the administrative privileges necessary to modify system files, then there's nothing you can do to prevent it from modifying any other files, or injecting code into running programs. – CBHacking Oct 11 '19 at 23:36
3

.NET has an DefaultDllImportSearchPathsAttribute you can use on a per p/invoke or per assembly basis to constrain LoadLibrary to only get the DLL from 'safe' locations.

[assembly: DefaultDllImportSearchPaths(DllImportSearchPath.System32)] 
0

Are all Windows applications doomed to have this security flaw in them?

To answer just this part of the question: No, of course not, because most applications don't operate under the extremely insecure set of preconditions necessary for this question to even apply.

  • Don't ever load code from a location that a less-privileged process could write to.
  • Don't ever let a less-privileged process write to your install directory.

If your attacker can write to your install directory (for example, to drop a DLL Redirection file), then they could probably just replace your executable, or at least edit it. Even if they have write access to the dir but not to your executable or existing local DLLs, and DLL Redirection is already enabled (it takes Admin to toggle it), you've already screwed up.

If your attacker is less privileged than you, give them a location where they can write files (and your process will read them, presumably) that is not your install directory. If your attacker has the same privileges as you, they don't need to plant DLLs for you; they can do anything you can do or just hijack your process using debug APIs once it starts.

EDIT: This isn't Windows-specific, either. This is how literally all general-purpose operating systems - even locked-down ones like iOS - work. The solution is the same, too: don't run potentially-untrustworthy code with permission to modify executable code loaded by more-privileged (or even differently-privileged) programs.

CBHacking
  • 40,303
  • 3
  • 74
  • 98
  • 1
    You are thinking of this in terms of someone "attacking" a machine which is not the case. To install the software you need to be an admin (program files), which implies you have access to copy and alter everything in the directory you install to. The question is how to prevent this, and since users will have full access to their own machines, they have the ability to make these modifications. These are not "extremely insecure set of preconditions", this is very typical for any software being installed. Installation location will only prevent unauthorized users, not admins on the machine. – BrutalDev Oct 11 '19 at 22:26
  • 1
    @BrutalDev Sorry I didn't even think it necessary to address that. Obviously you cannot prevent somebody who has the ability to install programs from installing programs that do malicious things. As I pointed out, if you can write to the install location, you don't need DLL planting or anything like that; just modify the executable itself. If you're asking "how can I prevent somebody with the ability to install arbitrary software on their own machine from installing anything malicious", I have a perpetual motion machine to sell you. – CBHacking Oct 11 '19 at 23:14
  • 1
    Also, security doesn't mean "no DLL planting", it means preventing unauthorized actions. If you, an admin, authorize a program (installer) to run, you have delegated all your administrative authority to whoever wrote that program. It's only a security flaw if the program runs without you authorizing it to do so, or if it is able to do things you didn't authorize it to do. You authorized it to "do anything an Administrator can do", when you launched it with Admin privileges. – CBHacking Oct 11 '19 at 23:20
  • By the way, "attacker" doesn't always mean "person sitting at a keyboard trying to break in right this moment". In this case, the attacker is the malicious software. In security, an attacker can be any agent, including a software agent (program), a network node, a physical device like a mouse or hard disk... A person was presumably involved at some step, but not necessarily immediately. If it makes you feel better, substitute "software written with harmful intent", or just "malware" in place of "attacker" in my answer. – CBHacking Oct 11 '19 at 23:31
  • Your answer is not constructive in the context of the question. You could have simply left it as "yes they are doomed if the person has admin access to the installation location" which you would because you installed the software. The point of the question was to determine if there is a way to prevent malicious drops to prevent software from being cracked. This is not a controlled network or machine, it just software/games people download and install. – BrutalDev Oct 12 '19 at 19:45
  • @BrutalDev what you're apparently trying to prevent will have no impact on the difficulty of that). The only way to meaningfully answer your question as asked is to make the assumption that we all did: that there's some potential escalation of privilege from non-admin to admin. If everybody starts as admin, then of course you can't prevent them from doing anything at all. Once you understand that, you'll hopefully understand the question you meant to ask is. – CBHacking Oct 12 '19 at 20:54