From 7b8d887d33c768a77f40dd15ff5ac6ebbbab25b9 Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Sun, 5 Feb 2012 11:08:08 +0100 Subject: [PATCH] Fixed potential XSS risk in redirect page --- CHANGES | 2 ++ werkzeug/testsuite/utils.py | 9 +++++++++ werkzeug/utils.py | 4 ++-- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 130004a95..94a9055a2 100644 --- a/CHANGES +++ b/CHANGES @@ -13,6 +13,8 @@ Version 0.8.3 that the debugger can be used on GAE better. - Fixed a bug with the redis cache for int subclasses (affects bool caching). +- Fixed an XSS problem with redirect targets coming from + untrusted sources. Version 0.8.2 ------------- diff --git a/werkzeug/testsuite/utils.py b/werkzeug/testsuite/utils.py index 5ef953cf9..ccb33e840 100644 --- a/werkzeug/testsuite/utils.py +++ b/werkzeug/testsuite/utils.py @@ -40,6 +40,15 @@ def test_redirect(self): assert resp.headers['Location'] == 'http://example.com/' assert resp.status_code == 305 + def test_redirect_xss(self): + location = 'http://example.com/?xss=">' + resp = utils.redirect(location) + assert '' not in resp.data + + location = 'http://example.com/?xss="onmouseover="alert(1)' + resp = utils.redirect(location) + assert 'href="http://example.com/?xss="onmouseover="alert(1)"' not in resp.data + def test_cached_property(self): foo = [] class A(object): diff --git a/werkzeug/utils.py b/werkzeug/utils.py index 491f40890..7083f2503 100644 --- a/werkzeug/utils.py +++ b/werkzeug/utils.py @@ -353,7 +353,7 @@ def redirect(location, code=302): :param code: the redirect status code. defaults to 302. """ from werkzeug.wrappers import BaseResponse - display_location = location + display_location = escape(location) if isinstance(location, unicode): from werkzeug.urls import iri_to_uri location = iri_to_uri(location) @@ -363,7 +363,7 @@ def redirect(location, code=302): '

Redirecting...

\n' '

You should be redirected automatically to target URL: ' '%s. If not click the link.' % - (location, display_location), code, mimetype='text/html') + (escape(location, True), display_location), code, mimetype='text/html') response.headers['Location'] = location return response