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?
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.
In brief, we have a website built in asp.net c# that we're adding a login area to for people to see some paid for content. There will be different levels of account, one which when logged in can download say 10 documents a day, another that can download 20 etc....
What the client has also now asked for is can they sell unlimited access to this facility to a customer, where that customer will only be able to get this unlimited access when using some specific computers.
Really don't know if there is an elegant solution to this? I'm thinking MAC addresses must be the key, but as far as I know the c# code doesn't have direct access to that? Have read that JavaSript will be too unreliable in it's getting of the MAC adddress...and that writing a Java applet may be the only way.
Does anyone else have a better suggestion than this?
Any help would be greatly appreciated.
You are looking for the idea of Device Fingerprinting. Since this is a web application, you need the sub-field of Device Fingerprinting known as Browser Fingerprinting.
It is pretty easy to get browser fingerprinting right 80% of the time, and quite hard to get it right 100% of the time.
Have a look at Panopticlick (from the EFF) to get an idea of how it works.
There are several commercial software providers that provide solid Browser Fingerprinting as a service.
Although the general case is not easy, your specific case may be easier. For example, if you sell access to a company that is large enough to route all traffic through one or a few well-known IP addresses, you could just use that IP to authenticate users.
Alternatively, or specifically if you need to allow only certain computers within a facility, you could create a browser plugin that checks hardware (like the MAC address) and makes that information available to your authentication code.
Getting this kind of code right (in that it shows neither false positives nor false negatives, and is tolerant to changes in hardware such as a NIC upgrade) is very hard. It may be worthwhile to use a commercial browser fingerprinting company.
Is there a way that you can rely on static IP addresses? I know that, depending on the site these can change, but so can network cards (though this is less common).
Another question: Do you wish to restrict to individual machines, or simply make sure that only "N" licenses on that address are used? If this is the case, you can keep track of N license records on your side, with a corresponding cookie on the machine (perhaps a concatenation / hash of the IP address and license key signed with your private key) which expires after a week or what-have-you.
You have your own database / list of IP address, license key, and expiration date, and so if a computer logs on with an invalid cookie (IP address doesn't match what its license is associated with in your DB, to prevent copying cookies across), if a license is available in your DB (due to one pairing expired / never being used), give them the new license (and the benefit of a doubt). If it isn't available, give a polite "no more licenses are available, here's our sales number" message. This means that the IP address in your database is more of a reference thing, but it will also slow down "computer hopping", as these records will not expire until "a week or what-have-you" has passed. If a computer logs on with a "Valid IP" (in your DB) but no cookie / invalid cookie, re-issue that cookie with the same license as before with a new expiration date. Maybe. Maybe the same expiration date.
If IP addresses change slowly at the customer's site, this should work. If they change more than once per computer per timeframe, this could pose problems.
The initial distribution of these licenses could be "first come, first serve", and rely on a network address range and logins.
There are sexier answers already provided. Would good old/boring digital certificates suffice?
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
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.
well I need to do 2 applications, one to users registers theirself (where the server is) and the another application is for the administrador can see who has register, but he doesn't have time to go (where the server is) so he need watch the information since other place, I haven't could do it, my another idea is using web services, but i dont know how to public the web service in internet for consum it since anothers pc's, then for application 2, how will be the connection string? i thoung with ip, but in what is your ip address i watched the ip is dinamic, and it change with turn on the computer (where is the server), then, how can i do it? (i coulnd't to have a connection with ip, and i couldn't with name of computer)
[heavily edited - hope I maintained the spirit] I want to use a web service, but I don't have a great way to connect to it. I thought about using the IP address, but the IP address is dynamic
If you have servers that must remain available, they must be registered in some form of hostname lookup service, such as DNS. Most people do this by maintaining a corporate intranet, using a hosting service to serve their database/application, or using a dynamic DNS service such as DynDNS.
[heavily edited...] I need two applications, one for users to register themselves, and the other for the administrator to see who has registered, without going to the server...
If this information is just for humans to read:
You could simply create a shared source of this information, such as an internal Wiki, or an Excel document on a Windows network share, or Microsoft Sharepoint site, and let users write new entries to it. The admin would simply read that document to find out the information. This is much more light-weight, and could be reused for many other purposes.
There is a lot of existing free wiki/CMS software you could install and use for this purpose.
If you need this to be accessible by other programs, rather than just human readers:
You'll have to make some sort of database, and possibly a web service to access it. Unfortunately, you'll need a lot more information for anyone to give you a good answer for these needs. Any answer will make a lot of assumptions, and might put you in a bad spot in terms of scalability, performance, security, or reliability.
Some basic questions to get you started (certainly not a complete list) - How many users? Where will they be located with respect to your servers (both this application you are writing, and the servers that the application seems to provide information about)? How safe must the information be? How much data? But even with this data, it is hard to recommend any sort of application design or network topology without knowing all of your requirements.
If you need this to be reliable and secure (e.g. you're supporting more than just yourself and a couple users), you'll probably need to turn this into a serious project, and devote business research, design, development, and IT resources to it. These resources can all be one person, but you should really go through all the motions if you don't want it to be an unmaintainable, insecure mess.