How can I certify the client? - c#

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.

Related

Creating a unique key for a software that can be used only once

Im have created a software application which is windows based. Soon im going to make it live. Means my clients will be able to use it after they download it from my website. Also to mention i have made the software in a way that it works only with the key that i provide. Initially its gonna be a free trial.
Here im generating 35 digit key and its a unique one. Means once the user requests me for the key and i send him/her the key, he/she may be able to use my application. But the real problem arises from here.
I want the code to be used only once.
Ex: If my application is downloaded by the user, he can use the key to use my application but the same key cannot be used by any one else. Lets suppose my key is xxx the same code xxx should not work for any other person who has downloaded my application. Just to make the software to be used only by genuine users.
i have also gone through this link
http://social.msdn.microsoft.com/Forums/zh/winformssetup/thread/301913a0-ecf9-4095-8d66-a3f4baeea6eb
by Danny Staten
I still haven't met my requirements.
First of all i thought to get the Ip address of the person who is registering to download my application and based on that i can limit my key to be used only by the person whose ip address would be stored in my database. But i think it would be wrong/ unnecessary process. And to use my application the persons network cable should have been plugged each and every time. But it wouldn't solve my purpose.
Secondly i thought of creating a process of the application pinging to my server or to me.
Like initially when the user runs the application(online or offline) the application should work, but as soon as he connects the network cable/plug to network an alert should be provided to my server or to me. And from my side i can make a check if the user is using the key that i have provided to him. If in either way the user is not genuine i should be able to stop him from using my application anymore. From my side i have decided to store the keys inside the database which have been provided by me. And each requested keys in another table. Im not sure if im going the right. But as of now this is the thing that has come into my mind.
But to summarize, in the end i want that a key should be used by only one user. Just to avoid a million different users using my application with a single key.
Im not sure with any idea that i have provided.
Now is there a way i can achieve that?
Get hardware fingerprint of his machine and generate key based on that. Your software should check whether the key was generated for that specific machine.
This however requires online activation of your software. You can do this in two ways
letting user start unactivated application and display HW fingerprint which he sends to you. You then return activation key which he enters.
your application connects automatically to activation service and sends the fingerprint, receives activation key and stores it
Another point would be to include information about several components of hardware and allow user to change one or few. E.g. take fingerprint of HDD serial number, MAC address, motherboard SN, some CPU info (e.g. family name), you should allow user to upgrade or add another HDD.
There is SO topic about getting hardware information.
You have to make a choice I think, the stronger your key system will be, harder it'll be for your users.
IE: A good system would be to generate a hardware key, so it only gets installed on the computers that are registered. Although it works well, users who buy a new computer will probably get in the trouble of asking you to register a new hardware key.
And if you only give them a key (like a serial number), it'll probably easy to use it on another computer.
So basically, if you don't think many users will give away their key because the software isn't going to be used by many people, I would not get a "super-strong" hardware authentication..
Also, don't register an IP address, everyone with a dynamic IP will hate you for doing this.

Need a Security Scenario for asp.net webservice

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

how to access to database since another pc's? (in any place)

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.

Is there a unique computer identifier that can be used reliably even in a virtual machine?

I'm writing a small client program to be run on a terminal server. I'm looking for a way to make sure that it will only run on specified server and in case it is removed from the server it will stop functioning.
I understand that there are no methods to make it 100% secure, none the less I want to make it difficult for most power users to be able to do it.
I was looking at different Unique Identifiers like Processor ID, Windows Product ID, Computer GUID and other UIs. Because the terminal server is a virtual machine, I cannot locate anything that is completely unique to this machine.
Any ideas on what I should look into to make this mostly secure. I do not have time or the need to make it as secure as possible, because it will defeat the purpose of the application itself.
I do not want to user MAC address. Even though it is unique to each machine it can be spoofed by following instructions found on internet.
As far as Microsoft Product ID, because our system team clones VM servers and we use corporate volume key, I found already two servers that I have access to that have same Product ID Number. I have no Idea how many others out there that have same Product ID
Alternatively instead of trying to identify the machine, I might be better off by identifying the user and create group based permission handled through AD for access to this software.
By design, uniquely identifying a virtual machine is difficult; anything that allowed you to uniquely identify it would imply that it was not fully virtual (because cloning a virtual machine should produce an identical machine).
Create a heartbeat application on the host machine that communicates with the VM via a loopback network adapter.
Have the heartbeat application refuse to run if it is not able to uniquely identify the host machine.
Have the main application refuse to run if the heartbeat application is not running.
You will need to find a way to ensure that the heartbeat application cannot be spoofed too easily.
It is not possible to protect the terminal program 100%. This question is equivalent to trying to prevent software piracy.
The best thing I've found is the BIOS UUID - but it's far from perfect for your use case.
The SMBIOS UUID available inside the VM is also used by the VMware hypervisor and management tools as VirtualMachine.config.uuid (See: the uuid property on this page). This means it is guaranteed to be unique on a particular host, or in a particular vCenter. However, it can be duplicated on separate hosts or separate vCenter installations.
Also, the BIOS UUID on a virtual machine is mutable. It can be changed through the API (though not easily through the client).
This probably approaches your 95% mark, as it would take some special effort and setup to duplicate the VM exactly.
However, from a virtualization-enablement perspective (including things like VM disaster recovery, and future upgrades of virtualization software): using a hardware ID like the UUID or MAC address causes all sorts of problems. When they want to rev the OS version underneath your software, usually by creating a new virtual machine, they would need to manually edit the VM config for both servers to change the UUID to match. Using the MAC, if they change the network architecture, your software requires that VM to be a special case. These things just cause headaches for a virtual admin (but they might be the exact headaches you're trying to cause - only you know for sure).
I'd recommend using the permissions-based approach you mention, or even a concurrent-licensing server if necessary. But I'm coming from a heavily-virtual background where hardware-tied licenses are a headache already.
Simplest solution is to use the mac address, but note that it is easily changed on Windows by editing the registry. I'd say less than 5% of people know how to do that though.
Here's how to get the mac address in C#:
System.Net.NetworkInformation.NetworkInterface.GetPhysicalAddress();
You can tie the license to the MAC address of the network card (or cards, if there are several).
Of course, changing the network card would then stop your software from working.
If/When TPM becomes standard on servers, you should be able to use it to authenticate the server.
You can get the PC's MAC Address as shown here: http://www.java2s.com/Code/CSharp/Network/GetMacAddress.htm
Of course, this approach is not without flaws. There are other approaches listed in this post, which is similar, but not an exact duplicate: What's a good way to uniquely identify a computer?
expanding on the macaddress approach. you could use the macaddress with an md5 function around it with a SALT that was only known to the system owners. this way, the macaddress is useless without knowing the SALT.
just my tuppence worth.. :)
[edit] - see also here for c# example on hashing/salting etc:
MD5 hash with salt for keeping password in DB in C#
http://www.obviex.com/samples/hash.aspx
If you want 95% I'd go with the Mac ID - it can be spoofed, but by default is unique for the machine.

Implementing a program that generates non-transferable licences

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?

Categories

Resources