mirror of
https://github.com/ansible/awx.git
synced 2026-04-06 18:49:21 -02:30
block users from making looping filters which can DoS Tower
This commit is contained in:
@@ -92,6 +92,9 @@ class FieldLookupBackend(BaseFilterBackend):
|
|||||||
# sure user cannot query using objects he could not view.
|
# sure user cannot query using objects he could not view.
|
||||||
new_parts = []
|
new_parts = []
|
||||||
|
|
||||||
|
# Store of all the fields used to detect repeats
|
||||||
|
field_set = set([])
|
||||||
|
|
||||||
for name in parts[:-1]:
|
for name in parts[:-1]:
|
||||||
# HACK: Make project and inventory source filtering by old field names work for backwards compatibility.
|
# HACK: Make project and inventory source filtering by old field names work for backwards compatibility.
|
||||||
if model._meta.object_name in ('Project', 'InventorySource'):
|
if model._meta.object_name in ('Project', 'InventorySource'):
|
||||||
@@ -124,6 +127,10 @@ class FieldLookupBackend(BaseFilterBackend):
|
|||||||
raise PermissionDenied(_('Filtering on %s is not allowed.' % name))
|
raise PermissionDenied(_('Filtering on %s is not allowed.' % name))
|
||||||
elif getattr(field, '__prevent_search__', False):
|
elif getattr(field, '__prevent_search__', False):
|
||||||
raise PermissionDenied(_('Filtering on %s is not allowed.' % name))
|
raise PermissionDenied(_('Filtering on %s is not allowed.' % name))
|
||||||
|
if field in field_set:
|
||||||
|
# Field traversed twice, could create infinite JOINs, DoSing Tower
|
||||||
|
raise ParseError(_('Loops not allowed in filters, detected on field {}.').format(field.name))
|
||||||
|
field_set.add(field)
|
||||||
model = getattr(field, 'related_model', None) or field.model
|
model = getattr(field, 'related_model', None) or field.model
|
||||||
|
|
||||||
if parts:
|
if parts:
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from rest_framework.exceptions import PermissionDenied
|
from rest_framework.exceptions import PermissionDenied, ParseError
|
||||||
from awx.api.filters import FieldLookupBackend
|
from awx.api.filters import FieldLookupBackend
|
||||||
from awx.main.models import (AdHocCommand, AuthToken, CustomInventoryScript,
|
from awx.main.models import (AdHocCommand, AuthToken, CustomInventoryScript,
|
||||||
Credential, Job, JobTemplate, SystemJob,
|
Credential, Job, JobTemplate, SystemJob,
|
||||||
@@ -77,3 +77,10 @@ def test_filter_sensitive_fields_and_relations(model, query):
|
|||||||
with pytest.raises(PermissionDenied) as excinfo:
|
with pytest.raises(PermissionDenied) as excinfo:
|
||||||
field, new_lookup = field_lookup.get_field_from_lookup(model, query)
|
field, new_lookup = field_lookup.get_field_from_lookup(model, query)
|
||||||
assert 'not allowed' in str(excinfo.value)
|
assert 'not allowed' in str(excinfo.value)
|
||||||
|
|
||||||
|
|
||||||
|
def test_looping_filters_prohibited():
|
||||||
|
field_lookup = FieldLookupBackend()
|
||||||
|
with pytest.raises(ParseError) as loop_exc:
|
||||||
|
field_lookup.get_field_from_lookup(Job, 'job_events__job__job_events')
|
||||||
|
assert 'job_events' in str(loop_exc.value)
|
||||||
|
|||||||
Reference in New Issue
Block a user