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

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.

Related

Using Wildcard in Windows Firewall

We are using Turbo.net for Publishing applications. One of this application (designed by our own Company) uses a Broadcast to find devices in the Network and then get a reply by a dynamic UDP Port (30000 - 50000). Opening all These ports on the Windows Firewall is not an Option.
I have therefore tried to specify the exe file in the Windows Firewall. That works but the Problem is, I Need to do this for 200 users. So I want to do this by GPO. Unfortunately the path to the exe is something like this:
%userprofile%\AppData\Local\Spoon\Servers\apps.elpro.com\Users\Firstname.Lastname.Domain\Sandboxes\ECOLOGPROModuleConfigurator__1-4-8-420__en-us__Default__AnyCpu\local\stubexe\0x4D80DB43F65B57C8\ PROModuleConfigurator.exe
The problem is "\Firstname.Lastname.Domain\". I was not able to find a way to use a wildcard for this in the Windows Firewall.
It seems that Windows-Firewall does not allow Wildcards.
Is there an easy fix for this or do I Need to script something and if how?
Thank you!
The fact that it can handle %userprofile% tells you that it's okay with Windows variables, so the thing to do would be to set up more such variables, to pass this path as %userprofile%\AppData\Local\Spoon\Servers\apps.elpro.com\Users\%Firstname%.%Lastname%.Domain\...
Sorry there's not a copy-paste solution for you. It would take some scripting on your end to pull this name data out of Active Directory (or some Linux/Unix LDAP server – whatever your organization is using) and fill these variables on a per-user basis. On the up-side, the variables could have other uses once you get them set up, like naming backup directories on a NAS in %Lastname%, %Firstname% format, and so on.
Exactly how to do this will vary by coding language, by OS version, and by directory service type. The information about this is scattered far and wide, so you'll have to search around a bit. E.g., for how to get an AD user's real names with C# under dotNet 3.0+, see this StackOverflow thread. And there are lots of SO threads with info on using Get-ADUser in Powershell to find and filter by user's IDs and names. This thread on SpiceWorks might also be of interest.
You'll almost certainly need Remote Server Administration Tools (RSAT) for Windows (see that page for installation details, which are totally different depending on OS version, even within Windows 10!). Tools that deal with ActiveDirectory need the AD stuff in RSAT to do their work, including both Powershell and C#.Net. RSAT requires Windows Pro or Enterprise (on the machine you're going to use to do the AD work; user workstations can be any version). But AD itself requires Windows Server.
This is only going to be doable with an Active Directory or other LDAP server, in which this user firstname/lastname information, as such, is even stored. Local accounts do not have this information at all except when they inherit it in munged "full name" form, e.g. from Microsoft.com account credentials. In Powershell, you can run 'Get-LocalUser | Select *', or follow the more "deep dive" local-ADSI method demonstrated here, and you'll find no first and last name data. It's just not part of an account, absent some systemic means (AD, or Microsoft online account connection, or Microsoft Family Group management, etc.) of injecting it. There are multiple ways of manually adding "full name", but even doing this across a bunch of users probably would not help you, since human names are not easily software-parseable into first name and last name (Many people have two last names, and many have two or more given names; so what is "Pat Morgan Otero"? And of course given-name versus family-name order varies culturally.) There appears to be no way to add separate first and last name fields to local accounts; tools like Set-LocalUser cannot do it.
[aside]There's no connection between Windows user data and Windows Subsystem for Linux user data (even the usernames can be different), so that's no help. If you have a network-wide unified user ID system via LDAP or whatever, and it has an end result of everyone's user IDs and their real names being in account information under any Linux/Unix system on your network (print server, NAS, anything you can get privileged shell access to), then you might have an easier go of it, given the text-processing tools available to bash in Linux/Unix (including macOS), like grep and sed and awk. All you'd need is a command-line tool for accessing LDAP (or whatever) to run directory queries, then parse the results for name information. Or that name info might even already exist in that Linux box's passwd file. This was how I did something similar for one client, but it was a Linux-heavy shop. If you have any (or most) users isolated from Linux in a Windows-only sphere of users, then this approach would not work.[/aside]
It looks like accessing AD data (or LDAP, whatever) in Windows with Windows-based scripting/programming is the only certain way to do what you want to do. Even then, it will only work if the data is present and correct. You'd need group policy that doesn't permit people to change their names (e.g. by removing their surname) once their account is configured, and human procedural rules that admins must enter this data when setting up accounts, and that it be correct and complete (not missing surname, and not be placeholder or role data that might be substituted out later or might even occur on multiple machines).
PS: Ultimately, I think you should write to the creators of that software and ask them to stop using first and last names in paths, as it breaks the administrability of their product.

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?

Shell script to call another script for password

I have a shell script which has password in clear text used in a command :
--username = 'USER'
--password ='abc100'
I dont want the password to be in clear text here in shell script. Is there a way i can keep this shell script password protected or to not pass the password in clear text and refer another file which is password protected ?
To solve this question well, it's really important to know how what this password represents and what sort of risks compromising it entails. It's also important to understand who has access to the machine on which this script and password file are stored, how the machines are set up, who needs to run this script, etc. It's really hard to give a good answer without understanding the full requirements and risks.
Assuming that compromising this password could have seriously negative repercussions and assuming that lots of people who should not have this password need to run this script, it would -- in my view -- be a mistake to store this password on the machines of everyone who needs to run this. You may want to consider having a smaller number of machines with much more limited access store this password and offer the functionality of the script through a webservice that uses an authentication mechanism such as OAuth (with Bearer tokens for automated access). Then the question becomes how do individual users have a script access the Bearer tokens needed to invoke the web service; although the Bearer tokens are also sensitive, they would at least be unique per user (giving a way to better detect compromise and abuse, though that is something you would still need to implement). In that sense, the question becomes similar to the original question, but with lower stakes.
Assuming that we are now talking about storing Bearer tokens, how you store it will depend on how many different users can access the same machine / filer system. For example, if many different people can have root access on the same machine, there is very little you can do. If there is one user per machine, however, and only that machine's owner can gain root, then you can use UNIX permissions to help limit / control access to files. For example, you could create a user+group that is dedicated to this specific script, have the script always run with that permission (e.g. via the sticky bit), and have the Bearer token information stored in a way that is readable only to that user/group (as a way to prevent other programs run by the same user from accessing that credential). In a setup where many people use the same machine but the people who can run as root can be trusted, you might just store the credential in a folder in the user's home directory that is accessible to only that user (and not readable/writable by the same group or other users); however, this does risk other programs run by that user reading the data. You could attempt to have the script encrypt/decrypt the content of the file on disk (e.g. embedding the key to encrypt/decrypt the data within the script), though unless the script were highly obfuscated and was regularly updated with this key rotated, that would do very little. You could also impose a short expiration on the bearer token so that the token need to be refreshed often as a mitigation measure to other programs misusing the token after it is no longer being used.

Best practice for storing cross domain web service access credentials?

I'm working on an application that will connect to various remote servers using a Web Service to retrieve some status information about those ( Windows ) machines.
It works well within a single domain where we can just use Windows Authentication and ensure that the user calling the services has the correct credentials. However if we are working across domains that is not going to work- we're going to need to store a set of credentials for a user with the requisite rights on the application side.
Is there a standard way of storing credentials for these purposes, some kind of central password store in Windows or a handy built in library to provide this kind of functionality? If not, what is the best approach to keeping the passwords on the central machine safe and make sure the remote machine credentials are available when those services need to be called?
I would expect this application to mostly be installed on one of the Windows Server operating systems- 2003 or 2008 - if that makes any difference to what is available.
I suggest you have a look at "Windows Identity Foundation". It may be overkill for you, or the prerequisite may not match, but it's anyway worth reading as its very instructive in terms of claims based architecture with Microsoft technology.
The two principal white papers for developers are:
Overview of the Claims Based Architecture
Microsoft Windows Identity Foundation (WIF) Whitepaper for Developers
I assume that this is not a question of Silverlight or Flash application, those would have some special things...
I have used authentication system by Federation of Finnish Financial Services (used by all major Finnish banks). It goes like this:
Both your client and server have a secret key (or 2 keys).
You can store it e.g. to a custom place in Windows registry (which is easy with .NET and you can control the registry access). Don't hard-code the key to code, because otherwise someone could use reflection to get it. Also a custom xml-file in a folder could be dangerous, if the platform is not secure enough.
Then, we have the request, let's say WebService REST Url and there is some id:
http://myserver/MyItems/15
Now, we need to use a timestamp and an one-way hash-algorithm.
There are lot of available ones like md5, SHA1, SHA512, ...
(also built-in to the Microsoft .NET library).
We calculate a hash-value over the id and timestamp (and maybe some other parameters).
To simplify a bit, those algorithms work like modulo-algorithm: Let's say that my id is 11, secret key is 3, then modulo 11 % 3 = 2, now the hash would be 2, and if you know the id (11) and hash (2), you can't get the secret key.
The real request would be like this:
http://myserver/MyItems/15?timestamp=20110304171900&hash=89A234BA645FD56
The service will check the hash. If some hackers would have enough time, they could guess valid requests.
But the service will also check if the timestamp is ok, like between 5min past and 5min future.
So you can't adjust the request because it would modify the hash.
And of course one more thing is to use the SSL protocol. Otherwise your requests could be read from a random proxy server.
I would also recommend the Windows Identity Foundation, but this is another option.

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.)

Resources