Are there any ways to cache secured data at client side such that it cannot be modified by users so that it is safe to be used again at server side ?
Or if there is any modification by user then it should be available but probably with flagged as not original data.
Are there any ways to cache secured data at client side such that it cannot be modified by users so that it is safe to be used again at server side?
No. Once the data is client-local, you've lost the game.
Or if there is any modification by user then it should be available but probably with flagged as not original data.
You could sign this data with a key known only to the server. With cryptographic signing, anyone can verify the identity of the signer, but only someone with the private key can generate the "right" signature.
Short answer - no.
Longer answer - you could probably use web storage/indexedDB/Web SQL Database, in conjunction with some kind of salted hash to check later that object hasn't changed, e.g.
Hash object with salt in server side
Send object and hash to user
get object and hash back from user
hash the object you got back from user again and check that the hash is equal to the one that you got back from user
Since storage on client side is limited to - websql(low support) localStorage/sessionStorage('argued support'), indexedDB (low support), and of course cookies are easily accessible, no, there is no way to secure data stored on the client side.Even if you encrypted the data using some JS method, the method could be found by a hacker. Server side is the only true way to secure data using some sort of HMAC.
Related
I'm looking to implement some efficient (i.e. with good performance) logic that does payload signing in our web application. The goal is for the HTML5 client to have a guarantee that the contents of a received payload are indeed those that were generated by our backend.
We don't want to do payload hash generation with shared salt because the user can easily open the HTML5 source and find the salt phrase.
We have implemented RSA signing for now where our backend adds a payload signature using its Private Key and our HTML5 client validates it using its baked in Public Key. However the signature generation process takes 250ms (for a relatively small payload) and due to the nature of the signed request this amount of time is unacceptable.
The only other idea is to generate a shared secret at runtime every time a client initializes its session with the backend. The secret however can't be sent in plaintext form so it seems we're going to have to implement a Diffie-Hellman exchange mechanism, something we'd like to avoid if possible or automate with existing libraries.
Remember that the secrecy and encryption need to be done at the Application layer, due to the nature of how we sell our product. We're not looking to encrypt our traffic, this is something that our customers might or might not implement (since it's an intranet application). However, we have to avoid exposing stuff that are related to our licensing checking mechanisms etc to them. The backend is not cloud based and is not controlled by us, but installed on the customers' machines, on premises.
Frontend is Javascript and backend is Java.
Note that Diffie-Hellman exchange mechanism is not protected against MITM attack, therefore not encrypting traffic means that you need to authenticate the DH data coming from the server. This is why a web server using a DH-based cipher suite signs the DH elements sent over the network with the private key of its server certificate, for the client to check that those elements are really from the server that he wants to connect to. Those elements are public but need to be signed.
What you call "payload hash generation with shared salt" is a keyed-hash message authentication code, so it is based on a shared secret, as you noticed, and since you do not want to use this mechanism, it means that you do not trust the client. Therefore, you have to use asymetric cryptography to sign your payload.
Signing a server payload with an asymetric algorithm means that you first need to let the server share a public key with the client. Since you do not encrypt data between the client and the server, you need to deploy the server public key inside the client source code.
You talk about the signature generation process, but the signature check process on the client side is also very important in your case, because the total time the user has to wait for the result is the addition of the time to sign and the time to check the signature (moreover, the signature can often be anticipated on the server, if the data to sign is not dynamically generated, but the verification can never be anticipated). So you need a rapid way of checking a signature on the client side. First, sign a hash, not the whole payload. Then choose the fastest asymetric signature algorithm that is available in your development environment, on the client side. Note that checking an RSA signature is faster that checking a DSA or ECDSA one, for respective keys length corresponding to the same security level. So you should stay with RSA.
All of this until this line may not help you so much! Now there is a way to increase the performances using RSA to sign and verify signatures, and this way is rather the same that SSL/TLS implements to increase browser performances when downloading multiple pages or other objects from the same server: use a session cache. You share a common secret for a specific session with one specific user. Never use this common secret for other sessions. When the user is connecting for the first time, use RSA only once, to exchange an ephemeral shared secret or exchange DH material to create this shared secret. Then, each time the server needs to sign an object, it creates a keyed-hash message authentication code with this specific secret. Therefore, if the user finds the secret, for instance using the debug mode of his browser, it's not a problem: this secret is only here to help him know that something that comes from the server has not been altered. So the user can not use this secret to alter data exchanges between the server and other users.
We ended up by using TweetNaCl both on the client and on the server side. The library provides a every easy and fast way to do DH-like shared secret exchange without going through a custom implementation. With an ephemeral shared secret we can easily generate hashes instead of signatures for our payloads dropping from 250ms to 10μs. Also RSA signing the initial DH exchange is important and the only place we use RSA.
Please read #AlexandreFenyo answer for proper theory on how to usually handle such cases.
I've recently started using modern front end technologies like React/Angular and as a result have started using tools like JSON Server to recreate dummy restful db interactions.
My understanding is that most rest api's authenticate via some kind of token and secret that is either passed as part of the url or as a header. This seems fine for retrieving data, but is it not risky exposing these login credentials in a front end language like JS when writing is possible?
My thinking is that all it would take is a simple view source for somebody to steal my token/secret and potentially start populating my db with data.
In the problem that you describe the client (browser) has the login credentials because the server provide them. There is no "exposing" as the credentials are already exposed. Exposing your credentials to every client means that there is no security.
When we talk about security we consider as a client the browser not the real person that operates the browser. As you said, the real person can access all the browser's data.
To secure your API the secret key must be kept secret. This means that each client has a different key and uses it to get their data/services from your RESTfull server.
In a simple senario this key can be used/managed like the session id.
The client should first pass through an authorization process (login maybe) and then a temporary key can be generated for the client's session.
Generally, a key is converted to rights. If every client by default has the key, everyone has the default rights, so you may also remove the key and set the default rights to every request.
A client that you don't want to have full access to your db should have a key that gives him limited access to your db.
On the other hand, if the client provides the key, this is secure. For example a php code on a server that uses the secret key for accessing your API.
Following this question: Can a cookie that was generated with Javascript (not send in the header by the server) be stolen / used by an attacker?
This is driving me crazy.
How can one ever keep state at the client using a FB access token?
One should use it to access resources on one's own server, and also from the FB server. Assuming that one uses a js framework (Backbone / Marionette) and REST authentication.
It cannot be encrypted as such, and yet there is no other way than to use a cookie to keep state at the client.
I have done plenty of research.
Every source mentions to keep state at the client, to avoid server sessions, yet I can't find a single source that explains how to do it safely.
If you know the answer, please share.
Thanks.
You can store information on the client safely if the server is delivering it.
You can encrypt or sign the data using a secret key which only the server knows and decrypt/validate the information using it.
However, by definition, you cannot store information safely which is also generated on the client itself. It's just the client playing with itself. Anyone can inspect what exactly is going on, so you can't sign or encrypt anything using any secret key, because by definition the key ceases to be secret if you give it to every client. You can also not trust any information the client is sending to the server because the client is free to send anything to the server it wishes. You cannot trust any code running on the client because it is entirely out of your control.
I just read about the Stanford Javascript Crypto Library (jsfiddle example) which supports SHA256, AES, and other standard encryption schemes entirely in javascript. The library seems very nifty, but I don't know of a reasonable use case for it.
As some questions have already pointed out, client side encryption is not a safe way to pass secure data to a server. HTTPS should be used instead. So, are there any projects that would benefit from or require client side encryption?
Use Case 1
How about local storage? You might want to store some data, but encrypt it so that other users of the computer cannot access it?
For example:
User connects to server over HTTPS.
Server authenticates user.
Server serves an encryption password specific to this user.
User does some stuff locally.
Some data is stored locally (encrypted with the password).
User wanders off
User comes back to site at later stage.
User connects over HTTPS.
Server authenticates user.
Server serves the user's encryption password.
Client-side JS uses encryption password to decrypt local data.
User does something or other locally with their now-decrypted, in-memory local data.
This could be useful in cases where you have a fat client, with lots of (sensitive) data that needs to be used across sessions, where serving the data from the server is infeasible due to size. I can't think of that many instances where this would apply...
It could also be useful in cases where the user of the application generates sensitive data and that data does not need to (or shouldn't) ever be sent to (or stored on) the server.
For an applied example, you could store the user's credit card details locally, encrypted and use JS to auto-enter it into a form. You could have done this by instead storing the data server side, and serving a pre-populated form that way, but with this approach you don't have to store their credit card details on the server (which in some countries, there are strict laws about). Obviously, it's debatable as to whether storing credit card details encrypted on the user's machine is more or less of a security risk than storing it server side.
There's quite probably a better applied example...
I don't know of any existing project which use this technique.
Use Case 2
How about for performance improvements over HTTPS, facilitated via password sharing?
For example:
User connects to server over HTTPS.
Server authenticates user.
Server serves an encryption password specific to this user.
Server then redirects to HTTP (which has much less of an overhead than HTTPS, and so will be much better in terms of performance).
Because both the server and the client have the encryption password (and that password was shared over a secure connection), they can now both send and receive securely encrypted sensitive data, without the overhead of encrypting / decrypting entire requests with HTTPS. This means that the server could serve a web page where only the sensitive parts of it are encrypted. The client could then decrypt the encrypted parts.
This use case is probably not all that worthwhile, because HTTPS generally has acceptable performance levels, but would help if you need to squeeze out a bit more speed.
Use Case 3
Host proof storage. You can encrypt data client side and then send it to the server. The server can store the data and share it, but without knowing the client's private key, it cannot decrypt it. This is thought to be the basis for services such as lastpass.
Like anything on the client, you can use obfuscation to make things more difficult for casual users to peek inside, but since the client would also need to have a copy of the decryptor there's nothing to stop the user from using the decryptor themselves either.
JavaScript is an insecure environment, period.
One use that comes to mind is host-proofing. That is where you want to store the data on the server or store and forward through the server but not give the server access to the data.
The client can encrypt the data prior to transmission to the server and keep the private key or at least the password for the private key locally.
I believe that this is the basis for services such as lastpass.
I need something like a cookie, but I specifically don't want it going back to the server. I call it a "client side session cookie" but any reasonable mechanism would be great.
Basically, I want to store some data encrypted on the server, and have the user type a password into the browser. The browser decrypts the data with the password (or creates and encrypts the data with the password) and the server stores only encrypted data. To keep the data secure on the server, the server should not store and should never receive the password. Ideally there should be a cookie session expiration to clean up.
Of course I need it be available on multiple pages as the user walks through the web site.
The best I can come up with is some sort of iframe mechanism to store the data in javascript variables, but that is ugly. Does anyone have any ideas how to implement something like this?
FWIW, the platform is ASP.NET, but I don't suppose that matters. It needs to support a broad range of browsers, including mobile.
In response to one answer below, let me clarify. My question is not how to achieve the crypto, that isn't a problem. The question is where to store the password so that it is persistent from page to page, but not beyond a session, and in such a way that the server doesn't see it.
You could use JavaScript's localStorage object. The Dive Into HTML5 ebook has an excellent chapter on it. I think the chapter also mentions some possible work-arounds for browsers which to don't support localStorage.
For what you are looking for I would say that javascript is the best you could do.
You can retrieve the encrypted data onto the server and decrypt it using javascript on the client side. No transmission of password, no secret for the user.
It depends which encryption algorithm you are using but there is libraries for that (for example Stanford Javascript Crypto Library)
(but I don't understand why are you talking about cookies)
If you are interested in the storage aspect rather than the cryptography aspect, perhaps you might consider Thomas Frank's session variables