Contact

Subscribe via Email

Subscribe via RSS

Categories

Creative Commons Attribution 4.0 International License
© Rakhesh Sasidharan

Elsewhere

Beware of takeown and recursively operating

takeown is an in-built Windows tool that lets you take ownership of files and folders. Unlike other tools (e.g. icacls) which only let you give someone the right to take ownership of a file or folder, takeown seems to actually let you become the owner. And not just yourself, you can run it under a different context and that user account can be made the owner.

But it has a quirk which isn’t obvious until it turns around and bites you!

Here’s what I am using takeown for. I have a bunch of roaming profile folders that my admin account can’t view because only the user has full access to it. If I were using the GUI I would have opened the security tab of these folders, changed ownership to myself or the Administrators group, set that to propogate to all the child folders, and then add myself to the ACLs of this folder setting it to replace the ACLs of this folder and its children.

I have a large number of such folders, however, and I want to create a batch file to do this easily.

The obvious solution is to use takeown.

But this only sets the ownership of the parent folder. Not a problem, there’s a switch /R which tells takeown to recurse, so let’s try that:

Note that harmless question: do you want to replace the directory permissions with ones granting us full control? Harmless, because that’s what you would do via the GUI too. Gaining ownership of a folder doesn’t give you any permissions. That’s a separate step, so it seems like the command is only being helpful and offering to do this for you (so it can peek inside the sub-folders and give you ownership there too). And there-in lies the quirk which turned around and bit me. If you answer YES to this question (or use a switch /D Y to answer YES by default) it replaces the existing permissions with a new set. Yes, replace, not append as the GUI would have done. The net result of this is that once you run the takeown command as above only the Administrators group has any permissions, even the user loses their rights!

That’s definitely not what we want!

The right approach here seems to be to use a mix of takeown and icacls.

First use takeown to get ownership to the parent folder:

Then use icacls to recursively grant Full Control to the parent folder and sub-folders. Note that this only appends to the ACLs, it doesn’t replace. (This takes a few minutes and there’s plenty of output).

I don’t know why AppData failed above. It did for all the profiles I tested with and I didn’t investigate further. Could be an icacls limitation I suppose.

At this point the roaming profile is owned by Administrators, and the ACLs have an entry for the Administrators group in addition to the existing ACEs.

Now I run takeown again, recursively, but this time I target only the sub-folders (i.e. not the parent folder, only the ones below it).

takeown doesn’t have limitions like icacls. It’s ruthless! It will change ownership of all the sub-folders – including AppData – and replace the ACEs granting Administrators full access.

Now I run icacls on all the sub-folders, enabling inheritance on them. (This too takes a few minutes, but there’s no output except towards the end). The result of this step is that the botched ACEs set by takeown are fixed by icacls as it enables inheritance.

And that’s it. That’s how to properly use takeown and icacls to take ownership and reset permissions on a folder and its children.

Setting file ACLs via PowerShell

Yesterday I ran WireShark at work with my admin account and saved the results to a file. Later I moved that file (as my admin account) to the desktop of my regular account so I could email it to someone. But as you know moving has the effect that the original permissions are retained so even though the file was now in my regular Desktop I as a regular user couldn’t access it.

Running Explorer as an administrator doesn’t help either. Because of UAC when I right click Explorer and do “Run as administrator” it still runs as me but in an elevated context. This is an Explorer specific quirk. So unless I were to logout and login as my admin account, there seemed to be no way of changing the file ACLs to give my regular account permissions.

But of course there are ways. PowerShell was my first choice (coz I knew it had a Set-ACL cmdlet) but I wasn’t sure how to assign permissions using PowerShell. A quick web search got me to this blog post that summarizes what needs to be done. Up shot of the matter is you do something along these lines:

What you do here is that first you store the current ACLs of the file into a variable. Then you create a new ACE object with the permissions you want. Add that to the previous variable and assign the new ACL to the file.

While the above is useful, it would be good if I could just copy the ACLs from a file with ACEs I like to the file I want to modify. Something like this:

This doesn’t work though.

If I run this in a PowerShell session under my regular account it fails (obviously):

But if I run this under my admin account, then too it fails (though for not an obvious reason):

This is because by default Set-ACL also tries to set the owner ACE, and since the owner is different from the user account under which Set-ACL is running it gives an error. In Windows you can’t assign someone else as an owner unless you have a privilege for doing that (the SeRestorePrivilege privilege, see this MSDN page). All you can do is grant someone a Take Ownership permission and then they have to take ownership. (See this forum post for more info. Another forum post gives a workaround. Also, this blog post from Lee Holmes is useful in the context of the second forum post).

So a simple copy-paste is out of the question …

I still might be able to fix this easily though. Remember the reason the file (in my case) has a different set of permissions is because its ACEs are protected from inheritance. If I had copied the file over instead of moving, then permissions won’t be protected and inheritance would have kicked in. But since I moved the file here its permissions are protected. I can confirm this via Get-ACL too:

So all I need to do here is remove protection. That can be done via the SetAccessRuleProtection method. This takes two parameters – the first determines whether protection is enabled ($true) or not ($false). The second is ignored if protection is disabled; but if protection is enabled then it determines whether the inherited rules are kept ($true) or discarded ($false) . Thus, in my case, all I need to do is the following:

After this the file has both the original ACEs as well as the ones inherited from my home folder (notice the last three rules in the list below):

Now I can just copy the ACLs from another file – with PowerShell running under my account – as I had tried earlier. This is optional, I did it so the permissions are consistent with others.

While on Set-ACL the following snippet too might be useful:

This takes the ACLs from an existing file and adds these to the file I want. Again, this only works if you already have permissions on the file – in case above, I could do this after I have turned off protection.

While on PowerShell and ACLs its worth pointing to this Tip post. That’s where I first learnt about PowerShell and ACLs though I admit I have forgotten most of what I learnt from lack of use. This blog post which I came across today is a good read too. I came across it while searching for how to enable inheritance.

Apart from PowerShell there are other commands which can set/ get ACLs. One of these is ICACLS, which is present in Windows Vista/ Server 2003 SP2 and upwards.

Interestingly ICACLS seems to be able to set the owner to another account even though PowerShell fails. Not sure why that succeeds …

ICACLS can also easily reset the ACLs with inherited ones (i.e. like the PowerShell above it disables protection but also replaces the non-inherited entries with inherited ones).

This is a good post on using ICACLS. Apart from resetting and changing owners, you can also use ICACL to add/ remove ACEs, find files belonging to a particular user, and even substitute an ACE username/ SID with another. You can even save all ACEs of files in a folder and then restore them.

Lastly, if you are an administrator and want to take ownership of a file or directory, the takeown command is useful. It is not as useful as ICACLS which lets you assign someone else as the owner, but is useful if you are an admin and want take ownership.