Sanity Check: SSL+ POST vs. un-encrypted GET - security

A classic dumb thing to do is pass something security related info via a GET on the query string ala:
http://foo?SecretFilterUsedForSecurity=username
...any yahoo can just use Fiddler or somesuch to see what's going on....
How safe is it to pass this info to an app server(running SSL) via a POST, however? This link from the Fiddler website seems to indicate one can decrypt HTTPS traffic:
http://fiddler2.com/documentation/Configure-Fiddler/Tasks/DecryptHTTPS
So is this equally dumb if the goal is to make sure the client can't capture / read information you'd prefer them not to? It seems like it is.
Thanks.

Yes, it's "equally dumb". SSL only protects data from being read by a third party; it does not prevent the client (or the server) from reading it. If you do not trust the client to read some data, they should not be given access to that data, even just to make a POST.

Yes, any user can easily examine the data in a POST request, even over HTTPS/SSL, using software like Burp Suite, Webscarab, or Paros Proxy. These proxies will complete the SSL transaction with the server, and then pass on the data to the client. All data passing through the proxy is stored and is visible to the client.
Perhaps you are trying to store sensitive/secret data on the client-side to lighten the load on your server? the way to do this so that the user cannot look at it (or change it) even with a proxy, is to encrypt it with a strong symmetrical secret key known only to the server. If you want to be sure that the encrypted data is not tampered with, throw on an HMAC. Make sure you use a sufficiently random key and a strong encryption algorithm and key length such as AES 256.
If you do this you can offload the storage of this data to the client but still have assurance that it has not changed since the server last saw it, and the client was not able to look at it.

This depends on who you're trying to protect your data from, and how much control you have over the client software. Fundamentally, in any client-server application the client must know what it is sending to the server.
If implemented properly, SSL will prevent any intermediary sniffing or altering the traffic without modifying the client. However, this relies on the connection being encrypted with a valid certificate for the server domain, and on the client refusing to act if this is not the case. Given that condition, the connection can only be decrypted by someone holding the private key for that SSL certificate.
If your "client" is just a web browser, this means that third parties (e.g. at a public wi-fi location) can't intercept the data without alerting the person using the site that something is suspicious. However, it doesn't stop a user deliberately by-passing that prompt in their browser in order to sniff the traffic themselves.
If your client is a custom, binary, application, things are a little safer against "nosy" users: in order to inspect the traffic, they would have to modify the client to by-pass your certificate checks (e.g. by changing the target URL, or tricking the app to trust a forged certificate).
In short, nothing can completely stop a determined user sniffing their own traffic (although you can make it harder) but properly implemented SSL will stop third-parties intercepting traffic.

The other, more important reason not to add confidential information into URL with GET requests is that the web server and any proxies on the way will log it. POST parameters don't get logged by default.
You don't want your passwords to show up in server logs - logs are usually protected much, much less than, for example, the password database itself.

Related

Mobile API Security Paradigm

I've coded the mobile api using Node.js, Redis & MongoDB. However right now I am looking for a concrete way to provide security in our system. The question I have inspired by the infamous principle of Auguste Kerckhoff;
"It must not be required to be secret, and it must be able to fall into the hands of the enemy without inconvenience"
After inspecting this principle I figure out that there is no safe way to secure data after a sniffer capturing the entire data package. Of course there are alternate ways like using an API key, using encryption algorithms like MD5 & MD6,Triple DES,SHA1 etc. However this also won't work if the entire data package is captured. And there is security precaution standarts like HTTPS, SSL certificates. However again if someone with talent captures the data package it can act just like a verified user in our system.
How would it be possible to apply a security method such that even though the entire data package is captured, the system would be able to distinguish the request coming from an outer source not from our verified user.
PS: I thought that applying a custom encryption algorithm with timestamp in order to prevent this problem could be a bit chaotic.
According to Kerckhoffs's principle "A cryptosystem should be secure even if everything about the system, except the key, is public knowledge." So the way cryptosystem, works is that the key is the only thing that can be used to decipher the system. If the key is fallen to the enemy then its all over.
In practice when you communicate over the internet or try to
authenticate your email account with the password. Your password is
never sent to, nor stored on the server in plain text. If you do then,
its not secure. The best security practice is not to store the
password at all (not even encrypted), but to store the salted hash of
the encrypted password.
That is one hash for one user. It is one way, you cannot get back user info, just test if it is in the database or not. Now even if the enemy takes control of the database, it cannot access your username/passwords.
Now coming to the point, it does not matter what you transmit in the communication channel, because the communication channel is the enemy!!! It is available to other users, anyone can sniff it. It is like enemies scanning each other on the radio.
The hash that has been sent over the channel can be sniffed and be used for authentication. True, but server can differentiate between spoofed attempt and the actual attempt, using HTTPS connection. Server tracks the HTTPS sessions and would ask to revalidate if something like this happens. HTTPS blocks use of sniffed data / MITM attacks. Even if sniffer gets hash (temporary ticket), he cannot do anything malicious, username and password cannot be cracked.
Thanks to Kerckhoff, our passwords are safe.
How to implement it on node.js ?? look for passport.js package. It implements the current standard OpenAuth.

Encrypting Amazon S3 URL over the network to secure data access

I want to host copyrighted data on a Amazon S3 bucket (to have a larger bandwidth available than what my servers can handle) and provide access to these copyrighted data for a large numbers of authorized clients.
My problem is:
i create signed expiring HTTPS URL for these resources on the server side
these URL are sent to clients via a HTTPS connection
when the client uses these URL to download the contents, the URL can be seen in clear for any man-in-the-middle
In details, the URL are created via a Ruby On Rails server using the fog gem.
The mobile clients I'm talking about are iOS devices.
The proxy I've used for my test is mitmproxy.
The URL I generated looked like this:
https://mybucket.s3.amazonaws.com/myFileKey?AWSAccessKeyId=AAA&Signature=BBB&Expires=CCC
I'm not a network or security expert but I had found resources stating nothing was going clear over HTTPS connections (for instance, cf. Are HTTPS headers encrypted?). Is it a misconfiguration of my test that led to this clear URL? Any tip on what could have gone wrong here? Is there a real chance I can prevent S3 URL to go clear over the network?
So firstly, when sending a request over SSL all parameters are encrypted. If you were to look at the traffic going through a normal proxy you wouldn't be able to read them.
However, many proxies allow interception of SSL data by creating dummy certificates. This is exactly what mitmproxy does. You may well have enabled this and not realised it (although you would have had to install a client-side certificate to do this).
The bottom line is that your AWS URLs could be easily intercepted by somebody looking to reverse engineer your app, either through a proxy or by tapping into the binary itself. However, this isn't a 'bad thing' per se: Amazon themselves know this happens, and that's why they're not sending the secret key directly in the URL itself, but using a signature.
I don't think this is a huge problem for you: after all, you're creating URLs that expire, so even if someone can get hold of them through a proxy they'll only be able to access the URL for as long as it is valid. To access your resources post-expiry would require direct access to your secret key. Now, it actually turns out this isn't impossible (since you've probably hard-coded it into your binary), but it's difficult enough that most users won't be bothering with it.
I'd encourage you to be realistic with your security and copyright prevention: when you've got client-side native code it's not a matter of if it gets broken but when.

Difficulty in understanding login mechanism password security?

In our login page we enter username password and then submit the form. The password goes to the server where it is crypted using some algorithm and then saved to database. But when it is posted to the server it can be seen in firebug post data. So how is it secure i have seen the similiar implementation in other cases as well. Can not it be trapped in between the time it is taken from client to server.
Firebug can see the password because it is acting as a proxy on your client (one of the two endpoints of the communications path). SSL/TLS (https) encrypts the data in transit between the two endpoints (think of it as a protected tunnel where the only way to see the real data inside is to be at one of the endpoints). Since Firebug runs on the client, it has access to the endpoint, where the data is not encrypted. Think of a tunnel you can pass data into that will be protected in transit; Firebug sits at the entrance to that tunnel so it can see everything that goes in (and comes out).
At a minimum, sending passwords (and any other sensitive data) should be done over SSL/TLS, to prevent someone/something not on an endpoint of the tunnel from seeing the data. Ideally, you will want to run everything over https to prevent session hijacking attacks (you can read all about that in the Wikipedia summary). Any site not encrypting at least the exchange of credentials (passwords, etc) is not following industry best-practices and should be considered an insecure implementation.
yes, you are right. If data is sent in clear text to the server, it can be captured in Transit. Hence, always use HTTPS connection.

Security advice: SSL and API access

My API (a desktop application) communicates with my web app using basic HTTP authentication over SSL (Basically I'm just using https instead of http in the requests). My API has implemented logic that makes sure that users don't send incorrect information, but the problem I have is that someone could bypass the API and use curl to potentially post incorrect data (obtaining credentials is trivial since signing up on my web app is free).
I have thought about the following options:
Duplicate the API's logic in the web app so that even if users try to cheat the system using curl or some other tool they are presented with the same conditions.
Implement a further authentication check to make sure only my API can communicate with my web app. (Perhaps SSL client certificates?).
Encrypt the data (Base 64?)
I know I'm being a little paranoid about users spoofing my web app with curl-like tools but I'd rather be safe than sorry. Duplicating the logic is really painful and I would rather not do that. I don't know much about SSL client certificates, can I use them in conjunction with basic HTTP authentication? Will they make my requests take longer to process? What other options do I have?
Thanks in advance.
SSL protects you from the man-in-the-middle attacks, but not from attacks originated on the client side of the SSL. A client certificate built into your client API would allow you to identify that data was crafted by the client side API, but will not help you figuring out if client side manually modified the data just before it got encrypted. Technically ssavy user on the client end can always find a way to modify data by debugging through your client side API. The best you can do is to put roadblocks to your client side API, to make it harder to decipher it. Validation on the server side is indeed the way to go.
Consider refactoring your validation code so that it can be used on both sides.
You must validate the data on the server side. You can throw nasty errors back across the connection if the server-side validation fails — that's OK, they're not supposed to be tripped — but if you don't, you are totally vulnerable. (Think about it this way: it's the server's logic that you totally control, therefore it is the server's logic that has to make the definitive decisions about the validity of communications.)
Using client certificates won't really protect you much additionally from users who have permission to use the API in the first place; if nothing else, they can take apart the code to extract the client certificate (and it has to be readable to your client code to be usable at all). Nor will adding extra encryption; it makes things much more difficult for you (more things to go wrong) without adding much safety over that already provided by that SSL connection. (The scenario where adding encryption helps is when the messages sent over HTTPS have to go via untrusted proxies.)
Base-64 is not encryption. It's just a way of encoding bytes as easier-to-handle characters.
I would agree in general with sinelaw's comment that such validations are usually better on the server side to avoid exactly the kind of issue you're running into (supporting multiple client types). That said, you may just not be in a position to move the logic, in which case you need to do something.
To me, your options are:
Client-side certificates, as you suggest -- you're basically authenticating that the client is who (or what, in your case) you expect it to be. I have worked with these before and mutual authentication configuration can be confusing. I would not worry about the performance, as I think the first step is getting the behavior your want (correctness first). Anyway, in general, while this option is feasible, it can be exasperating to set up, depending on your web container.
Custom HTTP header in your desktop app, checking for its existence/value on the server side, or just leveraging of the existing User-Agent header. Since you're encrypting the traffic, one should not be able to easily see the HTTP header you're sending, so you can set its name and value to whatever you want. Checking for that on the server side is akin to assuring you that the client sending the request is almost certainly using your desktop app.
I would personally go the custom header route. It may not be 100% perfect, but if you're interested in doing the simplest possible thing to mitigate the most risk, it strikes me as the best route. It's not a great option if you don't use HTTPS (because then anyone can see the header if they flip on a sniffer), but given that you do use HTTPS, it should work fine.
BTW, I think you may be confusing a few things -- HTTPS is going to give you encryption, but it doesn't necessarily involve (client) authentication. Those are two different things, although they are often bundled together. I'm assuming you're using HTTPS with authentication of the actual user (basic auth or whatever).

SSL session persistence and secure cookies

I currently have a roll-your-own application security service that runs in my enterprise and is - for the most part - meeting business needs.
The issue that I currently face is that the service has traditionally (naively) relied on the user's source IP remaining constant as a hedge against session hijacking - the web applications in the enterprise are not directly available to the public and it was in the past perfectly acceptable for me to require that a users' address remain constant throughout a given session.
Unfortunately this is no longer the case and I am therefore forced to switch to a solution that does not rely on the source IP. I would much prefer to implement a solution that actually accomplishes the original designer's intent (i.e. preventing session hijacking).
My research so far has turned up this, which essentially says "salt your authentication token hash with the SSL session key."
On the face of it, this seems like a perfect solution, however I am left with a nagging suspicion that real-world implementation of this scheme is impractical due to the possibility that the client and server can at any time - effectively arbitrarily - opt to re-negotiate the SSL session and therefore change the key.
this is the scenario I am envisioning:
SSL session established and key agreed upon.
Client authenticates to server at the application level (i.e. via username and password).
Server writes a secure cookie that includes SSL session key.
Something occurs that causes a session re-negotiation. For example, I think IE does this on a timer with or without a reason.
Client submits a request to the server containing the old session key (since there was no application level knowledge of the re-negotiation there was no opportunity for a new, updated hash to be written to the client).
Server rejects client's credential due to hash match failure, etc.
Is this a real issue or is this a misapprehension on my part due to a (to say the least) less-than-perfect understanding of how SSL works?
See all topics related to SSL persistence. This is a well-researched issue in the load-balancer world.
The short answer is: you cannot rely on the SSLID -- most browsers renegotiate, and you still have to use the source IP. If the IP address is likely to change mid-session then you can force a soft-reauthentication, or use the SSLID as a bridge between the two IP changes (and vice-versa, i.e. only assume hijacking if both IP address and SSLID change at the same time, as seen by the server.)
2014 UPDATE
Just force the use of https and make sure that that you are not vulnerable to session fixation or to CRIME. Do not bother to salt your auth token with any client-side information because if an attacker was able to obtain the token (provided that said token was not just trivial to guess) then whatever means were used to obtain it (e.g. cross-site scripting, or the full compromising of the client system) will also allow the attacker to easily obtain any client-side information that might have gone into the token (and replicate those on a secondary system if needed).
If the client is likely to be connecting from only a few systems, then you could generate an RSA keypair in the browser for possibly every new client system the client connects from (where the public part is submitted to your server and the private part remains in what is hopefully secure client storage) and redirect to a virtual host that uses two-way (peer/client certificate) verification in lieu of password-based authentication.
I am wondering why it would not be just enough to simply
require ssl in your transport
encode inputs (html/url/attribute) to prevent cross-site scripting
require only POSTs for all requests that change information and
prevent CSRF as best you can (depending on what your platform supports).
Set your cookies to HTTPOnly
Yes, but there are several things you can do about it. The easiest it to simply cache the session key(s) you use as salt (per user), and accept any of them. Even if the session is renegotiated you'll still have it in your cache. There are details--expiration policy, etc.--but nothing insurmountable unless you are running something that needs to be milspec hardened, in which case you shouldn't be doing it this way in the first place.
-- MarkusQ

Resources