As the title says. Should you pass an authentication token in the url of a GET request? What about man-in-the-middle attacks? Or Packet sniffing? All including the requests being wrapped with HTTPS
When you use https GET and POST are equally secure for man-in-the-middle attacks as the payload is encrypted and nobody except the receiver with the private key can see the data.
Using GET the urls visited are stored in the browser history and can also be shared (accidentally) with other pople (see also Session Hijacking). So I would not pass auth information as query parameter but use http header cookies or something wich is not stored in the browsers history. If you have to do it you should be sure that the auth information invalidated after some time.
Related
I have a restful api written in Go. I want to authenticate each request. To do so, the server and the client share a secret.
To authenticate a GET request to /foo/bar/, the client add a nonce parameter with a timestamp to the url, /foo/bar/?nonce=13899932199128265, and then add the hmac of data with the secret to the url. It gives something like /foo/bar/?nonce=13899932199128265&hmac=hd7nd7s9s702j
To verify the validity of an incoming request, the server verify that no requests from the client arrived after the time stamp and that the hmac is valide.
I believe it is a common way to authenticate requests. For instance, mtgox uses a similar process.
The problem that I have is that my client will likely require a list of urls [url1, ... urln] at the same time. In that case, nothing guarantee that the first request sent by the client will arrived first to the server. Indeed, any permutation of the requests will result in 403 errors.
My first question is simple: is that a real problem? Is it likely that request order will change during transport?
Second, is it entirely to the client to verify no 403 errors happen?
Is there better way to do?
Thanks a lot!
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.
I'm building an API with no server-side authentication. A unique key (assume the key is very long and impossible to guess) will be generated for the session, but no cookie will be set on the client. The client could be a web browser with AJAX, a PHP script using CURL, or a desktop application. The normal transaction process I'm imagining will be:
Initial encounter
The client makes an initial request, calling a start_session method
The server generates a key and returns it along with some initial data
The client stores the key for later use (e.g. JavaScript sets a cookie with the key)
Next request
The client requests the server again, calling some set_data method, providing the original session key, as well as loads of private data such as a credit card number, information about legal cases, etc.
The server responds, and the responds with a success message
Another request
The client requests the server again, providing the original session key, and calling some get_data method
The server responds with all of the private data in some format (e.g. XML, JSON, etc)
A session key expires, if not used, in a 20 minutes, and all API URIs will require SSL.
My concern / question is: Do I need to be worried about whether the client has leaked the session key. Without authentication, I'm trusting that the original requester to keep the session key private. Is this common / safe practice?
Unless you use HTTPS throughout, you're vulnerable to HTTP sniffing, a la Firesheep.
Eve, if you do use SSL, if the client page isn't SSL or contains any non-SSL Javascript (or non-SSL frames in the same domain), you're still vulnerable (and there's nothing you can do about it)
To answer your stated question, it completely depends on your situation.
EDIT: You should warn your clients (developers) in the documentation page to handle the key correctly.
Beyond that, it depends on the average skill level of the clients.
You should probably have a disclaimer of some sort (I am not a lawyer).
It's probably OK.
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.
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.