Drupal and SSL - Multiple Recipes to Possible Solutions for HTTPS

As Matt Cheney likes to say "Much like Scrabble, the S is an important letter on the internet." If you really care about the data you are sending across the internet you want to make sure you are using SFTP instead of FTP, SSH instead of Telnet, and HTTPS instead of HTTP. So, within a Drupal site how can you use HTTPS to secure the data sent to and from your site and prevent sessions from being hijacked?

There are four basic solutions, though each has its benefits and drawbacks. I'll try to describe each one and give some guidance on the problems. They are covered from what seem to be the most common to the most secure. Note that the third technique is somewhat novel.

Read the rest of Drupal and SSL - Multiple Recipes to Possible Solutions for HTTPS


This article is now part of the Knowledge Base of Drupal security articles on Drupal Scout.


This page is kept so the comments posted here are available since they provide additional help and insights.

Part of the reason that this is so important is that malicious snoopers can take advantage of fast processing speed, using high performance cloud GPU computing.

Comments

funny

I am working on http://drupal.org/node/1577#comment-1882244 this core patch right now. Care to land a hand? It's a novel idea, similar to Use HTTPS for a session after login but better.

Secure pages on shared hosts

Thanks for the good summary!

I have struggled to understand how to get secure pages with shared hosting SSL certificates provided by my Web host.

I think it would really boost Drupal security for lower-end, lesser-trafficked sites — the kind many people may use to learn Drupal — if there was a way to handle that scenario cleanly, easily, and preferably right in core. It seems that other CMS tools and frameworks handle this better, but maybe I'm just perceiving the grass in greener elsewhere.

In my case, the Web host gives a different URL path to get to my site when using the server's shared SSL certificate. They don't provide a different hostname, which some Web hosts may do (and which might be more convenient in some respects), but a different URL. That URL doesn't necessarily include my site's regular domain name — at least not until you get down to a deeper part of the URL path.

If there's a good resource for this topic — besides the Secure Pages issue queue — that I can be pointed to, I'd love to hear about it.

more a server question

I totally agree with you that it's important to make sure Drupal works in low cost hosting environments.

I think this is really more of a server question than it is a Drupal question. The idea of using a shared ssl certificate on a different domain/url is not required by shared host - you just need your own IP and either a self-signed certificate or a regular certificate.

SSL form submit is not working

Hi in my Drupal site the SSL added but now i submit the form means one blank page is display then after i refresh the page so many times then only i will get the display even in login itself

how can i solve this i tried

wrote one .htacess file in the root

RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R,L]

still not working

then i tried

$request_type = ($_SERVER['HTTP_X_FORWARDED_HOST'] == 'ssl.proxy.org') ? 'SSL' : 'NONSSL';
if($request_type!="SSL"){
//header("Location:https://ssl.proxy.org/www.example.com");
$base_url = 'http://www.mydailylifecoach.com'; // NO trailing slash!
//$cookie_domain = 'www.example.com';
} else {
$base_url = 'https://www.mydailylifecoach.com/SSL'; // NO trailing slash!
//$base_url = 'https://ssl.proxy.org/www.example.com/some/dir'; // NO trailing slash!
$cookie_domain = 'ssl.proxy.org';
$_SERVER['HTTPS']='on';
$_SERVER['REQUEST_URI']='https://www.mydailylifecoach.com'. $_SERVER['REQUEST_URI'];
//$_SERVER['REQUEST_URI']='/www.example.com'. $_SERVER['REQUEST_URI']; // Only the DNS name of the site needed here!
$conf = array(
'reverse_proxy' => TRUE,
'reverse_proxy_addresses' => array($_SERVER['REMOTE_ADDR']),
);
}

this is also not working any one hlp me to find the solutions in my drupal site

thank you
David
www.way2tour.com

get ssl working on its own first

This is tricky and depends on so many external factors, which is part of why I didn't cover it, but

still not working

If it's still not working you need to solve that first - try getting your site to work with all requests under HTTPS. If that works then you can start looking at one of these mixed mode solutions.

Mitigating User Confusion w/ 3rd Technique

If using the "Use HTTPS for a session after login" technique, I recommend writing a custom access denied menu item that redirects to the user's My Account if the user is trying to access the user/login path and they are already logged in on the HTTPS side, but followed the login link from the HTTP side. That will mitigate the con that you mentioned.

So add the following to the hook_menu in a custom module:

$items['custom/denied'] = array(
'access callback' => TRUE,
'page callback' => 'custom_denied',
'title' => 'Access denied',
'type' => MENU_CALLBACK,
);

Then write the following function:

function custom_denied() {
if (request_uri() == '/user/login' && user_is_logged_in()) {
drupal_set_message(t('You are already logged in.'));
menu_set_active_item('user');
$return = menu_execute_active_handler();
}
else {
drupal_set_title('Access denied');
$return = t('You are not authorized to access this page.');
}
return $return;
}

Lastly you will need to edit the site_403 variable. You can do this in your custom module by calling:

variable_set('site_403', 'custom/denied');

Can you elaborate on Securepages Prevent Hijack

What does it prevent and what does it fail to prevent?

Thanks!

Purpose of securepages prevent hijack

Sure thing. Basically the problem is that when you do "mixed mode" SSL someone can use the cookie from their secure session on a non https page which allows the cookie to be sniffed and the session to be hijacked.

Securepages Prevent Hijack prevents that ;)

Secure Page Prevent Hijack

In the article, you say "Session hijack still possible, but limited in what damage can be done and data is still sent in the clear sometimes (may be an acceptable risk)."

How is the damage limited, and when is the data sent in the clear (assuming on non https pages) ?

It is possible to hijack the

It is possible to hijack the session, but as long as you've configured securepages and securepages then the hijacked session will be lost as soon as the person tries to do something "important." The definition of important is up to your site and your configuration.

Since it is "mixed mode" ssl there will still be content sent in the clear on "unimportant" pages (i.e. those configured to not use ssl).

Caching and SSL

Hi,

will using the method "Use HTTPS for a session after login" cause problems with caching and modules such as pathfilter? I had SSL enabled and used Apache to enforce SSL for /user and /admin pages, but as soon as I enabled caching under Performance, it all went crazy. Some sites were cached in SSL, some not. Apparently, the cache does not differentiate between http or https versions and caches and delivers whatever was first opened. Example: I clear all caches, open 50% of pages in http and 50% of pages in https, then my cache will have 100% of my pages in the cache, but output internal links on my own site both in http and https...

Cheers, Jn.

New Drupal Module Inspired by this Blog Post

I wrote a simple module, 443 Session, incorporating some of the ideas in this blog post.

It forces all logged in users to use HTTPS for their entire session, while anonymous users use HTTP. It also implements the custom access denied handler as mentioned in the comments above, to mitigate confusion caused if a logged in user navigates to a HTTP page.

Another option if you have contributor/consumption separation

We use the following option and it works since all our logged in users (contributors) are internal users and the rest of our visitors are just viewing the public site (except for public comments).

The public (consumption) version of the site is available at http://mydomain.org. This points to the Drupal codebase and database. In this Apache virtualhost we use mod_rewrite to protect/hide important Drupal paths such as /user and /admin so no one accessing the site at this URL can get to those pages. You could also redirect users to the https URL for these pages, but we want to keep the contributor site private.

The private (contributor) version of the site is available at https://site1.mydomain.org. This points to the SAME Drupal codebase and database. In this Apache virtualhost we allow access to important Drupal paths and use the php configuration option mentioned in the post above, "php_value session.cookie_secure 1". Additionally you could enable another layer of authentication in Apache to completely protect this version of the site from unwanted visitors.

You can do this same setup using a single hostname and an SSL certificate for it, but if you are going to host multiple public sites on one server with this same configuration you can save some money by using a single wildcard SSL certificate for all the contributor sites. So if you buy a wildcard certificate for *.example.com you can use one IP address in Apache and still have multiple SSL virtualhosts like site1.mydomain.org, site2.mydomain.org, etc, for the secure URLs.

Some issues we've had with this setup is that it can be confusing for our less technical contributors in that they might enter an internal, absolute link to content using the wrong domain. This mistake can be corrected automatically by using a custom input filter or avoided by using a WYSIWYG editor with an internal node picker that inserts links without the domain (relative).

-Tim

I'm using your solution

I'm using your solution number three but had to change:

if ($_SERVER['HTTPS']) {

to

if (!empty($_SERVER['HTTPS'])) {

or else my log would fill with errors:

...PHP Notice: Undefined index: HTTPS...

great point - updated

Great point, I've updated the original post.

Thank you for the document! I

Thank you for the document!

I found the same problem as BrianM, my solution seems more rigorous:
if (isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] == 'on')) {

Found some functions that work perfect for me.

Here are some functions I found in the comment section of this page: http://php.net/manual/en/function.header.php

Go to the page above and search the page for "These functions turn on SSL". They wouldn't paste correctly on this post due to some javascript in one of the functions.

They work great for what I am trying to do. I have a public section of the site that acts like a sales front end and then a private section for paying members only. I also have private login pages with the company names displayed for each company that I use these functions on to set the page to ssl. Then I use these functions on the private pages to set to non-ssl. Works great. Note that you would need this function on every page though if you want to prevent someone from manually switching back to http by just removing the "s" from the https in their title bar and hitting "enter". I tried doing this while logged in to gmail but google won't let you do that. Enjoy.

session hijacking

In the who's online block if there are 2 of the same users showing does that mean the site has been session hijacking?

Great write up!

One more thing, do You like to reduce the cookies time length in settings.php?

Thanks again

guests online even when site is offline

While building my site I keep it online with just Lorem ipsum content, and on my who's online block, I can see the number of guests online going up and down then up again (from 1 to about 18). It goes on even when I take the site offline.
No idea who these users are and what they're looking at.
My google analytics report doesn't show any suspicious destination page they're landing on.

is my site diverting some traffic, how can I find if there's some malicious code?
Your help will be most welcome.

just send all authenticated traffic over SSL

The best solution is to just send all authenticated traffic over SSL. It doesn't add much to the CPU (see the Overclocking SSL writeup from earlier this year and the related discussion on YC News) and it's a simple enough business rule to implement.

For the mixed content warnings we're all too familiar with, you can load images and CSS/JavaScript files with <img src="//path/to/image.png"> and the image will load using the current protocol, whether it's http or https.

Drupal 7 backport?

It's nice to hear that Drupal 7 handles all of this by design and solves the cookie problem by using two different cookies.

If we're lucky, someone will backport the code to D6.

Would you recommend 443 session module?

Hi Greg - thanks for this post.

I am trying to implement the option "Use HTTS for a session after login". Would you, and others, recommend using the 443 Session module for this?

http://drupal.org/project/session443

It looks like a great solution, but there aren't many people using it and it's only alpha. Has anyone out there used it? Any words of wisdom would be appreciated.

Thanks,
Kristin

Hi Kristin, I haven't tested

Hi Kristin,

I haven't tested it out, but obviously should. The description seems really great.

firesheep: implications on mixed mode ssl

Greg,

Now that firesheep is well-known and easy to use, what are the exact implications of Option 2: using mixed mode and basic SecurePages + SecurePages_Prevent_Hijack.

It seems like the key information is here, but it still seems cryptic.

The hijacked session will be lost as soon as the person tries to do something "important."

Mind elaborating on exactly what this means, with perhaps an example?

Thanks,
James

depends on your configuration

That all depends on your configuration and which pages you have configured to require SecurePages.

I was purposefully vague because the answer is site-specific, but perhaps that makes it harder to understand ;)

I'm currently using Secure

I'm currently using Secure Pages.

It's basically a personal site with the only user as me.

Wonder if I should add Secure Pages Hijack Prevention or switch to 443 Session instead?