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 rogueTOTALLYSAFE.DLL
on the systemPATH
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.
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.
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...
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...
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.
@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...
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.
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...
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.
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...
OUCH: kids which are even unable to write their name are clueless!
Creating a junction requires NO privilege, every user can do this!
Isn’t there a user-local PATH variable?
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),...
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.
Is this just Windows messing up an upgrade or you intentionally coax it? Also, are there programs simply not working due to this?
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...
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.
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...
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.
If only things were that simple, Mr. Chen. Alas.
Rest assured, however, that I won’t be attacking myself.
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.
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...
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.
*cough* C:\Python27 *cough*
*cough* pythonclock.org *cough*
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.
Your comment has no sense. Please don’t write any more comments and let the rest of us enjoy Raymond’s ruminations.