Closed Bug 649354 Opened 14 years ago Closed 14 years ago

Django's anti-CSRF Referer validation can be bypassed using the X-FORWARDED-HOST header

Categories

(addons.mozilla.org Graveyard :: Developer Pages, defect)

defect
Not set
major

Tracking

(Not tracked)

VERIFIED FIXED

People

(Reporter: albinowax, Unassigned)

Details

(Keywords: reporter-external, wsec-csrf, Whiteboard: [infrasec:csrf][ws:critical])

User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.13) Gecko/20110103 Fedora/3.6.13-1.fc14 Firefox/3.6.13 Build Identifier: When Django receives a POST request it validates the Referer header against the Host. However, if the X-Forwarded-Host header is present, it validates the referer against that instead. That header can be spoofed to match the referer, so Django accepts the request. When combined with the csrf-token overriding attack outlined in https://bugzilla.mozilla.org/show_bug.cgi?id=648881 this probably exposes all AMO users with non-updated browsers to potentially account-hijacking CSRF. ( On slightly out of date browsers, using the technique outlined in http://lists.webappsec.org/pipermail/websecurity_lists.webappsec.org/2011-February/007533.html attackers can make victims spoof the X-Forwarded-Host header cross domain. ) Reproducible: Always Steps to Reproduce: 1. Browse to https://addons.mozilla.org/en-US/firefox/users/edit, click 'update' 2. Intercept the request and change the 'Referer' value to 'https://cow.org/ 3. Add a new header 'X-FORWARDED-HOST: cow.org' 4. Observe that the request succeeds ('302 found' rather than '403 forbidden') The X-Forwarded-Host trick was suggested by 'barbarianbob'. I'll try and get his email so he can see the bug. If he agrees, any bounty can be split 50/50.
Django starts the Referer checking when the request is https[1]. It compares HTTP_REFERER[2] to request.get_host()[3] which checks for (in this order) HTTP_X_FORWARDED_HOST, HTTP_HOST, or SERVER_NAME + SERVER_PORT. It returns the first one of those it finds. I haven't tried to reproduce but it looks valid from browsing the code. [1] https://github.com/django/django/blob/master/django/middleware/csrf.py#L118 [2] https://github.com/django/django/blob/master/django/middleware/csrf.py#L134 [3] https://github.com/django/django/blob/master/django/http/__init__.py#L153
Status: UNCONFIRMED → NEW
Ever confirmed: true
Why not just overwrite the Referer header from the start instead of adding the X-Forwarded-Host header?
The Referer header can't be spoofed using that technique, since it's blacklisted: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/URLRequestHeader.html If it wasn't for that blacklist, the token injection into the cookie could be done that way, too.
(In reply to comment #3) > The Referer header can't be spoofed using that technique, since it's > blacklisted: > http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/URLRequestHeader.html > > If it wasn't for that blacklist, the token injection into the cookie could be > done that way, too. Makes sense. Thanks. This issue will be addressed in its entirety by django's CSRF upgrade to include tokens within
I've confirmed this issue is valid. To summarize: Django's CSRF defense will verify the csrf token and the referrer (for HTTPS) 1. This issue requires the attacker to know (or have set) the CSRF token (e.g. bug 648881) 2. The x-forward-for issue discussed in this bug addresses the referrer checking.
The solution to this issue is to get rid of CSRF tokens in cookies (something I'm all for).
Whiteboard: [infrasec:csrf][ws:critical]
Jbalogh, Is this issue now addressed with our CSRF enhancements?
(In reply to comment #9) > Jbalogh, > > Is this issue now addressed with our CSRF enhancements? Yes, we don't care about the Referer anymore since the token is never in a cookie.
Status: NEW → RESOLVED
Closed: 14 years ago
Resolution: --- → FIXED
Status: RESOLVED → VERIFIED
Could the security sensitive flag be removed?
Keywords: wsec-csrf
Flags: sec-bounty+
Group: client-services-security
Product: addons.mozilla.org → addons.mozilla.org Graveyard
You need to log in before you can comment on or make changes to this bug.