I’ve been messing around with permissions on Windows lately. Not so pretty. Almost chocking at times.
It’s a long story though, and to shorten it just a little, I wasn’t entirely happy with the way the utility xcacls
works. Its’ flaws made me curious enough to lean over the edge and dig deep into the horror known to man as The Windows API.
xcacls
is a utility made by Microsoft to manipulate permissions from a command prompt, originally released as part of the Resource Kit for Windows 2000. Although the utility was released on Windows 2000, little has changed in the NTFS
specification, as far as file and directory permissions go – xcacls
still does its’ magic on XP and Vista as well.
Permissions on Windows are controlled in an ACL
, an access control list, carried in every file and directory. Every ACL
has a set of ACE
s (access control entry), which is basically a compound of a user or group identifier, a deny or allow rule, and a set of flags that further describe how the ACE
is to be enforced and inherited to child objects (a file is to its’ containing folder as a child is to its’ parent).
This could be a pretty clean approach to access controlled content.
A summary of what was going on is in order, so here it is. I was building a VBScript
at work, to solve an annoyance of mine. The computers we’re hosting are locked down systems, clients based upon Windows XP professional. On the laptops we’re occasionally hosting, the locked down policies on the system makes working on it a little quirky while not being docked to a stationary area, where one can access the network storage and other network resources. Because users may choose to do work on the laptop several weeks unconnected, they need a temporary yet somewhat protected area to put their files in.
So basically, we create a folder in the root folder of the system drive, then add to the user group “Everyone”, the permissions to write and alter files and folders in this particular folder, but also deny them the right to delete the folder itself.
As a final convenience, we place a shortcut to it on the desktop of all users. Simple enough to do in the GUI
(graphical user interface). Even the tricky part, here being to check the right checkboxes in the permissions dialog. But, as it turns out, doing this programmatically is a flagrant nightmare.
So there are utilities to make this as easy as pie. Mmmm, pie!
Apparently Microsoft didn’t read the recipe on this one, because xcacls
fails. It runs fine and all, and the permissions seem to get set just fine… unless of course you check with the GUI, where you get abused by this fancy error message: “The permissions on [folder name] are incorrectly ordered, which may cause some entries to be ineffective. Press OK to continue and sort the permissions correctly, or Cancel to reset the permissions*“. This guy describes the problem so well, and I qoute: “Apparently using the program in a way that is concistent with the instructions is not supported”.
At this point, when you come down to it, there are two ways to respond to this. There’s A, nod in silent distaste, reorder the entries and be happy with the fact that although you still have to manually adjust things, you’ve just automated 80% of the previously manual work. And there’s B, refuse to accept anything less than perfection, and especially refuse to accept the fact that you can’t properly adjust settings programmatically, which can otherwise be set in a GUI by the click of a mouse button.
I’m a B kind of person.
When I arrived home that evening, I searched around for clues on what had happened. There weren’t many. Especially since we’re using a multilingual version of Windows, which means all error messages are obscured at best. So I turned to the MSDN library, the main resource for all programmers programming on Windows, to read up on ACL
s and access control on Windows. At this point I wanted simply to know why this error message was showing. Turns out ACL
s are pretty complex, as described earlier. Didn’t really do it for me in the documentation though.
So I blew the dust away from my compiler, run Microsoft Visual Studio 2008, and took my usual approach to cocky, logical numb spots refusing to comply, I dissolved the matter into its’ building components.
It was now personal, and curiosity didn’t kill this cat!
I dug into winnt.h
to find the appropriate definitions of ACL
s, ACE
s and headers respectively. I messed about with API calls, such as GetNamedSecurityInfo
, GetSecurityDescriptorDacl
, GetAclInformation
and ultimately GetAce
.
While reading the documentation of this last one, GetAce
, I browsed its’ sibling nodes on the hierarchical tree of related topics. I came across something called “Order of ACEs in a DACL”. The “D” in DACL
is discretionary. It’s complicated, I’ll address that some other time. “Order” being the right password, I checked it out.
The access control API lets you add or delete ACE
s. It does not provide you with a method to insert an ACE
. Rules in the ACE
s are handled in the order they are defined, not by the function they have on the object it protects. If you need to insert an ACE
, you are responsible for putting it in the right order in the list, or you can ultimately render the whole access control list useless, either blocking all access or allowing all access, depending on what the ACE
does. If you can’t just append the ACE
to the list, but indeed have to put it somewhere in the middle of all the entries, you have to create a new ACL
and basically create a new ACL
, GetAce
the old entries and AddAce
them to the new ACL
, inserting your own ACE
at the appropriate place in the list, then SetEntriesInAcl
to the object. Of course, you have to make sure there are enough memory reserved to hold your new ACL
, which of course is also your responsibility.
Suddenly it struck me. xcacls
have inherited the same erroneous logic as the API
s it’s using. It just goes ahead and AddAce
whatever you tell it to do, which means in my case more specific ACE
s are placed below inherited ACE
s, and so of course the order is wrong.
This new knowledge is infuriating. Not that a utility from the 20th century isn’t working, but the fact that the order of ACE
s in an ACL
this is still a pickle! This means basically that third-party utilities and/or applications addressing these API
s for whatever the reason, are responsible for placing the ACE
s in a certain order, or parts of the operating system may not function properly. Are file permissions not an important enough issue? And hey, google confirms third-party applications (as well as Microsoft’s xcacls
) are having trouble with the API
s.
To you and me, on our desktops at home, this may or may not qualify as eyebrow elevating material. But to a bank, for instance, incorrect file permissions may jeopardize your personal records, information private and delicate to you.
And worse yet, ACL
s are not used only for protecting files in a system. ACL
s have evolved to protect other, more delicate portions of the system. Keys in the registry, for instance. Certain tasks between processes/applications, inter-process communication. Permissions to the Active Directory
, the main database in a domain of Windows servers. If the people coding malicious software find themselves hesitant on where to begin looking for exploitable features, I’d recommend a dart board.
The routine to check if ACE
s are in the correct order is clearly there, or the GUI
would never have complained in the first place. How about moving this check to the point where your are actually setting the ACE
s, instead of until later, when the potential damage is already done?
Having said that, I’ve found another (third-party) utility called fileacl
, that looks promising. Microsoft sort of recommends it. Check it out at http://www.gbordier.com/gbtools/fileacl.asp!
EDIT: As seems to be almost always the case, there is a superior open source project on Sourceforge called SetACL
. Blindfolded and hand-cuffed, it would still kick the sorry butt of xcacls
, cacls
, icacls
(Vista) and probably fileacl
as well, from here to orbit. In seconds.
*) On a side note, clicking on Cancel in this dialog, revert permissions to default settings – full access to everyone.
Filed under: Programming, Security, Fail, Microsoft, Open source, Programming, Security, Windows