Files
strix/strix/prompts/vulnerabilities/mass_assignment.jinja

142 lines
7.0 KiB
Django/Jinja
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<mass_assignment_guide>
<title>MASS ASSIGNMENT</title>
<critical>Mass assignment binds client-supplied fields directly into models/DTOs without field-level allowlists. It commonly leads to privilege escalation, ownership changes, and unauthorized state transitions in modern APIs and GraphQL.</critical>
<scope>
- REST/JSON, GraphQL inputs, form-encoded and multipart bodies
- Model binding in controllers/resolvers; ORM create/update helpers
- Writable nested relations, sparse/patch updates, bulk endpoints
</scope>
<methodology>
1. Identify create/update endpoints and GraphQL mutations. Capture full server responses to observe returned fields.
2. Build a candidate list of sensitive attributes per resource: role/isAdmin/permissions, ownerId/accountId/tenantId, status/state, plan/price, limits/quotas, feature flags, verification flags, balance/credits.
3. Inject candidates alongside legitimate updates across transports and encodings; compare before/after state and diffs across roles.
4. Repeat with nested objects, arrays, and alternative shapes (dot/bracket notation, duplicate keys) and in batch operations.
</methodology>
<discovery_techniques>
<surface_map>
- Controllers with automatic binding (e.g., request.json → model); GraphQL input types mirroring models; admin/staff tools exposed via API
- OpenAPI/GraphQL schemas: uncover hidden fields or enums; SDKs often reveal writable fields
- Client bundles and mobile apps: inspect forms and mutation payloads for field names
</surface_map>
<parameter_strategies>
- Flat fields: isAdmin, role, roles[], permissions[], status, plan, tier, premium, verified, emailVerified
- Ownership/tenancy: userId, ownerId, accountId, organizationId, tenantId, workspaceId
- Limits/quotas: usageLimit, seatCount, maxProjects, creditBalance
- Feature flags/gates: features, flags, betaAccess, allowImpersonation
- Billing: price, amount, currency, prorate, nextInvoice, trialEnd
</parameter_strategies>
<shape_variants>
- Alternate shapes: arrays vs scalars; nested JSON; objects under unexpected keys
- Dot/bracket paths: profile.role, profile[role], settings[roles][]
- Duplicate keys and precedence: {"role":"user","role":"admin"}
- Sparse/patch formats: JSON Patch/JSON Merge Patch; try adding forbidden paths or replacing protected fields
</shape_variants>
<encodings_and_channels>
- Content-types: application/json, application/x-www-form-urlencoded, multipart/form-data, text/plain (JSON via server coercion)
- GraphQL: add suspicious fields to input objects; overfetch response to detect changes
- Batch/bulk: arrays of objects; verify per-item allowlists not skipped
</encodings_and_channels>
<exploitation_techniques>
<privilege_escalation>
- Set role/isAdmin/permissions during signup/profile update; toggle admin/staff flags where exposed
</privilege_escalation>
<ownership_takeover>
- Change ownerId/accountId/tenantId to seize resources; move objects across users/tenants
</ownership_takeover>
<feature_gate_bypass>
- Enable premium/beta/feature flags via flags/features fields; raise limits/seatCount/quotas
</feature_gate_bypass>
<billing_and_entitlements>
- Modify plan/price/prorate/trialEnd or creditBalance; bypass server recomputation
</billing_and_entitlements>
<nested_and_relation_writes>
- Writable nested serializers or ORM relations allow creating or linking related objects beyond callers scope (e.g., attach to another users org)
</nested_and_relation_writes>
<advanced_techniques>
<graphQL_specific>
- Field-level authz missing on input types: attempt forbidden fields in mutation inputs; combine with aliasing/batching to compare effects
- Use fragments to overfetch changed fields immediately after mutation
</graphQL_specific>
<orm_framework_edges>
- Rails: strong parameters misconfig or deep nesting via accepts_nested_attributes_for
- Laravel: $fillable/$guarded misuses; guarded=[] opens all; casts mutating hidden fields
- Django REST Framework: writable nested serializer, read_only/extra_kwargs gaps, partial updates
- Mongoose/Prisma: schema paths not filtered; select:false doesnt prevent writes; upsert defaults
</orm_framework_edges>
<parser_and_validator_gaps>
- Validators run post-bind and do not cover extra fields; unknown fields silently dropped in response but persisted underneath
- Inconsistent allowlists between mobile/web/gateway; alt encodings bypass validation pipeline
</parser_and_validator_gaps>
<bypass_techniques>
<content_type_switching>
- Switch JSON ↔ form-encoded ↔ multipart ↔ text/plain; some code paths only validate one
</content_type_switching>
<key_path_variants>
- Dot/bracket/object re-shaping to reach nested fields through different binders
</key_path_variants>
<batch_paths>
- Per-item checks skipped in bulk operations; insert a single malicious object within a large batch
</batch_paths>
<race_and_reorder>
- Race two updates: first sets forbidden field, second normalizes; final state may retain forbidden change
</race_and_reorder>
<validation>
1. Show a minimal request where adding a sensitive field changes persisted state for a non-privileged caller.
2. Provide before/after evidence (response body, subsequent GET, or GraphQL query) proving the forbidden attribute value.
3. Demonstrate consistency across at least two encodings or channels.
4. For nested/bulk, show that protected fields are written within child objects or array elements.
5. Quantify impact (e.g., role flip, cross-tenant move, quota increase) and reproducibility.
</validation>
<false_positives>
- Server recomputes derived fields (plan/price/role) ignoring client input
- Fields marked read-only and enforced consistently across encodings
- Only UI-side changes with no persisted effect
</false_positives>
<impact>
- Privilege escalation and admin feature access
- Cross-tenant or cross-account resource takeover
- Financial/billing manipulation and quota abuse
- Policy/approval bypass by toggling verification or status flags
</impact>
<pro_tips>
1. Build a sensitive-field dictionary per resource and fuzz systematically.
2. Always try alternate shapes and encodings; many validators are shape/CT-specific.
3. For GraphQL, diff the resource immediately after mutation; effects are often visible even if the mutation returns filtered fields.
4. Inspect SDKs/mobile apps for hidden field names and nested write examples.
5. Prefer minimal PoCs that prove durable state changes; avoid UI-only effects.
</pro_tips>
<mitigations>
- Enforce server-side allowlists per operation and role; deny unknown fields by default
- Separate input DTOs from domain models; map explicitly
- Recompute derived fields (role/plan/owner) from trusted context; ignore client values
- Lock nested writes to owned resources; validate foreign keys against caller scope
- For GraphQL, use input types that expose only permitted fields and enforce resolver-level checks
</mitigations>
<remember>Mass assignment is eliminated by explicit mapping and per-field authorization. Treat every client-supplied attribute—especially nested or batch inputs—as untrusted until validated against an allowlist and caller scope.</remember>
</mass_assignment_guide>