Page MenuHomePhabricator

Allow tool's maintainers to force HTTPS for their tool
Closed, DeclinedPublic

Description

Hi,
I've recently experienced an issue when I wanted to enforce HTTPS traffic for my Wikinity tool.

Reason
My new Wikinity tool (https://tools.wmflabs.org/wikinity) includes another page over HTTPS by JavaScript. But when it get loaded over HTTP the browser complains about "No 'Access-Control-Allow-Origin' header is present on the requested resource" (http://tools.wmflabs.org is another origin than https://tools.wmflabs.org) and do not work. The only one solution I've found out are to send Access-Control-Allow-Origin header from the included page but I think loading over HTTPS is better as it protect the traffic over manipulating on the way to the user.

There could be scope to enforce HTTPS for all tools (which can and will break some tools which are including some HTTP page, when this tool will be loaded using HTTPS stuff breaks) but at least, tool maintainers should have ability to enforce HTTPS for their tool.

Thank you in advance,
Martin Urbanec


Answer

Check the X-Forwarded-Proto HTTP request header that your application will receive in each request. This header is added by the nginx proxy that figures out where to send requests for your tool's path. If the value of that header is http then send a redirect to the browser telling it to use https.

Check and redirect in PHP
if ( $_SERVER["HTTP_X_FORWARDED_PROTO"] === "http" ) {
	header( "Location: https://{$_SERVER['HTTP_HOST']}{$_SERVER['PHP_SELF']}" );
	return;
}
Check and redirect in Python Flask
@app.before_request
def force_https():
    if request.headers.get('X-Forwarded-Proto') == 'http':
        return redirect(
            'https://' + request.headers['Host'] + request.headers['X-Original-URI'],
            code=301
        )

Event Timeline

Restricted Application added a subscriber: Aklapper. · View Herald Transcript

Same for Labs Projects please

Can't they just do them themselves?

I've tried to add the following code to my .lighttpd.conf according to https://redmine.lighttpd.net/projects/1/wiki/HowToRedirectHttpToHttps which resulted in redirect-loop.

$HTTP["scheme"] == "http" {
    # capture vhost name with regex conditiona -> %0 in redirect pattern
    # must be the most inner block to the redirect rule
    $HTTP["host"] =~ ".*" {
        url.redirect = (".*" => "https://%0$0")
    }
}

Same for Labs Projects please

Can't they just do them themselves?

The unencrypted HTTP and the encrypted SSL traffic go both via port 80 between the Webproxy and the Instance.
Hence, I can't configure redirect rules for redirecting traffic from Port 80 to 443 on my Instance.

Seems this Is the same issue for toollabs.

Might be because Tool Labs uses the infrastructure of Labs.

I've tried to add the following code to my .lighttpd.conf according to https://redmine.lighttpd.net/projects/1/wiki/HowToRedirectHttpToHttps which resulted in redirect-loop.

You want to redirect based on the HTTP_X_FORWARDED_PROTO header, not the scheme, as the scheme (as far as the webservice is concerned) is always http -- the connection between the proxy and the webservice is not encrypted.

Alternatively, you can use protocol-relative URLs to load the javascript file, i.e. src="//tools.wmflabs.org/...", which will load the javascript over http if the original page is loaded over http.

Do you know how can I add the redirect rule to lighttpd config? Or do it need to be set somewhere else?

Do you know how can I add the redirect rule to lighttpd config? Or do it need to be set somewhere else?

It need to set somewhere else: In the proxy. Not on the lighthttpd server.

Do you know how can I add the redirect rule to lighttpd config? Or do it need to be set somewhere else?

I've done it in the main PHP file. Thank you for the header-help!

Do you know how can I add the redirect rule to lighttpd config? Or do it need to be set somewhere else?

It need to set somewhere else: In the proxy. Not on the lighthttpd server.

No no no. You receive a header informing the request came over HTTP from the proxy, then you may redirect. For example my Wikinity tool is now https only (applies only for the main file but the others should not be accessed by users directly).

Where do I get this information in the header?

This is a HTTP header. For example in PHP you may do the following

if (getallheaders()['X-Forwarded-Proto'] == "http") {
	header("Location: https://".$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF']);
}

This would redirect all requests with X-Forwarded-Proto header set to http (exactly as it is set when receiving request over HTTP by the proxy) to the same URL but with https protocol.

I don't know how can you do it in the webserver's config sadly.

Note that the code must be at the beginning of your PHP code before any other output. Otherwise the location thing would just appear on the screen.

Slightly off topic to this bug, but why do we even allow non secure http on tool labs? Https-only (+hsts) is quickly becoming the norm for major websites

dpatrick subscribed.

This seems to be a non-Security issue, and one which is best handled by another team, so I'm untagging the Security project.

bd808 updated the task description. (Show Details)

Slightly off topic to this bug, but why do we even allow non secure http on tool labs? Https-only (+hsts) is quickly becoming the norm for major websites

That's good question. I personally think we can throw HTTP away, I'm enforcing HTTPS for tools.wmflabs.org for my computer and didn't find anything broken but...

Some tools I messed in T172065 doesn't work on HTTPS on some browsers (including my non-usual-non-testing Firefox) due to loading HTTP.

bd808 changed the task status from Open to Stalled.Oct 15 2017, 8:55 PM
bd808 triaged this task as Low priority.
bd808 subscribed.

I went down the rabbit hole of trying to get http -> https redirection based on the X-Forwarded-Proto header value to work in ~/.lighttpd.conf for a tool.

It turns out that this could only be done if we do one of these things:

  • Change the headers that dynamicproxy passes to the proxied http server so that mod_extforward will recognize that a proxy is in use
  • Update to lighttpd that supports lua scripting and use mod_magnet
  • Write a custom lighttpd module

Mod_extforward is designed to support reading an X-Forwarded-Proto header to set $scheme inside lighttpd, but it has several layers of guarding that turn out to be incompatible with the current headers that dynamicproxy passes. It might work if we added an X-Forwarded-For header. If we did that we would want it to be a fake value like 127.0.0.1 or a 10/8 address so that we do not expose the actual client IP to the tool.

The mod_magnet and custom module options are both pretty complex changes. As shown in the current summary, this type of redirection can be handled at the application layer. Beyond that, this may be easier to solve in a future where we having something like T120486: Set "https_upgrade" configuration flag for domainproxy to enforce HTTPS upgrade for GET|HEAD requests and T125589: Allow each tool to have its own subdomain for browser sandbox/cookie isolation.

Moving forward with T102367: Migrate tools.wmflabs.org to https only (and set HSTS) instead of adding per-tool configuration for this.