Is it possible to store a Kerberos ticket to later use it to impersonate the user?
I have the scenario where a user directly invokes an external system to process some data. The external system relies on the user being impersonated/authenticated correctly in the AD.
Now the calling system has to change so that a queue sits between the user and the external system and work from the queue is handed over to the external system from that queue by a Windows service.
This service needs to impersonate the user in order for the external system to correctly handle user-rights.
Given that I can't change the external system and can not store the username and password in the queue, can I save a Kerberos ticket when the user adds new work items to the queue and later impersonate the user by the service when it hands over the data to the external system. How would I do that in C#?
Edit: This is the closest I can get to your actual question: Can you start a separate thread under impersonation, make the request from there, however long it takes? Under the covers this will do what is needed (unless the service process is terminated of course).
As a microsoft guy once told us "security is the thing which stops your application working when you deploy it". (His point was to test with a realistic security setup).
The ticket may have a lifetime of 10 hours but that is the time from when it was issued. It may only have a fraction of that left by the time the user makes the request.
I suggest you simply solve the underlying problem in a different way.
What is the reason why you now need to queue? Simply because the external service is choked at peak times?
Can you beef up or scale out the hardware? Usually the cheapest way.
Do you actually have completely separate permissions or do the users slot into a finite number of roles? If roles you could record the role the user was in, and use specially created usernames to access the external service, one for each role.
Is the external service yours? Can you add a "pretend to be Bob" option that doesn't rely on Windows Impersonation?
Can you start a separate thread under impersonation, make the request from there, however long it takes? Then mail it back to the user? (yes this will under the covers be doing what you ask)
Finally you could place the user in a browser "ration queue". I.e. issue them with a number, then have the browser refresh every 10 seconds (or use Ajax) to tell them how many people ahead of them in the queue. When it is their turn, make the actual request under impersonation. (This requires them to keep the browser window open while waiting in the queue, and also requires you to keep track of outstanding requests and active browsers vs. gone-away browsers). Nasty, but will work.
Without knowing the actual problem, it is hard to advise, other than to say don't do it this way - too many gotchas.
It might be possible to save it, but I think the ticket will be short lived. Unfortunately, you'll definitely run in to the Kerberos double-hop issue where authentication fails from service to service unless you have delegation properly set up on your network. This will require you to set up some SPN's (service principal names) on your active directory to tell the servers to trust each other.
I've never tried to save Kerberos tickets for any length of time so even after fighting with delegation and SPNs it may not work.
Here's a quick post on setting up IIS7 to handle double hop Kerberos tickets and another article on handling it from the networks point of view.
I wish I could be of more help, and posting code and not articles - but as you investigate you'll see this is the bane of Kerberos authentication. Good luck!
This solution comes with a huge caveat, but instead of storing tokens/tickets, you could use the LsaLogonUser function and constrained delegation to obtain a token for impersonation without supplying credentials, at the moment the work is ready to be dequeued.
This is how protocol transition is implemented, in which non-Windows credentials (e.g. on a public website) can be mapped to a domain user who is impersonated for access to internal resources.
The caveat is, this is obviously a huge potential security hole, and the account running the process which calls LsaLogonUser has to be granted SeTcbPrivilege ("Act as part of the operating system").
If there is a way of storing a ticket, that would obviously be much better, but the first thing I thought when I saw the question was the expiry time problem that #Ben mentioned.
Edit:
A couple of excellent articles on protocol transition and constrained delegation, with extensive coverage of the risks involved.
Related
I have three applications running in three separate app pools. One of the applications is an administrative app that few people have privileged access to. One of the function the administrative app allows is creating downtime notices. So when a user goes into the administrative app and creates a downtime notice the other two apps are supposed to pick up on there being a new notice and display it on the login page.
The problem is that these notices are cached and being that each app is in a separate app pool the administrative app doesn't have any way to clear the downtime notices cache in the other two applications.
I'm trying to figure out a way around this. The only thing I can think of is to insert a record in the DB that denotes the cache needs to be cleared and the other two apps will check the DB when loading the login page. Does anyone have another approach that might work a little cleaner?
*Side note, this is more widespread than just the downtime notices, but I just used this as an example.
EDIT
Restarting the app pools is not feasible as it will most likely kill background threads.
If I understand correctly, you're basically trying to send a message from the administrative app to other apps. Maybe you should consider creating WCF service on these apps that could be called from the administrative application. That is a standard way to communicate between different apps if you don't want to use e.g. shared medium such a database and it doesn't force you to use polling model.
Another way to look at this is that this is basically an inter-application messaging problem, which has a number of libraries already out there that could help you solve it. RabbitMQ comes to mind for this. It has a C# client all ready to go. MSMQ is another potential technology, and one that already comes with Windows - you just need to install it.
If it's database information you're caching, you might try your luck at setting up and SqlCacheDependency.
Otherwise, I would recommend not using the ASP.NET cache, and either find a 3rd party solution that uses a distributed caching scheme, that way all applications are using one cache, instead of 3 separate ones.
I'm not saying this is the best answer or even the right answer, its just what I did.
I have a series of ecommerce websites on separate servers and data centers that rely on pulling catalog data from a central backoffice website location and then caches them locally. In my first iteration of this I simply used GET requests that the central location could ping the corresponding consuming website to initiate its own cache refresh routine. I used SSL on each of the eCommerce servers as I already had that setup and could then have the backoffice web app send credentials via SSL GET to initiate the refresh securely.
At a later stage, we found it more efficient to use sockets instead on the backoffice where each consuming website would be a client and listen for changes in the data. The backoffice website could then communicate to its corresponding website when a particular account change and then communicate this very specifically. This approach is much more granular and we could update in small bits as needed as opposed to a large chunked update but this was definitely more complicated than our first try.
We've built a two-factor authentication process for our web application. We've built a small standalone app that generates an 8 digit security code every minute. When a user logs in they are prompted for the security code. When submitted the web app, generates the security code on it's end and compares it to the security code entered. If the two are equal then the user is allowed into the application. This is used like an RSA token.
However, I am using atomic clock servers to make sure the security code generation is the same for both the USB app and the web app as time zone and clock syncing poses an issue. This is a pain not only because the servers can sometimes be unreliable, but we also have to add in firewall rules to allow us to hit the specific atomic clocks. Is there a secure way to do this without using a remote atomic clock?
You don't need precise clock, but rather the same value. So expose some sort of "current time" service from the same web app (i.e. basic HTTP get "/currenttime" with JSON response) and query it from the USP app . In this case you only will need to synchronize time between servers serving the app (if you have more than one).
If your application does not have to be fully RSA token secure, you could modify the web application to accept the last 2 or 3 security codes. That way, you're not so dependent on time consistency.
If you have to have time synchronization, you can run your own time server that can be accessed by the web application and the USB application. The time has to be consistent, not necessarily correct.
Relying on external time is a bad idea, because if the time source can be manipulated (by, say, a man-in-the-middle attack, malicious upstream DNS changes, etc), then one can remotely query the device to collect future values.
You should really evaluate your security requirements before rolling your own crypto. It's very easy to fall victim to a number of mistakes, like accidentally using a PRG which is not cryptographically secure, side-channel timing attacks, or similar.
If you must do this for production make sure you open up your implementation so that it can reviewed.
I'd like to have two processes running within the same user's logon session communicate via WCF. NetNamedPipesBinding seems the most appropriate for this. BUT there could be multiple users logged in and running these processes, so I want a way to ensure each process only talks to other processes in the same user's logon session. Also each user could in theory be logged in to the same machine more than once - again here the processes in different logon sessions should not talk to each other.
I'm not particularly concerned with security (unlike this question), it's just a matter of having a way so each process only talks to the other process within the same user session.
One solution would be to add a unique logon session id to the endpoint address, but I'm not sure how to get a unique logon session (see my question on this here). I thought there might be some way baked into WCF for this, or a standard way of approaching this.
If you can be sure that:
the processes are never run with
elevated privileges (Run As
Administrator); and
You'll always be running on Vista/Win7 or later
then you will get what you want by default using WCF.
This is because the shared memory mechanism by used by NetNamedPipeBinding to publish the actual pipe name (which is based on a GUID) is automatically scoped by logon session if the process hosting the WCF service does not have sufficient privilege (SeCreateGlobalPrivilege) to make it globally visible: the named shared memory region is put in the "Global" kernel namespace only if the process has this privilege, otherwise it is put in the "Local" kernel namespace related to the user session.
Unfortunately, WCF doesn't provide any way to specify that you don't want it even to consider publishing the pipe via the "Global" namespace. So if these conditions 1 and 2 above can't be guaranteed, the only way I can think of is to name your endpoints with names based on the unique logon session ID, as you've suggested. Getting the Logon SID is a bit of an effort, requiring non trivial P/Invoke of Win32 APIs, but I see you've already found an answer on SO which shows how to do it.
I'm taking a security class and am required to implement a licensing server that sends licenses that are non-transferable. I have no idea how to do that. Could you please give me some of your ideas?
You need to find something to tie the license to that is unique and immutable for sufficiently realistic values of unique and immutable. The canonical example is the network adaptor's MAC address. This address is usually set at the factory, "cannot" be changed, and is globally unique. (Did I hedge that enough to keep the nit-picker at bay...?)
Once you have this identifying info making a non-transferable license is pretty easy, you basically have a trusted authority sign the address and use that as the license. If you want to check that a machine is the one you are licensed to run on you just check to see if the signature is OK using the public part of the key.
If you can assume web access you can require the user to log in to a central server. It sends back a token referencing the user id as described in the other answer, plus a time range when it's valid. The idea is that you don't want to require continuous web access, just access once an hour or day or whatever your risk tolerance is.
Ideally this is done behind the scenes, e.g., using an initial token obtained from the server when the user first registered their product. Your app uses this token to log into the central server for an operational token, nothing is ever done in cleartext with user names and passwords.
The benefits: this is not tied to the physical hardware like a MAC address (network card). It REALLY pisses off users when they're told that they'll lose everything because they replaced their hardware.
The drawback: a knowledgeable attacker could copy the token to additional systems. However there are three ways of dealing with this:
personalize the application. "Chris"
is probably not going to be happy if
the application keeps referring to him as
"Bob".
only allow one active instance at the
server. Be careful though - this
might lead to 'denial of service'
attacks on your users. Or just
frustration if they can't access the
app at home because they forgot to
log out at work.
live with it. What's the cost of
lost sales vs. the cost of
implementing something stronger
and/or pissing off honest users?
I'm writing (in C# with .NET 3.5) an administrative application which will poll multiple Windows systems for various bits of data. In many cases it will use WMI, but in some cases it may need to read remote registry or remotely execute some command or script on the polled system. This polling will happen at repeating intervals - usually nightly, but can be configured to happen more (or less) frequently. So the poll could happen as often as every 10 minutes or as rarely as once a month. It needs to happen in an automated way, without any human intervention.
These functions will require admin-level access to the polled systems. Now, I expect that in most use cases, there will be a domain, and the polling application can run as a service with Domain Admin (or equivalent) privileges, which means I do not have to worry about storing passwords - the admin setting up the app will define the service's username/password via standard Windows mechanisms.
But there's always a few black sheep out there. The program may run in nondomain environments, or in cases where some polled systems are not members of the domain. In these cases we will have to define a username and password, store them securely, then invoke this user/pass pair at the time we poll that system. So keep in mind - in this case the program being written is the user who sends password to the authenticating system.
I am not sure whether I will need to use a reversible hash which I then decrypt to plaintext at time of use, or if there is some Windows mechanism which would allow me to store and then reuse the hash only. Obviously the second mechanism is preferable; I'd like my program to either never know the password's plaintext value, or know it for the shortest amount of time possible.
I need suggestions for smart and secure ways to accomplish this.
Thanks for looking!
The answer is here:
How to store passwords in Winforms application?
Well it seems that your program needs to impersonate a user other than the context under which it is already running. Although, it does look like a pretty automated process, but if it's not, can you simply not ask the administrator to put in username and password at the time this 'black-sheep' computer is being polled?