I am building a Drupal website with a lot of user-specific information that will be posted using jQuery/ajax. The information it self is not very sensitive, it is just important to verify that the form-data has not been tampered with tools like Firebug, as well as ensuring the information is really requested from the specified user. In other words, I am trying to figure out the best way to protect the integrity and authenticity of the data when posting with ajax.
Ideally I would like to use some well known message authentication system, like the HMAC algorithm. But since this incorporates a symmetric key, I don't see how I can encrypt the POST data without exposing the secret key in my javascript file (which obviously is visible to anyone).
Please correct me if I have got the wrong idea about how this should work.
For example, info I need to send
field1=x&field2=y&uid=10
...then calculate the hash of the data together with a secret key. Is this possible to do without exposing the hash function in my javascript code?
CHECKSUM: hash(postdata, "secret_key")
... and finally append checksum to original postdata.
field1=x&field2=y&uid=1&c=CHECKSUM
Alternative
An alternative I though of was using the session ID of the logged in user. This however would not check the integrity of the message...
When generating form with PHP, I can generate a hidden input with following
CHECKSUM: hash(session id for the current user, "secretkey")
What I then would post using ajax is
field1=x&field2=y&uid=10&c=CHECKSUM
With this it would be fairly secure to authenticate the appropriate user (again pseudo-code)
ssid = SELECT ssid FROM sessions WHERE uid = $_POST[uid]
if(ssid && hash(ssid, "secretkey") == $_POST[c]) {
//User OK
} else {
//Invalid user
}
You cannot do what you're trying to do. Basically, you're trying to verify that one component (your form) on an untrusted and uncontrolled client is not tampered with by another component on that same client. You don't control the client. You can come up with all sorts of methods to make it harder for someone to do this on their client, but in the end you must expose how you're doing those integrity checks to the client. Whatever you do in your form scripts can be read and understood by the person on that client (it has to run on the client, so whomever is interacting with the client can reverse engineer anything you're doing to recover the techniques used and any keys/etc that you have to enable your scheme).
Basic rule of web application security is that you cannot control what's happening on the client, so you cannot trust client-side verification/security schemes like this.
In the end, it's unlikely that the protection offered by such a scheme would be worth the time and investment to implement it. Someone who is determined to break it will be able to.
You need to keep
uid
stored server-side. This is usually accomplished by storing it in a session variable.Because your server stores the session data, it is impossible for a client to tinker with their session's data. The best a malicious user could hope for would be to hijack someone else's active session key, which is not a practical attack on a properly secured system.
See also this detailed write-up about why we use sessions.
As already mentioned by others, you can’t control the client side. And that means you can’t control and thus can’t trust what the client sends and anything could be tampered.
But now think about this: The less parameters you expose to the client, the less they could tamper. So try to keep as much parameters in control (i. e. on the server side) as possible. That’s what sessions are used for.
So you could store the parameters that are not to be changed in the session instead of sending them to the client where they are out of your control. All you need is to associate the form instance with the server side form parameters. You can do this with a random identifier that you use as key in the session data array:
Then when you process the form request you just take the form data identifier to look up the form data in
$_SESSION['formdata']
to get the data for further processing.May be this page will help: http://www.jcryption.org
Check my answer on following mention issue
Securing and/or encrypting (hiding) POST variables in a jQuery ajax request
There is absolutely no way to prevent someone from making "fake" requests. You just have to think this way:
If you put some kind of encryption on the user-side, then it'll be easy for anyone to get how you made your encryption, and then do the same manually. For example, when you are talking about hashes:
Your
secretkey
is not secret, because it's inside of a javascript file.The only thing you can do is to throw a spanner in the "hacker"'s works. For example, you can get this secretkey from an AJAX request. This secret key would be unique and deleted on every successful request. In a more general way, you'll have to move the logic of your application as close to the server-side.