Fixing email link injection bug

Several templates used a variable set by the user (the request host header).  This led to a vulnerability where an attacker could inject their domain name into these templates (i.e., activation emails).  This patch fixes this vulnerability.

LMS-532
This commit is contained in:
Julia Hansbrough
2013-12-03 19:53:48 +00:00
committed by e0d
parent 9e8a24bfc0
commit f351b05031
5 changed files with 86 additions and 1 deletions

View File

@@ -11,6 +11,8 @@ from mock import Mock, patch
from django.http import Http404, HttpResponse
from django.conf import settings
from nose.plugins.skip import SkipTest
from edxmako.shortcuts import render_to_string
from util.request import safe_get_host
class TestException(Exception):
@@ -50,6 +52,11 @@ class EmailTestMixin(object):
settings.DEFAULT_FROM_EMAIL
)
def append_allowed_hosts(self, hostname):
""" Append hostname to settings.ALLOWED_HOSTS """
settings.ALLOWED_HOSTS.append(hostname)
self.addCleanup(settings.ALLOWED_HOSTS.pop)
@patch('student.views.render_to_string', Mock(side_effect=mock_render_to_string, autospec=True))
@patch('django.contrib.auth.models.User.email_user')
@@ -83,6 +90,16 @@ class ReactivationEmailTests(EmailTestMixin, TestCase):
context
)
# Thorough tests for safe_get_host are elsewhere; here we just want a quick URL sanity check
request = RequestFactory().post('unused_url')
request.META['HTTP_HOST'] = "aGenericValidHostName"
self.append_allowed_hosts("aGenericValidHostName")
body = render_to_string('emails/activation_email.txt', context)
host = safe_get_host(request)
self.assertIn(host, body)
def test_reactivation_email_failure(self, email_user):
self.user.email_user.side_effect = Exception
response_data = self.reactivation_email(self.user)
@@ -227,6 +244,16 @@ class EmailChangeConfirmationTests(EmailTestMixin, TransactionTestCase):
context
)
# Thorough tests for safe_get_host are elsewhere; here we just want a quick URL sanity check
request = RequestFactory().post('unused_url')
request.META['HTTP_HOST'] = "aGenericValidHostName"
self.append_allowed_hosts("aGenericValidHostName")
body = render_to_string('emails/confirm_email_change.txt', context)
url = safe_get_host(request)
self.assertIn(url, body)
def test_not_pending(self, email_user):
self.key = 'not_a_key'
self.check_confirm_email_change('invalid_email_key.html', {})