How to properly drop (remove or disable) privileges in Windows? - windows

I'm trying to write a secure application that performs a privileged operation on Windows (in particular it changes system time). Because of that I ask the user to run this application with Admin privileges. As one of the first things I want to do in the program is to drop all unnecessary privileges from my access token to limit the impact of any bugs I introduce later. From the Microsoft documentation on the topic I understand that I can either "disable" those privileges via AdjustTokenPrivileges, or create a new access token with "removed" privileges via CreateRestrictedToken and relaunch my application with it. If I understand this correctly the disabled privileges can be re-enabled at any time, so any sufficiently compromised application will just do that and ignore any restrictions I tried to impose. On the other hand, If I remove the privileges completely with CreateRestrictedToken they can't be added back, which sounds safer and what I'd generally imagine under the term "dropping privileges" (also this way sounds like an enormous amount of hassle with the relaunching and such).
I suspect that this understanding might be wrong. What would be the most appropriate way of dropping all but needed privileges in Windows?

My understanding was indeed wrong. Despite what the documentation claims, you can "easily" remove privileges using AdjustTokenPrivileges() by setting the attribute SE_PRIVILEGE_REMOVED to the appropriate privilege in the NewState field.

Related

Windows: where can I store data secretly in order to implement a time-limited demo?

I'm writing a Windows app that has a time limited demo. There's not going to be a server that the app can phone home to, so I need to store data on the system in order to figure out if the demo has been started and how much time is remaining. The location of this data needs to be obfuscated so that a typical user (and possibly even some power users) are unlikely to be able to find it.
I already know the logistics of how to implement a time limited demo as long as I can store data secretly somewhere on the system, but I'm not sure how to do that last part. The requirements here are:
The data needs to be globally readable and writable so that any user account can access it and modify it without requiring elevated privileges (as the demo applies system-wide and not on a per-user basis)
Preferably it doesn't require elevated permissions to create the data, but if it's necessary to do that once (for example to create the data and adjust its permissions so that everyone has write access) that's acceptable though not ideal.
Whatever method or combination of methods I use to do this needs to work in Windows 7 and later
Does anyone have any idea on how I can accomplish this?

Speed of Windows' ImpersonateLoggedOnUser() + RevertToSelf() vs Unix's seteuid() + setegid()

In Unix, when doing some action on behalf of some user, a system program usually calls seteuid(UID) (with accompanying setegid()) to switch to that user first, perform the action, and on finish switch back to superuser using seteuid(0). I time seteuid() and it's in the order of one to several microseconds (meaning, it's quite cheap relative to the action that needs to be done like manipulating files or running a CGI program).
I'm not familiar with Windows API. Do we do the same thing on Windows (but using ImpersonateLoggedOnUser() + RevertToSelf() API functions)? In general, how fast are these functions?
It is mostly the same, but there is one important difference to keep in mind : the Windows API you mentionned require a HANDLE to a valid token.
In other words, even running as SYSTEM (or any process that has SeTcbPrivilege), you need to impersonnate a logged on user.
The user can be logged on many ways :
Interactive with at a physical computer
Through a Remote Desktop Session
Pretty much any Microsoft network connections like file shares, name pipes, mailslots, RPC and all the others built on top.
Creating a process will make it inherit the current token in most cases.
It does not matter whether you used Kerberos, NTLM or maybe HTTP BASIC auth in IIS. It's all authenticated by Windows, so you get a token. On the other hand, an HTTP BASIC authentication in Tomcat will not give you a Windows token, so impersonation is out of reach.
Now with the tricky part.
When you think about it, a token is really just a memory structure with access control lists for authorisation (DACL) and auditing (SACL). It is created by an Authentication Package (AP). It is the AP that creates the token. And somewhat like a PAM in Unix, an AP can be replaced by custom code.
As a matter of fact, an open source setuid Authentication Package exist. Folks who ported CVS to Windows NT did the work of writing an AP that creates a token out of thin air, as long as your have the SeTcbPrivilege (root equivalent). I have never tried it, but it could give a token on the local machine for a user that is absent. The code is rather old (it will only create elevated tokens) but besides that, it LGTM. There is no authentication, no password or smart card involved, so a process running with that made up token will not be able to use it to authenticate to another computer.
To conclude :
The general idea is the same
If you play by the rules, you will only be able to impersonate a logged on user, regardless of the login procedure or location
You can change that behavior, but it
Impersonation is probably just as fast in Unix and Windows, as the inner workings are roughly similar. Chances are you will not notice the difference.
A suggestion : my copy of Programming Windows Security is all yellow from coffee, with post-it notes hanging out and torn pages. The best text ever on the subject, a must read if you want to understand Windows security.

CreateProcessAsUser and LogonUser Without Password

Using WTSGetActiveConsoleSessionId and WTSQueryUserToken, I know it is possible for a service running as SYSTEM to launch an application onto the current desktop without using a password. Is to launch CreateProcessAsUser without needing a password for LogonUser provided the program launching the process has sufficient privileges?
EDIT 1: The situation is vaguely similar to this instance, but I need to be able to launch a process as a user regardless of whether or not they are logged on to the system at the time.
There is the possibility of using the undocumented NtCreateToken function; I think this example project uses it. Short of that, it is not possible.
Depending on the token you are trying to forge, you will require certain privileges, in particular the TCB one springs to mind. Services have that. The "Windows NT/2000 Native API Reference" by Nebett has an example.
However, services creating a process as SYSTEM on the current desktop is not as easy anymore since Vista. The improved session separation is the issue here. However, you could impersonate the user at the other end of a pipe and the current thread should be able to act as that user (e.g. SYSTEM).
Theoretically, at least, you could implement your own authentication package and then use it to generate a suitable token.
Another possible option, depending on your exact requirements, is to use the SidsToRestrict and PrivilegesToDelete option of the CreateRestrictedToken function along with SetTokenInformation to create a suitably modified derivative of your own token.
However, I would not trust this approach if you're going to be running untrusted code: I'm not entirely certain that it wouldn't be possible for a sufficiently ingenious attacker to use such a token to attack the parent process or other privileged processes. (In particular I'm not sure whether you'd be able to create a new logon session and assign it to the restricted token; this might not be the only issue.)

Is it acceptable for a server-based application installer to create a new group?

We're building an application designed to run on Windows-based servers. One of the considerations we're looking into at the moment is how to control access to the application's GUI, which allows configuration and controls the "back end" services.
In order to secure the application properly, there are several objects which will need ACLs to be applied - files, directories, Registry keys, named pipes, services etc. We need to provide administrators with some way to configure those ACLs in order to limit access to authorized users only.
One approach we have considered is to create a tool which can modify the ACLs on all those objects simultaneously, but that would be a fair chunk of work and could be fragile.
The other possible approach we're looking at is to create a custom group (e.g. "My App Users") so we can give that group the appropriate rights to each object. This means that administrators will be able to add/remove authorized users by using familiar Windows group membership tools.
So: is creating groups at install time an acceptable thing to do, or is it likely to upset administrators? I'm more familiar with the UNIX world, to be honest, where server-based apps are more or less expected to create groups, but I'm uncertain of the etiquette in the Windows ecosystem.
Also: is there a better solution to this that I've missed?
Thanks in advance!
The question is twofold - one technical, and one political. Technically a local group is fine, you can add AD or domain users into a local group and everyone's happy. In terms of whether an app should be messing with a server's security 'stance', the only reasonable answer is to pop up some kind of request telling the user what you are going to do and asking permission (make sure you also document the decision in some kind of log or entry). This also addresses everybody's legal a$$ eg if they click "no, leave my app unsecured" and get hacked).
Taking a UNIX approach, you could tell the user what you need, suggest a local group (and give the user the chance to pick another local or domain/AD group). Take a look at how (eg) Oracle installs on UNIX do it.
Since this is a server app and you might have to support silent/unattended install, make sure that the behavior can be specified in the install script and very, very sure that the behavior of the script is documented so that no one installs the program without realizing the change in security policy that the installer implements.
I think it's perfectly fine to create a local group for this purpose.
Furthermore I have not been able to come up with a better solution after giving it some thought.
Depending on the size of the implementation, groups could be the way to go.
But please keep in mind that the relevant ACLs on directories and the registry ought to be set. I do agree that setting them once to the group and then let access control be maintained by group memberships.
In regards to klausbyskov's answer, I think a local group could be fine, but consider using LDAP instead. From a security perspective you would detach the authentification process and let the Directory handle it; using kerberos.

Mark an Active Directory Object as "Read-Only"?

We had a bad day yesterday. One of our Domain Admins deleted an OU containing 700+ users and the same amount of computers as well as assorted other useful things like groups etc.
We restored from a backup, but it wasn't pretty.
I know that ADUC asks you if you're sure etc... but I'd like it if it was not possible to delete this particular OU without going into something like ADSIEdit to set it "allowable" for deletion - thereby not allowing people to delete without actually opening a new app and specifically indicating that "YES - I know what I'm doing". This would have the added benefit of stopping accidental miscoding from deleting critical AD objects.
Any such attribute or method that you folks could think of?
There is a feature in AD for Win2k3 and higher to mark an object to prevent accidental deletion. This check box on the object actually changes the underlying permissions for you to remove delete permissions. Therefore it is not tool specific and must be respected by other tools (like powershell and vbscript).
Simply remove the permission to delete things from those unable to get it right. You can give very fine-grained permissions in AD.
There is no "readonly" attribute. That's what the ACLs are for.
You could deny the Delete privalge from Administrators through Delegation at the root level and then you would need to be an enterprise admin to perform deletions. Ensure that no admins are in the Enterprise Admins group for day-to-day usage.

Resources