From da7910d4834726eca596af0a830762fa5fb2dfd9 Mon Sep 17 00:00:00 2001 From: Marti Raudsepp Date: Mon, 24 Oct 2016 15:22:00 -0400 Subject: [PATCH] Fixed CVE-2016-9013 -- Generated a random database user password when running tests on Oracle. This is a security fix. --- django/db/backends/oracle/creation.py | 16 ++++++++++++---- docs/ref/settings.txt | 7 ++++++- docs/releases/1.10.3.txt | 14 ++++++++++++++ docs/releases/1.8.16.txt | 14 ++++++++++++++ docs/releases/1.9.11.txt | 14 ++++++++++++++ 5 files changed, 60 insertions(+), 5 deletions(-) diff --git a/django/db/backends/oracle/creation.py b/django/db/backends/oracle/creation.py index 01b4056b4b..18653c39aa 100644 --- a/django/db/backends/oracle/creation.py +++ b/django/db/backends/oracle/creation.py @@ -4,11 +4,11 @@ import time from django.conf import settings from django.db.backends.base.creation import BaseDatabaseCreation from django.db.utils import DatabaseError +from django.utils.crypto import get_random_string from django.utils.functional import cached_property from django.utils.six.moves import input TEST_DATABASE_PREFIX = 'test_' -PASSWORD = 'Im_a_lumberjack' class DatabaseCreation(BaseDatabaseCreation): @@ -223,7 +223,11 @@ class DatabaseCreation(BaseDatabaseCreation): ] # Ignore "user already exists" error when keepdb is on acceptable_ora_err = 'ORA-01920' if keepdb else None - self._execute_allow_fail_statements(cursor, statements, parameters, verbosity, acceptable_ora_err) + success = self._execute_allow_fail_statements(cursor, statements, parameters, verbosity, acceptable_ora_err) + # If the password was randomly generated, change the user accordingly. + if not success and self._test_settings_get('PASSWORD') is None: + set_password = "ALTER USER %(user)s IDENTIFIED BY %(password)s" + self._execute_statements(cursor, [set_password], parameters, verbosity) # Most test-suites can be run without the create-view privilege. But some need it. extra = "GRANT CREATE VIEW TO %(user)s" success = self._execute_allow_fail_statements(cursor, [extra], parameters, verbosity, 'ORA-01031') @@ -298,7 +302,7 @@ class DatabaseCreation(BaseDatabaseCreation): """ settings_dict = self.connection.settings_dict val = settings_dict['TEST'].get(key, default) - if val is None: + if val is None and prefixed: val = TEST_DATABASE_PREFIX + settings_dict[prefixed] return val @@ -315,7 +319,11 @@ class DatabaseCreation(BaseDatabaseCreation): return self._test_settings_get('USER', prefixed='USER') def _test_database_passwd(self): - return self._test_settings_get('PASSWORD', default=PASSWORD) + password = self._test_settings_get('PASSWORD') + if password is None and self._test_user_create(): + # Oracle passwords are limited to 30 chars and can't contain symbols. + password = get_random_string(length=30) + return password def _test_database_tblspace(self): return self._test_settings_get('TBLSPACE', prefixed='USER') diff --git a/docs/ref/settings.txt b/docs/ref/settings.txt index a5d8205ba4..494988cc62 100644 --- a/docs/ref/settings.txt +++ b/docs/ref/settings.txt @@ -794,7 +794,12 @@ Default: ``None`` This is an Oracle-specific setting. The password to use when connecting to the Oracle database that will be used -when running tests. If not provided, Django will use a hardcoded default value. +when running tests. If not provided, Django will generate a random password. + +.. versionchanged:: 1.11 + + Older versions used a hardcoded default password. This was also changed + in 1.10.3, 1.9.11, and 1.8.16 to fix possible security implications. .. setting:: TEST_TBLSPACE diff --git a/docs/releases/1.10.3.txt b/docs/releases/1.10.3.txt index 0d0507d41e..953544d55b 100644 --- a/docs/releases/1.10.3.txt +++ b/docs/releases/1.10.3.txt @@ -6,6 +6,20 @@ Django 1.10.3 release notes Django 1.10.3 fixes two security issues and several bugs in 1.10.2. +User with hardcoded password created when running tests on Oracle +================================================================= + +When running tests with an Oracle database, Django creates a temporary database +user. In older versions, if a password isn't manually specified in the database +settings ``TEST`` dictionary, a hardcoded password is used. This could allow +an attacker with network access to the database server to connect. + +This user is usually dropped after the test suite completes, but not when using +the ``manage.py test --keepdb`` option or if the user has an active session +(such as an attacker's connection). + +A randomly generated password is now used for each test run. + Bugfixes ======== diff --git a/docs/releases/1.8.16.txt b/docs/releases/1.8.16.txt index b650340330..aa5d9cccea 100644 --- a/docs/releases/1.8.16.txt +++ b/docs/releases/1.8.16.txt @@ -5,3 +5,17 @@ Django 1.8.16 release notes *November 1, 2016* Django 1.8.16 fixes two security issues in 1.8.15. + +User with hardcoded password created when running tests on Oracle +================================================================= + +When running tests with an Oracle database, Django creates a temporary database +user. In older versions, if a password isn't manually specified in the database +settings ``TEST`` dictionary, a hardcoded password is used. This could allow +an attacker with network access to the database server to connect. + +This user is usually dropped after the test suite completes, but not when using +the ``manage.py test --keepdb`` option or if the user has an active session +(such as an attacker's connection). + +A randomly generated password is now used for each test run. diff --git a/docs/releases/1.9.11.txt b/docs/releases/1.9.11.txt index 664a52d1a2..3c29187e86 100644 --- a/docs/releases/1.9.11.txt +++ b/docs/releases/1.9.11.txt @@ -5,3 +5,17 @@ Django 1.9.11 release notes *November 1, 2016* Django 1.9.11 fixes two security issues in 1.9.10. + +User with hardcoded password created when running tests on Oracle +================================================================= + +When running tests with an Oracle database, Django creates a temporary database +user. In older versions, if a password isn't manually specified in the database +settings ``TEST`` dictionary, a hardcoded password is used. This could allow +an attacker with network access to the database server to connect. + +This user is usually dropped after the test suite completes, but not when using +the ``manage.py test --keepdb`` option or if the user has an active session +(such as an attacker's connection). + +A randomly generated password is now used for each test run.