Given that C# can be decompiled incredibly easily, exposing all set variables as well as functionality, is there a way I can fully protect the API Secret that Facebook provides for creating an App?
Thanks
A general rule of software design is to not trust the client. Whatever the client can do, anyone can do. You can try some security by obscurity and have a method that does something to "generate" the secret or you can hide it away in a seemingly unrelated class, but at the end of the day, anyone with a little bit of time can just look at the outgoing packets and extract the key from that.
If you want real security, route all your networking through your server. Have the client send commands to your server, which will interpret the commands and use the Facebook API with your secret to send the client back the proper data.
One possible solution to this problem is to store these credentials in your app.config file and then encrypting the section containing these credentials using DPAPI.
http://msdn.microsoft.com/en-us/library/ff647398.aspx
Decrypting config values is transparent and can still be done through the ConfigurationManager class.
Related
If I have a stored key file used to decrypt the encrypted input coming into my application, and I store that key file as an embedded resource so that it is embedded in the assembly when deploying, how difficult would it be for someone to reverse engineer the application and retrieve the key file?
Also, the application is deployed through ClickOnce "Online only" mode which I imagine would also make it more difficult to reverse engineer? (I'm not exactly sure of the workings of ClickOnce but I wasn't able to find the dll's/assemblies on my local machine after running the application in online only mode...).
Update:
As Ralf essentially answered the main question below in his comment (answer: it's not really safe at all), here's some more information so that you knowledgeable people can possibly suggest a better security model.
The encryption will be used to encrypt the login password for my application, to be used in a SSO setup (the user will first sign on to a different system and then by clicking a link will be able to directly open my application without having to enter in their login details).
The encrypted data will be sent as a base-64 string URL parameter in the link that will launch the my click-once application.
I will also be developing the application that will create the encrypted data for the URL parameter (clarification: not the first application the user will sign in to for the SSO, I will only be creating a small tool to convert the plain text password into an encrypted base64 string).
It's only an internal application so bullet proof security isn't essential and ease of deployment is more important, but it'd be nice to know what the best practices and different options that are available.
Whether in clear text or encrypted, you don't want to store the password. When you get a password, all you should do is pass it to your server app where you compare it against the salted hash of the password you have in the DB. Even if you don't think security is that important, you need to take care with the password because people frequently reuse passwords across different systems. I know they shouldn't but they do.
If you want to implement a single sign on (SSO), create a sign on token on the server side and pass it back to the client, either encrypted or signed (HMAC is a good choice for signing). This is an unforgeable token because you need to know the encryption key or shared secret for the HMAC and that data is only known on your servers. So you have your SSO and all data involving the SSO is managed on servers so there's no data leakage or chance of spoofing.
As long as the aplication can be launched, the files have to be somewhere on the computer. You just have to know where to look. The reverse-engineering may be ugly but it is always possible. The computer has to be able to understand what he is supposed to do so you only have to extraxt the information one is looking for. Therefore the security of your application should never depend on the difficulty of reverse-engineering! I believe that a secure application should be open-source anyways.
You propably need a diffent security model. The important thing here is that you know against what you want to protect the data. If you simply want that you know the data is sent by the server and not somebody else (man in the middle attack) you could use digital signatures instead.
If you do not want anybody to read any data sent between server and client you should use some sort of ssl implementation to create an encrypted channel. Then you only need to watch out that the public key of the server is not altered on the client. This may be done by an certificate of an official CA but unfortunately those are usualy not for free.
My organization has a Win32 application that is written in the "fat client" style. I am writing a C# Client / Server solution that will replace this Win32 application. I am using ASP.NET MVC for the server and the client is a WPF application. I did my own custom implementation of the OAuth 2 spec. I am planning on creating a Restful API, and I want for not only my client to use it, but also allow 3rd parties to use it as well.
Every app will have an api key issued to it including the official client, but the official client's api key should be allowed additional api scopes (permissions) that 3rd party users aren't allowed to use. It is pretty obvious how to solve this but if you consider not everyone plays nicely, you have to ask "What would stop someone from just pretending like they are the official client and using it's api key?" Communication will be encrypted, but the server is not in the cloud or anything like that where we could control it. Our customers install the servers on their own machines and they will more than likely have access to the server application's SSL cert. Once you have that you can easily write an app that would run on our customer's machine that could glean the API key and secret from the official client app and use that info to request tokens from the server as if you were the official client.
I am planning on self signing the default key that the server uses and I could try and hide it in the application, but that really is just obfuscation. Besides, I wanted to allow users to provide their own SSL certs so browser based 3rd party applications wouldn't have issues with the browsers complaining that they are trying to communicate with on a self-signed SSL channel.
Is there anything I can do? Here are my choices as I see it:
1) I can set it up so that only SSL certs provided by us can be used and we hide them on disk encrypted using a secret that is obfuscated in the application code. We then just hope no one bothers to take the time to dig through our .net assemblies to find the secret used to encrypt/decrypt the certs on disk.
2) We allow them to provide certs so that we don't need to be involved with that process at all when they want to use a signed cert (we don't want to be in the cert business). Now we can't even hide behind obfuscation so if someone wants it, then the official client's API key and secret is easily obtainable.
Neither seems very desirable to me. Option 1 makes us have to request addition funds from them and manage SSL certs when self-signed doesn't work for them and in the end if someone really wants them they can still take the time to get them. Option 2 just makes it super easy to steal the official client's secret.
Reasons to want to limit unofficial Apps:
1. Discourage clones
A. Tell people not do it. Have a lawyer send cease and desist letters to authors of popular apps (and to anyone helping distribute them). Intermittently download them and alter the client/server code so that the popular apps will break. For added discouragement, temporarily ban any users who used the popular app. Authors will mostly give up on cloning your app; temporarily banning users will kill their install base. This is not great for your reputation.
2. Prevent unauthorized behavior.
A. Any behavior allowed by the official app should be allowed by the custom app. Whatever scenario you are worried about, block it server-side so that neither app can do it.
You can try to hide credentials (code obfuscation, hidden credentials, etc.), but this is only raises the cost/difficulty. This is often enough to discourage code theft (no need to make code theft impossible; it is sufficient to make it more difficult than copying it by hand). However, users who want to use your api in unsupported ways can work around this.
The answer is simple. each instance of you app should have its own unique key effectively a user sign up. You then ban users who infringe your rules. in this case signing in with a non authorised client. should be pretty easy to detect by pushing updates more frequently than it would be cost effective to reverse engineer them. Much like punk buster or other anti cheating tech
I have made a WCF REST service which consumes data from an OLAP database and it is not Microsoft technology, ultimately, I would like to connect many other OLAP database to a single platform.
And after a lot of reading, the security for WCF REST is very discouraging, in summary, I have 2 choices, one is to use the Basic Authentication which expose username and password over the wire, or maybe a bit better, using Basic Authentication with SSL, now I need to get different certificates from the webserver. Or using Digest Authentication, which use an encrypted password and authenticate against the database, that's the best option, but in my case, it is not possible as I am not using Microsoft technology, the security is on different platform and I cannot encrypt my password using MD5 because the database cannot read the encrypted password.
That concludes me only be able to use Basic Authentication with SSL, but is this the correct way of doing? I see many products out there doing something similar to what I do, when they login, I do not see https, but only http, are they not secure and easy to hack?
I am not trying to make a bullet proof website, but a simple website, using Basic Authentication is too simple, or in fact it's almost like giving away the password, but using https, is that overkill?
So, after REST being that discouraging, let's not use REST, use the normal WCF, from what I have read, they shares the same problem.
Please give me some guidance. I think I have lost.
Many Thanks
PlayKid
Often, basic authentication is used for regular websites and yes, the username and password often go over the line readable if used with http. Https is already better, because the information is send encrypted over the line. But in practice, you only see this in place for commercial or banking applications. You cannot use MD5, which is a pitty, because that would be sort of middle-of-the-road approach.
So, depending on the application you will expose, use http for simplicity or https with a bit more complexity and safety.
By the way, big safety problems often have to do with SQL injection or a hacker being able to get some admin level privileges on your site. That way they get acess to a lot of info, while sniffing your line and getting a single user password combination is relatively harmless, if you take the needed precautions and counter measures.
Basically, Basic authentication with SSL is really very secure and shoul be used if its going to be exposed to outside world.
One easiest hack approach I have seen before and if you just want to authenticate (not authorize a endpoint) clients which are known set of clients use:
OperationContext.Current.ServiceSecurityContext.WindowsIdentity.Name
This will provide username accessing the service, Authenticate this usern with your DB or AD using LDAP if a valid user is accessing the service and with every request add a encrypted key that user needs to send as part of request. This way you know the username and encrypted key from the request.
You can also use this along with Basic authentication to be sure its not insecure.
In many Application's i had Cases where i should write Username and Password's in my Application inside the Class ,like HTTP Authentication ,FTP Authentication MSSQL Server Connection String also Provides Authentication Information's ,so which is the Best way to protect these Information's because someone could Decompile my Application easily maybe using Reflector and get these Information's which can be useful for some Attack's or something like that .
Bests
Can you explain more specifically what your general goal is? Usually there's better designs than hard coding passwords and authentication tokens.
There's really nothing you can do to protect those secrets if you are distributing your application. Even encrypting your config files, the application still needs the key to decrypt, so your attacker has all they need.
You can choose other designs though, such as prompting a user for their own unique password, and then making database calls against a web service, rather than distributing an application that connects directly to a central database. But you'd have to explain the scenario for a better recommendation.
I am looking forward to have the less information as possible on my application resulting in pulling most of the data from a website or server and I would like to hear by advices and recommendations from everyone with experience in the field to help me improve my application.
Currently my authentication consists of:
To start the application the user have to input their username and password (without a valid user and pass the app does not work) and click login.
The credentials will be sent to my login page using HTTPS, the script only accept SSL connection and a personalized User-Agent name.
The login page will verify the credentials and send back a session and some initial data.
The session is reused to gather more data over time or as needed.
Side note: the SSL is 256 bits, the session auto expire after a few minutes
For the above basic authetication and data pulling would you recommend me anything else to implement ?
Should I change anything ?
2nd Layer of protection
Now I would like to implement more security by encrypting all the data sent from/to my application, my question:
What should I use to encrypt and decrypt the data, a pair of private and public keys held on both sides or RIJNDAEL's method ?
What is the proper way or what parts of information should I leave on the client and server or how should I form the knowledge of the common passwords or keys ?
For example if I was using a pair of RSA keys, I would need to leave 1 private key at the client and 1 public key since you cannot decrypt any data with the public key on c# while you can do it on the server and for Rijndael would need to have the IV and the key on both side.
What is the proper way to handle these ?
I will be very glad with practical reading material, comments, examples, suggestions, advices :)
UPDATE:
No one else wants to say anything ? I was hoping to get more input on this question and also tough that this was a fairly used method around ...
Sounds like you've considered the security of the app side of the equation at length. I'd suggest you turn your thinking to the website part of the equation.
When I look at security, I always look at two things:
Transport security--is your data protected while in transit? Sounds like it is, assuming you are using sufficient key length for the SSL cert on the server. Also, you can force the website do client cert validation as part of the SSL handshake. That ensures that no one can spoof the client app and convince your website to share information.
Payload security--should you encrypt the data payload? Is there a chance someone may be able to break into your web server, or better yet, via the DNS poisoning or some other method, convince your app to connect to a malicious server with a valid (for that cn), but different HTTPs certificate? Should you choose to encrypt the payload, you can piggy back the whole thing onto the same certificates you already use. Just make sure that the certs have data encryption bits turned on, and you can use private/public keys from the certs to encrypt the payload. So, if the malicious user replaced the cert, not only do they need to spoof the cn and the chain of trust, but also have the right public key from the app to decrypt the data you are encrypting with your private key and signing with server's public key.
Some other questions to ponder:
You are saying that the session is reused? Does it not expire? If not, you'd want to make it expire.
Can you leverage network security? Can you use a VPN tunnel or IP ACL to limit who can even gain access to the web server?
What about keyloggers? Passwords can be intercepted. The second authentication factor can be something a user has, like a key card or a fingerprint, or an RSA SecurId. If you don't want to go that far, you can present a user with a "site seal"-- an image that they have to recognize as associated with their account. Maybe even present several images and let them choose one that they've chosen during the signup process. You can also make them solve a small puzzle--something that will distinguish a human from a machine (CAPTCHA-type).
All these points minimize info stored on the client side--just a cert or two and a key to go with that cert.
The topic of security is vast, and we can start a whole discussion here on different implementation details. The above is just some points to think about.
Remember, that everything has cost. Security costs usability and CPU cycles. Proper balance is key, but that of course is up to you.
Before you build Fort Knox, make sure someone is going to want to live there :)