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?
Related
I have the following scenario: a client connects over tcp to a server. The client sends his credentials to the server (password, username, mac address). The server validates the credentials and handles the client if the data is correct.
But is this right? I want to ensure that only one (on the user profile registered) computer can use this client. That means the client and the computer must be identified. I'm be sure that my suggestion above are pretty wrong. But how I can do this better?
This is a tricky problem, for as the comments pointed out, users may fake any machine information to pretend to be another computer.
What I would recommend is that you hash the machine information (e.g. with SHA-256), so that it isn't immediately obvious what information you use to identify a computer. Of course this can always be learned by attackers in multiple ways (monitoring, disassembly, etc).
Here are some tips on which data you could use to uniquely identify a machine. I would pick several characteristics, put them all together and then hash them. This of course means that if the user changes e.g. his hard drive (and you use its serial to identify the computer), then he cannot connect anymore. I suppose you will need to offer a "re-create key" function anyway in case users switch or modify their computer.
This approach makes it harder to trick your system, by using multiple pieces of information and hashing them, forcing users to a) figure out what information you use and b) how you hash it (definitely use a salt).
However, it still is very possible to do just that. The question now is: how high are your requirements? A typical user won't be able to bypass this, if that's all you want then it should be sufficient.
I'm not sure whether there can even be a "perfect" solution to this problem, as you want to protect your system from your very user. This means that all encryption keys, certificates or whatever you use is known by and available to the user. On top of that, users have access to your client application and analyze it. They can modify their computer in ways you cannot prevent of forsee. All in all, I think the best you can do is make it a huge pain in the backside to bypass your guards, so much that nobody will want to bother with it / you can minimize the number of users that may do so.
The only other thing I can think of is fancy logging and monitoring on your server, e.g. to detect that a user connected multiple times with his one machine, then alerting you or aborting all but one connection. Again, this can only reduce abuse, but not completely prevent it.
I have developed a .Net 3.5 windows forms application. I also want to design a website that has a webservice with multiple Webmethods to query the database on the host machine. I want the webservice to be called ONLY through my winapp and my website! And I don't want any other people to be able to call and use my webservice but only some people who have access to the windows application that I have developed.
I need a good security scenario for this! I truly appreciate anyone who can help me because this is my first experience of developing a webservice and I really need it to be as secure as I mentioned!
What you're talking about is going to be difficult to do for several reasons, but primarily this:
If you put anything in code on your WinForms app, it can be decompiled very easily. You can obfuscate the code all you like, but it can be de-compiled.
Because of that, any code that you have in your app can be read by anyone with access to the code. You should always treat any WinForms app as if it's completely compromised, and ensure that the security at the server end compensates.
Because of this, you can't simply store usernames and passwords in configuration files or in code. You have to come up with something else. You CAN use authentication and prompt the user to enter a username/password on program launch, and use that. However, people tend to share these things, so you may want to go for extra protection.
You can put the connection info, or secrets into the app.config and encrypt it, but anyone who can de-compile the code, can recompile it, and add code to decrypt it at will.
You can provide signed keys with your app, and use that in an authentication mechanism, but that can be bypassed.
You can restrict your IP address to specific IP addresses, but those can be spoofed.
However...
By layering all of the above techniques, you can make it difficult for an attacker to bypass your precautions. We did the following in one of our apps where we had a similar requirement:
We set up a database that holds a GUID record for each authorized customer, and IP addresses allowed for that customer.
Every web method expects a CustomerKey parameter. (the guid mentioned above) Each call to a web service checks the key against the IP address.
If it matches, valid data is returned.
If it fails, valid looking data is returned. We actually return what looks like good data, but it's really not. This makes it harder for an attacker to know if they've actually broken through the defenses.
In the WinForms app, the key is stored in the app.config, which is encrypted in the main() event (the entry point for WinForms apps). This is to prevent the casual reader from accessing it.
The program is launched automatically on install, so that the encryption happens at startup, to minimize the chance someone can read the file before it's encrypted.
Also, the code is obfuscated.
Layering the defenses, hopefully, will discourage the average attacker.
Microsoft has some guidelines as well: http://msdn.microsoft.com/en-us/library/ff648643.aspx
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.
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.
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?