mirror of
				https://github.com/django/django.git
				synced 2025-10-28 08:06:09 +00:00 
			
		
		
		
	[3.2.x] Fixed #32713, Fixed CVE-2021-32052 -- Prevented newlines and tabs from being accepted in URLValidator on Python 3.9.5+.
In Python 3.9.5+ urllib.parse() automatically removes ASCII newlines and tabs from URLs [1, 2]. Unfortunately it created an issue in the URLValidator. URLValidator uses urllib.urlsplit() and urllib.urlunsplit() for creating a URL variant with Punycode which no longer contains newlines and tabs in Python 3.9.5+. As a consequence, the regular expression matched the URL (without unsafe characters) and the source value (with unsafe characters) was considered valid. [1] https://bugs.python.org/issue43882 and [2]76cd81d603Backport ofe1e81aa1c4from main.
This commit is contained in:
		| @@ -92,6 +92,7 @@ class URLValidator(RegexValidator): | |||||||
|         r'\Z', re.IGNORECASE) |         r'\Z', re.IGNORECASE) | ||||||
|     message = _('Enter a valid URL.') |     message = _('Enter a valid URL.') | ||||||
|     schemes = ['http', 'https', 'ftp', 'ftps'] |     schemes = ['http', 'https', 'ftp', 'ftps'] | ||||||
|  |     unsafe_chars = frozenset('\t\r\n') | ||||||
|  |  | ||||||
|     def __init__(self, schemes=None, **kwargs): |     def __init__(self, schemes=None, **kwargs): | ||||||
|         super().__init__(**kwargs) |         super().__init__(**kwargs) | ||||||
| @@ -101,6 +102,8 @@ class URLValidator(RegexValidator): | |||||||
|     def __call__(self, value): |     def __call__(self, value): | ||||||
|         if not isinstance(value, str): |         if not isinstance(value, str): | ||||||
|             raise ValidationError(self.message, code=self.code, params={'value': value}) |             raise ValidationError(self.message, code=self.code, params={'value': value}) | ||||||
|  |         if self.unsafe_chars.intersection(value): | ||||||
|  |             raise ValidationError(self.message, code=self.code, params={'value': value}) | ||||||
|         # Check if the scheme is valid. |         # Check if the scheme is valid. | ||||||
|         scheme = value.split('://')[0].lower() |         scheme = value.split('://')[0].lower() | ||||||
|         if scheme not in self.schemes: |         if scheme not in self.schemes: | ||||||
|   | |||||||
							
								
								
									
										22
									
								
								docs/releases/2.2.22.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								docs/releases/2.2.22.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | |||||||
|  | =========================== | ||||||
|  | Django 2.2.22 release notes | ||||||
|  | =========================== | ||||||
|  |  | ||||||
|  | *May 6, 2021* | ||||||
|  |  | ||||||
|  | Django 2.2.22 fixes a security issue in 2.2.21. | ||||||
|  |  | ||||||
|  | CVE-2021-32052: Header injection possibility since ``URLValidator`` accepted newlines in input on Python 3.9.5+ | ||||||
|  | =============================================================================================================== | ||||||
|  |  | ||||||
|  | On Python 3.9.5+, :class:`~django.core.validators.URLValidator` didn't prohibit | ||||||
|  | newlines and tabs. If you used values with newlines in HTTP response, you could | ||||||
|  | suffer from header injection attacks. Django itself wasn't vulnerable because | ||||||
|  | :class:`~django.http.HttpResponse` prohibits newlines in HTTP headers. | ||||||
|  |  | ||||||
|  | Moreover, the ``URLField`` form field which uses ``URLValidator`` silently | ||||||
|  | removes newlines and tabs on Python 3.9.5+, so the possibility of newlines | ||||||
|  | entering your data only existed if you are using this validator outside of the | ||||||
|  | form fields. | ||||||
|  |  | ||||||
|  | This issue was introduced by the :bpo:`43882` fix. | ||||||
							
								
								
									
										22
									
								
								docs/releases/3.1.10.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								docs/releases/3.1.10.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | |||||||
|  | =========================== | ||||||
|  | Django 3.1.10 release notes | ||||||
|  | =========================== | ||||||
|  |  | ||||||
|  | *May 6, 2021* | ||||||
|  |  | ||||||
|  | Django 3.1.10 fixes a security issue in 3.1.9. | ||||||
|  |  | ||||||
|  | CVE-2021-32052: Header injection possibility since ``URLValidator`` accepted newlines in input on Python 3.9.5+ | ||||||
|  | =============================================================================================================== | ||||||
|  |  | ||||||
|  | On Python 3.9.5+, :class:`~django.core.validators.URLValidator` didn't prohibit | ||||||
|  | newlines and tabs. If you used values with newlines in HTTP response, you could | ||||||
|  | suffer from header injection attacks. Django itself wasn't vulnerable because | ||||||
|  | :class:`~django.http.HttpResponse` prohibits newlines in HTTP headers. | ||||||
|  |  | ||||||
|  | Moreover, the ``URLField`` form field which uses ``URLValidator`` silently | ||||||
|  | removes newlines and tabs on Python 3.9.5+, so the possibility of newlines | ||||||
|  | entering your data only existed if you are using this validator outside of the | ||||||
|  | form fields. | ||||||
|  |  | ||||||
|  | This issue was introduced by the :bpo:`43882` fix. | ||||||
| @@ -2,9 +2,24 @@ | |||||||
| Django 3.2.2 release notes | Django 3.2.2 release notes | ||||||
| ========================== | ========================== | ||||||
|  |  | ||||||
| *Expected June 1, 2021* | *May 6, 2021* | ||||||
|  |  | ||||||
| Django 3.2.2 fixes several bugs in 3.2.1. | Django 3.2.2 fixes a security issue and a bug in 3.2.1. | ||||||
|  |  | ||||||
|  | CVE-2021-32052: Header injection possibility since ``URLValidator`` accepted newlines in input on Python 3.9.5+ | ||||||
|  | =============================================================================================================== | ||||||
|  |  | ||||||
|  | On Python 3.9.5+, :class:`~django.core.validators.URLValidator` didn't prohibit | ||||||
|  | newlines and tabs. If you used values with newlines in HTTP response, you could | ||||||
|  | suffer from header injection attacks. Django itself wasn't vulnerable because | ||||||
|  | :class:`~django.http.HttpResponse` prohibits newlines in HTTP headers. | ||||||
|  |  | ||||||
|  | Moreover, the ``URLField`` form field which uses ``URLValidator`` silently | ||||||
|  | removes newlines and tabs on Python 3.9.5+, so the possibility of newlines | ||||||
|  | entering your data only existed if you are using this validator outside of the | ||||||
|  | form fields. | ||||||
|  |  | ||||||
|  | This issue was introduced by the :bpo:`43882` fix. | ||||||
|  |  | ||||||
| Bugfixes | Bugfixes | ||||||
| ======== | ======== | ||||||
|   | |||||||
| @@ -34,6 +34,7 @@ versions of the documentation contain the release notes for any later releases. | |||||||
| .. toctree:: | .. toctree:: | ||||||
|    :maxdepth: 1 |    :maxdepth: 1 | ||||||
|  |  | ||||||
|  |    3.1.10 | ||||||
|    3.1.9 |    3.1.9 | ||||||
|    3.1.8 |    3.1.8 | ||||||
|    3.1.7 |    3.1.7 | ||||||
| @@ -71,6 +72,7 @@ versions of the documentation contain the release notes for any later releases. | |||||||
| .. toctree:: | .. toctree:: | ||||||
|    :maxdepth: 1 |    :maxdepth: 1 | ||||||
|  |  | ||||||
|  |    2.2.22 | ||||||
|    2.2.21 |    2.2.21 | ||||||
|    2.2.20 |    2.2.20 | ||||||
|    2.2.19 |    2.2.19 | ||||||
|   | |||||||
| @@ -226,9 +226,15 @@ TEST_DATA = [ | |||||||
|     (URLValidator(), None, ValidationError), |     (URLValidator(), None, ValidationError), | ||||||
|     (URLValidator(), 56, ValidationError), |     (URLValidator(), 56, ValidationError), | ||||||
|     (URLValidator(), 'no_scheme', ValidationError), |     (URLValidator(), 'no_scheme', ValidationError), | ||||||
|     # Trailing newlines not accepted |     # Newlines and tabs are not accepted. | ||||||
|     (URLValidator(), 'http://www.djangoproject.com/\n', ValidationError), |     (URLValidator(), 'http://www.djangoproject.com/\n', ValidationError), | ||||||
|     (URLValidator(), 'http://[::ffff:192.9.5.5]\n', ValidationError), |     (URLValidator(), 'http://[::ffff:192.9.5.5]\n', ValidationError), | ||||||
|  |     (URLValidator(), 'http://www.djangoproject.com/\r', ValidationError), | ||||||
|  |     (URLValidator(), 'http://[::ffff:192.9.5.5]\r', ValidationError), | ||||||
|  |     (URLValidator(), 'http://www.django\rproject.com/', ValidationError), | ||||||
|  |     (URLValidator(), 'http://[::\rffff:192.9.5.5]', ValidationError), | ||||||
|  |     (URLValidator(), 'http://\twww.djangoproject.com/', ValidationError), | ||||||
|  |     (URLValidator(), 'http://\t[::ffff:192.9.5.5]', ValidationError), | ||||||
|     # Trailing junk does not take forever to reject |     # Trailing junk does not take forever to reject | ||||||
|     (URLValidator(), 'http://www.asdasdasdasdsadfm.com.br ', ValidationError), |     (URLValidator(), 'http://www.asdasdasdasdsadfm.com.br ', ValidationError), | ||||||
|     (URLValidator(), 'http://www.asdasdasdasdsadfm.com.br z', ValidationError), |     (URLValidator(), 'http://www.asdasdasdasdsadfm.com.br z', ValidationError), | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user