What is the purpose of nonce and hmac in a session cookie? - session

I am looking at some code, and they are storing a "nonce" and a "hmac" in a users session cookie. What is the purpose of a nonce? What is the purpose of the hmac?

The HMAC (Hash-based Message Authentication Code) is a cryptographic Hash of the actual data of the cookie. So that the server can verify the data hasn’t been tampered with.
The Nonce (Number used once) is most likely used to encrypt the data of the cookie. Usually, when you encrypt something, you don’t want the ciphertext to be the same for identical plain messages. So you use the static encryption key in conjunction with a random Nonce changing on every encryption.

Related

Authentication and encryption keys in cookie based session management

My query comes from trying to use session store for eg. RedisStore in Golang where the store takes a vararg as last argument which as per document are pairs of authentication and encryption keys.
Most of the examples I see just use a single argument here (for eg. "secret", "mysecret" etc.) and I couldn't get any information about what is achieved by sending multiple pairs of authentication and encryption keys.
Could someone please explain more or direct me to some information about the purpose of the authentication and encryption keys in session management using cookies.
From the docs:
Keys are defined in pairs to allow key rotation, but the common case is to set a single authentication key and optionally an encryption key.
The first pair is used for authentication, encryption and decryption, all other pairs are only used for authentication and decryption (but not encryption).
This is a very common strategy for key rotation. A new key pair is generated regularly and becomes the new key for encryption. Some or all other keys are kept around so that existing data can still be decrypted for some time. The oldest key can be discarded eventually. This limits the impact of a disclosed key because it becomes useless after some time.
Other software that uses this method:
Google's KMS: https://cloud.google.com/kms/docs/key-rotation
Amazon's KMS: https://docs.aws.amazon.com/kms/latest/developerguide/rotate-keys.html
HashiCorp's Vault: https://www.vaultproject.io/api/secret/transit/index.html#rotate-key

Password security in sessions

Instead of stroing plain text passwords, we use a strong hashing function with high computation cost and random salt to thwart rainbow attacks etc.
But when a user is in a session, typically his or her username is stored along with a hash of their password as a cookie to authenticate the sesssion. If the user's browser cookie space is compromised, doesn't an attacker obtain an easier target of cracking the username+ session hash, instead of username + pass hash?
In Django for example, passwords are hashed with PBKDF2 or bcrypt, but session hashes use a less complex HMAC and no random salt. Is this a security issue? If yes, what is the right way to handle sessions?
For each session, I suggest to use dedicated SessionID - random long 128bit value. And, keep session key as:
username:SessionID:hash
where
hash = sha1(SessionID|username|client_IP|secret_server_side_password);
Every time, when you receive cookie, you need again compute hash, and compare with received one.
As result, this cookie is useless after session is closed (mismatch SessionID).
Moreover, if cookie will be stolen from active session, server can
figure out attack with stolen cookie from another computer, because of client_IP from real client will be different to actual client_IP.
Of course, if ClientIP is changed, session automatically will be disconnected.
Alternative - using authentication system, based on client's
SSL certificates, for example - emcSSL.

ajax login procedure - is using salt and hash is really neccessary?

I'm sending password that user inputs to the server without obscuring it. I've read some suggestions to do the following before sending the data:
Ask the server for a seed value (a salt) using an ajax request
Hash the password + seed using a sha1 sum
Are these steps really enforce security in any substantial way? The salt isn't going to be unique so everyone can get it. The algorith of applying the salt is available to everyone as it is applied on a client. The algorithm of sha1 sum is also available so anyone can use it to unhash the password. So what's the benefit?
As far as I know these steps (Digest auth) the salt is unique for every session, so every login attempt will get its own, different salt. Please consult your sources if it is the case there, too.
The client, after reading the salt for the current login process and sends the hash of the password+salt to the server wich compares it to its own hash of password+salt.

With a session store on the server, what does session secret do?

I understand if one saves sessions to cookies, you need to encrypt them with a secret else malicious clients could modify their session at will. This design is still bad for many reasons popularly discussed.
However, if one saves sessions on the server (I happen to use a Memcache store via Rack:Session:Dalli) , I understand all the client gets is a cookie with a key the server uses to lookup their session from the store. I still set a session secret. But I don't understand what it does anymore.
Encrypting a large random number results in essentially another large random number. In other words, if there is no meaning ascribed to the information (its just a random number), then there is no security benefit to encryption. If the ID you're storing has some information embedded in it, like a certain bit set or only a certain subset of IDs are used, then encryption is useful.
The length of the session ID is important. Obviously, the longer the ID, the more resistant it is to brute forcing. The expected number of simultaneous user sessions is also a factor, as the number of sessions reduces the number of brute force attempts needed to find a valid session ID. For example, two simultaneous sessions reduces the effective strength of the ID by one bit (a 128 bit key becomes as effective as a 127 bit key would be with one session only). An Amazon-scale website with (say) 1,000,000 simultaneous sessions would effectively lose 20 bits of its session key strength.
If you need to defend against brute force attacks, implement a middleware to check for that. Adding information to the session id, like an application-unique string, can make detecting a brute-force attack easier (and requires session id encryption). Note that this does not enhance the security of the key itself, and is basically wasted effort unless the app takes some action when presented with an improper session id.
Whatever you do, just make sure to use SSL and set the cookie to https only. Time out the session server-side, and don't rely on cookie expiration and the good will of the client browser.
TL;DR: If only using cookies for session ID storage, encryption is not necessary if a good RNG is used. Use SSL and set the cookie secure attribute.

What is a secure way to serve API service that does not create a lot of communication overhead?

I had an interview few days ago, and the employer asked me about secure way to serve API service. He said
Each API request requires API key.
Each API request will request 1 single method, which takes a single parameter, and every service will work through this single method.
He wanted to see if there is a secure way for a client side to API request to the server side without exposing the API key.
I talked about general public/private cryptography, but he wanted simpler method than that.
In the end, he talked about using common hash algorithm (md5, sha1) for client side to safely hash its key, and also hash the method with parameter and request to the server, but I do not think I got the point very well.
I remember some libraries out there first encodes the body of the API request to be encrypted with md5 or sha1. But what is the point of doing it with 1-way hash? It may be true that man-in-the-middle won't know about API key, but how will server know 1.API key, 2.What method that client has requested?
You can hash the request together with API key. And then add the hash to the request.
That way the hash never goes over the wire. And the server can verify from his own copy of the API key.
For example the client does:
var request = "http://example.com/bla?a=1&b=2";
var hash = sha1(request + ApiKey).ToHex();
var request-with-hash = request +"&key="+hash;
And the server does:
var receivedRequest = "http://example.com/bla?a=1&b=2&key=ABC...09"
var key=extractKey(receivedRequest); // ABC...09
var strippedRequest = stripKeyFromRequest(receivedRequest);
var hash = sha1(strippedRequest + ApiKey).ToHex();
if(hash!=key)
Error("ApiKeyWrong")
Note that this still suffers from at least two problems:
Replay attacks. This can be avoided by using a better protocol, with some kind of nonce.
The API key can be simply extract from the client, unless it's running on a secure system. This is a fundamental problem, and cannot be avoided. ApiKeys on untrusted systems are not secure.

Resources