From 8c61042dfe3bb51eb74dbb1fac27cb87fd9af85d Mon Sep 17 00:00:00 2001 From: HackTricks News Bot Date: Thu, 23 Oct 2025 01:21:51 +0000 Subject: [PATCH 1/2] Add content from: FIA Driver Categorisation: Admin Takeover via Mass Assignmen... --- src/SUMMARY.md | 1 + src/pentesting-web/json-xml-yaml-hacking.md | 6 + src/pentesting-web/mass-assignment-cwe-915.md | 195 ++++++++++++++++++ .../web-vulnerabilities-methodology.md | 1 + 4 files changed, 203 insertions(+) create mode 100644 src/pentesting-web/mass-assignment-cwe-915.md diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 323d407ed86..f8fb2fb5a47 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -588,6 +588,7 @@ # 🕸️ Pentesting Web - [Less Code Injection Ssrf](pentesting-web/less-code-injection-ssrf.md) +- [Mass Assignment Cwe 915](pentesting-web/mass-assignment-cwe-915.md) - [Web Vulnerabilities Methodology](pentesting-web/web-vulnerabilities-methodology.md) - [Reflecting Techniques - PoCs and Polygloths CheatSheet](pentesting-web/pocs-and-polygloths-cheatsheet/README.md) - [Web Vulns List](pentesting-web/pocs-and-polygloths-cheatsheet/web-vulns-list.md) diff --git a/src/pentesting-web/json-xml-yaml-hacking.md b/src/pentesting-web/json-xml-yaml-hacking.md index f601f2b62f4..7a30b0bc97e 100644 --- a/src/pentesting-web/json-xml-yaml-hacking.md +++ b/src/pentesting-web/json-xml-yaml-hacking.md @@ -172,6 +172,12 @@ Result: | libyaml ≤0.2.5 double-free | Upgrade to **0.2.6** or distro-patched release | | RapidJSON { + const user = await User.findByIdAndUpdate(req.params.id, req.body, { new: true }); + res.json(user); +}); +``` +Fix: +```js +// 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 + +Vulnerable (no strong parameters): +```rb +def update + @user.update(params[:user]) # roles/is_admin can be set by client +end +``` +Fix (strong params + no privileged fields): +```rb +def user_params + params.require(:user).permit(:first_name, :last_name, :nick_name) +end +``` + +Laravel (Eloquent) + +Vulnerable: +```php +protected $guarded = []; // Everything mass-assignable (bad) +``` +Fix: +```php +protected $fillable = ['first_name','last_name','nick_name']; // No roles/is_admin +``` + +Spring Boot (Jackson) + +Vulnerable pattern: +```java +// Directly binding to entity and persisting it +public User update(@PathVariable Long id, @RequestBody User u) { return repo.save(u); } +``` +Fix: Map to a DTO with only allowed fields and enforce authorization: +```java +record UserUpdateDTO(String firstName, String lastName, String nickName) {} +``` +Then copy allowed fields from DTO to the entity server-side, and handle role changes only in admin-only handlers after RBAC checks. Use @JsonIgnore on privileged fields if necessary and reject unknown properties. + +Go (encoding/json) +- Ensure privileged fields use json:"-" and validate with a DTO struct that includes only allowed fields. +- Consider decoder.DisallowUnknownFields() and post-bind validation of invariants (roles cannot change in self-service routes). + +--- +## 5) Test Checklist (Offense) + +- Do self-service PUT/PATCH include privileged attributes in the response? Try sending them back in the request. +- Try setting: roles/isAdmin, status (e.g., APPROVED/ACTIVATED), ownerId/accountId, permissions arrays, verification flags, plan limits. +- Try nested objects (e.g., profile.role.name, profile.flags.isStaff). +- If change seems successful but UI remains the same, re-login or force a token refresh. + +--- +## 6) Mitigations (Defense) + +- Enforce server-side authorization on every update. Self-service endpoints must reject/ignore privileged fields. +- Use DTOs/allow-lists; never bind request bodies directly to persistence models. +- Split role/permission management into dedicated admin-only endpoints guarded by RBAC/ABAC checks and step-up auth. +- Do not reflect privileged attributes (roles, internal flags) in ordinary profile responses. +- Add regression tests for authZ invariants, and monitoring/alerting for role or status changes. +- For JSON binding, reject unknown fields by default and validate nested structures. + +--- +## 7) Example Workflow Cheat-Sheet + +- Recon: update your profile; note any privileged fields echoed back. +- Client bundle: enumerate valid role names/IDs and payload shapes. +- Exploit: include a crafted roles array in a PUT/PATCH to your own user resource. +- Activate: re-authenticate to refresh session/claims; verify admin UI and high-privilege endpoints. + +## References + +- [FIA Driver Categorisation: Admin Takeover via Mass Assignment of roles (Full PoC)](https://ian.sh/fia) +- [OWASP Top 10 – Broken Access Control](https://owasp.org/Top10/A01_2021-Broken_Access_Control/) +- [CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes](https://cwe.mitre.org/data/definitions/915.html) + +{{#include ../banners/hacktricks-training.md}} \ No newline at end of file diff --git a/src/pentesting-web/web-vulnerabilities-methodology.md b/src/pentesting-web/web-vulnerabilities-methodology.md index 5dc2c81b6e0..4325bfcabbd 100644 --- a/src/pentesting-web/web-vulnerabilities-methodology.md +++ b/src/pentesting-web/web-vulnerabilities-methodology.md @@ -127,6 +127,7 @@ These vulnerabilities might help to exploit other vulnerabilities. - [ ] [**Domain/Subdomain takeover**](domain-subdomain-takeover.md) - [ ] [**IDOR**](idor.md) +- [ ] [**Mass Assignment (CWE-915)**](mass-assignment-cwe-915.md) - [ ] [**Parameter Pollution**](parameter-pollution.md) - [ ] [**Unicode Normalization vulnerability**](unicode-injection/index.html) From 2abd9962a67636b50bc8eac979f2b77a5b0739d1 Mon Sep 17 00:00:00 2001 From: SirBroccoli Date: Sat, 25 Oct 2025 19:20:50 +0200 Subject: [PATCH 2/2] Update mass-assignment-cwe-915.md --- src/pentesting-web/mass-assignment-cwe-915.md | 43 ++++--------------- 1 file changed, 8 insertions(+), 35 deletions(-) diff --git a/src/pentesting-web/mass-assignment-cwe-915.md b/src/pentesting-web/mass-assignment-cwe-915.md index b48b8f8bd4d..0887dcc6c1d 100644 --- a/src/pentesting-web/mass-assignment-cwe-915.md +++ b/src/pentesting-web/mass-assignment-cwe-915.md @@ -6,7 +6,6 @@ Mass assignment (a.k.a. insecure object binding) happens when an API/controller This is a Broken Access Control issue (OWASP A01:2021) that often enables vertical privilege escalation by setting roles=ADMIN or similar. It commonly affects frameworks that support automatic binding of request bodies to data models (Rails, Laravel/Eloquent, Django ORM, Spring/Jackson, Express/Mongoose, Sequelize, Go structs, etc.). ---- ## 1) Finding Mass Assignment Look for self-service endpoints that update your own profile or similar resources: @@ -52,7 +51,7 @@ Content-Type: application/json } ``` ---- + ## 2) Exploitation – Role Escalation via Mass Assignment Once you know the bindable shape, include the privileged property in the same request. @@ -79,7 +78,7 @@ Notes - Role identifiers and shapes are frequently enumerated from the client JS bundle or API docs. Search for strings like "roles", "ADMIN", "STAFF", or numeric role IDs. - If tokens contain claims (e.g., JWT roles), a logout/login or token refresh is usually required to realize the new privileges. ---- + ## 3) Client Bundle Recon for Schema and Role IDs - Inspect minified JS bundles for role strings and model names; source maps may reveal DTO shapes. @@ -91,12 +90,12 @@ Handy greps against a downloaded bundle: strings app.*.js | grep -iE "role|admin|isAdmin|permission|status" | sort -u ``` ---- + ## 4) Framework Pitfalls and Secure Patterns The vulnerability arises when frameworks bind req.body directly onto persistent entities. Below are common mistakes and minimal, secure patterns. -Node.js (Express + Mongoose) +**Node.js (Express + Mongoose)** Vulnerable: ```js @@ -117,7 +116,7 @@ app.put('/api/users/:id', async (req, res) => { // Implement a separate admin-only endpoint for role updates with server-side RBAC checks. ``` -Ruby on Rails +**Ruby on Rails** Vulnerable (no strong parameters): ```rb @@ -132,7 +131,7 @@ def user_params end ``` -Laravel (Eloquent) +**Laravel (Eloquent)** Vulnerable: ```php @@ -143,7 +142,7 @@ Fix: protected $fillable = ['first_name','last_name','nick_name']; // No roles/is_admin ``` -Spring Boot (Jackson) +**Spring Boot (Jackson)** Vulnerable pattern: ```java @@ -160,36 +159,10 @@ Go (encoding/json) - Ensure privileged fields use json:"-" and validate with a DTO struct that includes only allowed fields. - Consider decoder.DisallowUnknownFields() and post-bind validation of invariants (roles cannot change in self-service routes). ---- -## 5) Test Checklist (Offense) - -- Do self-service PUT/PATCH include privileged attributes in the response? Try sending them back in the request. -- Try setting: roles/isAdmin, status (e.g., APPROVED/ACTIVATED), ownerId/accountId, permissions arrays, verification flags, plan limits. -- Try nested objects (e.g., profile.role.name, profile.flags.isStaff). -- If change seems successful but UI remains the same, re-login or force a token refresh. - ---- -## 6) Mitigations (Defense) - -- Enforce server-side authorization on every update. Self-service endpoints must reject/ignore privileged fields. -- Use DTOs/allow-lists; never bind request bodies directly to persistence models. -- Split role/permission management into dedicated admin-only endpoints guarded by RBAC/ABAC checks and step-up auth. -- Do not reflect privileged attributes (roles, internal flags) in ordinary profile responses. -- Add regression tests for authZ invariants, and monitoring/alerting for role or status changes. -- For JSON binding, reject unknown fields by default and validate nested structures. - ---- -## 7) Example Workflow Cheat-Sheet - -- Recon: update your profile; note any privileged fields echoed back. -- Client bundle: enumerate valid role names/IDs and payload shapes. -- Exploit: include a crafted roles array in a PUT/PATCH to your own user resource. -- Activate: re-authenticate to refresh session/claims; verify admin UI and high-privilege endpoints. - ## References - [FIA Driver Categorisation: Admin Takeover via Mass Assignment of roles (Full PoC)](https://ian.sh/fia) - [OWASP Top 10 – Broken Access Control](https://owasp.org/Top10/A01_2021-Broken_Access_Control/) - [CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes](https://cwe.mitre.org/data/definitions/915.html) -{{#include ../banners/hacktricks-training.md}} \ No newline at end of file +{{#include ../banners/hacktricks-training.md}}