Drupal lacks any organized method (that I am aware of) of controlling which pages can/must be accessed via SSL. Some modules (e.g. authorize_net in the upcoming E-Commerce release) hard-code certain behaviors, and a few various hacks have been proposed in the forums, but generally these approaches conflict with each other and lead to complexity and not using SSL when it should be (e.g. all user logins and registrations, admin pages with security-critical data (e.g. authorize_net merchant account passwords) or for that matter all admin pages, etc.).

I propose a simple module to handle this centrally, which I'll call sslcontrol for now. It has a settings page which lets the admin declare which pages should be SSL-protected just like declaring where blocks should appear. It also defines hook_sslcontrol(...) which lets modules declare that the current URL should be SSL-protected.

In sslcontrol_menu(), the module combines its own settings and the results of hook_sslcontrol() to decide if the current page should be protected. If so, and if the page is not already using SSL, it redirects to the SSL-equivalent page. If not, and if the page is using SSL, it redirects to the non-SSL-equivalent page. It would be an admin configuration error to define a POST-targeted page as requiring SSL when its submitting page is not, or vice versa, since you cannot redirect in that situation without generating a browser warning dialog.

This will also make it simple to handle sites where the SSL base url is not https://www.sitename.com but something like https://www.myisp.com/sitename. Right now, for example, the Authorize.Net module explicitly does not support that configuration.

Since modules would have to be forbidden from making SSL-related redirects outside of this module (to prevent redirect loops), it seems to me this should be part of core. But I'm a newbie without the creds to make such a suggestion. :-)

Comments?

Barry

Comments

bjaspan’s picture

Another thought: The l() and url() functions could be modified to be aware of sslcontrol and produce correct http/https links based on it, thus eliminating the need for a redirect.

Barry

bjaspan’s picture

Given that relatively few page require SSL, modifying l() and url() to query every module for every link just to avoid a redirect is a false optimization.

Barry

solanas’s picture

I'm looking for something like that. I thoght Drupal was implemented a solution for secure logons. That will be perfect for me but I'm newbei. If somebody start with the module I would like to be a tester for it.

Marco Solanas

bomarmonk’s picture

This would be terrific! I've been fishing around for how to do this, but it would be nice if it was wrapped up in one module and compatible with webform. Just my two cents. ++1

killes@www.drop.org’s picture

Secure logins are both quite easy to achieve and pointless at the same time.

1) Easy: Disable the login block and define /user as a ssl protected page through setting the base_url in settings.php based on the current path.

2) Pointless: You will be sending your login cookie through unencrypted http once you leave the secured user page.
--
Drupal services
My Drupal services

pwolanin’s picture

If I can reverse the logic of this comment a little, I think it implies the conclusion that if one wants to access a site securely, then everything should be done via SSL?

I'd pretty much come to that conclusion already. One also need to think about the access for FTP, etc. Your site is not really secure if somone can sniff your unencrypted FTP password and go in a substitute anything they want in your PHP files. Unfortunately, many commercial hosts doen't make it easy to use sftp.

---
Work: BioRAFT

bomarmonk’s picture

I want to use webforms to send private, confidential information (asw private as possible) from an anonymous user to a given e-mail address. I would like to be able to secure a webform so that the data wouldn't be intercepted, without making my entire site SSL. (Isn't this like killing a fly with a nuclear weapon?)

Anyway, if what Killes points out is true, shouldn't this module potentially do something with the session cookie so that sites can be secured? Either that, or could Drupal handle this differently? This may be like asking can a car run on something other than fossil fuel (possibly, but it aint cheap or easy).

I would still say that a module that secures certain nodes with SSL (with a redirect, etc), would be a convenient plug-in feature, even if it isn't perfect. It could include a disclaimer... it doesn't make you bulletproof.

pwolanin’s picture

Just wondering about your scheme. If you're sending the data out by (unencrypted) e-mail, it's not secure anyhow.

I see your general point, however, that users might prefer to enter confidential information in a secure form, even if their entire session is not secure. Once they submit the webform, an imposter can't pull the information back out of the database even if they steal the session cookie.

---
Work: BioRAFT

mr700’s picture

Mail servers *can* talk to each other with ssl, do they and how should this happen is another question.

killes@www.drop.org’s picture

Yes, you need to use ssl for the whole site if you want real security. No responsible hoster should even offer FTP anymore in the year 2006.
--
Drupal services
My Drupal services

moshe weitzman’s picture

just about all hosts do offer ftp because thats what their customers expect.

solanas’s picture

Maybe the solution is to write a handbook explaining step by step how to secure Drupal. These handbook could collect all the posibilities and everybody could choose the best way for him.

Some ideas:

-https just for logon and edit pages. Those pages could use an alternative cookie to verify the session and this cookie never would be exposed through unencrypted http.

-best practices for not to be hacked.

-Which are the pointless when you secure with https all your site?

-Do Google index secured pages? Do get secured pages the same page rank?

...

Marco Solanas

mfb’s picture

I'd agree that there is no real security without enforcing ssl-only session cookies.

But there is _some_ benefit to ensuring that certain forms are always passed securely, even if the session could later be hijacked. The hijacker could not decrypt data which was already sent like passwords, credit card numbers and other sensitive info.

lewiz’s picture

I realise that it would be pointless in terms of Drupal security.
I'm going to use the LDAP authentication module so my goal is to secure the user's LDAP password. In this case am I right in thinking that it would provide the necessary security I desire?

bjaspan’s picture

killes, you imply that there is no need to SSL security anywhere except during login. This is not correct as there are other pages that require it. Obviously, industry standards require all forms containing credit-card info to be encrypted. There are also forms that display security-critical data (such as the E-Commerce Authorize.Net module which uses a merchant account username/password) (frankly I don't think such things should be stored in the database at all, but that is a separate issue).

You also state that securing the login process is pointless if a session can be hijacked later. However, disclosure of a password is a far greater risk than disclosure of a session ID. The password has a potentially unlimited lifetime and may be useful at a wide variety of sites, whereas a session id will expire if not used (ummm... at least I assume so, is that configurable?) and in any case is only valid at a single site.

Enforcing SSL for /user in settings.php is a good start but does not solve the whole problem; in fact, I was doing just that until I started using E-Commerce. With some modules (e.g. Authorize.Net) performing their own SSL redirects, it becomes difficult or impossible to implement a general SSL protection scheme in settings.php.

My next post will suggest an approach to prevent SSL session hijacking.

Barry

killes@www.drop.org’s picture

killes, you imply that there is no need to SSL security anywhere except during login. This is not correct as there are other pages that require it. Obviously, industry standards require all forms containing credit-card info to be encrypted.

I was referring to a standard Drupal install. And what I was saying as rather that you should use SSL for your whole site if you want security.

There are also forms that display security-critical data (such as the E-Commerce Authorize.Net module which uses a merchant account username/password) (frankly I don't think such things should be stored in the database at all, but that is a separate issue).

Drupal does not store the password, it stores a hash of it.

You also state that securing the login process is pointless if a session can be hijacked later. However, disclosure of a password is a far greater risk than disclosure of a session ID. The password has a potentially unlimited lifetime and may be useful at a wide variety of sites, whereas a session id will expire if not used (ummm... at least I assume so, is that configurable?) and in any case is only valid at a single site.

That is of course true. However, only securing the login page will instill a false sense of security and thus is not a good idea.

Enforcing SSL for /user in settings.php is a good start but does not solve the whole problem;

I was trying to say that it is not a good idea. Sorry, if that came across as me saying it was a good idea. Everybody who does only want "secured log ins" will think it would be a good idea. It is not. See above.

in fact, I was doing just that until I started using E-Commerce. With some modules (e.g. Authorize.Net) performing their own SSL redirects, it becomes difficult or impossible to implement a general SSL protection scheme in settings.php.

If you need to build SSL connections to different servers, you might ave trouble.

My next post will suggest an approach to prevent SSL session hijacking.

I look forward to that.

--
Drupal services
My Drupal services

bjaspan’s picture

killes makes the excellent point that even if a username/password are transmitted to a site over SSL, the session is still subject to hijacking because the session cookie is passed in plaintext. One obvious solution is to require SSL for all requests but this has downsides. A valuable compromise would be prevent a hijacked session ID from being used to access an SSL-protected page; any pages that allow some kind of critical activity (buying products against a stored credit card number or whatever) could then require SSL and know the session ID was not hijacked.

This can be accomplished by using a second session ID cookie with the 'secure' flag set so it is only transmitted to SSL-protected pages. Here's how it would work:

- When a user logs in, a second unique session ID is generated. In reply to the login submission (which was to an SSL-protected page), the secure session ID is sent to the user as a second cookie named (e.g.) PHPSESSID_SECURE with the 'secure' flag set and is also stored in $_SESSION['PHPSESSID_SECURE'] which of course is keyed by the non-secure session ID.

- Whenever a request arrives via SSL, the session is loaded in the normal way (using the non-secure session ID) and then the PHPSESSID_SECURE cookie is compared against $_SESSION['PHPSESSID_SECURE']. If they don't match, the session has been hijacked and the request is refused.

This is way more complexity than most people would put into their settings.php but would be easy enough to implement once centrally in my proposed sslcontrol module.

In case it wasn't clear, I'm offering to write this module myself. Since it will require prohibiting other modules from doing their own SSL redirects (and changing those that already do), I'm just hoping to get buy-in from the core developers so I know it will be used.

Barry

bomarmonk’s picture

Pairing it with E-commerce has an obvious usefullness and the convenience of managing SSL through a module seems very convenient. Even better, it also sounds like your proposed module would handle the SSL in a way that would be as secure as possible. I hope others will support you in your efforts. I will be very thankful if you write such a module.

bomarmonk’s picture

This seems to be a module that does some of what we are discussing. It's probably worth a look before you build a new one (maybe features can be added to this one?)

http://drupal.org/node/65632

killes@www.drop.org’s picture

killes makes the excellent point that even if a username/password are transmitted to a site over SSL, the session is still subject to hijacking because the session cookie is passed in plaintext.

The initial session cookie is transferred as plaintext. After SSL connections are made, the cookie will be encrypted as well. Thus you need to set a new cookie after log-in. Which is what Drupal does.

One obvious solution is to require SSL for all requests but this has downsides.

This is the only secure way to do it, however.

A valuable compromise would be prevent a hijacked session ID from being used to access an SSL-protected page; any pages that allow some kind of critical activity (buying products against a stored credit card number or whatever) could then require SSL and know the session ID was not hijacked.

This can be accomplished by using a second session ID cookie with the 'secure' flag set so it is only transmitted to SSL-protected pages. Here's how it would work:

- When a user logs in, a second unique session ID is generated. In reply to the login submission (which was to an SSL-protected page), the secure session ID is sent to the user as a second cookie named (e.g.) PHPSESSID_SECURE with the 'secure' flag set and is also stored in $_SESSION['PHPSESSID_SECURE'] which of course is keyed by the non-secure session ID.

As I said, Drupal already generates a second cookie which replaces the original one.

- Whenever a request arrives via SSL, the session is loaded in the normal way (using the non-secure session ID) and then the PHPSESSID_SECURE cookie is compared against $_SESSION['PHPSESSID_SECURE']. If they don't match, the session has been hijacked and the request is refused.

This is way more complexity than most people would put into their settings.php but would be easy enough to implement once centrally in my proposed sslcontrol module.

In case it wasn't clear, I'm offering to write this module myself.

This was clear to me.

Since it will require prohibiting other modules from doing their own SSL redirects (and changing those that already do), I'm just hoping to get buy-in from the core developers so I know it will be used.

I believe the best way to achieve what you want is the following. You split up your ecommerce site into two sites with different subdomains. The first one is used to collect things into a shopping basket and the second (which runs SSL) is used to do the checkout.

A mechanism similar to the one proposed by you could be used to ensure the SSL cookie does not get sent to the plain site should the user go back to it.

Running your mechanism on one Drupal site seems to be quite complicated and I am not even sure it would work.

--
Drupal services
My Drupal services

solanas’s picture

I'm not sure if it could be done but...

What about to redirect all the URLs to https when the user is in a registered session. In that case anonymous users read the node 105 with http://www.mydomain.com/node/105 and a registered user reads it with https://www.mydomain.com/node/105. Could be the same node to be read in both cases?

Marco Solanas

gordon’s picture

See secure pages module http://drupal.org/node/65632 which transfer required pages to SSL, and redirects any forms that need to posted to a page which is meant to be SSL to the SSL version.

There is both 4.6 and 4.7 versions. Just take a look at the settings to set up the which pages are secure and which are not.

I do need to add some documentation, but I haven't gotten around to it.
--
Gordon Heydon
Heydon Consulting

--
Gordon Heydon

bomarmonk’s picture

I can't submit and issue to the project page for your module, Gordon (it's not listed in the projects yet, even though it looks like I can "submit an issue").

So far it's working fairly well, but I get an error with an anonymous user accessing an SSL protected webform:

Fatal error: Call to undefined function: url() in /mysite/WWW/modules/securepages/securepages.module on line 71

gordon’s picture

It is most likely in moderation. I only created the project yesterday.

I have fixed this issue when it is dealing with cached pages.
--
Gordon Heydon
Heydon Consulting

--
Gordon Heydon

jyamada’s picture

Hi,

I am using the secure pages module and I'm trying to track down a problem.
After installing this module, whenever I'm in the user/admin section, I am in SSL, otherwise I'm not in SSL.
When I am in SSL, you said this module "redirects any forms that need to posted to a page which is meant to be SSL to the SSL version."
But I'm getting "Although this page is encrypted, the information you have entered is to be sent over an unencrypted connection and could easily be read by a third party." when updating an admin page.

Is this a bug?
I have selected "Switch back to http pages when there are no matches" - YES
But I have no Base URL because I'm using multiple domains on a single instance, so there is no single root base url for all the domains.

Can you or someone else comment on this ?

Thanks,
Joe

mwu’s picture

I'm trying to understand security issues. This is my current understanding after reading this page, talking with some security experts, and looking at some security books:

1) to be secure, the entire site should be accessed via https because otherwise cookies are transmitted unencryped.

2) this will produce performance issues. does anyone know how much?

3) secure pages is finished and can handle this task.

my knowledge is rather minimal and so I may have misunderstood.
thank you for your feedback.