views:

303

answers:

8

Despite all the advices to use SSL/https/etc. I decided to implement my own security layer on top of http for my application... The concept works as follows:

User registers -> a new RSA Keypair is generated
the Private Key gets encrypted with AES using the users login Password
(which the server doesnt know - it has only the sha256 for authentication...)

Server stores the hash of the users password
 and the Encrypted Private Key and Public Key

User logs in -> authenticates with nickname+password hash
(normal nick/password -> IP-bound sessionid authentication)
Server replies: sessionid, the Encrypted RSA Private Key
    and an Encrypted randomly generated Session Communication Password

Client decrypts the RSA Private Key with the users Password
Client decrypts the Session Communication Password with the RSA Private Key

---> From this point on the whole traffic gets AES-encrypted
     using that Session Password

I found no hole in that chain - neither the private key nor the login password get ever sent to the server as plaintext (I make no use of cookies, to exclude the possibility of the HTTP Cookie header to contain sensitive information)... but I am biased, so I ask - does my security implementation provide enough... security?

A: 

Hmm...I'd say it's certainly still prone to Grizzlies, African Killer Bees, and Bombadier planes ;)

akellehe
This would be OK if it were a comment, but it's hardly an answer.
NullUserException
Perhaps not the answer you were looking for my friend, but it is certainly technically correct.
akellehe
@NullUserException: Though the "answer" is not quite helpful, still, at least it's humorous... an attribute many people are lacking :)
apirogov
+23  A: 

Why does everyone have to come up with their secure transport layer? What makes you think you've got something better than SSL or TLS? I simply do not understand the motivation to re-invent the wheel, which is a particularly dangerous thing to do when it comes to cryptography. HTTPS is a complex beast and it actually does a lot of work.

Remember, HTTPS also involves authentication (eg: being able to know you are actually talking to who you think you are talking to), which is why there exists a PKI and browsers are shipped with Root CA's. This is simply extremely difficult (if not impossible) to re-invent and prone to security holes. To answer you question, how are you defending against MITM attacks?

TLDR: Don't do it. SSL/TLS work just fine.

/endrant.

NullUserException
As far as I know - for https/SSL you need to buy a certificate... and the rare ways getting it for free are rather complicatedI do it just out of interest and for fun - I'm not going to pay..Sure, maybe I can get a kind of "untrusted" certificate... but what is more ugly - a browser warning telling me that every time I call the page? Or maybe a sufficient secure solution of my own? When choosing between those 2nd-class solutions, I certainly choose my own...
apirogov
@apriogov - Do you live in Africa? No? Then quit being cheap and pay the tiny number of dollars for a security certificate!
Coronatus
I thought about MITM... but for me it seemed that spying on the traffic would not be productive at all in my constellation... Or do you have a concrete idea how a spy could decipher the AES encrypted traffic without the password? If he'd brute-force it, he'd finish when that session is long gone...
apirogov
Another thing... Let's say this works... What is going to happen to users who have JS disabled?
NullUserException
@Coronatus: 1) let Africa out of the game 2) At the moment coding is just my hobby, one I do for FREE... The projects I do right now are mainly for fun and my self-education - why should I invest money into a certificate if I am not getting any payback except knowledge and fun? Even what you call "a few dollars" is quite an investment, if you're a guy still going to school!
apirogov
@NullUserException: Well, the whole thing is fully AJAX based... (it's going to be a secure web based (rudimentary) IM)... If I'd try to make it work without JS, I'd have to write from scratch and yes... then of course it won't work.
apirogov
@apirogov: You just thought about MITM *after* key exchange.
Marian
@Marian: But the key exchange itself is RSA encrypted! I'm sorry, but I don't see the problem... And the private rsa key is never transmitted unencrypted too...
apirogov
Is your time worth so little that you value tens of hours developing your own, inevitably inferior solution, less than the few dollars it costs to buy a certificate?
Nick Johnson
@apirogov - A year-long certificate probably costs one month of server hosting (it does for me). If you paid $20 for a certificate, now you have many more hours to invest in something else (other code, or offline money making).
Coronatus
@apirogov: Get a free certificate from [StartSSL](http://www.startssl.com/?app=1).
caf
@caf: Now THATs a good tip, thanks... I read through the page and probably will give it a try..
apirogov
+2  A: 

SSL/TLS provide transport layer security and what you've done does nothing but do that all over again for only the authorization process. You'd be better served to focus on authorization techniques like client certificates than to add an additional layer of line-level encryption. There's a number of things you could also introduce that you haven't mentioned such as encrypted columns in SQL Server 2008, IPSec, layer 4 & 7 hardware solutions and even setting up trusts between the server and client firewalls. My biggest concern is how you've created such a deep dependency on the username and password, both which can change over time in any system.

I would highly recommend that you reconsider using this approach and look to rely on more standard techniques for ensuring that credentials are never stored unencrypted on the server or passed in the clear from the client.

Nissan Fan
+3  A: 

It looks like you've made more complexity than is needed, as far as "home-grown" is concerned. Specifically, I see no need to involve assymetric keys. If the server already knows the user's hashed password, then just have the client generate a session id rolled into a message digest (symmetrically) encrypted via the client's hashed password.

The best an attacker might do is sniff that initial traffic, and attempt a reply attack...but the attacker would not understand the server's response.

Keep in mind, if you don't use TLS/SSL, then you won't get hardware-accelerated encryption (it will be slower, probably noticeably so).

You should also consider using HMAC, with the twist of simply using the user's password as the crypto key.

Brent Arias
If I use the hash to encrypt the sessionkey (thats what you meant? the sessionid approach is the standard one...), while I transmit the hash for authentication, an attacker sniffing from the beginning on could decipher everything! Or do you mean something different?One reason why I decided to use those RSA keys is, that they are used for client -> client communication anyway, so that a user can trust the server (that has no ability to read the communication of the clients)... as I said - the project is a secure webbased instant messenger...
apirogov
@apirogov: yes, I meant session key. When you say "from the beginning," I suppose you are including the user's registration step (I was assuming kerberos or similar already handled that). But your approach has the same problem -> the registrant's password is still in-the-clear during the registration process. If you are not counting the registration step, then I disagree -> an attacker will only see the user id and a message digest. Not possible to get the user's password from that info.
Brent Arias
But on the registration process only the hash is transmitted, too! The same as login! I never send the plain text login password to the server.. that should not be a problem..
apirogov
+1  A: 

While I would also advocate the use of SSL/TLS for this sort of thing, there is nothing wrong with going re-inventing the wheel; it leads to innovation, such as the stack exchange series of websites.

I think your security model is quite sufficient and rather intelligent, although what are you using on the client-side? I'm assuming javascript since you tagged this post with 'web-development'? Or are you using this to communicate with a plug-in of sorts? How much overhead does your implementation produce?

Some areas of concern:

-How are you handling initial communication, such as: user login, registration?

-What about man-in-the-middle attacks (assuring the client that it is talking to the authorized server)?

Cypher
right, I'm using Javascript... I think I have already described the registration process... On registration the server gets a nickname,password hash and encrypted private key + unencrypted public key, on normal login just the nickname and password hash... the server responses a sessionid to be attached to every request further on - the server checks a session by comparing nick,sid and IP on login with the values from the current request... the AES and SHA256 works really fast (milliseconds), RSA just noticible on key generation (few seconds), I think thats quite ok...
apirogov
I am generally OK with reinventing the wheel when you can get a better wheel, but cryptography is not something inexperienced people should fiddle with.
NullUserException
@NullUserException - I agree with you... with one exception: learning. :-)
Cypher
@apirogov - So you mean to say that your client-side script is going to hash your password and send two keys to the server? Have you considered that anything written client-side is automatically unsecured? Web registration involves data being sent from client to server. Without SSL your encryption won't be happening behind closed doors - it will be public (javascript) for all to see and manipulate, and thus hack, your system.
Cypher
@Cypher: Yes, you're right, that was pointed out by different answers already... I didn't think about the fact that its possible to tamper with my JS...
apirogov
A: 

The major problem you have is that your client crypto code is delivered as Javascript over unauthenticated HTTP.

This gives the Man-In-The-Middle plenty of options. He can modify the code so that it still authenticates with your server, but also sends the password / private key / plaintext of the conversation to him.

caf
+11  A: 

I'm not a crypto or security expert by any means, but I do see one serious flaw:

There is no way the client can know that it is running the right crypto code. With SSL/TLS there is an agreed upon standard that both your browser vendor and the server software vendor have implemented. You do not need to tell the browser how SSL works, it comes built in, and you can trust that it works correctly and safely. But, in your case, the browser only learns about the correct protocol by receiving plain-text JavaScript from your server.

This means that you can never trust that the client is actually running the correct crypto code. Any man-in-the-middle could deliver JavaScript that behaves identically to the script you normally serve, except that it sends all the decrypted messages to the attacker's servers. And there's no way for the client to protect against this.

That's the biggest flaw, and I suspect it's a fatal flaw for your solution. I don't see a way around this. As long as your system relies on delivering your crypto code to the client, you'll always be susceptible to man-in-the-middle attacks. Unless, of course, you delivered that code over SSL :)

bcherry
A: 

Javascript encryption can be enough when your adversary is an eavesdropper that can see your traffic but not modify it.

Please note that I am not referring to your specific idea (which I did not take the time to fully understand) but to the general concept of Javascript encryption.

flybywire
You can't simplify this protocol in that way.There is no actual CHAP handshake in client login: client just sends password hash, if intercepted it will be as good as real password. So something should be encrypted using plaintext password (private key in this case).
blaze