Best practice: Write files to C:\ProgramData only readable by administrators - windows

I am working on a program that runs as a service and needs to keep some dynamic files. I have decided to create a folder in %ALLUSERSPROFILE%\MyFolder, i.e. C:\ProgramData\MyFolder and put my files there (in subfolders).
The data in the files can be sensitive, so it is important that only administrators can read them, not normal users.
So far, I have just created C:\ProgramData\MyFolder during installation using the CreateDirectory API and specified a restrictive Security Descriptor. All the files and folders I have created have then inherited this Security Descriptor and it seems to have worked fine.
However, I suspect this is not really secure: I suspect an evil user could create the folder C:\ProgramData\MyFolder before my application is installed. He could make himself owner of this folder and then set permissions as he sees fit.
So what should I do to avoid this problem?
I could try to call SetNamedSecurityInfo on C:\ProgramData\MyFolder during installation if the folder exists. But it looks somewhat hard to get that done right. For example, SetNamedSecurityInfo takes a security descriptor in another format than functions such as CreateDirectory. And there are a lot of flags that seem to control inheritance in various complicated ways.
I could try to delete C:\ProgramData\MyFolder and everything contained in it during installation and then recreate it. But it seems pretty invasive to me to just delete an entire subfolder regardless of its content.
I could create all my files in C:\ProgramData\MyFolder and subfolders with CreateFile using the CREATE_ALWAYS flag and with my restrictive security descriptor. In this way I will not rely on inheritance. However, it seems somewhat inelegant: What if an administrator wants to give everybody read access to C:\ProgramData\MyFolder after my program is installed? That will not be possible since my program rewrites files regularly.
I will appreciate any guidance!

Calling SetNamedSecurityInfo is not harder than CreateDirectory, the basic security descriptor members are the same, it just wants them as separate parameters. Given a SECURITY_DESCRIPTOR intended for CreateDirectory, just call GetSecurityDescriptorDacl to get the DACL pointer etc.
There is also SetFileSecurity and it just takes a SECURITY_DESCRIPTOR as the input. This function might only follow the NT4 DACL rules so calling SetNamedSecurityInfo is probably the best option.

Related

On Windows/NTFS can a symbolic link be moved to another computer?

For the purposes of a security test involving Windows servers, I would like to attempt uploading a Symbolic link to a Windows web application. However, based on the information officially available, it is unclear whether Windows hard links (Which I suppose are the same as NTFS junctions) exist as a file that can be copied from the hard disk the same way it does on Linux. It's vague, but I get the sense that NTFS junctions are some other kind of file system artifacts which is different than "regular" files - I can't find the documentation to confirm or deny this. I.E NTFS I want to know if NTFS supports the direct manipulation of the symlink record such that I could move the symlink to a different computer.
I am aware that Windows softlink files (.lnk) are not limited in this way, but they do not suit the purposes of the test.
My Aim is to copy a symlink off of a virtual machine, and then upload it to the server which I am testing.
Is this possible? (I am under the impression it is not.) From what I have seen absolutely every program on Windows would regard the hardlink as the destination file. Is there a way around this, perhaps by using a special editor to temporarily corrupt the file? If the symlink exists as a normal file on the file system can the symlink be altered so it can moved to a non-Windows OS for further use?
Let me know if this would be a better question for server fault. Since this is not directly about security, and is more of mundane technical problem in the service of a security exercise, I don't think it would fit on Stack Exchange security.
It's hard to provide a very direct answer. I work on a backup/repair/imaging project, and I copy whole disk images to a server via a web service - so, it's possible to do what you want, but there's a lot to consider.
Hardlinks
It is generally assumed that hardlinks cannot be distinguished from each other, however, there is a subtle difference between linked files and their "original" file. That difference is that queries to the $MFT (using USN-related arguments on the winapi function DeviceIOControl) will only return one of the files. This may be considered the original file. You can then call the winapi function NtQueryInformationFile to enumerate the hard links.
Symlinks and junctions are different animals...
You can know that a folder is a junction or a symlink, by getting the attributes from it. There's a ReparsePoint flag in the attributes if it's a junction or a symlink. BTW - the difference between junctions and symlinks is that the junction is a redirect to another location on the same volume, while a symlink is a redirect to an off-volume location. The redirect target is always another folder either way.
What's interesting is that both symlinks and junctions look and act like folders, while they are really files containing redirect information. When you open 'em, NTFS will normally look at the redirect, and open the redirect target. NTFS checks the permissions at the redirect target, so as an attack, this might not be a robust strategy.
When opening a junction/symlink, you can add a flag FILE_FLAG_OPEN_REPARSE_POINT. When you do this, NTFS does not perform the redirect, but opens the content, which is actually redirect information, and assuming you know the format of that information, it is possible to reconstruct the junction/symlink at the server. Note that the redirect may point to a location that may not exist, or may exist only temporarily. This is expected as some network resources may not always be available.
So, in short, it's possible to copy a junction or a symlink...while copying a hard link nominally means copying the file...with the foregoing subtleties in mind. You can create a hard link manually, too, as long as the target file exists.
With hardlinks, there's one interesting kink in the NTFS security picture. If a user has access to a file, and you create a hardlink to that file in a folder the user doesn't have access to, the user can still open that file using the path to the hard link. This is because the link and the original file are both pointing to the same file (and security info) on disk. Permissions changed on any of the links affect all the links. Without knowing this, you can inadvertently wreak havoc on a file system :-)
I know this is a bit helter-skelter, so let me summarize this way:
NTFS directory entries can be folders or files. Hardlinks are directory entries that all point to one file. Symlinks and junctions are really files that act like folders for most practical purposes (until you know how to get at the redirect info as described above).
AFAIR, NTFS (directory) junctions are actually symbolic links. The juctnion is implemented as a special file attribute called repars point that contains the link target.
Hardlinks, on the other hand, are implemented as direct references to the base MFT record of the target file and are stored as regular entries inside directory tree. You actually cannot distinguish a hardlink from the "original" file (every file and directory actually has at least one hardlink since it is contained somewhere within the directory tree).
If you wish to copy a symbolic link itself, you need to know that it is a symbolic link and extract the information about its target. File operations (except deletion and, probably, renamng) are redirected to the link target. So, you can, in general, copy a symbolic link by creating its exact copy in the destination area.
The actual question is, whether the interface you are using to perform the copy operation allows you to create symbolic links on the target.

Is there a way to append/remove a resource to a binary at execution time?

Is it possible to append/remove a ressource file to a binary at execution time?
I have an application written with go, which saves/searches data from a database file, and i would like this database file to be embedded to the binary, and updated by the application itself.
This way the application would be self contained with its database.
Modifying the executable, this is generally a very bad idea.
Several issues pop right into my head, such as:
Does the current user have sufficient permissions?
Is the file locked during execution?
What about multiple running instances of the application?
Even if you manage to do just that, think of what anti-virus and firewall applications will say to it: most when they detect the change will flag the executable and/or contain it, or deny running it, or some may even delete it. Rightfully, as this is what many viruses do: modify existing executables.
Also virus scanner databases maintain reports where files (their contents) are identified based on the hash of their content. Modifying the executable will naturally change the file content hash, thus render the file unknown / suspicious to these databases.
As mentioned, just write / cache data in separate file(s), preferably in user's home folder or in the application folder (next to the executable, optionally in sub-folders). Or make the cache file / folder a changeable option (command line flags).
Technically, this is possible, but this is a bad idea. Your application could be run by users not having write permissions to your binary.
If you're talking about a portable app, your best option might be using a file in the same directory the binary is located, otherwise - use the user's home directory according to the conventions of the OS you're running on. You can use the os/user package to find the home directory.

Should application log files and user generated data files be stored in APPDATA or PROGRAMDATA

We are migrating our APP to Win7. The program generates log files to help us support and also saves a number of dictionary files and settings files that are useful for the user though the user will rarely if ever actually want to interact with the files outside of our application. They can though because they are csv files. I built the first run through with using the APPDATA\LOCAL\OURAPPLICATION folder as the destination. Now I am wondering if it should be PROGRAMDATA\OURAPPLICATION.
I actually think the first choice is better because it seems that everything I have scanned suggests that the PROGRAMDATA folder should be considered untouchable by the user but as I am not a programmer I am not sure.
I hope this is the right place to ask this question
The key point to consider is what the scope of the data is. If you are storing data that is associated with a specific user then you should use APPDATA and if you are storing data that is global to your program then you should use PROGRAMDATA.
Both APPDATA and PROGRAMDATA are hidden folders so the intent is for users not to be poking around in there (not that they couldn't if they wanted to).

Recovering files after disabling UAC virtualization

We're finally getting around to moving our software's documents out of the program's own directory and into "My Documents". We're also adding a "requestedPrivileges" line to the manifest to prevent further trouble with virtualization.
However if we only did that then anyone who had been running the old versions in Vista/7 is likely to lose their work somewhere within the hidden VirtualStore directory after updating. So what's the preferred way of migrating into the 21st century?
Frankly I'm a little wary of copying files around, especially as I can't seem to find a programmatic way of getting at the shadow directory, but presumably plenty of other people must have had the same problem before us.
Don't add requestedPrivileges unless you legitimately need administrative rights in order for your program to work - nothing in your description suggests that you do. That should also let you simply copy the files on the first boot as if they were still in your program directory, because any virtualization would still be in effect.
However, if you absolutely must do the migration without UAC enabled, you can find your files in %LOCALAPPDATA%\VirtualStore\path\to\file. For example, if your file would have been stored in C:\Program Files\OurApp\, you'll find it in %LOCALAPPDATA%\VirtualStore\Program Files\OurApp\.
To get the path to %LOCALAPPDATA%, you can use SHGetSpecialFolderPath with CSIDL_LOCAL_APPDATA as the CSIDL parameter.

Where you you store your setting.xml?

For several of our applications we use an application configuration file. It usually just stores some directory paths and a few universal settings. We usually save it in the application directory (C:/Program Files/MyAppName)
One problem we see is users want to edit this (from the application) while logged in as a user that doesn't have access to write to the directory. Our applications are commonly installed and initially configured as an admin, but mostly used by (several different) limited users.
Is there a good way to make the setting.xml file read/write accessible to all users? Or a good place to put it?
C:\Documents and Settings\All Users\Application Data\<Your App> might be a decent place to consider.
Pass CSIDL_COMMON_APPDATA to SHGetSpecialFolderPath to get the writable, shared root data directory. Given that you can create a directory for your company and application.
Application data folder or moving to registry.
How important is localization? If localization isn't a high priority, you can store the files in %allusersprofile%\Application Data\ - that's the appdata folder accessible to all user accounts, and will work regardless of where things are installed, but only on English operating system installs.
If you want to store a file in the local user's directory and give each user their own, you can use %appdata% - that one will be entirely localized. But, each user will need their own copy, so it won't work if you need a common configuration.
If you need it to both be common to all users, and be 100% localized, you need to do a bit more work. I tried to find something like %allusersappdata%, and while I can find references online to that string, I can't get it to work on my own system. The workaround I found was to pull up %appdata% to find the localized text for the words Application Data, then use that to browse to that subfolder under %allusersprofile% - a bit more complicated, but it's the most bulletproof way I can find to do it. Someone please correct me if there's a direct path you can use to get to that folder.
I would try this previous question.
Which says:
System.Environment.SpecialFolder.LocalApplicationData
If you are using .NET

Resources