79

For a webapplication, when HTTPS is not available as a security measure, is it possible to still make the login somewhat secure? E.g.:

  • Tokenize logins, to make repeat attacks difficult?
  • Somehow encrypt the sent password from a HTML password field?

In particular I'm using CakePHP and an AJAX POST call to trigger authentication (includes provided username and password).

Update on the problem:

  • HTTPS is not available. Period. If you don't like the the situation, consider it a theoretical question.
  • There are no explicit requirements, you have whatever HTTP, PHP and a browser (cookies, JavaScript etc.) offers in real life (no magic RSA binaries, PGP plugins).
  • Question is, what is the best, you can make out of this situation, that is better than sending the passwords plaintext. Knowing the drawbacks of each such solutions is a plus.
  • Any improvement better than plain passwords is welcome. We do not aim for a 100% l33tG0Dhx0r-proff solution. Difficult to crack is better than complicated to hack which is better than a trivial sniffing revealing the password.
Vikas Gupta
  • 4,455
  • 1
  • 20
  • 40
sibidiba
  • 6,270
  • 7
  • 40
  • 50
  • 9
    How secure? How high are the stakes (ballpark dollar figure can be handy guide)? How powerful are potential attackers? I wouldn't trade stocks, or share my darkest secrets on a website that lacked SSL. :) – mctylr Feb 25 '10 at 19:16
  • 2
    @mctylr This sort of security is obviously not military, financial nor government grade. But still better than plain text login, which is unfortunately common for small sites or sites that must work behind heavy firewalls filtering out HTTPS, or for cheap hosting sites not providing HTTPS (not even a self signed one for a differnt URL). The question is interested in any possible way to increase any aspect of security. – sibidiba Feb 25 '10 at 23:31
  • 1
    @Michael: Why are you trying to make a point in that HTTPS is required. I know that HTTPS can't be fully mimiced on HTTP with JS/cookies and such. There is still no HTTPS available (See desciption. "If you don't like the the situation, consider it a theoretical question.") But also, most shared hostings are like this. Go to any community forum or self hosted blog or most of the sites with less then 10.000 visitors a day, and you will not see a trusted certificate on port 443. And they are still secure enough! Why not add some more to their security? Btw., HTTPS is also no silver bullet. – sibidiba Feb 27 '10 at 13:39
  • 1
    Using JavaScript to obscure your password is still violation of (A3 Broken Authentication and Session Management)http://www.owasp.org/images/0/0f/OWASP_T10_-_2010_rc1.pdf It is a short read and it is very informative, and this is my final point in this argument. – rook Feb 27 '10 at 17:45
  • 1
    @sibidiba I hope the fact that nearly everyone on SO disagrees with you answers your question. – rook Jul 03 '10 at 19:58
  • 2
    @The Rook: facts and scenarios, just like requirements, aren't democratic – sibidiba Jul 04 '10 at 04:23
  • 3
    how does your application defend against attacks like firesheep or deal with OWASP A9? – rook Oct 26 '10 at 20:08
  • 1
    I don't know. Maybe my application does not defend against FooBarMagicHack9000. But the question is nevertheless about not having HTTPS available and what you do in that particular scenario to make things more difficult to crack. SSL is no silver bullet either. – sibidiba Oct 27 '10 at 11:26
  • 1
    @sibidiba github is now fully https because of firesheep, facebook and twitter are soon to follow suit. Firesheep is nothing new, but its brining attention to OWASP A9. The most recent problem with https came to light with sslstrip, but thats easy to defend against, just enable the STS flag. Also your answer has a -4 because it do anything. – rook Nov 10 '10 at 18:38
  • 1
    What about JS-implemented SSL ? just found out this : http://www-cs-students.stanford.edu/~tjw/jsbn/ – Sherbrow Sep 09 '12 at 17:32
  • 2
    If you're running code over an insecure channel, this can't be secured, period. Even if you could send code that establishes a secure channel, it wouldn't matter, because the interceptor can simply replace that code with his own. You should instead be asking how to obscure what's happening to delay the attacker from owning you. – L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳ Mar 31 '13 at 01:35
  • 4
    I strongly recommend changing the answer to this question to anyone else, or leave it unanswered. The current answer is terrifying. – rook Jan 01 '15 at 21:00
  • 1
    I think the question needs clarification. Or the answerers need to re-read the question. The OP only wants to secure the login, not the whole protocol. Perhaps there is no need for a session token. Perhaps the OP only wants to POST data in association with a login as a one-step process, etc. – Sentinel Jan 07 '15 at 14:23
  • 2
    @sibidiba I have updated my answer to provide a real solution. Please change the answer to this post to anyone else. Security is my profession, and this is a serious question that needs a serious answer. – rook Jan 07 '15 at 17:12
  • 1
    You cannot simulate HTTPS using PHP. There are lot's of options to make your login more secure but if HTTPS is not available, you are out of luck. – Peter Jan 09 '15 at 08:19
  • 1
    The short answer: You need HTTPS to have secure authentication. It's free, why not use it? – Scott Arciszewski Jun 25 '15 at 16:31
  • 2
    Why do you believe HTTPS is not an option? Shared hosts provide TLS just fine nowadays. – Sven Slootweg Jun 25 '15 at 16:46
  • I appreciate your frustration with the answers that don't fit your criteria. For a non-HTTPS solution, please accept [SLaks' answer](http://stackoverflow.com/a/2336736/1114) instead. The currently-accepted answer encourages direct password hashing using MD5, which is very broken, and *much* less secure (against passive observers in the style of Firesheep) that SLaks' suggestion of using RSA or AES. It's a much better way to make the best of the situation. :) – Jeremy Aug 04 '15 at 18:59
  • 1
    @sibidiba Could you please reconsider the acceptance of ESL's answer? It's vapid and has bad security advice. You cannot get security through MD5 hashing, and "it's better than nothing" is incorrect: a MitM can alter the JS to append the plaintext to the HTTP requests and capture passwords that way. – Scott Arciszewski Aug 10 '15 at 16:06
  • @sibidiba Your question is worded as follows: `For a webapplication, when HTTPS is not available as a security measure, is it possible to still make the login somewhat secure?`. The answer is "No." Whether your *like* that fact or not, is irrelevant. rook's answer is the only correct answer to your question, as asked. – Dan Bechard Apr 20 '16 at 21:34

20 Answers20

77

It is a bad engineering practice to reinvent the wheel. Engineers who do this are falling victim to the "Not Invented Here" bias, which can cause a lot of damage when it is a security critical system.

SSL/TLS which is behind HTTPS is absolutely vital in maintaining a secure connection between a website and a browser. Public wifi networks put users at risk, and when used correctly, HTTPS is the only tool that can protect user accounts from this vulnerability.

In the case of two clients that need secure end-to-end (e2e) encryption then there is the open source and vetted Signal Protocol which has received number opens source ports on github and a wide adoption from popular apps like WhatsApp. There is no need to brew your own, these protocols work well for a reason.

If your host doesn't support HTTPS then a service like Cloudflare Universal SSL can be used to ensure all browsers connect to your site using HTTPS, even if your server doesn't support SSL/TLS. The connection between Cloudflare and your website will still be unprotected, but this Cloudflare service is intended to protect users against threats found on public wifi networks. From the perspective of a penetration tester, not providing HTTPS is highly suspect, if you aren't providing a basic security requirement as delivering traffic, then what other security requirements are you missing? HTTPS certificates can be obtained for free using Let's Encrypt or Start SSL, there is no legitimate reason not to support HTTPS.

HTTPS is vital because it does lot more than just "encrypt passwords". Another important role is that it should prevent the user from giving logging into a malicious server that is impersonating a real server. Using a system to protect the password alone is still a violation of OWASP A9 - Insufficient Transport Layer Protection because you would still be transmitting session credentials in plain text which is all the attacker needs (Firesheep).

  1. JavaScript-based cryptography cannot be used to construct a secure transport layer.

  2. "Tokenize logins": If an attacker is sniffing the traffic, they'll have the plain text username/password and then they can just login with these new credentials. (Replay attack)

  3. "Somehow encrypt the transmitted password": After the person has logged in an attacker can sniff the traffic to get the valid session id (cookie) and then just use this instead of logging in. If the entire session was protected with SSL/TLS then this is not a problem.

There are other more complex attacks that affect both this system and our current SSL infrastructure. The SSLStrip attack goes into greater detail. I highly recommend watching Moxie Marlinspike's Blackhat 2009 talk, which lead to the HTTP-Strict-Transport-Security standard.

rook
  • 66,304
  • 38
  • 162
  • 239
  • 6
    I'm (somewhat) aware of what S offers in HTTPS. But HTTPS is *not* available in this case. My question is still open, what is the best, what is worth doing, when it is not available? – sibidiba Feb 25 '10 at 20:03
  • 1
    @sibidiba https should always be available, even if it is a free self-signed certificate. If it is not then another encrypted tunnel such as a VPN can be used. – rook Feb 25 '10 at 20:35
  • 53
    HTTPS is ***not*** available. Existing problems most of the time can not be solved by requiring the situation to change into one where the problem does not exit. Assume you are stranded on the South Pole after a plane crash. / Survivor: How do we get out of this? There is no mobile network coverage to call help. / You: We must call help on phone! / Survivor: There is no network coverage on this continent. / You: Network coverage should always be available. – sibidiba Feb 25 '10 at 23:15
  • 6
    The Rook has listed many of the myriad caveats about the ways you're gonna shoot yourself (mitm is particularly bad here). The only other suggestion I have is to look at Digest Authentication, which is not particularly swell. It's still susceptible to MITM because without an SSL login page, I don't even know if the HTML for the login prompt came from you, so I DA could get turned off on me. Basically you're making a joke of your password system. I'm not saying that to be mean or in-your-face. Figure out how to break the 'no-SSL' problem, or pray nobody gets interested in your site. – Jason May 05 '10 at 21:07
  • 9
    @sibidiba: The point is that without SSL, you *can't* make it secure. Yes, the scheme you linked to is "better than plaintext passwords." But it's still not even "somewhat secure." Sometimes there just isn't a good solution to a problem, other than changing the scenario. If you want security, your hosting choice (or whatever the limitation is) is wrong. – Andrew Coleson Jun 19 '10 at 02:06
  • 2
    @Andrew: so because WEP encryption is easy to crack, you use *no encryption at all* when only WEP is available? Crackable does not mean that the attacker you aim for is also on the level. – sibidiba Jun 19 '10 at 14:00
  • 3
    @sibidiba: You must've missed the part where I said "Yes, it's better." That doesn't mean you would call WEP "secure", because it isn't. Yes, it's a question of semantics, but it's an important distinction whether you call something "secure." – Andrew Coleson Jun 19 '10 at 17:48
  • 1
    @sibidiba [Network coverage is always availble](http://en.wikipedia.org/wiki/Satellite_phone)! Every webserver supports the equivalent of sattelite phones, by default. – alexanderpas Jul 03 '10 at 19:36
  • 1
    A strong - 1, this post contains multiple problems. First and foremost, **it's not what ask** @sibidiba: HTTPS **sometimes is not an option** (when you don't have power to decide). Additionally, **there is not absolut security** as you talk, always there are less or more secure options. This post should be modified or removed – ESL Jan 02 '15 at 04:07
  • 2
    @ESL nothing in your post is "secure" or a "solution" – rook Jan 02 '15 at 18:02
  • @rook 1) There is no "secure" method, HTTPS **it's not secure**, it's just *more* secure.[1][2][3] (and a long etc.). If you said so, **you lie**. [1]: http://en.wikipedia.org/wiki/Certificate_authority [2]: http://en.wikipedia.org/wiki/Heartbleed [3]: http://en.wikipedia.org/wiki/POODLE – ESL Apr 20 '15 at 12:02
  • rook 2) Your answer it's not a solution, **it's not even an answer** to the @sibidiba question. You made up your own question and answer it. – ESL Apr 20 '15 at 12:05
  • dear @rook, what part of "HTTPS is not available" you did not understand? – a.costa Nov 19 '16 at 01:02
  • @sibidiba If you crash on the south pole and you cannot contact anybody then you die. There doesn't *need to be a positive answer. Rook just gave you a negative one. And sorry, there is always the possibility to get TLS, even if it means switching to another provider. – Maarten Bodewes Oct 14 '18 at 14:18
  • @Maarten Bodewes But there is a great answer - just tunnel out over HTTPS. This isn't a plane crash, no one has to be stuck here. – rook Oct 16 '18 at 22:22
  • Answer unrelated to question. – David Sep 28 '22 at 15:58
  • @David the answer is fine, it is the question that is wrong. – rook Nov 22 '22 at 19:20
  • @rook Logic like that has made Stack overflow what it is today. – David Nov 23 '22 at 20:34
  • @David Reinventing the wheel often leads to vulnerable code because these problems are difficult, and I know this because i review code for a living. If you think there is a problem with my post - then the problem lies with you and everyone who uses your code. – rook Nov 27 '22 at 04:27
  • @David "yeah i'd like to write an app, but hold on and let me write my own layer 4 from scratch." While you are at it, why not write your own kernel and programming language for that kernel? Maybe call it TempleOS. – rook Nov 27 '22 at 04:31
  • @rook Theorizing and Discussion is the heart of innovation. Stack overflow has become more and more about people attacking the question then answering it. You had no idea how to contribute anything useful to this topic so instead you attacked the question proved how superior you are by degrading the idea of the question and got a bunch of folks to spend their currency of contempt on the question to give you more rep points. Congratulations your 65.4k in rep and advanced the discussion nowhere. – David Nov 28 '22 at 05:08
  • @David Suggesting that people need to reinvent the wheel in order to get to their distention will only cause pain and suffering. You are speaking to someone who writes exploit code for vulnerabilities written by engineers who think they know better - and don't. If they knew better they would see the value in what has already been built - and stand on the shoulders of giants instead of claiming that they never existed. This question was trying to promote a commercial product that simply cannot compete with TLS, and nor should it. 'libsingal' and 'noise' are great but that is not this. – rook Nov 28 '22 at 19:22
  • @rook this question is litterallly "How do I reinvent the wheel" answering them "Don't" doesnt answer the question. – David Nov 29 '22 at 20:37
  • @David No, the answer that they accepted was downvoted to oblivion and was deleted by admins by my request. This post was created to sell snake oil, and only a noob subscribes to: https://en.wikipedia.org/wiki/Not_invented_here This isn't a game, people get hurt over this invention ego flex – rook Nov 30 '22 at 20:05
  • @rock Congratulations. So your THAT guy. If you dont like the answer or dont like the question you attack them both. As I said at the start people like you make SO what it is today. – David Dec 01 '22 at 21:39
16

Since you cannot do SSL at the web server, and you are not a security expert, look for an existing secure authentication service that you can utilize, and let them handle both the SSL and the complexities of handling credentials for you.

In particular, I would suggest that you use a free third-party authentication service, such as OpenID. They have libraries for PHP including one for CakePHP.


Edit: (about risks)

While using a 3rd-party secure authentication service (that uses HTTPS itself) can mitigate the problem doing authentication itself without using HTTPS (on your server), it does not entirely eliminate the possibility of attacks.

The most common two attacks would be replay attacks, and session-hijacking where the attacker is able to either re-uses a genuine login session token later, or use a valid session token for their own malicious purpose.

The replay attack can be mitigated by having the session token expiry, and preferably by using a nonce to prevent session replay and to reduces the risk of session hijacking. With a nonce, a legitimate session generates an error if successfully hijacked, because the nonce has expired (been used), so their own session is no longer valid.

If you cannot use HTTPS to encrypt the session token while being transmitted to and from your server, you cannot entirely prevent active attacks such as session-hijacking or man-in-the-middle attack. This may be acceptable in some cases, such as websites with a small user base for non-commercial usage.

mctylr
  • 5,159
  • 20
  • 32
  • 1
    My thinking exactly. If you can't have SSL on your server, let a third party do the SSL for you. – stevenf Feb 28 '10 at 18:34
  • 7
    This is a **very** bad idea. The problem is that authentication is the least of your worries. You need to protect the entire session. The weakest part of your system is the strength of the entire system. And since you brought up OpenID, [This article on the broken StackExchange auth is pertinent](http://www.troyhunt.com/2012/08/is-stack-overflow-secure-kind-of.html)... – ircmaxell Sep 08 '12 at 01:55
  • 2
    @ircmaxell Except the article you cite, fails to clarify that his demonstration doesn't not identify the potential solution to the weakness discussed, that may be already in place, of server-side session management, where a session is keyed to IP address, perhaps a [nonce](http://en.wikipedia.org/wiki/Cryptographic_nonce) or salt, and has an expiry time. I.e. An attacker would need an active attack doing IP spoofing, rather than merely passively listening (sniffing) to TCP/IP or WiFi traffic, while the legitimate user is actively logged in. – mctylr Sep 12 '12 at 02:42
  • 2
    _need to protect the entire session_: This gets back to the fact that you for a comprehensive answer, you need to do a risk assessment of the **particular** situation and weight the risk/reward of attacks vs. security. If TLS/SSL is not available, then any solution will be subject to the lack of secrecy (or _excess of availability_ in the [CIA](http://it.med.miami.edu/x904.xml) sense), but that doesn't necessarily mean that integrity, authentication, or [non-repudiation](http://en.wikipedia.org/wiki/Non-repudiation) is entirely impossible depending on the level of confidence required. – mctylr Sep 12 '12 at 02:54
  • This answer rings kind of true, but I think any self respecting authentication provider will require you to have *at least* the same security requirements as that a TLS session will provide. So it remains to be seen if it is a practical solution. And yes, you would still not protect the data being send to the browser - but that's less bad than leaking the authentication details or allowing replay. – Maarten Bodewes Dec 19 '18 at 15:42
15

The short answer is that without SSL endpoint to endpoint encryption, it's impossible to do it securely...

One of the primary reasons for this is that you can't do secure crypto in a browser. See this reference - Javascript Cryptography Considered Harmful.

Additionally, there's no way that you can be sure that the source of the credentials are indeed who you're talking to. Meaning that there's absolutely no way without SSL to be sure that there's not a Man-In-The-Middle Attack going on.

So no, you can't do it.

Additionally, don't even try. Get SSL. You can get free certificates. Hosts will usually give you a dedicated IP for a few $$$ per month. And if you really care about security, you'd be using at least a VM with a dedicated IP address anyway.

To even attempt this would be Security Through Obscurity at best, and nothing at worst. SSL is a solved problem. Why not use that solution. Security is not something to guess at. Use the proper techniques. Don't try to invent your own. It won't work...

ircmaxell
  • 163,128
  • 34
  • 264
  • 314
  • 2
    I'd just like to add: If anyone is reading this thinking that they found a way to develop a secure protocol better than TLS, they ought to send it to the IETF for consideration for a new internet standard. :) – Scott Arciszewski Jun 09 '15 at 00:43
  • "So no, you can't do it." Sure you can hash it. Its slightly better then open text. TFA again better. – David Sep 28 '22 at 16:02
12

As you suggested, you may be able to generate a unique token each time the page is created. That same token would need to be sent back with the form data and could not be reused. You could also keep the password safe by using JavaScript to hash it, if you can rely on it being enabled by your users.

This scheme is still not secure, however. An attacker could still see everything going across the wire. They could intercept the token and send a response back to you before the user does. Or they could just wait for someone to login, steal that person's credentials (as they are sent over the wire), and just make their own login request later on.

Bottom Line - you need to use HTTPS to guarantee the site is secure.

Justin Ethier
  • 131,333
  • 52
  • 229
  • 284
7

You can encrypt the password using Javascript and decrypt it on the server.

I would recommend generating an RSA keypair on the server, send the public key along with a timed salt to the browser, then encrypting the password, combined with the salt, using the public key in Javascript.

You can find an RSA implementation in Javascript here

You should include both the IP address and the entire X-FORWARDED-FOR hedaer in the authentication cookies to prevent cookie theft behind proxies.

If you're dealing with sensitive data, you could generate a random AES key in Javascript, then send it to the server along with the password encrypted with RSA.
You could then make the entire application use encrypted AJAX requests from a single page and not use an auth cookie at all.

Note that it is not possible to protect against an active man-in-the-middle attack without SSL. An active attacker can completely replace your site with his own proxy, and there isn't any way to defend against that. (Since there cannot be any known good code)

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • 1
    This is a valid use of RSA, but its a moot point. Its not going to stop anyone from getting hacked. – rook Feb 25 '10 at 18:55
  • Is RSA possible in JavaScript today?. A few years ago I was looking at them, and they did not scale to current key lengths. – sibidiba Feb 25 '10 at 18:56
  • X-FORWARDED-FOR is not set by all proxies. Also it is trivial for an attacker to spoof X-FORWARDED-FOR. – rook Feb 25 '10 at 19:04
  • The author knows what he is doing regarding cryptography and security, but I don't know if he considers the implementation a secure alternative to SSL. In particular the PRNG looks potentially weak which would undermine the entire thing anyway. There are also attacks on PKCS #1 that this may be vulnerable to. http://www.iacr.org/archive/eurocrypt2000/1807/18070374-new.pdf – mctylr Feb 25 '10 at 19:14
  • 4
    Actually, I don't see how this approach prevents a man-in-the-middle attack. – mctylr Feb 25 '10 at 19:19
  • @Michael: AFAIK, if you use the _entire_ XFF string plus the physical IP address, you aren't vulnerable to spoofing. (Except for proxies that don't set it) – SLaks Feb 25 '10 at 19:20
  • @mctylr#2: It doesn't. Read my last paragraph – SLaks Feb 25 '10 at 19:20
  • Okay, I did not notice your additional two paragraphs that you added after your initial answer. No problem, glad we can agree. – mctylr Feb 25 '10 at 19:43
  • There's absolutely no point in using RSA here - a digest-based authentication scheme would provide the same security with much less complexity. – Nick Johnson Nov 01 '10 at 09:12
  • 2
    Except that RSA [can't be done securely on the client side](http://www.matasano.com/articles/javascript-cryptography/). So all of that work for nothing... – ircmaxell Sep 08 '12 at 02:03
  • @ircmaxell: Yes. That's what I said in my last paragraph. – SLaks Sep 09 '12 at 02:23
  • 3
    This post should be changed, it is Cargo-Cult security. http://matasano.com/articles/javascript-cryptography/ – rook Jan 07 '15 at 16:40
  • @rook Does this not protect the specific password value from a passive observer on the network? It certainly isn't very secure (since the encrypted passwords or session cookies could still be stolen and used to authenticate to the site), but it should provide nonzero value for the many users who reuse passwords. It should at least be better than the answers suggesting standard HTTP Digest authentication. (However, I'm not a security expert. I'd be very interesting in learning if my understanding is wrong in some way.) – Jeremy Jul 12 '15 at 07:17
  • 1
    @Jeremy Banks good question. In SLacks' scenario, an attacker can [obtain the plaintext password by modifying the HTTP response, and backdooring the encryption process](https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/august/javascript-cryptography-considered-harmful/). Two other resources on this topic: https://www.owasp.org/index.php/Session_Management_Cheat_Sheet and https://www.owasp.org/index.php/Transport_Layer_Protection_Cheat_Sheet . In short, if a malicious user can obtain an admin account, then who cares what the password is, it's game over. – rook Jul 12 '15 at 15:18
  • @rook Thanks, but if they're modifying the http traffic then that's not a passive observer. And my comment already explained why you care what the password is: password reuse. I'm not suggesting that it's ever excusable practice from a company, just that it could provide marginal value. – Jeremy Jul 12 '15 at 20:49
  • 1
    @Jeremy Banks It will not benefit your application to assume that the attacker is def and blind. – rook Jul 13 '15 at 19:49
  • Unfortunately, a lot of times that the connection is vulnerable against eavesdropping, it is also vulnerable against active attacks. Just protecting against passive attacks is therefore kind of a moot point. E.g. public WiFi is almost always vulnerable to active / MitM attacks. Using a VPN tunnel would be required if you choose to use this kind of scheme, and even then you would be unprotected where the tunnel ends. – Maarten Bodewes Dec 19 '18 at 15:48
7

You can use HTTP Digest authentication, which is supported by most browsers and does not send the password in clear over the wire.

The downside is the ugly log in box displayed by broswer. If you preffer to stick with forms, then you can implement exactly the same protocol as HTTP Digest in your forms authnetication: send hidden fields containing the realm and the challenge, and have the client add in JavaScript the nonce and compute the digest. This way you'll use a well known and proven exhange protocol, rather than roll your own.

HTTP Digest requires only hash operations.

Remus Rusanu
  • 288,378
  • 40
  • 442
  • 569
  • Is logging out possible by now? How can I detect from the server side that the login was a success? – sibidiba Feb 25 '10 at 20:28
  • 1
    You are still in control of the authentication process, it happens on the server php scripts. You authenticate the response form against a user database where you have the user name and the HA1 part of the http digest ie. md5(user:realm:password). From the response you reconstruct the Digest hash, starting from the HA1 stored in the database and compare it with the response in the form submit, if they match it means the user had the correct password. – Remus Rusanu Feb 25 '10 at 22:14
  • 1
    The big advantage over other schemes is that it allows for a unified authentication model for browser/user sessions (using forms and cookies, but not transmitting the password over the wire) *and* REST services, using HTTP Digest. – Remus Rusanu Feb 25 '10 at 22:15
  • Logging out is handled the usual way, by resetting the auth cookie. It is true though that if the user hits in the browser a part that challenges him to do HTTP digest (eg. enters an REST URL from the site) and if the user enters the correct password in the browser log in dialog, is much harder to log out: the user has to manually clear the password from the browser setting. But that should not happen normally, as the UI part of the site is usually separated from the REST part. – Remus Rusanu Feb 25 '10 at 22:19
3

Create a public/private key pair using an asymmetric cipher.

Create a symmetric key on the server.

Send the public key down to the client side.

Create a random key for the symmetric cipher client side.

Encrypt that random key using the public key client side.

Send the encrypted key to the server.


Server does the following:

a. Decrypts the random symmetric key using the private key.

b. Creates a token containing the generated client key.

c. Signs the token.

d. Encrypts the token using the server symmetric key.

e. Encrypts the already encrypted token with the client generated key.

f. Sends the encrypted token down.


The client receives this token and does the following:

a. Decrypts the token with the key it generated.

b. Stores the decrypted token.

c. At this point the stored token is only encrypted with the server symmetric key.


On every from the client to the server:

a. Encrypt the outbound data using the client generated key.

b. Send the token + encrypted data


On every request the server receives:

a. Decrypt the token using the server symmetric key.

b. Verify the signature.

c. Decrypt the data using the client generated key stored in the token.

Hedzer
  • 119
  • 6
  • I suppose this is how to secure the connection, but doing login through that afterwards should be trivial. This is like a rudimentary version of HTTPS done manually. – Hedzer Dec 19 '18 at 21:09
2

What about HTTP Digest Authentication? It provides security by MD5-hashing username, password and a nonce (among other things) before sending it to the server. MD5 isn't really secure, but it's a good way for simple security with HTTP.

Of course this doesn't prevent hackers from changing the message... but it secures your password.

AndiDog
  • 68,631
  • 21
  • 159
  • 205
  • 1
    The digest can be sniffed and replied. HTTP digest authentication requires HTTPS to protect the credentials transmitted as the "Authorization" http header. – rook Jan 07 '15 at 16:41
  • MD5 is secure for key derivation. It is however not secure as a password hash, and therefore the password may still leak. – Maarten Bodewes Dec 19 '18 at 15:51
2

HTTPS has numerous use cases, most of which are designed to defend against Man-in-the-middle attacks. Anyone with a hacker's mindset will shudder to tell you that there is no way other than the established way to accomplish something. The fact is that just because you use TLS (the standard which modern HTTPS uses), does not mean you are using it well. Additionally, just using TLS does not prevent someone from exploiting known weaknesses. Just as you may be finding creative ways to secure your data, there are people who are finding creative ways to exploit your security measures.

So, what to do?

First of all, if you're going to forego TLS, it is helpful to understand how it works. And it is all about a handshake.

Once the client and server have agreed to use TLS, they negotiate a stateful connection by using a handshaking procedure.[7] During this handshake, the client and server agree on various parameters used to establish the connection's security:

  • The handshake begins when a client connects to a TLS-enabled server requesting a secure connection and presents a list of supported cipher suites (ciphers and hash functions).
  • From this list, the server picks a cipher and hash function that it also supports and notifies the client of the decision.
  • The server sends back its identification in the form of a digital certificate.[contradiction] The certificate usually contains the server name, the trusted certificate authority (CA) and the server's public encryption key.
  • The client may contact the server that issued the certificate (the trusted CA as above) and confirm the validity of the certificate before proceeding.
  • In order to generate the session keys used for the secure connection, the client encrypts a random number with the server's public key and sends the result to the server. Only the server should be able to decrypt it, with its private key.
  • From the random number, both parties generate key material for encryption and decryption.[contradiction] This concludes the handshake and begins the secured connection, which is encrypted and decrypted with the key material until the connection closes.

If any one of the above steps fails, the TLS handshake fails, and the connection is not created.

Source: Wikipedia

So, is it possible? Yes. I was taught that anything is possible. It may be expensive, but it is always possible.

I want to fully disclose that I am NOT a security professional, just an enthusiast. I do not recommend attempting this for a production-grade project or anything other than your own edification. You should DEFINITELY check out this SO post which provides an excellent explanation as to roadblocks in setting up your own security protocol.

However, if you want to move on, here are some thoughts that come to mind. These are realities that will exist regardless of which direct you went with this project.

  • HTTPS is supported by all major modern browsers. Even with this reality, HTTPS load times are slower than plain HTTP. Without extensive production, it is highly likely your alternative implementation will be a fraction as secure while being significantly slower. This will be a drawback of any homegrown implementation unless you are utilizing browser features, which brings us full circle back to using TLS, which is what modern HTTPS utilizes.

  • If you manage to encrypt your password without TLS on the browser side using Javascript in an unpredictable enough fashion that an MiTM attack would be difficult, don't rest there. You also should be securing the data you send back and forth. Otherwise the password being encrypted really is irrelevant. Sure, an attacker might not know bobsmith109's password, but he doesn't need it, because he can sniff every single activity on the network. He knows what times bobsmith109 logs in, can probably trace his IP, and any other sensitive piece of data you send back and forth.

  • No matter what security measures you take, there is security in depth. So one thing that you can do right off the bat is make sure you encrypt your data in the database while also requiring strong passwords.

I reiterate that I am not a security professional and strongly discourage this as anything other than to satiate your curiosity. It is astronomically improbable that you can create a viable alternative to TLS without an extraordinarily large group of security professionals contributing to a project for years if not decades, which is what SSL/TLS can boast. That being said, a good starting point if you choose to go forward is to look at the handshake model above and see how you can implement a version of this without TLS.

I would be remiss to not share in my post that most real-life barriers to using HTTPS are being actively fought against. One of the largest - cost - is very close to becoming a non-issue. A free certificate authority will be coming out 2Q 2015 is supported by some big guns, including Mozilla and Akamai, to name a few. Here is an article.

Community
  • 1
  • 1
smcjones
  • 5,490
  • 1
  • 23
  • 39
  • This "answer" doesn't state anything that can be used. It says "So is it possible?" but it doesn't even state *what* is possible. Some handwaving about **it** being expensive, without even indicating what **it** is. Probably "setting up your own security protocol". Then it finishes up with some pitfalls from creating your own protocol. Just basic security advice, but *no solution* (which indeed, may not exist). Nothing about how to prevent MitM attacks or sidestep the problem with missing trusted CA certs in JavaScript. – Maarten Bodewes Oct 14 '18 at 14:28
2

Login without HTTPS, how to secure?

Since there is no secure channel between your server and your client:

  • because there is no secure channel, anybody can snoop your traffic.
  • because anybody can snoop the traffic, you are open to a MITM attack.
  • because you are open to MITM attack, there is no guarantee you client will see a legitimate page.
  • because the pages are not legitimate and your page is in effect not being served (the guy in the middle is serving the pages), all tricks used server-side are rendered useless.

What can you do? Theorically?

  • both client and server need to use encryption to make snooping / MITM less susceptible.
  • assume you cannot have a handshake,
  • assume your client already has your key and knows how to speak the same gibberish as your server.
  • how about some SSL over HTTP but wrapped in base64-encoded message for some gibberish?

But wait... Since you said no magic binary, or plugin, not even RSA, I don't know if any of this is possible save for (some potentially very weak) in-house encryption.

--

dnozay
  • 23,846
  • 6
  • 82
  • 104
1

You can try to replicate it to some point, by using public key encryption (GPG maybe) and making use of browser caching.

This is not something secure, even just putting up SSL won't be enough for a sophisticated attacker, you need to make use of HSTS, public key pinning etc to just to consider a web site secure today.

The rest of the answer is just food for thought.

  1. Create a public-private key pair. Keep private one secure.
  2. Create a js file containing the public key and a encrypt function, find a secure encryption algorithm. This function should encrypt a given string (serialized form) with an additional timestamp, to avoid a replication attack.
  3. Serve this file with Cache-Control:public, max-age=31536000 HTTP header. We try to mitigate when the attacker tries to replace the script. The file will always be served from the browser cache.
  4. Send all the forms via Javascript, using the encrypt function. Serve these with the same header as above.
  5. At the server side, decrypt the data, check the timestamp, if it's still valid. Do you thing, if not, discard it.
  6. Create a cookie token which can only be used once for a very short amount of time. If the attacker captures a cookie, he won't have much time to do stuff. However, if the attacker is fast enough, then he might log the original user out.
  7. Change the cookies with every response. But then what do you do when the user sends multiple requests at once and then they arrive in the reverse order? Which cookie is valid? This creates tons of problems at the cost of a false sense of security.

Any listeners won't be able to make use of the data going back and forth, and they won't be able to change/inject the existing JS files until the cache expires / user clears the cache. However, any sophisticated attacker can replace the whole HTML file which would discard all the security measurements I have just mentioned. If you can at least serve this file / form over HTTPS, you might get away with it, put them on github pages or whatever. However, if you put the file some other domain, then you need to set up CORS for the receiving domain for this to work.

Another try

One time passwords sent to email.

  1. User fills out their email, clicks a link which then sends a link to their email with a token that will enable them logging in.
  2. User clicks the link
  3. Server checks the token, logs the user in.
  4. Rolls the cookies like the previous example.

All in all, whatever you do, it is not secure. Given a fast, sophisticated attacker, nothing stands in the way.

Get SSL, if the infrastructure does not support it, change it. If your manager does not believe in SSL, convince him/her. Don't create a false sense of security. Protect your user's data, depending on your location, you are legally required to protect the data of your users.

Then let's talk about how to make a site secure with SSL.

Umur Kontacı
  • 35,403
  • 8
  • 73
  • 96
0

Have a look at "The Secure Remote Password Protocol".

Instead of formulating it myself, let me quote from their webite:

The Secure Remote Password protocol performs secure remote authentication of short human-memorizable passwords and resists both passive and active network attacks.

and:

[The] protocol combines techniques of zero-knowledge proofs with asymmetric key exchange protocols and offers significantly improved performance over comparably strong extended methods that resist stolen-verifier attacks such as Augmented EKE or B-SPEKE.

Although the Stanford University doesn't provide implementations for PHP and JavaScript themselves, they link to some 3rd-party implementations.

One of those links leads to "Clipperz", which is an online password manager. It is also available as a community edition on GitHub. There they host their "javascript-crypto-library", which implements the protocol and the "password-manager" itself, which contains backends written in PHP and Python.

I can't say how difficult it would be to extract the relevant portions of code, but maybe you can reuse their implementation (it's licensed under AGPL).

Edit 2014/10/24:

Wikipedia's article on SRP lists some more implementations. Relevant for PHP/JS:

ben
  • 557
  • 4
  • 9
  • 2
    JavaScript cannot be used as a secuirty system in this context: http://matasano.com/articles/javascript-cryptography/ – rook Jan 07 '15 at 16:42
  • SRP is a great protocol and often overlooked. At least it won't send any password in the clear before establishing a shared secret (which can be used to authenticate). However, I agree with rook that it doesn't solve the issues with JS crypto. – Maarten Bodewes Oct 14 '18 at 15:10
-1

The best solution I have seen for somewhat secure HTTP connections is to use a Javascript implementation of md5sum (or some other hash) to avoid transmitting the password in plaintext. You can create a form onsubmit handler in Javascript that replaces the password field with a hash of the original value. This adds a modest amount of security to an unsecure connection, but relies on Javascript running in the browser to work properly.

brandon k
  • 620
  • 6
  • 6
  • This doesn't stop anything, the attacker will just hijack the session after it has been authenticated. – rook Feb 25 '10 at 19:03
  • 1
    Whatever Michael said. If you do go with md5, at least have server send unique challenge, client should send md5(challenge+pass). Sending md5(password) for most users is same as pass in clear. More than replay, the bigger concern would be passive attacker can crack most of your users password. Also if you are over http and you have active attacker, apart form replay and hijacking, it has been demonstrated that attacker can inject script to modify the login form so that they get a copy of entered username, password. use https unless you are supporting some weird mobile device. – mar Feb 25 '10 at 19:29
  • 1
    @Rook Your criticism applies to any plausible solution that doesn't use SSL, as you've already amply indicated. Let's take it as a given that they're all vulnerable to this. – Nick Johnson Nov 01 '10 at 09:14
  • "but relies on Javascript running in the browser to work properly." ...and the attacker can just replace the js with something that sends him the password. – L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳ Mar 31 '13 at 01:38
  • 1
    JavaScript cannot be used as a security system in this context: http://matasano.com/articles/javascript-cryptography/ – rook Jan 07 '15 at 16:42
-2

I have the same issue on a system of mine. I have taken steps to try and increase security without compromising the user experience with convoluted mechanisms. What I noticed was that the vast majority of users logged in from the same machine using the same browser, (but not necessarily the same IP address), or from a couple of browsers (eg: desktop or mobile). I decided I could use this to identify a pattern.

1) During registration, users are required to have strong passwords (to prevent dictionary attacks), a security question/answer and standard email verification (as proof of real person)

2) During login, after 5 failed login attempts (not before), a captcha is displayed to prevent brute force attacks.

3) Finally, I created a hash of parts of the user-agent string following a successful login, containing the users OS, browser (general not versions) and language - forming a sort of secondary password. If the useragent hash is significantly different on next login, the user is asked to answer the security question. Then, if this is answered satisfactory, the new UA string is hashed and added to their "safe machines" list, so that they wont be asked again from this machine. This is similar to a mechanism employed by the Steam gaming system.

This has been in use for over a year very successfully with about 700 users and it had the additional benefit of preventing "login sharing" - a problem where multiple users were using the same credentials for convenience!

Dave
  • 386
  • 2
  • 8
  • The user-agent is attacker controlled. If an attacker is on an open wifi network, they can sniff traffic, obtain the full session id, as well as the current user-agent. Have you heard of the OWASP top 10? – rook Jan 07 '15 at 16:47
  • Nothing but HTTPS will prevent MITM attacks, the question has asked what measures can be taken to improve security, not stop a dedicated attack. Pattern matching a users behaviour represents an extra layer of security. A casual hacker would need to guess the UA string of the legitimate user in order to spoof it, or be faced with a security question. – Dave Jan 07 '15 at 17:01
  • What this post is describing is cargo-cult security, and the only person it is fooling is the programmer. – rook Jan 07 '15 at 17:29
  • @Rook can you add any explanation as to why you think this is cargo-cult? Steam place a lot of reliance on this mechanism and as I have explained, it has solved a very real problem of login sharing within my company. – Dave Jan 07 '15 at 18:50
  • The user agent is an attacker controlled string, it is not a secret value, as adversary with access to the Session ID will also have the user-agent. This security check **serves no purpose**, except to have the appearance of "security". Which makes this cargo-cult programming. None of these suggestions mitigate the impact of plaintext transmission. – rook Jan 07 '15 at 20:08
  • 1
    But you are only considering MITM attacks, where an attacker has access and the necessary knowledge to compromise the users session. My solution is mitigating password loss to a third party other than the legitimate user. This is a far more common form of security breach, and your comment is about another security issue than the one Im trying to prevent. – Dave Jan 09 '15 at 11:48
-2

I guess you care about secure transmission of password to the server? My answer is: dont transmit passwords to the server :)

Infact you may not transmit anything from browser (user) to server to authenticate the user, as an attacker who is spying http traffic would also be able to retransmit the data and authenticate.

Proposal:

Obvious solution would be to use a one-way, one-time transaction authentication originating from server; like a transaction number which can only be used once. Eventually, you still need a secure channel once to sync the list of transaction numbers with user.

You could use something google authenticator, yet you need a secure channel once to setup parameters on either side. If you consider email to be secure, that would be a way to go.

comeGetSome
  • 1,913
  • 19
  • 20
  • What about protecting other authentication credentials, such as session IDs? Are you familiar with the OWASP Top 10? – rook Jan 07 '15 at 16:37
  • lol, author is asking about a way to securely login without https, of course there are huge other points to consider, but who asked about session ids? are you sure author wants to maintain sessions? – comeGetSome Jan 07 '15 at 17:01
  • Why only protect one type of authentication credential? This post strike me as cargo-cult security. – rook Jan 07 '15 at 17:25
  • the whole post is against owasp. that does not mean there is no answer. – comeGetSome Jan 07 '15 at 17:44
-2

The answer is shorter, and if you really matter about security you always have options that different levels of bureauocracy.

Absolut security does not exists. The number one flaw is always on the client side, with trojans ans keyloggers. SSL doesn't help with that.

1) Token generators: banks use them, blizzard uses then. It can be a device or an app. Well.. it's expensive.

2) SMS pins. interesting and affordable solution. There is a lot of good prices from trnasactional sms on the market and everyone has a phone capable of receiving it.

3) If you have to use HTTP, you can force a third party oauth service, like google or facebook. That's the best you can do without a token generator.

Guilherme Viebig
  • 6,901
  • 3
  • 28
  • 30
-3

Use hashing mechanisms to store password and always compare the hashed password then nobody knows the real password even you. It is very simple but it is effective.However, nothing is completely secure and there are some ways to broke the scurity layers.

Abi
  • 1
  • While your answer is not wrong, it doesn't answer the question. The problem here is about how to transfer the password securely to the server. – martinstoeckli Oct 09 '14 at 11:42
  • @martinstoeckli : Not necessarily. A one-use only password could be sent by email or sms. This could actually be used for each request. – Sentinel Jan 07 '15 at 14:28
  • @Sentinel - Password hashing is done server side, so an attacker cannot get the real passwords if he gets the stored hashes. If you send a one time token per sms to the user, there is no advantage in calculating a hash client side. A ManInTheMiddle could simply use the hash, and even when he knows the original token he could not reuse it. – martinstoeckli Jan 07 '15 at 14:41
-3

Try this : On each request of the login page, send across a nonce and a timestamp. While posting to server, send the following four details :

The username, the nonce and the timestamp in plaintext. Then concatenate the above with a separator (Eg: newline) and encrypt using the user's password as encryption in chained-block-cipher mode.

On the server end use the username to lookup the password and verify the encrypted string.

Since the password is never sent across in clear, it is secure and the timestamp can be used to avoid a re-submit of the same data.

To avoid hijacking of session by obtaining the session key through a man-in-the-middle attack, the password or a hash of the password can be stored in-memory by the application on the client end and be used for generating unique session keys for validation by server.

Taking a look at OAuth 1.0 is also not a bad idea.

Community
  • 1
  • 1
Ravindra HV
  • 2,558
  • 1
  • 17
  • 26
  • 1
    My answer was to make the login secure. So the user is already expected to know the password. – Ravindra HV Jan 05 '15 at 18:13
  • I think using a timestamp hashed with the password is an interesting idea provided the server and browser are in time sync. Not sure why this was voted down. – Dave Jan 07 '15 at 17:20
  • @MaartenBodewes - Until the point where javascript has access to the browser's truststore, allowing one to implement https at the application layer, the only option left is to provide an independent interface on https to reset the password. – Ravindra HV Oct 14 '18 at 13:29
  • I've now voted this down, because it simply indicates that you need to encrypt something without explaining how the shared secret is communicated or computed. This is not a protocol, this is a bunch of interesting ideas. Maybe it is useful in the long run, but it doesn't answer the question. – Maarten Bodewes Oct 14 '18 at 14:08
-3

If you can't use HTTPS or you don't want to use HTTPS, consider using jCryption. jCryption offers encryption for the data being sent through HTTP requests (POST, GET etc.).

You can test the technique here: http://www.jcryption.org/#examples

If you're using Firebug, you'll see that all the data is encrypted.

It has jQuery library to encrypt the data on the front-end and a PHP library to decrypt the data in the back-end.

Wissam El-Kik
  • 2,469
  • 1
  • 17
  • 21
  • 1
    JavaScript cannot be used to create a secure transport layer: http://matasano.com/articles/javascript-cryptography/ – rook Jan 08 '15 at 17:05
  • I totally agree that it's not 100% secure, but jCryption relies on OpenSSL and one several handshake methods. All the data sent through a HTTP Request is encrypted: the keys and the values are completely modified/merged etc. It uses RSA and AES for the encryption and you need to generate a Public and a Private Key to use jCryption. [Click here to check how it works](http://www.jcryption.org/#howitworks) – Wissam El-Kik Jan 08 '15 at 23:12
-4

It is hard to secure the communication without a trusted third party, however, there are some security tricks for you:

DO NOT expose users' sensitive information to public network.

Every sensitive information should be well hashed or public-key encrypted. Pay attention: If you choose to encrypt users' sensitive information by a public-key, please make sure that the user can verify the public-key. For example, you could send some kind of public-key fingerprint to user via SMS or even an auto-call.

Generate a SHARED SECRET after log on successfully

After a secure log on transaction, a shared secret should be generate. The generation procedure could refer to SSL Handshake. Pay attention: Once the shared secret is generated, it must on be transported anymore. The only function of it is to encrypt/decrypt the data between Server and Broswer

There SHOULD be a two-step-verification to avoid repeat attack

May these tricks will help you

user3024431
  • 461
  • 4
  • 8