
Issue: Bitbucket relies on the Referer HTTP header - whyagaindavid
https://bitbucket.org/site/master/issues/10726/bitbucket-relies-on-the-referer-http
======
Analemma_
Seems fairly clear that this is a Django issue, not a Bitbucket issue. Maybe
change this link to point to the equivalent Django bug:
[https://code.djangoproject.com/ticket/16870](https://code.djangoproject.com/ticket/16870).

~~~
1_2__3
So when my car breaks down I should expect Toyota to say "sorry that's a
Takata issue take it up with them"?

~~~
innoying
But that's not what happened here at all. Bitbucket has responded explaining
why this (self-inflicted) bug exists (a security decision in an underlying
framework) and deferred to the framework maintainers for further discussion
because they have the best context on why that decision was initially made and
under what scenarios it might be changed.

~~~
nickpsecurity
They chose to use a framework without understanding the implications of its
security issues. When one comes up, they tell their users it's someone else's
problem. Maybe they're an impoverished company that can't afford to pay to
solve the problem. Or they dont care much.

------
hedora
Does anyone know of a good alternative to the atlassian suite? Given their
price structure and popularity, I'd expect them to fix stuff like this in a
timely fashion, and fix some basic UI issues.

Bitbucket server (aka "stash") examples:

\- Create a pull request (the most common workflow in bitbucket) takes far too
many page loads, and is buried in "hamburger"/"more options"

\- For teams with per-developer repos, it does not remember which repos the
currently logged in user frequently uses, so you scroll through everone on the
team's name for most operations. (And the new version "improved" this in some
places with a JavaScript-heavy list that renders like molasses on no-gpu xeon
vms).

\- Each product (bitbucket, jira, confluence) uses a different markup
language.

And so on. I could complain about other workflows or other products, but this
is pretty typical for their stuff.

~~~
circular_logic
I would be interested to know as well. To add to your list. If you need to
scale up to huge intsances it hurts. Repo Clones take huge amount of resources
for some reason, and updates require hours of downtime to spin the cluster up
again. Aparrently there development team haven't even had a very large
instance for test until late 2016 so fixing there issues is likely to take
time.

~~~
rbbitbucket
Bitbucket product manager here.

Sorry to hear you've been having trouble. What you describe is most definitely
unusual so I'd suggest contacting us (or having your admin contact us) at
support.atlassian.com so we can look into it.

The team has spent a great deal of effort over the entire life of the product
to ensure it performs at scale for broad range of load profiles. The notion
that we only recently had a very large instance for test is untrue. Perhaps
someone got the wrong idea from our most recent series on how we build
Bitbucket Data Center to _already_ support massive scale:
[https://developer.atlassian.com/blog/2016/12/how-we-built-
bi...](https://developer.atlassian.com/blog/2016/12/how-we-built-bitbucket-
data-center-to-scale/)

------
MrBuddyCasino
Relying on the referrer header for CSRF protection is dubious at best. Just
use a token like everybody else, protect against session fixation, call it a
day.

~~~
berdario
They are using a token, just like everyone else... this is just some added
protection on top

Let's not spread FUD :)

~~~
hedora
But this isn't added protection. Here is the textbook list of security goals:

\- availability

\- integrity

\- confidentiality

It breaks availability and confidentiality to protect against an attack that
is already prevented by https.

This is like installing an open ip cam and welding my padlock shut, then
claiming you've improved my storage unit.

~~~
berdario
Have you read the discussion on security.stackexchange.com ?

there's no decrease in availability by an attacker (there's only a self
inflicted denial by the user)

there's also no decrease in confidentiality for the service itself (and if the
user uses an appropriate extension[0], or the browsers implement an
appropriate whitelist mechanism, there's no confidentiality decrease for the
user in general either)

This is simply defense in depth

If you leaked the SECRET_KEY/misconfigured the CSRF creation (which should be
impossible, but it's the whole point of adding layers) AND the victim is being
MITM AND you don't implement HSTS AND You correctly set cookies as Secure

You would have a potential vulnerability, exploitable (only?) via CSRF, which
this check prevents

[0] like [https://addons.mozilla.org/en-US/firefox/addon/smart-
referer...](https://addons.mozilla.org/en-US/firefox/addon/smart-referer/) but
I'm not advocating for the use of this extension

~~~
hedora
So redirecting all port 80 requests to [https://<domain>/](https://<domain>/)
(or otherwise kill port 80 on the server).

Then, make sure each page view overwrites / clears any side-effecting session
state.

Put another way, why should unexpected cookies change the side effects of post
requests?

Anyway, if the browser is connecting via port 80, the MITM can just use a
transparent http->https proxy to rewrite the referrer, and forward the request
to the https server, so you've already lost.

~~~
innoying
I think you're misunderstanding the attack scenario here:

> Anyway, if the browser is connecting via port 80, the MITM can just use a
> transparent http->https proxy to rewrite the referrer, and forward the
> request to the https server, so you've already lost.

That wouldn't actually work since the user's active session cookie has the
"Secure" flag set (i.e. isn't sent over HTTP). Sure if the user logged-in
again on the HTTP page you could exploit this with a transparent proxy but
there's very little outside of implementing HPKP that BitBucket could do to
prevent that attack.

~~~
berdario
Exactly

But even shutting down access to port 80 on the server wouldn't be enough: the
attacker only needs the victim to send the request, it doesn't need for the
plaintext request to actually reach the server

(did you mean HSTS instead of HPKP, btw? The scenario I described didn't
involve MITM of a HTTPS connection, and thus HPKP wouldn't be strictly needed
)

also, I agree that the condition under which this check might be useful are
quite convoluted... since Security is often in tension with Usability there is
a case to be made for less defense-in-depth, and removing (potentially?)
redundant checks... but I think we should be wary of making simplistic
arguments for it, due to how delicate web app security is

~~~
hedora
Agreed; killing port 80 just decreases the chances the browser makes
subsequent port 80 requests.

I still think the referrer is only helping paper over a deeper design flaw
(using cookies to carry post state) at the expense of getting some users to
trade privacy for availability, and decreasing performance/opening up attacks
for people that install extensions as a workaround.

------
unknownsavage
I really don't think this is a big deal. I run a medium size website with well
over 2000 uniques users per day and also require the referer header to use the
website. So far, I've yet to receive a single complaint or find a browser that
doesn't send it.

It might be optional as per the spec, but it's completely ubiquitous at this
point, and provides an easy way to add an extra layer of safety for web
developers.

------
marcosdumay
Well, you should not post from HTTP to HTTPS anyway.

I highly doubt there is any good reason to do it anywhere, and on the one case
you think you got a good reason (I still doubt it), don't try to anonymize the
hell out of a logged-on request.

~~~
ubercore
From memory when this came up, I think the concern is someone spoofing a non-
HTTPS version of your site to trick a browser into posting to the HTTPS
version? Someone that understands this stuff properly will need to chime in.

~~~
r1ch
It looks like Django relies on client-side tokens embedded in cookies for CSRF
protection, there is no server-side state that the attacker has to guess. A
MITM can trick someone to visit [http://example.com/](http://example.com/),
set their own token in a HTTP cookie for example.com, use the same token in
the POST request to [https://example.com](https://example.com) and it will
pass validation, as cookies set over HTTP are still sent to HTTPS.

Should be easy to mitigate this by using server-side CSRF state, or signing
the tokens.

~~~
berdario
I'm a bit confused... I thought that Django always signed the CSRF tokens with
the app's SECRET_KEY

But upon looking at the code, it seems that the SECRET_KEY is only used to
reseed the PRNG O_o

[https://github.com/django/django/blob/stable/1.10.x/django/u...](https://github.com/django/django/blob/stable/1.10.x/django/utils/crypto.py#L54-L77)

~~~
ubercore
Secret key is used for signing.
[https://github.com/django/django/blob/master/django/core/sig...](https://github.com/django/django/blob/master/django/core/signing.py#L156)

~~~
abeyer
Unfortunately the csrf implementation doesn't use that. (At least not in the
absence of a session store.) It "encrypts" the random token by adding a random
salt to it, but has no way of validating that after generation. When a csrf
protected request is made the token in the cookie is compared to the token in
the POST data, but not validated in any other way.

[https://github.com/django/django/blob/master/django/middlewa...](https://github.com/django/django/blob/master/django/middleware/csrf.py#L50)

I wonder how much of this is just a political issue about the core/contrib
division and the fact that csrf is in core while sessions is in contrib. It
seems to me that the "right" fix is to make csrf protection require a session
store, and move (at least) the signed cookie session support into core.

Edit: Actually it looks like cookie signing is already implemented in core, so
now I'm really unsure why csrf isn't using that already.

~~~
berdario
Yeah, weird... I guess that since sessions are enabled by default, they didn't
bother making it independent/explicitly requiring it

------
i386
How dare Bitbucket have a bug in their code while the rest of us live and
breath standards compliant perfection?

------
bsusuabw
Twitter does this. If you filter all referrers, all Ajax requests fail (even
posting something).

