Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions dojo/api_v2/permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,23 @@ class UserHasFindingNotePermission(BaseRelatedObjectPermission):
}


class UserHasBurpRawRequestResponsePermission(permissions.BasePermission):
def has_permission(self, request, view):
return check_post_permission(
request, Finding, "finding", Permissions.Finding_Edit,
)

def has_object_permission(self, request, view, obj):
return check_object_permission(
request,
obj.finding,
Permissions.Finding_View,
Permissions.Finding_Edit,
Permissions.Finding_Edit,
Permissions.Finding_Edit,
)


class UserHasImportPermission(permissions.BasePermission):
def has_permission(self, request, view):
# permission check takes place before validation, so we don't have access to serializer.validated_data()
Expand Down
2 changes: 1 addition & 1 deletion dojo/api_v2/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3011,7 +3011,7 @@ class BurpRawRequestResponseViewSet(
filterset_fields = ["finding"]
permission_classes = (
IsAuthenticated,
permissions.UserHasFindingRelatedObjectPermission,
permissions.UserHasBurpRawRequestResponsePermission,
)

def get_queryset(self):
Expand Down
61 changes: 61 additions & 0 deletions unittests/test_rest_framework.py
Original file line number Diff line number Diff line change
Expand Up @@ -1788,6 +1788,67 @@ def test_request_response_get(self):
self.assertEqual(200, response.status_code, response.content[:1000])


@versioned_fixtures
class RequestResponsePairsAuthzTest(DojoAPITestCase):

fixtures = ["dojo_testdata.json"]

def _client_for(self, username):
user = User.objects.get(username=username)
token = Token.objects.get(user=user)
client = APIClient()
client.credentials(HTTP_AUTHORIZATION="Token " + token.key)
return client

def test_admin_can_create_request_response_pair_positive_control(self):
client = self._client_for("admin")
before = BurpRawRequestResponse.objects.filter(finding_id=7).count()
response = client.post(
"/api/v2/request_response_pairs/",
dumps({
"finding": 7,
"burpRequestBase64": "cmVxdWVzdAo=",
"burpResponseBase64": "cmVzcG9uc2UK",
}),
content_type="application/json",
)
self.assertEqual(response.status_code, 201, response.content[:1000])
self.assertEqual(BurpRawRequestResponse.objects.filter(finding_id=7).count(), before + 1)

def test_unrelated_user_cannot_create_request_response_pair_on_hidden_finding(self):
client = self._client_for("user2")
# Sanity: the victim finding is genuinely hidden from this user.
get_response = client.get("/api/v2/findings/7/")
self.assertEqual(get_response.status_code, 404)

before = BurpRawRequestResponse.objects.filter(finding_id=7).count()
response = client.post(
"/api/v2/request_response_pairs/",
dumps({
"finding": 7,
"burpRequestBase64": "cmVxdWVzdAo=",
"burpResponseBase64": "cmVzcG9uc2UK",
}),
content_type="application/json",
)
self.assertIn(response.status_code, (403, 404), response.content[:1000])
self.assertEqual(BurpRawRequestResponse.objects.filter(finding_id=7).count(), before)

def test_post_without_finding_returns_4xx(self):
client = self._client_for("user2")
response = client.post(
"/api/v2/request_response_pairs/",
dumps({
"burpRequestBase64": "cmVxdWVzdAo=",
"burpResponseBase64": "cmVzcG9uc2UK",
}),
content_type="application/json",
)
# check_post_permission raises ParseError (400) when "finding" is omitted.
self.assertGreaterEqual(response.status_code, 400)
self.assertLess(response.status_code, 500)


@versioned_fixtures
class FilesTest(DojoAPITestCase):
fixtures = ["dojo_testdata.json"]
Expand Down
Loading