Fixed #19866 -- Added security logger and return 400 for SuspiciousOperation.

SuspiciousOperations have been differentiated into subclasses, and
are now logged to a 'django.security.*' logger. SuspiciousOperations
that reach django.core.handlers.base.BaseHandler will now return a 400
instead of a 500.

Thanks to tiwoc for the report, and Carl Meyer and Donald Stufft
for review.
This commit is contained in:
Preston Holmes 2013-05-15 16:14:28 -07:00
parent 36d47f72e3
commit d228c1192e
38 changed files with 363 additions and 77 deletions

View file

@ -44,9 +44,24 @@ SuspiciousOperation
-------------------
.. exception:: SuspiciousOperation
The :exc:`SuspiciousOperation` exception is raised when a user has performed
an operation that should be considered suspicious from a security perspective,
such as tampering with a session cookie.
The :exc:`SuspiciousOperation` exception is raised when a user has
performed an operation that should be considered suspicious from a security
perspective, such as tampering with a session cookie. Subclasses of
SuspiciousOperation include:
* DisallowedHost
* DisallowedModelAdminLookup
* DisallowedRedirect
* InvalidSessionKey
* SuspiciousFileOperation
* SuspiciousMultipartForm
* SuspiciousSession
* WizardViewCookieModified
If a ``SuspiciousOperation`` exception reaches the WSGI handler level it is
logged at the ``Error`` level and results in
a :class:`~django.http.HttpResponseBadRequest`. See the :doc:`logging
documentation </topics/logging/>` for more information.
PermissionDenied
----------------

View file

@ -270,6 +270,13 @@ Minor features
stores active language in session if it is not present there. This
prevents loss of language settings after session flush, e.g. logout.
* :exc:`~django.core.exceptions.SuspiciousOperation` has been differentiated
into a number of subclasses, and each will log to a matching named logger
under the ``django.security`` logging hierarchy. Along with this change,
a ``handler400`` mechanism and default view are used whenever
a ``SuspiciousOperation`` reaches the WSGI handler to return an
``HttpResponseBadRequest``.
Backwards incompatible changes in 1.6
=====================================

View file

@ -231,3 +231,25 @@ same way you can for the 404 and 500 views by specifying a ``handler403`` in
your URLconf::
handler403 = 'mysite.views.my_custom_permission_denied_view'
.. _http_bad_request_view:
The 400 (bad request) view
--------------------------
When a :exc:`~django.core.exceptions.SuspiciousOperation` is raised in Django,
the it may be handled by a component of Django (for example resetting the
session data). If not specifically handled, Django will consider the current
request a 'bad request' instead of a server error.
The view ``django.views.defaults.bad_request``, is otherwise very similar to
the ``server_error`` view, but returns with the status code 400 indicating that
the error condition was the result of a client operation.
Like the ``server_error`` view, the default ``bad_request`` should suffice for
99% of Web applications, but if you want to override the view, you can specify
``handler400`` in your URLconf, like so::
handler400 = 'mysite.views.my_custom_bad_request_view'
``bad_request`` views are also only used when :setting:`DEBUG` is ``False``.

View file

@ -394,7 +394,7 @@ requirements of logging in Web server environment.
Loggers
-------
Django provides three built-in loggers.
Django provides four built-in loggers.
``django``
~~~~~~~~~~
@ -434,6 +434,35 @@ For performance reasons, SQL logging is only enabled when
``settings.DEBUG`` is set to ``True``, regardless of the logging
level or handlers that are installed.
``django.security.*``
~~~~~~~~~~~~~~~~~~~~~~
The security loggers will receive messages on any occurrence of
:exc:`~django.core.exceptions.SuspiciousOperation`. There is a sub-logger for
each sub-type of SuspiciousOperation. The level of the log event depends on
where the exception is handled. Most occurrences are logged as a warning, while
any ``SuspiciousOperation`` that reaches the WSGI handler will be logged as an
error. For example, when an HTTP ``Host`` header is included in a request from
a client that does not match :setting:`ALLOWED_HOSTS`, Django will return a 400
response, and an error message will be logged to the
``django.security.DisallowedHost`` logger.
Only the parent ``django.security`` logger is configured by default, and all
child loggers will propagate to the parent logger. The ``django.security``
logger is configured the same as the ``django.request`` logger, and any error
events will be mailed to admins. Requests resulting in a 400 response due to
a ``SuspiciousOperation`` will not be logged to the ``django.request`` logger,
but only to the ``django.security`` logger.
To silence a particular type of SuspiciousOperation, you can override that
specific logger following this example::
'loggers': {
'django.security.DisallowedHost': {
'handlers': ['null'],
'propagate': False,
},
Handlers
--------