Using HTTPS for the client-server communication - authentication

I would like to use the HTTPS to secure the communication between my client and the server. The first encrypted communication will be used to authenticate the user - i.e. checking his/her user name and password.
After the user credentials will be successfully checked by server I would like to start getting some data in subsequent requests. BUT how the server will determine that the subsequent request is send by the user, whose credentials were already checked?
Since the TCP connection might be closed between login and subsequent HTTPS requests, (I think) this means that the SSL context must be released by the server, so with the new GET request, the new TCP connection must be established and the new SSL(TLS) handshake must be done (i.e. new shared password for the encryption must be exchanged by both sides, etc.)
For this I think server needs to send back to the client in 200 OK response for the initial authentication request some randomly generated nonce (which is valid for a certain time), which I will include in every subsequent request, so the server will be able to detect, based on this randomly generated nonce, which user name is behind the request and check that this user is already logged in. Is my understanding correct?
Thanks a lot for the reply
BR
STeN

The simplest method is to require all communication to go via HTTPS (so the data is confidential; nobody other than the client and the server can see it) and to use simple username and password on every request inside that secure connection. This is dead simple to do in practice (the username and password actually go over the connection as an HTTP header, which is OK here because we're using HTTPS) and the server can check every time that the user is allowed. You don't need to worry about the SSL handshakes; that's the SSL/HTTPS layer's responsibility (and that's why HTTPS/SSL is nice).
Alternatively, the login can be done with any method and generate some kind of magic number (e.g., a UUID or a cryptographic hash of a random number and the user's name) that is stored in a session cookie. Subsequent requests can just check that the magic number is one that it recognizes from session start (and that not too much time has passed since it was issued); logout just becomes forgetting the magic number on the server side (and asking the client to forget too). It's a bit more work to implement this, but still isn't hard and there are libraries for server-side to handle the donkey work.
The first option is particularly good for where you're writing something to be used by other programs, as it is really easy to implement. The second option is better where the client is a web browser as it gives users more control over when their browser is authorized (program APIs don't tend to need that sort of thing). Whenever the client is going to be a browser, you need to take care to armor against other types of attack too (e.g., various types of request forgery) but that's pretty much independent of everything else.

Inventing custom authentication mechanism in your case is very risky - it's easy to make a mistake that will let lots of wrong doing. So the right approach, as for me, would be to use HTTPS and pass user credentials with each request.

Related

Using socket io over http, is a secure log in procedure possible?

I have built a game server in nodejs using socket io.
I am planning to remove express and cookies from the authentication procedure and instead use webstorage and a client which attempts to log in during the socket io handshake.
However, I am using http and sending the user id and password in cleartext. Please, have mercy on me! I believe using https for the entire socket connection would add a huge overhead since updates are sent every 100ms. My current solution has worked for development, but I am sure it is insecure.
I should mention I have never set up/used https, so correct me if I am wrong regarding the overhead, which I know is a very debated topic. An ideal solution appears to be authenticating users over a https connection and then transmitting game state stuff over http, but I have no idea if or how this could be achieved.
Finally, I have 2 options for logging users in. I could allow the socket io connection on the server and just emit the log in credentials from the client. Then disconnect them if they are incorrect.
However, a cleaner solution would be to send the user id and pw in the http header for the handshake, and then authenticate the user from a socket.io middleware, but I am not sure if sending the data this way would be safe.
I do not think this is such a niche problem that a standard practice does not exist, however it may be to just use https. I believe there is no advantage to encrypting the users credentials as the data can still be snooped between the client and server. Any information on how I can achieve this is appreciated,
Or just point me in the right direction :)
Use one https connection for the login authentication and reply back to the client with a unique security token if the username/password is valid.
Use ordinary http connections for the rest of the dialog between client and server. Include the security token in the dialog if the client is requesting something that requires validation. Your client can store the security token in a cookie if you find that convenient, as the token can only be used for one session.
Have the server purge session tokens once a client signs off, or after the token has been idle for some period of time.
This is cheap and effective for medium-security applications. Variations on this scheme get used in many applications. It is not foolproof - a packet sniffer may be able to grab the security token in transit.
If the security token is constructed from a hash of the client IP address and a server timestamp, then it is easy for the server to validate the token in every message and very difficult for a 3rd-party to hijack the session.

Login via websocket - is this safe?

On webpage (with https)
Client connects to server with websocket (secure wss over TSL)
Server send 'ready-for-user-and-password'-message
User enters info and Client sends it
Server validates and as long as websocket is connected, knows who the recipient is
EDIT:
I am considering the above instead of using a post method.
It can be safe against some attacks but as usual, there are ways to break into the site and we have to evaluate security holistically
DB passwords
It is not clear from the description but plausible that the setup you've described stores user passwords in plain text.
Best practice in that respect is to calculate password's hash sum with salt and keep that in the database, so if attacker manages to get a db dump, they will need a lot of time to guess a password based on that.
Rate limiting
You should limit unsuccessful login attempts so the attacker won't be able to easily pick a password by bruteforce.
Logging
Another thing which can be problematic here is logging: you need to make sure the credentials don't end up on application log files (I've seen that with credit card numbers).
Similar concern is retaining the sensitive info for too long after verification has ended which makes them more vulnerable (to e.g. forcing a heap dump in Java and picking them from that file)
SSL secret material
If you don't pay enough attention to reducing the access to ssl private key, somebody can play a man-in-the-middle attack.
Depending on the ciphersuites your app server supports, previously recorded communications can be vulnerable to decryption if an attacker steals the key. The concept of resistance to that is called forward secrecy. You can validate if you properly tuned your web app here.
Your cert authority (or any other else) can issue a certificate for your website to somebody else allowing the attacker to misrepresent you (see Mozilla and WoSign, Additional Domain Errors).
CORS
You should also set the Content-Security-Policy so that it will be trickier to force the browser code to send this auth info to other servers.
Social Engineering
Attacker can trick your user into launching some code in the web tools console - you can try opening a web console e.g. on Facebook and see what they've done against that.
New stuff
Vulnerabilities get discovered each day, some of them are published on bulletins, you should follow those for your stack (e.g. OpenSSL) and patch / upgrade where appropriate.

Using a RESTful API - Is it secure?

We are partnering with a service provider which exposes their services via RESTful API.
We can authenticate with the API by passing a username and password as URL parameters.
Example: https://example.com/api/service.json?api_user=Username&api_key=Password
I know this is using SSL. However, since the username and password are part of the URL, couldn't this be intercepted by a third party?
No, a third party will only be able to see the destination (example.com). The rest of the URL is actually embedded inside the request.
It helps to understand the process of how an HTTP (or HTTPS) request is made.
determine protocol (in this case HTTPS, using port 443)
get IP address of server using DNS
establish a TCP connection to server (if SSL is involved, it's a bit more complicated)
issue a request to server on the new connection which will look something like
GET /api/service.json?api_user=Username&api_key=Password
Since the actual request is part of the encrypted data stream, there's no way for someone monitoring the connection to extract sensitive information.
The previous answers are both technically correct; if you're using HTTPS, the URL and querystring data will be encrypted prior to transmission and can be considered secure.
However, the fact that an API is asking for a username and password as querystring parameters may indicate a somewhat lax approach to security.
For example, many webservers will log the request querystring parameters by default , which means that your plain-text credentials might be lying around on disk somewhere (and many companies will store, or back up, webserver logs in insecure ways).
In short: passing credentials as querystring parameters isn't a security risk per se, but is generally a bad practice and may be symptomatic of larger security issues.
However, since the username and password are part of the URL, couldn't
this be intercepted by a third party?
The URL is sent under encryption as well. In other words, the process that secures the channel occurs before the URL is sent to the server.
You're safe.

How do sites support http (non-SSLed) sessions securely?

I note that some sites (such as gmail) allow the user to authenticate over https and then switch to http with non-secure cookies for the main use of the site.
How is it possible to have http access to a session but this still be secure? Or is it not secure and hence this is why gmail gives the option to have the entire session secured using https?
Please give an example of how this works and avoids session hijacking attacks, whilst still allowing access to authenticated content over http. I want to be able to implement such a scheme if it's secure, to avoid having to have a whole site as https for performance reasons.
As Thilo said, but I'll explain a little further :)
A webserver is stateless! This is really the problem of the authentication-case. You can't just log in, and then say "from now in, this user is logged in" - you need some way to identify which user it is that's requesting a new site this time.
A common way of doing this is by implementing sessions. If you packet-sniff your network traffic while logging into, and then browsing a site you'll commonly notice something like this:
Logging in: You will transmit your username and password to the server. Completely unencrypted! (SSL / HTTPS will encrypt this request for you to avoid man-in-the-middle attacks)
Response: You will receive a randomly generated string of a lot of weird characters. These will typically be stored in a cookie.
Request of some site only you should have access to: You will transmit the randomly generated string to the server. The server will look this string up, and see that it's associated with your session. This allows the server to identify you, and grant you access to your sites.
.. Now, HTTP in itself is not secure. This means that your password and your session-cookie (the randomly generated string) will be transmitted completely un-encrypted. If someone has access to your traffic (through trojans, router hijacking, whatever), he will be able to see your username / password when you log in, if you're not using HTTPS. This will grant him access to your site untill you change your password (unless he changes it first :P ). In the rest of the requests he will be able to get your session cookie, which means he could steal your identity for the rest of that cookie lifecycle ('till you log out, or the session expires on the server).
If you want to feel secure, use HTTPS. Realistically though, it's a lot easier to social engineer a keylogger into your computer than it is to read all your traffic :)
(Or as others have pointed out, use cross-site-scripting to read your session cookie)
It is only secure insofar as the password is not transmitted in the clear. It is possible (and has been done) to intercept and abuse the GMail session cookie in HTTP mode.
To avoid session hijacking, you need to stay in HTTPS mode (which GMail now offers, I think).
This is just a tiny bit more secure than plain HTTP - the login name/password doesn't go over the wire in plaintext. Apart from that, it works exactly like a normal HTTP cookie-based session (because that's what it is); therefore, all the session hijacking issues apply.
It's not really possible and not secure. That's why we got "secure cookies". Although it's good against passive sniffing attacks because username/password won't be exposed however session hijacking is still possible.
Also check out this SSL Implementation Security FAQ paper.

Is a HTTPS query string secure?

I am creating a secure web based API that uses HTTPS; however, if I allow the users to configure it (include sending password) using a query string will this also be secure or should I force it to be done via a POST?
Yes, it is. But using GET for sensitive data is a bad idea for several reasons:
Mostly HTTP referrer leakage (an external image in the target page might leak the password[1])
Password will be stored in server logs (which is obviously bad)
History caches in browsers
Therefore, even though Querystring is secured it's not recommended to transfer sensitive data over querystring.
[1] Although I need to note that RFC states that browser should not send referrers from HTTPS to HTTP. But that doesn't mean a bad 3rd party browser toolbar or an external image/flash from an HTTPS site won't leak it.
From a "sniff the network packet" point of view a GET request is safe, as the browser will first establish the secure connection and then send the request containing the GET parameters. But GET url's will be stored in the users browser history / autocomplete, which is not a good place to store e.g. password data in. Of course this only applies if you take the broader "Webservice" definition that might access the service from a browser, if you access it only from your custom application this should not be a problem.
So using post at least for password dialogs should be preferred. Also as pointed out in the link littlegeek posted a GET URL is more likely to be written to your server logs.
Yes, your query strings will be encrypted.
The reason behind is that query strings are part of the HTTP protocol which is an application layer protocol, while the security (SSL/TLS) part comes from the transport layer. The SSL connection is established first and then the query parameters (which belong to the HTTP protocol) are sent to the server.
When establishing an SSL connection, your client will perform the following steps in order. Suppose you're trying to log in to a site named example.com and want to send your credentials using query parameters. Your complete URL may look like the following:
https://example.com/login?username=alice&password=12345)
Your client (e.g., browser/mobile app) will first resolve your domain name example.com to an IP address (124.21.12.31) using a DNS request. When querying that information, only domain specific information is used, i.e., only example.com will be used.
Now, your client will try to connect to the server with the IP address 124.21.12.31 and will attempt to connect to port 443 (SSL service port not the default HTTP port 80).
Now, the server at example.com will send its certificates to your client.
Your client will verify the certificates and start exchanging a shared secret key for your session.
After successfully establishing a secure connection, only then will your query parameters be sent via the secure connection.
Therefore, you won't expose sensitive data. However, sending your credentials over an HTTPS session using this method is not the best way. You should go for a different approach.
Yes. The entire text of an HTTPS session is secured by SSL. That includes the query and the headers. In that respect, a POST and a GET would be exactly the same.
As to the security of your method, there's no real way to say without proper inspection.
SSL first connects to the host, so the host name and port number are transferred as clear text. When the host responds and the challenge succeeds, the client will encrypt the HTTP request with the actual URL (i.e. anything after the third slash) and and send it to the server.
There are several ways to break this security.
It is possible to configure a proxy to act as a "man in the middle". Basically, the browser sends the request to connect to the real server to the proxy. If the proxy is configured this way, it will connect via SSL to the real server but the browser will still talk to the proxy. So if an attacker can gain access of the proxy, he can see all the data that flows through it in clear text.
Your requests will also be visible in the browser history. Users might be tempted to bookmark the site. Some users have bookmark sync tools installed, so the password could end up on deli.ci.us or some other place.
Lastly, someone might have hacked your computer and installed a keyboard logger or a screen scraper (and a lot of Trojan Horse type viruses do). Since the password is visible directly on the screen (as opposed to "*" in a password dialog), this is another security hole.
Conclusion: When it comes to security, always rely on the beaten path. There is just too much that you don't know, won't think of and which will break your neck.
Yes, as long as no one is looking over your shoulder at the monitor.
I don't agree with the statement about [...] HTTP referrer leakage (an external image in the target page might leak the password) in Slough's response.
The HTTP 1.1 RFC explicitly states:
Clients SHOULD NOT include a Referer
header field in a (non-secure) HTTP
request if the referring page was
transferred with a secure protocol.
Anyway, server logs and browser history are more than sufficient reasons not to put sensitive data in the query string.
Yes, from the moment on you establish a HTTPS connection everyting is secure. The query string (GET) as the POST is sent over SSL.
You can send password as MD5 hash param with some salt added. Compare it on the server side for auth.