C# How to windows impersonate over distributed system? - c#

I have distributed system, in which I access some internal network resource through Windows Authentication:
User #345 request -> MyWebInterface -> SerializableQueue -> Worker #123
Worker #123 access resource through WinAuth (currently under service account, not from user account).
User #345 response <- MyWebInterface <- SerializableQueue <- Worker #123
The problem is in step 2 - I need to impersonate under User #345 and then access resource. This is security requirement to use this resource.
How one should serialize user credentials and then deserialize them at worker to accomplish WinAuth impersonation?

Impersonation is not a native feature of any queueing system I’m aware of - MSMQ in particular does not offer this functionality.
I’m taking the scenario where you have an asynchronous service that Requires impersonation to a back end service you do not control (e.g. an SMB share or another service which requires windows auth). If you do control the back-end service, consider allowing your service to authenticate as itself then “act as” the real client.
So, under the assumption you need real impersonation, you have a couple options: S4U and C2WTS. Both are essentially ways to use SeTcbPrivilege to issue tokens for users by username (no password required). A good tutorial of both technologies is available on MSDN.
If that doesn’t immediately trigger the warning bells, it should be noted that this would be a very security critical piece of code. SeTcbPrivilege by itself only affects the local machine and is therefore manageable, but if used in combination with delegation it can be used to access remote resources with the same privileges as the caller. You essentially are running your service with “domain admin” rights unless constrained and planned very carefully.

Related

Client Credentials Flow or Authorization Code Flow (with PCKE) for a trusted desktop client

I'm developing the authentication/authorization architecture for several APIs.
I'm using IdentityServer4 as a Security Token Service (STS).
From what I've read from "Dominick Baier" (one of the persons that built IdentitySever4), there are only two types of Flows that should be used:
Client Credentials Flow. (machine-to-machine)
Authorization Code Flow + PCKE. (for iteractive users).
I have several C# Web API's that will communicate with each (Machine-To-Machine), and I will use the Client Credentials Flow.
But then there are some WPF Desktop Applications, that will need to access some APIs, and don't have a user.
Which flow should be used?
I've read that:
Desktop/Native & Mobile Applications should use Authorization with Authorization Code Flow (with Public Client and PKCE), since they are hosted on the Client side, and the Client/Secret is can be leaked (maybe on a Desktop application we can Encrypt the Secret? But then will need to manage a way how to store the secret that decrypts that right?)
Then I've read:
"Anytime you have a system that isn’t concerned with the end-user identity (and just needs to authenticate the system), use the OAuth2 Client Credential Grant."
For now, this is my case, I'm not concerned with the end-user identity (but maybe in a near future I will).
So since the above points conflict with each other:
- Which flow should I use?
- Can I have a Desktop Client using Clients Credential Flow and be safe?
Also, I've read a bit about Mutual TLS, If I use that, does this change which flow should I use?
You can't trust a client because you can't be sure a request originates from the client. And another problem is that clients are not good in keeping secrets. But there are different types of clients.
Clients that run on servers often having a single task, like synchronizing data which is user independent, are suitable to use the client credentials flow. To some degree they can keep a secret (running on a server).
You can use unique credentials for each instance but that doesn't make it safer. It helps you to identify the client, but doesn't add security. Security is about monitoring behaviour and detecting anomalies. Or perhaps narrowing access by filtering on ip address.
But you are not limited to use the two flows you've mentioned. Being a token provider, you can extend IdentityServer with custom flows using extension grants.
Without user the client credentials are somewhat similar to the resource owner password credentials (ROPC) flow (another option that is no longer covered in the grant type documentation but still exists, see the old docs). Neither are really safe in the sense that both can be automated. The user factor can be eliminated since user interaction isn't required for these flows.
But I wonder why your app has no user, running on a user machine. Because ideally you have a client (without secret) where the user logs in and let the client contact the api (delegation).
So there are two things: do you need to identify the client? If not you could suffice with an ApiKey, like e.g. Sendgrid. And you can never trust a client. Security has to be server side.
So basically it doesn't really matter, there is nothing you can do to make it much safer client side. The only thing you can do is add the requirement of user interaction. So perhaps now you don't need it, but it will increase security and allows you to delegate api access to the client.

Secured License validation in distributed application c#

Let's assume I have two applications: service_1 and service_2.
service_1 is a basic application, every user with valid license can use this application according to its license.
service_2 is a premium application, means user with special license can get it with this flow:
service_2_login => service_1_login (service2 asks login from service1, if all right then the user can access to service2).
The challenge here: When user logged-in to service2 and wants to use service2.getService() we need to check its licensing permissions for this operation. Since the license_service located at service1 server with web method is_licensed(User user, Operation operation), we have to operates this communication in well secured manner - means avoid Man In the middle attacks etc ...
The question: How to design this mechanism? My thinking is with Challenge Response mechanism.
First: Is that the right way? If yes, it seems a large development effort. So is there some c# implementation for this mechanism?
Thanks!

C# security, Scheduled Task/Windows Service, use one user for web calls, another for DB updates

I have a scheduled task to create to get data from a site using the webclient
class. How do I execute a database update with the data retrieved under a different windows user? I was told not to use the same account to access the site as performs the update. Should I just create a windows service that runs the web request then call a db component with authentication settings set under IIS to run under a different user? Or is there a tidier way to do this running a single exe as a scheduled task? The Scheduled task runs under a single user. Could I run the task and switch user for the update? We are using Windows authentication at the database level.
Run two Windows Services. One to get the data from the website, running under Account "A" which stores the data locally. The other Windows Service running under Account "B" picks up the locally stored data and executes the database update.
Other designs will require you to store the credentials somewhere in a config or other file - this way the Windows Services are always running under the correct account for the task they are attempting.
You clearly stated that you will have to use a Windows user to get access to the database. However, often this will not be the case when you authenticate against a web site so exactly how you solve your problem will depend on the details of that.
You should probably execute your process as the Windows user that has access to the database. Then you have to solve how to authenticate against the web site. If the site uses forms based authentication it is a bit complicated but there is an answer to the question WebClient accessing page with credentials that might help.
If you need to use the WebClient.Credentials property to authenticate against the web site you might find it easier to execute your process as the user that has access to the web site. You then need to use impersonation to access the database. A simple way to do that is to use the SimpleImpersonation NuGet package.
In most cases you will have to store the password for one of the users so your process can use it to either log in to the web site or impersonate the user. A relatively safe way to store the password is to use the Windows Data Protection API (DPAPI). The class ProtectedData can assist you in storing secrets so only a specific user on the computer can access the secret (e.g. the password).

Multi-Tenant physical isolation

We have a multi-tenant Asp.Net MVC 4 web application with each tenant having its own repository of files (a folder in the file-system). We took the shared database, shared schema approach and we identify tenants by their subdomain.
What is the best way to ensure that a tenant can only access his repository folder and no other folder in the file-system? we check it in the application business logic, but what if we make a mistake...?
When running the application, all tenants run under the same user (which is defined in IIS application pool).
Do we need to serve each tenant as a separate user - using impersonation? do we need to impersonate each time a request is made to the server - in order to fill it?
I've heard this has performance drawbacks and is not the prefered way, but what is?
We also have a windows service which fills requests in the background (for all tenants), sent to it through MSMQ. Does this service also needs to change its identity every time it gets a request?
Edit:
In addition, we need a type of isolation which if someone uploads a file infected with a virus - it will affect only this tenant's files, and not every tenant on the server. We use ant-virus software, but we need this separation also in case the antivirus software will not identify the virus.
Thank you
all tenants run under the same user
If each tenant has a separate IIS Web App and identity (whether app pool or "normal" user), then you can use NTFS access control.
These does not depend on having all users having a local or domain user accounts on the web servers to allow impersonation (and this NTFS access control).
However it will add memory overhead on the servers of course – each tenant will have their own worker process.
[…]MSMQ. Does this service also needs to change its identity every time it gets a request?
I'm not sure you can do impersonation based on MSMQ messages, I would expect this not to work (MSMQ messages do not carry the necessary identity information).
Anything shared is going to need to be implemented to check all access: depending on the nature of the processing this may be more difficult (eg. if client requests can be something of the order "get information from the file" for an arbitrary file: the service would need to do the access checks1).
1 There are Win32 functions that will do the heavy lifting.

Windows Impersonation from C#

How can a C# program running as LocalSystem impersonate the login identity of another user temporarily? Roughly speaking I have a Windows Service that I'd like to run as LocalSystem but at times impersonate user XYZ (when connecting to a db using windows integrated security).
Most important of all: Is there a way to do this without knowing the other user's password?
Note: if a password is mandatory is there a recommended strategy for storing a password securely (c# and/or vbscript).
It's possible, although it requires you to do a lot of code. See NtCreateToken and CreateToken. You need SeCreateTokenPrivilege, although that won't be a problem since you're running under NT AUTHORITY\SYSTEM. You can then use the created token to impersonate inside a thread.
Short answer: you can't without the user password or the user calling your service through COM.
To impersonate another user in your process, you have to call ImpersonateLoggedOnUser. ImpersonateLoggedOnUser requires a token handle. There are several ways you can obtain token handle:
by logging on as the user with LogonUser. This however requires you to know the user password.
by duplicating an existing token with CreateRestrictedToken, DuplicateToken, or DuplicateTokenEx.
by opening the token from another process or thread, that already is loggen on as the user, with OpenProcessToken or OpenThreadToken
For the password storing part, you may want to have a look at this question asked recently.
This was my answer:
You could/should use the DPAPI, the Data Protection API that provides storage encryption.
It's there just for this type of problem.
Encryption of the storage is based on either:
the user account, so only the logged-in user can access the data. This makes the data transferable to another PC with the exact same user credentials.
the machine, making the data only accessible on that particular machine setup and not transferable to another PC.
There is a dnrTV show with Karl Franklin showing exactly what's needed to implement this, and other encryption functions.
The source code from the show is also available on the page.
There are, of course, lots of other articles on that subject.

Categories

Resources