Some may want to use HTTPS for logging in.

Comments

killes@www.drop.org’s picture

Some comments bei redLED on #drupal:

01:12 < redLED> "interesting, but not generally applicable"
01:13 < redLED> ssl generates chain of trust warnings if you use it out of context
01:13 < redLED> e.g, without a valid certificate
01:13 < redLED> and without a dedicated IP address
01:13 < redLED> you can't bulk-host SSL on same IP like you do with apache vhosts
01:13 < redLED> the errors will obviously be confusing
01:14 < redLED> valid certs cost $'s, dedicated ip for ssl hosting costs most people $'s
01:14 < redLED> now
01:14 < redLED> what we probably do want to do if we want to improve security
01:14 < redLED> is steal someone's GPL javascript implementation of MD5
01:14 < redLED> then hash the password client-side, on the browser
01:14 < redLED> and then send it for verification

killes@www.drop.org’s picture

I am not sure the JS idea will be mich better than sending the password. If somebody can get the hash, he will also be able to submit the same http request.

Anonymous’s picture

I think SSL login is useful. To make it possible to support multiple sites on the same IP address, I think you should be able to specify the URL drupal users as the "action" parameter. An example:

A hosting company runs its SSL server at https://ssl.thehostingcompany.com/. On this server, users can put scripts in /members/sitename/. A user runs drupal on http://mysupersite.com/. To use SSL, the user tells drupal to process user logins with https://ssl.thehostingcompany.com/members/mysupersite/user/login. When someone logs in, the user/login page detects it is being accessed at this non-normal URL and redirects to the regular HTTP page.

Chris Johnson’s picture

If there is any interest in using a Javascript hashed, challenge-response login which falls back to the plain text arrangement we have now if the browser does not have Javascript enabled, there is well-tested (in use for years) GPL code to do it available from the PHPLIB base library:

http://phplib.sourceforge.net/

Uwe Hermann’s picture

+1

Although I agree with killes that this isn't a proper solution, I think it might be useful to at least not send the password plain-text. Yes, this is security through obscurity, but IMHO it's still slightly better than no security at all.

Steven’s picture

MD5-hashing the password on the client-side offers no security. The only security you can get is by hashing the password-hash concatenated with a random key to prevent replaying the HTTP request. But this gets tricky, as we need to tie the key to the client/session. We can't use cookies, because if an attacker can spy on network traffic, he can retrieve the cookie/session ID too and imitate the client.

I'm not sure if PHP sessions are tied to an IP, but even if they are, there are cases where people might share an IP (e.g. NAT firewalls). Plus, in the case of such a local area network, the chance of someone spying on traffic is often bigger due to misplaced trust.

The complicated SSL mechanism exists for a reason, we should not try and duplicate it.

Anonymous’s picture

Actually, the Chris Johnson on November 21, 2004 - 02:03 solution checks out quite fine to all the concerns you outlined.

http://phplib.sourceforge.net/ provides a challenge-respose mechanism. This is *not* just MD5ing the password and sending it out, making the hash reusable; this will not allow replaying of credentials, nor will it make the captured hashes suspectible to rainbow table (http://www.antsight.com/zsl/rainbowcrack/rcracktutorial.htm) type attacks. A JS client gets challenge-response, and the non-JS client gets to send his password in clear text and still authenticate. This affords for inexpensive security benefit toward JS capable clients; everyone wins, as less passwords are on the wire (JS capable use challange-response, and everyone else clear-text); all of this, can optionally, happen inside an SSL tunnel.

SSL, if used, should be kept out of the realm that is Drupal, it should be implemented on the web server, via mod_ssl on Apache for example. The module is a lot stronger than the capabilities one would bother to encorporate into drupal. One could for example, authenticate users versus client certificates they present; this can be made into a syncronious Drupal login via the authentication API, using for example webserver_auth.

Things, as they are, allow for maximal flexibility. The move to challenge-response by incorporating a peice of phplib might improve security a bit at no cost; and SSL can be implemented pretty well as is.

killes@www.drop.org’s picture

The patch does not apply anymore.

sami_k’s picture

Version: » 4.6.0
Assigned: chx » sami_k

I am working on a new version of this patch, should be available very soon, if it's not please send me an e-mail.

zwoop’s picture

StatusFileSize
new0 bytes

I played around with this patch as well, on my 4.6.x system, and with some tweaking it does work as "intended". However, it only seems to apply to the login pages, which I found less than ideal since user password (and possibly other sensitive information) is sent in clear text in several other pages and forms. For instance, changing your password would still send the password in the clear.

So, with this in mind, I prepared a slightly different "patch" for this, which I've made available at

http://www.ogre.com/tiki-download_file.php?fileId=9

Sorry, it's not using Drupal yet, hopefully soon :-). Note that this patch doesn't change the user module at all, it's all done in the common.inc file instead. I thought this was "cleaner". Let me know what you think.

-- leif

walterw’s picture

Hey guys,

I am currently using this bit of code in my own web application, still determining whether to use drupal or another CMS ...

This works fine as it redirects the user to an https connection. I haven't done anything to redirect the user back to http after authenticating or viewing a page that does not requires ssl.

I am not quite sure how this would get implemented in drupal without touching their code as well as tables. All I know is that this works fine for redirects and prevents the infinite loop (redirecting to oneself).

Walter

walterw’s picture

StatusFileSize
new6.74 KB

I apparently couldn't include my code because it was suspicious ...

Here it is attached, hopefully it is.

Anyways, with this class file I have attached, I extend it with a class customized for my website ... it changes which page is displayed (first visit, and what the root url should display, folder, element, ...).

walterw’s picture

StatusFileSize
new6.74 KB

I apparently couldn't include my code because it was suspicious ...

Here it is attached, hopefully it is.

Anyways, with this class file I have attached, I extend it with a class customized for my website ... it changes which page is displayed (first visit, and what the root url should display, folder, element, ...).

neale’s picture

Walter, it looks like your code just redirects users to "SSL" pages. The problem is, by the time the redirect is posted in the HTTP response, the form submission (username and password) has already crossed the wire.

I would not recommend using this method.

zoop's patch, while a tad kludgy, is very clever. (There's no non-kludgy way to do it, I'm afriad, without being a bit invasive into the code.) I suggest using zwoop's patch instead.

ñull’s picture

Zwoop's patch seems to work fine here. I will be expanding on it that other pages with sensitive personal information like addresses in e-commerce check-out, will be in SSL mode as well. I will try to make something where the user can add other URLs that will switch to SSL mode.

sami_k’s picture

Assigned: sami_k » Unassigned
Chris Johnson’s picture

Title: Use HTTPS for login » Challenge / Response login
Version: 4.6.0 » x.y.z
Assigned: Unassigned » Chris Johnson

Ok, chx has talked me into working on this as a challenge/response login.

Changed the title, and assigned it to myself.

Chris Johnson’s picture

Basic theory of how this will work

The login form uses a challenge/response mechanism to authenticate the user. The password does not travel over the network if the client browser has Javascript enabled.

Drupal will generate a challenge value which is incorporated into the login form. When the user tries to submit the form, md5("username:password:challenge") is calculated and filled into the reply field. The password field is erased.

The server can calculate the expected reply and compare it to the actual reply value. If they match, the user is authenticated.

If the reply field is empty and the password is set, the server knows that the client cannot do Javascript. The user can still be authenticated, but the password will have crossed the network as it does now.

Draft Javascript bits

// <sscript src="md5.js"></script>  <-- needs to be obtained -->
// <sscript>
  function doChallengeResponse() {
    str = document.login.username.value + ":" +
          MD5(document.login.password.value) + ":" +
          document.login.challenge.value;
    document.login.response.value = MD5(str);
    document.login.password.value = "";
    document.logintrue.username.value = document.login.username.value;
    document.logintrue.response.value = MD5(str);
    document.logintrue.submit();
    return false;
  }
// </script>

Draft PHP bits

function user_login(...) {
  $challenge = md5(uniqid($magic));
  $form['challenge'] = array('#type' => 'hidden', '#value' => $challenge);
  ...
}

function user_login_validate(...) {
  ...
  $expected_response = md5($account->name .':'. $account->pass .':'. $challenge);

  if ($form_values['response'] != $expected_response) {
    form_set_error('login', t('Sorry. Unrecognized username or password.') .' '. l(t('Have you forgotten your password?'), 'user/password'));
  watchdog('user', t('Login attempt failed for %user: %error.',           array('%user' => theme('placeholder', $form_values['name']), '%error' =>        theme('placeholder', $error))));
  }
  ...

Steven’s picture

Hmm afaik this will not work:

function user_login(...) {
  $challenge = md5(uniqid($magic));
  $form['challenge'] = array('#type' => 'hidden', '#value' => $challenge);

The $form array is not stored anywhere between requests, but created when needed (this makes sense when you think about it, because there is nowhere for it to be stored). So the challenge would be different when the form is output than when it is processed, and login would fail.

The problem is that we need to tie the challenge to the end-user somehow. But, ip/hostname tends to work badly because of multiple proxies at an ISP.

Let's step back though. Suppose we do get a reliable unique challenge/response going. That means an attacker can not replay the authentication... but he could still just sniff the session ID cookie and use it directly! Remember: our sessions are not tied to IP either (for the same reason as above).

And if an attacker can not just sniff, but also intercept traffic, then he can simply strip out the Javascript and force a plain-text log in.

So it would seem that the use of this patch is only to prevent plain-text passwords from travelling around. While it does offer a tiny bit of safety for the end user (especially for people who re-use passwords), it is not much at all. If a feature like this is added we need to clearly document what it does and does not protect.

mfb’s picture

In order to handle SSL logins securely, you need to add

php_value session.cookie_secure 1

to your .htaccess or httpd.conf. Any newly created session cookies will be set to only be sent back to the server over encrypted SSL connection. When users connect via the regular http URL, they will always be logged out, even if they have a valid session on the https site. But this configuration does have the advantage of not causing browsers to send session IDs over an unencrypted connection.

Chris Johnson’s picture

I believe Steven's remarks on the usefulness of this feature raise an important issue. Do we really want to implement this feature? It provides some amount of additional security, but it is not panacea. Because of the challenge with keeping the challenge value across forms that Steven pointed out, the technical effort will be higher than I originally thought. Thus the feature has a lower cost-benefit ratio.

killes@www.drop.org’s picture

IMHO it is "won't fix".

Chris Johnson’s picture

Now we just need chx's agreement, since he directed me to pursue this thing. :-)

moshe weitzman’s picture

"So it would seem that the use of this patch is only to prevent plain-text passwords from travelling around. While it does offer a tiny bit of safety for the end user (especially for people who re-use passwords),"

i think this is a significant win ... phpmyadmin does this as well as some other major projects.

fax8’s picture

Challenge/Response were discussed earlier.. I was one of the biggest fan of this...
http://drupal.org/node/36793
http://lists.drupal.org/pipermail/development/2005-November/011022.html

There were lot of comments there and I finally understood that the real way to get
security is over an SSL connection.

fax8’s picture

ChrisKennedy’s picture

Version: x.y.z » 6.x-dev
chx’s picture

Status: Active » Closed (won't fix)
Leeteq’s picture

I would like to argue for a less secure yet better-than-no-security approach, coupling the question of sending the password as clear text with another (new) useful user account feature.

Consider this scenario:

  • I am increasingly working through public Wi-Fi networks, "insecurely".
  • I use SSL on all my own sites, and becoming increasingly aware of how valuable my identity/history/user/etc. is (becoming, increasingly). So I am trying to avoid web services that does not do at least basic protection of my credentials. If I know that by starting to use a particular web service - and if it turns out to be satisfactory, leading me to become "dependent" on it (meaning I will hate to loose it or get my login stolen), then I will look to find another similar service that provides basic security before I even get started with the one that would be my first choice, if it wasnt for the lack of protection.
  • For me, most often it is sufficient if I know that at least not tech novices or the common (wo)man could just get a tool from the internet to intercept the traffic and get hold of my credentials in clear text. Even if it would be fairly simple to get around this, I think it will significantly reduce the number of people who could "easily" get hold of my credentials. That is enough for me when it comes to a site like drupal.org, for example.

An important additional feature that will help us accept the above:
I love the way sites like Yahoo is using a separate "security key" that cannot be the same as the current password. This means that even if someone gets hold of my login, at least they cannot manage to block me out of my account as they would not have the second "key" that let them change the password. The only thing they could do was impersonate me. I would probably notice, and be able to change my password to block them out.

I mention this here in this issue even if this could be a separate feature request. If this sounds interesting, maybe we either use this issue for this, or file a new one about a secondary "key" (password).

Leeteq’s picture

FYI - there is a "duplicate" (open) issue here:

"SSL security for login/admin" :
http://drupal.org/node/1577