I am building a WebApp which connects to my server through a web service.
Users (there is no login) which use the webapp can send their scores to the
server.
The code is written mostly in javscript, so anyone can read it.
As I know there is no 100% gurantee method of doing this, I am just looking for ideas
how to make it as hard as possible for users to send false scores.
Ideas?
10X!
EDIT
The server side web service is an asmx (.net) web service hosted on an IIS.
I can modify it as needed.
I'd say the best thing to do would be to have a webservice call that generates a guid on the the serverside, which is passed back. This becomes your session token. It's stored on the database or in cache on the server
Each subsequent call requires the passing of the token back to the server, which validates the token. If they pass a bad token you don't update.
This will only insure that the calls come from the correct process. They won't be able to spoof the entry with a single call
For a process (you seem to be talking about a game?) with a limited number of interaction points, you can record each user interaction and play it back to check that it results in a certain score at the server side (either in real time or later on for suspicious scores).
Otherwise (and this is typically impractical for an real-time action game where there are too many interaction points), there is not much you can do. You can have the game digitally sign the information it is submitting... but given that you are giving the full code including signing key to the client side, it is still easy for an attacker to obtain the key and sign invalid scores.
At this point you get yourself into an obfuscation arms race - how much can you make the client-side code unreadable and difficult to unravel, to prevent attackers from obtaining the key? You can never win this game, only deter the casual attacker. And ultimately you have to protect the entire client-side process from alteration, to stop all other forms of cheating (eg using Firebug to change variables like score or lives).
Related
I want to implement an authentication system by following good practices, i want it as simple as possible and secured (im not going to implement some magic hashing function or something to feel a hero..) just wanting to use already known hash but not sure the right way of using it.
I read some articles on how Lastpass (a password management company) mange to handle their authentication and i loved their idea.So i wanted to implement my own authentication based on it.
Basically im creating an authentication key from the password on the client side (so the password is never sent as a plan text to the server).
that authentication key im sending to the server than do some hashing operations also in the server side and compare the result to the one inside the database.
On my client side:
auth_key = PBKDF2(SHA256, password+username, last_login_fe_salt, fe_rounds)
explanation - hashing password+username+last_login_fe_salt text fe_rounds times
last_login_fe_salt -> a random salt sent to the user once he/she input their username in text field -
To be honest, not sure how this last_login_fe_salt is efficent for the cryptography against Dictionary attacks but atleast two people having the same password will send different hashes on their network.
any hacker can get this data by asking from the server, i can add server side limitations (req/s if it makes some difference etc.. let me know what you think) also adding captcha might be a good idea. When a user logged in successfuly the server generates a new random string and saves in into the database.
*I didnt see any explanation which salt Lastpass uses on their client side hashing, they are using PBKDF2 algorithm that needs a salt parameter.
fe_rounds -> number of rounds given by the server when typing username -
its fixed for everybody and configurable by the server, also in articles i read about Lastpass they dont explain from where they receive the client side number of rounds...
so now we send auth_key as is to the server...
On my server side
now we are creating a new hash to compare the one inside the db.
Why another hash? if i understand correctly we bind the hash for server side data, like a combination of a password (that only the user knows) and server data.
db_auth=PBKDF2(SHA256, auth_key, user_be_salt, 100,000+user_configurable_rounds)
user_be_salt -> a random number that saved in db known only to the server and the ones who obtain the database, this changes on every successful login.
user_configurable_rounds -> number of iterations, every user can choose the amount of iterations (like in Lastpass) so attacker need also to guess the number or iterations?
I would be happy to hear what do you think about this authentication system, if its wrong than explain to me why and tell me what Lastpass do because i did not understand their entire authentication flow.
Most of what you're doing is useless from a security perspective. Lastpass has unusual security requirements -- don't treat them as a source of best practices.
If the client is responsible for hashing, and all of the parameters to that hashing are fixed, the hash effectively becomes the password. An attacker doesn't need to know the original password; they can simply pass the hash to the server.
Generally speaking, there is no way to verify a password over a network without either sending the password across the network (for traditional password authentication protocols), or having the server store the password in plaintext (for less commonly used protocols like SRP). Of the two, the former is preferable, as it's possible to secure the password in transit using protocols like SSL/TLS, whereas protocols like SRP require the plaintext of the password to operate.
Tweaking the PBKDF round count, either on the client or server side, is pointless. Set a fixed round count that makes the hash slow, but not so slow that it will place an undue load on the client or server. (100,000 rounds is probably excessive for a server-side hash. It takes roughly half a second to verify a password with those settings, so just two login requests per second would use 100% of one core on your server!)
I have a web application that has form based authentication.
the application has registration functionality also. Since last few weeks, i have observed that some users with specific domain is making fake entries into the website and getting the benefits as We do not have any approval workflow.
this user either do it manually or run some script. We thought that we can restrict the registration process as per IP based, however this is not possible to get the visitor exact IP address using C# (please correct if i am wrong).
Can we do it using some other techniques. our requirement is - single registration from a machine per 2 days.
unfortunately I would call this mission impossible.
Idea 1: IP address. The user can use a proxy to register multiple accounts depending on how many proxy he can find (there are a bunch on the internet for free)
OR they could just fake the ip package by putting a random ip in the header. Since all they need is to register so it doesn't matter if the confirmation message was sent to another random guy
Idea 2: one registration per machine. I could fake as many machines as I want with virtual machine and you will have no way to tell from http request.
Alternatively I could just fake all the information with raw http request and I can do that with a script with no issue.
And from what I know you don't have the system right to read hardware id from js (correct me if im wrong)
No method is guarantee to restrict 2 registration per day but IP based method should work against most normal users. Do keep in mind that everyone using the same router could have the same IP (example school, public wifi in apartment)
You could find out the user's IP address within HttpContext object
Whatever your restriction would be - it will be based on the data the browser sends (as long you restrict a specific computer).
Your main desire is to create a "footprint" on that machine in order to use it later - per request.
Whatever your manipulation would be, you should also obfuscate your JS code.
for example, on pageload code you can request for httpheaders dedicated to that machine and save them in cache, then you generate a guid for the client which it suppose to use in order to register.
another option is to use AES to encrypt the data before sending it "on the wire", that way you won't be able to manipulate it.
the most important thing is that once you "drop" a js code on the client he can do whatever he wants, the question is how hard it would be.
**edit:
a more secured way but more complicated that i have once used is creating a sync-key.
an async ajax call to the server requesting an encryption key.
the server call will save the new guid-key in memory and will generate a new one for each request.
you can use this idea to keep track of user debug and browser behavior.
as debuging will hold the code from running the sync key will be change and you can "catch" him.
Neither cookies nor IP can protect against fake entries.
You should look at it from another side. You get unwanted entries and you don't know if it's an automated bot, or spammer, or someone who just doesn't care about your data. Instead of banning entries you should think how to validate them. For example, if you get "aaaaa" as a name and "bbbbb" as an email address - add, at least, regexp validation on client and server side to ensure you get data in a required format. Next level would be to verify the email address by querying the mail server or sending validation email. This will not only help to stop spammers, but also people who doesn't care. If you think it's an automated bot - add a captcha. In case of emergency - ban IP in the web.config (See ASP.Net How to limit access to a particular IP address to a particular page through web.config file (.htaccess similar)?)
If I placed a javascript game on my website and part of the game asked for user addresses (in order to refer to local landmarks for example) is it possible that some third party might be able to hijack my game to send the user addresses their way?
I understand that javascript is not very secure, but I'm also thinking that no one will be able to hijack my javascript code without hacking my site, so it's secure in that respect.
Am I being naive?
Just asking because I have an idea for a game that I'm trying to think through.
If you consider your user's addresses to truly be a secret, then yes you probably have some work to do:
XSS attacks
You need to be very careful about how you display user input. For example, if I say my name is <script>alert('hello world')</script>, are you actually going to print that out in the website? If so, can then insert their own JavaScript into your application. Here's an example of an XSS attack, and Wikipedia has more information. If attackers can insert custom JS, they can intercept secret user input like addresses or passwords or cookies.
HTTPS
When your web server sends its message back to the user, the message doesn't go directly to the user's computer. It first goes through intermediate computers in a relay race. If attackers control one of the computers in the middle of the relay race, they can modify the server's message and insert their own JS. Once again, the attackers win. To circumvent this, you'll need HTTPS, which is a protocol that among other things encrypts the message. You'll also need something called a certificate; StartSSL sells them affordably.
Note that the attacker doesn't have to be some corporation or government sitting miles away to control an intermediate computer. It could be someone running Firebug on your school campus' unencrypted Wi-Fi network, for example.
But really
A better way to structure your web application is to never send the user address back to your server in the first place. One of the first rules of information security is that it's hard to get right; the more you can rely on other people's work the better. Instead, maybe keep a fixed list of landmarks in the JS code. Or use a public API provided by a service like Google Maps, which already runs over HTTPS.
I create js app with Backbone and RequireJS for registred or non registred users. To retrive data from database I use simple JSON web service and of course some of methods are not avaiable for quest. Problem is that I don't know where or how I should store auth data retrive from server without reloading it in every view. Should I use cookies ?
I guess it depends on your authentication, authorization methods as well as the kind of security you need to consider for your users. If you're trying to be RESTful, you can't have sessions to save state (at least server-side). You could, but it wouldn't be RESTful due to saving of state on the server, if that matters to you. I've heard that it is okay to save state client-side but from what I've read, I'm not sure how the community feels about certain implementations that take this approach. (Like cookies, I'll revisit this later.)
Say you have someone login with username and password. You can hold that information in your Backbone app, maybe you have a model called AUTH that does this. Each time you make a request to the server you'd send that data each trip at which point the server authenticates and gives or rejects access to given resources. If you use Basic Auth this information would be in the header I think. Using SSL mitigates some of the major security concerns surrounding the sending of this information over the wire and for the rest of the discussion let's assume this is what we are using.
The other way that you could do this is to use encrypted cookie, encrypted cookie sessions. This is what I do with my current application. Honestly, I don't know if this is considered a violation of RESTful principles or not. The general chatter on the web seems to be a lot of "cookies bad, sessions bad" with some people saying, "get real." Using cookies would expose you to cookie hijacking if someone had access to the users computer, but depending on your application and the security needs it might not be an unreasonable option. It works for me and if it isn't RESTful, I like to call it RESTLike.
To close I'll just describe my setup. It would be nice to get your thoughts as well as the Stack's opinions on this also.
Basically I have a setup where when someone goes to the main page, the server checks for the encrypted cookie session. If the cookie session is invalid or non-existent, it gives the user the regular page with a chance to login. When they login, I send that information over POST so it's in the body of the request rather than the URI. (This is technically a violation of the REST HTTP verb concept since you use POST to save a resource.) When that information is processed, check the username, pass hash created by a unique salt, then the server creates an encrypted session cookie and passes it back to the user. Now, each time my user hits a route that requires authentication, the server checks the cookie to make sure it is still valid (time limit, user information, etc.) and if so - allows access. If not, it destroys the cookie information and sends back an appropriate status code. The backbone app reacts to this by resetting any view and data that shouldn't be in the hands of an unauthenticated user and shows them the login screen.
Hope this gives you an idea. This is the answer to how I do it, but if someone has criticisms or better ideas I'd be happy to upvote them instead.
We've just developed a small Facebook puzzle that people win some gifts from our customer. I'd like to ask a few questions since I'm pretty stuck despite tried lots of things. First I'd like to write what we have and then will explain our problems.
What we did so far:
Root of application (/) checks for signed_request in POST params, extracts information from it to see if we've registered the logged in user into our database. This checks are also used to understand if the request is sent from Facebook or not to prevent requests coming outside of Facebook. (will write why we want this)
Once the application is successfully rendered, Facebook JS API takes place, does its checks and sets the fbsr cookie. We use that cookie information while processing ajax requests to check if the request really belongs to the logged in user (e.g.: scores being sent for a user belong to the logged in user).
We implemented CSRF protection and another protection to check if the requests are POST and more specifically AJAX requests and return 40x if not.
Problems:
Despite I do some checks to prevent spoofed scores, I couldn't think of a way that the logged in user could improve its own scores by simply calling the same JS code I do for real scores. We just ignored this for some time until we just found out that some people seem to take advantage of this bug.
One way I thought of is to ignore all requests except coming from Facebook. Since the ajax requests are blocked (cross site) we should have been safe. However this leaded to another problem that, once we redirect users to e.g. leaderboard the signed_request data is lost and our index page returns 40x once the user tries to go back since our application thinks that the user tries to visit our application outside of Facebook.
I hope that I made our problem clear. Gaming time is calculated by Flash (game is programmed in AS3) and it's sent via JavaScript methods to server side. We could have done it in Flash but that only prevents our problem from becoming trivial. Afterall we'd have the same problem if we had implemented the game in HTML5.
Any thoughts, suggestions are really welcome and thanks for your feedback!
This is a bug by design. You are calculating the scores on client side and then send them to the server. The server has no way to validate if the score is correct. This can ALWAYS be faked by clever users.
Never ever ever calculate things that could give users advantage on clientside. Clientside is evil. Everything on clientside can be manipulated - no matter how hard you try.
Calculate your scores on the server and use the client side only to display them. Every other solution is crackable.