301 Redirect and HSTS in .htaccess - apache

I've changed a site to https and have set up a redirect in .htaccess. But I've also set Strict Transport Security. Are both necessary or useful?
<IfModule mod_headers.c>
Header always set Strict-Transport-Security "max-age=16070400"
</IfModule>
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
</IfModule>
Cheers

A redirect tells people who enter http://www.example.com to go to https://www.example.com. Since the default is http, if you leave off the protocol and just type www.example.com then you will go to http://www.example.com so yes you need this redirect.
There's a few problems with this though.
First up http is insecure and can be read, and altered by other people on the network. That's the very reason you should use https. However, as http is insecure, that means they could intercept your redirect and keep you on http version and continue to intercept your traffic. Or alternatively redirect you to https://www.evilexample.com instead.
HTTP Strict Transport Security (or HSTS) is a security mechanism which attempts to address this issue. Your server tells the browser to ALWAYS use https for that site. Even if the don't type the protocol (when http would normally be used) and even if you DO type the protocol as http.
Once a browser has loaded HSTS for a site it will not even send a http request at all and will automatically change these to https instead. This has several advantages:
It's more secure as it cannot be intercepted.
It's quicker as doesn't waste time sending a request to http://www.example.com just to be told to go to https://www.example.com.
It can be used to address mixed content errors as http resources (for that site only but not loaded from other sites) will automatically be changed if you accidentally include a http source. Content Security Policy's upgrade-insecure-requests is probably a better solution for that but HSTS still provides a basic version.
Also as the other answer stated another separate benefit is that this setting also means browsers will not allow visitors to click through certificate errors for this site which adds extra security against attacks.
The main downsides of HSTS are that:
Your site needs to be https only - which may seem obvious but easy to miss part of the site on http only. Or a subdomain on http if using includeSubdomain option.
The visitor needs to visit the site first to pick up the HSTS policy though you can preload this into browsers but that's not a decision to be taken likely.
Browser support is not universal yet. And even if it was crawlers used by search engines and the like probably wouldn't use it.
So hopefully that explains why HSTS is a good thing and is something you should keep. On top of the redirect.

Yes! You should keep both of them. From OWASP docs, there're many benifits to use HSTS. E.g:
automatically redirects HTTP requests to HTTPS.
prevent user from overridding invalid certificate message.

I think you should have a look on this documentation https://varvy.com/pagespeed/hsts.html which says:
It is basically like a 301 redirect, but at the browser level, rather than the webpage level. It is superior to a 301 redirect as it can be implemented to always only use https, whereas 301 redirects are actually unsecure when first seen by a browser.
After reading the documentation, you can decide about it.

Related

.htaccess entry for redirecting to a folder without showing the folder name in url

my website resides in public_html/rhf folder.
1. i want if some one enter url https://rhf.in , it should be redirected to https://rhf.in/rhf in background and browser should display only https://rhf.in
also for if some one enters http://rhf.in or http://www.rhf.in it should redirected to https://rhf.in/rhf and shows only https://rhf.in/ in browser address bar.
first case is working fine for me by adding following in .htaccess
RewriteRule !^rhf/ /rhf%{REQUEST_URI} [L]
But second case is not working
Kindly help in this regard
This would be the classical setup:
RewriteEngine on
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,QSA,END]
RewriteCond %{REQUEST_URI} !^/rhf(?:/|$)
RewriteRule ^ /rhf%{REQUEST_URI} [QSA,END]
For the first redirection to http you obviously need to listen and react to the unencrypted http protocol at all. This implements a general redirection. In case you only want to redirect for that specific path you mentioned, the rule would have to be extended by a condition as well.
It is a good idea to start out with a 302 temporary redirection and only change that to a 301 permanent redirection later, once you are certain everything is correctly set up. That prevents caching issues while trying things out...
In case you receive an internal server error (http status 500) using the rule above then chances are that you operate a very old version of the apache http server. You will see a definite hint to an unsupported [END] flag in your http servers error log file in that case. You can either try to upgrade or use the older [L] flag, it probably will work the same in this situation, though that depends a bit on your setup.
This implementation will work likewise in the http servers host configuration or inside a distributed configuration file (".htaccess" file). Obviously the rewriting module needs to be loaded inside the http server and enabled in the http host. In case you use a distributed configuration file you need to take care that it's interpretation is enabled at all in the host configuration and that it is located in the host's DOCUMENT_ROOT folder.
And a general remark: you should always prefer to place such rules in the http servers host configuration instead of using distributed configuration files (".htaccess"). Those distributed configuration files add complexity, are often a cause of unexpected behavior, hard to debug and they really slow down the http server. They are only provided as a last option for situations where you do not have access to the real http servers host configuration (read: really cheap service providers) or for applications insisting on writing their own rules (which is an obvious security nightmare).

How would you block all referring domains via .htaccess while allowing a certain one through. Not IP address. Script isn't working

I need to have a .htaccess file made to the following specifications.
Allow ONLY "exampledomain.com/sometext" to access "mydomain.com/folder"
Block all other referrers and redirect them to "google.com"
But I am not sure how to go about doing this.
So far this is what I have got. But it is not working.
<If "%{HTTP_HOST} != 'google.com'">
Redirect / http://www.yahoo.com/
</If>
Using the latest Apache. I really appreciate the help here. I have gone through a few other posts but can't seem to figure it out.
Does the 'google.com' have to include the full url or is their a way to make it be a wildcard like *google.com*?
This should point you into the right direction:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^mydomain\.com$
RewriteCond %{HTTP_REFERER} !^exampledomain\.com$
RewriteRule ^ https://www.google.com [R=301,END]
It is a good idea to start out with a 302 temporary redirection and only change that to a 301 permanent redirection later, once you are certain everything is correctly set up. That prevents caching issues while trying things out...
In case you receive an internal server error (http status 500) using the rule above then chances are that you operate a very old version of the apache http server. You will see a definite hint to an unsupported [END] flag in your http servers error log file in that case. You can either try to upgrade or use the older [L] flag, it probably will work the same in this situation, though that depends a bit on your setup.
This implementation will work likewise in the http servers host configuration or inside a distributed configuration file (".htaccess" file). Obviously the rewriting module needs to be loaded inside the http server and enabled in the http host. In case you use a distributed configuration file you need to take care that it's interpretation is enabled at all in the host configuration and that it is located in the host's DOCUMENT_ROOT folder.
And a general remark: you should always prefer to place such rules in the http servers host configuration instead of using distributed configuration files (".htaccess"). Those distributed configuration files add complexity, are often a cause of unexpected behavior, hard to debug and they really slow down the http server. They are only provided as a last option for situations where you do not have access to the real http servers host configuration (read: really cheap service providers) or for applications insisting on writing their own rules (which is an obvious security nightmare).

What happens when you setup the free GeoTrust SSL certificate on 1and1?

1and1 UK hosting provides you with a free GeoTrust SSL certificate for your website.
But not wanting to break my existing site(s) I want to know beforehand what happens when you set it up.
Currently I have setup my webspace like this:
/www <-- www.foo.com
+-- /images
+-- /css
/test <-- test.foo.com
+-- /images
+-- /css
I only want the SSL cert for the www.foo.com website.
The documentation tells you how to setup the certificate - but not what happens when you do.
Is it as easy as it creates a new top level dir called /www-ssl ? If so I could just copy the site into there and work with that.
Thanks.
Funnily enough the original question is actually something I've
actually just finished rolling out over the last two days.
If you are just using 1and1's webspace/domains (not server) it's pretty straight forwards (it doesn't change files, it doesn't automatically make the site SSL). It will continue to run as a HTTP server until you start editing your .htaccess files to redirect to HTTPS.
You should be aware: If you intend to use 1&1's CDN and want SSL, the free one they gave you won't work with it. (I'm guessing it's
down to how the automated process for creating CNAME's in the zone
record conflicts with each other. It's also incidentally why you need
to make sure you are using 1and1's NS's so they have control over the
zone record to do alterations for setting up the CDN or Geotrusts SSL
Cert)
you will either have to buy the CDN package with SSL cert (which is more expensive) or you can do what I've done:
Set up the Free Geotrust SSL Cert for your server
turn OFF/Remove the 1and1 CDN (if you've set it up)
Visit https://www.cloudflare.com and sign up for a free account, Only set this up once you have the Geotrust Cert running on your server as it will require changing your domains NS's to cloudflares one in your 1and1 adminpanel which would cause problems with any automatic subdomain creation used by 1and1).
The difference between using 1and1 CDN & SSL and SSL & Cloudflare is the latter version is cheaper (it uses whats free and what you already have, as well as having more CDN options available to you.) and the only thing you lose from it is Mirage caching (image optimisation for mobiles, which is in beta) You can of course pay cloudflare to get that option (and other extras) but to be honest it's a small loss.
There is a difference between the Geotrust SSL and the SSL Starter certs.
The Geotrust SSL Cert will handle both foo.com, www.foo.com.
The starter SSL will only handle one of them, not both.
If that checks out Setup your GeoTrust SSL certificate to handle both www.foo.com and foo.com
Once you've got your cert just add the below to a .htaccess file (It assumes that foo.com traffic is also www.foo.com traffic)
<If "%{REQUEST_SCHEME} =='http' && (-f %{REQUEST_FILENAME} || -d %{REQUEST_FILENAME})">
Redirect permanent "/" "Https://foo.com/"
</If>
<ElseIf "(%{HTTP_HOST} == 'foo.com') && (-f %{REQUEST_FILENAME} || -d %{REQUEST_FILENAME})">
Redirect permanent "/" "Https://www.foo.com/"
</ElseIf>
This can be used instead of mod_rewrite in apache >=2.4
REQUEST_SCHEME is used since the server isn't using a FULL(Strict) method where the server itself is set to run in HTTPS. Certain mod_rewrite rules will actually cause infinite* redirect loops. (*until the server timeouts from recursion)
While it is possible to reduce this so you have less redirects, if you intend to further tighten your SSL if you use cloudflare, you'll likely end up using HTTP Strict Transport Security (HSTS) and it's strict in how HTTP is escalated to HTTPS. The Pseudocode below shows the elevation it requires (having to do it this way due to limited links being allowed here):
http(domain) >301> https(domain) >301> https(sub+domain)
I'm not entire sure how the HSTS protocol would handle how I initially intended the failure of a File/Directory not being found creating a 404 message that breaks it's strict redirects.
(If you use this method, sanitise how the 404 message is handled since it can be outside of HTTPS.).
As for test.foo.com test folder. You can just treat that as you
have already, it's outside of the SSL Cert and not handled by the
.htaccess of the www folder.
If/When you get to looking at setting up HSTS, you will want to add headers to your If/ElseIf statements.
<If "%{REQUEST_SCHEME} =='http' && (-f %{REQUEST_FILENAME} || -d %{REQUEST_FILENAME})">
Redirect permanent "/" "Https://foo.com/"
Header set Strict-Transport-Security "max-age=2592000; includeSubDomains; preload" env=HTTPS
</If>
<ElseIf "(%{HTTP_HOST} == 'foo.com') && (-f %{REQUEST_FILENAME} || -d %{REQUEST_FILENAME})">
Redirect permanent "/" "Https://www.foo.com/"
Header set Strict-Transport-Security "max-age=2592000; includeSubDomains; preload" env=HTTPS
</ElseIf>
I hope that helps,
Edit
To clarify, the question seems to be more about how TLS works rather than how to get around it.
A TLS certificate is an agreement between a website and a browser to use a common shared secret to send and receive encrypted communications between each other. This is NOT anything that changes the website content or the website data. It is simply a more secure transport system.
Imagine, you're trying to send out magazines to customers in the real world, and you post these magazines in thin, skimpy plastic wrappers with the address in the corner, that's ok, that works, but the postman, the whole postal working staff and anyone whose popping into the post office at the time will be able to see what you're posting, and what magazine your friend is receiving.
So, you update and instead post your magazines out in thick dark paper bags, with duct tape wrapping, this means no one in-transit can view the magazine and no one knows what magazine is contained within the paper bag. This is a very rough equviliant of what TLS does for the website, it doesn't change the website contents (the magazine) but it does ensure that this contents is much, much harder to sniff and read.
By saying you want to encrypt some websites but you don't want to encrypt others, this seems somewhat odd, as surely all customers (in the scenario painted above) would like their magazines delivered in thick paper bags rather than thin transparant plastic wrappers. As there is no cost involved, there is little gain if any in only encrypting some of your sites or data.
Historic Original Answer:
A TLS certificate can be enabled for any site but is not required unless you tell the site to require it. What you can do is set the certificate for your account (and this will cover all domains on the account including subdomains, unless there's a specific setup option to avoid subdomains) and then use htaccess to tell the server to clarify your actions, so you can tell the server that:
RewriteEngine On
rewriteCond %{HTTP_HOST} ^www.(.*)$
rewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [L,R=301]
So this will tell your server that if the www.site.whatever is accessed then to use HTTPS... And you can, if you really want, use a similar inverted rule to prevent the non-www subdomain using the secured TLS port, but really, why wouldn't you want to use TLS encryption for all your web data?

Redirection on Apache (Maintain POST params)

I have Apache installed on my server and I need to redirect from http to https. The reason for this is our load balancer solution cannot hand https so requests come in on http and then we transfer them to https using the below lines in the httpd.conf file.
<VirtualHost 10.1.2.91:80>
Redirect 302 /GladQE/link https://glad-test.com/GladQE/link.do
</VirtualHost>
This works fine for GET requests but POST requests will lose the parameters passed on the URL. What would be the easiest way to perform this redirect and maintain POST params?
I need to get from http://glad-test.com/GladQE/link.do to here https://glad-test.com/GladQE/link.do maintaining POST params
Thanks
Tom
You can try with the HTTP status code 307, a RFC compilant browser should repeat the post request.
Reference: http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
In contrast to how 302 was historically implemented, the request
method is not allowed to be changed when reissuing the original
request. For instance, a POST request should be repeated using another
POST request.
To change from 302 to 307, do that:
<VirtualHost 10.1.2.91:80>
Redirect 307 /GladQE/link https://glad-test.com/GladQE/link.do
</VirtualHost>
Standard Apache redirects will not be able to handle POST data as they work on the URL level. POST data is passed in the body of the request, which gets dropped if you do a standard redirect.
You have an option of either using a PHP script to transparently forward the POST request, or using a combination of Rewrite (mod_rewrite) and Proxy (mod_proxy) modules for Apache like follows:
RewriteEngine On
RewriteRule /proxy/(.*)$ http://www.example.com/$1 [P,L]
P flag passes the request to the Proxy module, so anything that comes to your site (via GET or POST doesn't matter) with a URL path starting with a /proxy/ will transparently be handled as a proxy redirect to http://www.example.com/.
For the reference:
http://httpd.apache.org/docs/current/mod/mod_rewrite.html
http://httpd.apache.org/docs/current/mod/mod_proxy.html
Either your public facing website MUST use SSL to protect confidentiality or there is no sensitive data enver passing through it, and no possibility that your site will ever be used for a lauinchboard for sslstripping (there's a very good reason why Google serve up search results over HTTPS).
If you are not encrypting traffic between browser and your site then why are you trying to encrypt them between your load balancer and your webserver? If you do happen to have a SSL termination outside the load balancer (a very silly approach) then using HTTPS between the load balancer and the webserver is far from efficient. The question also implies lots of other security problems like session fixation/sniffing and SSLStripping vulnerabilities.

Level of obscurity of destination URLs via mod_rewrite

To achieve a single layer of content delivery security, I'm looking into the possibility of obscuring a resource URL via an .htaccess RewriteRule:
RewriteEngine on
RewriteBase /js/
RewriteRule obscure-alias\.js http://example.com/sensitive.js
It would of course be implemented as:
<script type="text/javascript" src="obscure-alias.js"></script>
Because this is not a 301 redirect, but rather a routing scenario similar to that of many of our frameworks we used today, would it be safe to say that this RewriteRule adequately obfuscates the actual URL where this resource is located, or:
Can the destination URL still be found out via some HTTP header sniffing utility
Might a web browser be able to reveal the "Download URL"
I'm going to pre-answer my own questions by saying no to both since the "internal proxy" is taking place on the server-side and not on the client side if I understand it correctly: http://httpd.apache.org/docs/current/mod/mod_rewrite.html. I just wanted to confirm that when Apache goes to serve the destination URL, that it also isn't passing along information to the user agent what the URL was that it rewrote the original request as.
It depends on how you specify the redirect target.
If your http://example.com/ is running on the same server, there will be an internal redirect that is invisible to the client. From the manual:
Absolute URL
If an absolute URL is specified, mod_rewrite checks to see whether the hostname matches the current host. If it does, the scheme and hostname are stripped out and the resulting path is treated as a URL-path. Otherwise, an external redirect is performed for the given URL. To force an external redirect back to the current host, see the [R] flag below.
if the absolute URL points to a remote domain, a header redirect will be performed. A header redirect is visible to the client and will reveal the sensitive location.
To make sure no external redirect takes place, specify a relative URL like
RewriteRule obscure-alias\.js sensitive.js
Note that the sensitive JS file's URL can still be guessed.
To find out whether a request results in a header redirect, log in onto a terminal (eg. on a Linux server) and do
wget --server-response http://www.example.com
If the first HTTP/.... line (there may be more than one) is something that begins with a 3xx, like
HTTP request sent, awaiting response...
HTTP/1.1 302 Moved Temporarily
you are looking at a header redirect.
Possible using proxy throughput.
See http://httpd.apache.org/docs/2.4/rewrite/proxy.html
Also alluded to here as well: mod_rewrite not working as internal proxy