Validate consistency between ID-based and name-based identifiers in import/reimport#14636
Validate consistency between ID-based and name-based identifiers in import/reimport#14636Maffooch merged 5 commits intoDefectDojo:bugfixfrom
Conversation
Validate that ID-resolved objects (test, engagement) are consistent with name-based identifiers (product_name, engagement_name) in both the permission check layer and the AutoCreateContextManager resolution layer. This prevents an attacker from passing their own engagement/test ID to satisfy the permission check while using name-based fields to target a victim's product. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
8ecbd1f to
985e0b8
Compare
- Switch permission checks to use ID comparisons (product_id, engagement_id) where resolved objects are available, with name fallback for unresolved cases - Add engagement_name validation to UserHasImportPermission (was missing) - Fix ruff string quoting in auto_create_context.py Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The engagement field is not declared on ReImportScanSerializer and gets stripped during validation. The permission check must also strip it so it resolves targets the same way execution does — by name, not by a stale engagement ID from request.data. Update test to verify the engagement param is ignored and permission is checked against the name-resolved target. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace error messages that leaked resolved object names (product names, engagement names) with generic messages. An attacker could enumerate object names by sending conflicting ID-based and name-based identifiers and reading the detailed error responses. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
This pull request introduces validation checks that compare user-supplied identifiers (e.g., test/engagement/product IDs or names) against resolved database objects before authorization checks, which can leak information via distinct ValidationError responses and enable enumeration of valid resource IDs and relationships (engagement→product) even to unauthorized users. The behavior reveals object existence and associations by returning 400 errors for mismatches instead of 403 permission errors, posing a low-severity information disclosure risk.
Resource Enumeration via Validation Error in
|
| Vulnerability | Resource Enumeration via Validation Error |
|---|---|
| Description | The code introduces explicit validation checks that compare user-provided identifiers (e.g., product/engagement names or IDs) against resolved database objects before performing an authorization check (user_has_permission). By submitting various combinations of identifiers (both valid and invalid/mismatched), an unauthorized user can receive distinct ValidationError messages or observe different response behaviors based on whether the resolved test object exists and its relationships to the provided parameters. This allows for the systematic enumeration of valid test IDs, their associated engagements, and parent products, as well as the inference of their specific names via error messages. |
django-DefectDojo/dojo/api_v2/permissions.py
Lines 792 to 794 in 70c2c19
Resource Enumeration via Validation Error in dojo/api_v2/permissions.py (drs_86777e02)
| Vulnerability | Resource Enumeration via Validation Error |
|---|---|
| Description | The validation check happens after the objects (engagement and product) have already been fetched from the database, likely using system-level privileges or public read access. By comparing whether an engagement belongs to a product and raising a ValidationError (400 Bad Request) when they do not match, the application reveals whether a specific engagement belongs to a specific product. This is distinguishable from a PermissionDenied (403 Forbidden) error, which would be returned if the user lacks access to the object. An attacker can use this difference to enumerate existing relationships between resources even if they lack direct read access to those resources. |
django-DefectDojo/dojo/api_v2/permissions.py
Lines 477 to 479 in 70c2c19
Comment to provide feedback on these findings.
Report false positive: @dryrunsecurity fp [FINDING ID] [FEEDBACK]
Report low-impact: @dryrunsecurity nit [FINDING ID] [FEEDBACK]
Example: @dryrunsecurity fp drs_90eda195 This code is not user-facing
All finding details can be found in the DryRun Security Dashboard.
identifiers (e.g. test, engagement) and name-based identifiers (e.g. product_name, engagement_name) are
provided, they refer to the same objects
target lookup layer