MVC: Mass Assignment Vulnerability
Soeleman 25 Januari 2017
Kadang kala bug bukan terjadi karena kesalahan kode saja. Loose-Coupling seperti pada HTTP protokol kadang dapat dimanfaatkan untuk inject informasi ke dalam server. Dan itu yang terjadi pada Mass Aassignment Vulnerability.
Karena framework seperti ASP.Net MVC, Ruby-on-Rails dan Java Play memberikan fitur untuk me-mapping http-form-collection ke dalam Model secara automatis. Kadang kebersihan http-form-collection itu jadi kurang diperhatikan.
App
Sekarang kita akan buat sebuah Form dengan 2 project, ASP.Net (VB.Net) dan ASP.Net-Core (C#). Dengan begitu kita bisa lihat Mass Aassignment Vulnerability ini masih dapat terjadi pada 2 projek yang berbeda.
Model
Dalam demo kali ini, kita buat Model Member. Ada beberapa property di sana, tapi yang kita pakai adalah Id, UserName dan IsAdmin.
< VB.Net >
< C# >
Controller
Dalam Controller Member hanya ada 2 method. Satu untuk Get dan Post. Tidak banyak berbeda di sini kecuali di ASP.Net-Core menggunakan IActionResult.
Dalam Get kita buat object-member dengan Id yang berisi 1. Ini hanya untuk mencegah sebuah div terlihat, detailnya lihat di-View-nya.
Sedangkan Post sebaliknya, kita buat Id menjadi 0. Yang perlu diperhatikan adalah ketika di Post apa nilai dari property IsAdmin.
< VB.Net >
< C# >
Razor
Dalam view-nya, ada 2 class css(cssAdminBackground dan cssAdmin) yang di gunakan memberikan penegasan atas status. Dan kita hanya menggunakan property UserName agar lebih sederhana.
Kalau di perhatikan view ASP.Net-Core ada yang berbeda. Terutama adanya penggunaan tag-helper tapi secara keseluruhan tidak banyak bedanya.
< VB.Net >
< C# >
Form-Member
Kita pastikan dahulu ini berjalan seperti yang di harapkan. Terlihat pada gambar di bawah, sebuah Form.
Yang terjadi apa bila kita menekan submit adalah muncul informasi UserName dan IsAdmin. Dan ini yang kita harapkan terjadi.
Exploit
Sekarang kita coba melihat apakah Mass Aassignment Vulnerability ini masih ada. Seperti yang dikatakan di atas kita mencoba lewat ASP.Net (VB.Net) dan ASP.Net-Core (C#).
Http-Get
Caranya melakukan ini sederhana sekali, cukup kita gunakan query-string. Jadi kita memanggil halaman Member dengan query-string IsAdmin dengan nilai True. Dengan begitu, form-nya akan meng-ingat alamat itu ketika Submit.
Dan ini yang terjadi. Muncul-nya warna biru itu menunjukkan bahwa kita bisa memodifikasi property IsAdmin hanya dengan Http-Get. Di sini terlihat Mass Aassignment Vulnerability masih berlaku.
Http-Post
Sekarang kita coba lewat Http-Post. Kita buka halaman Member seperti biasa. Setelah itu kita gunakan developer-tool yang disertakan dalam browser. Biasanya disertakan juga untuk merubah dom yang ada.
Kita masukkan element seperti pada gambar di bawah. Yang kita taruh itu hampir sama dengan cara Http-Get, bedanya ini di anggap sebagai bagian form-nya.
Dan seperti yang kita perkirakan, Mass Aassignment Vulnerability tetap terjadi. Yang terjadi pada saat submit adalah element yang kita masukkan akan terkirim sebagai bagian dari form tersebut.
Solusi
Secara architektural kita bisa membuat class member baru yang isinya hanya property yang kita butuhkan saja. Tentu saja ada beberapa alternatif lainnya seperti membuat custom attribute, membuat filter atau menggunakan AutoMapper. Sekarang kita akan coba lihat solusi umum yang lebih sederhana untuk mengatasi ini.
BindAttribute
Dengan BindAttribute biasanya digunakan untuk memberitahukan pada binding-model untuk mem-filter pada saat mengubah http-form-data ke dalam Model di MVC. Ada dua cara untuk melakukan filter, baik Include maupun exclude. Dengan begitu kita bisa mempertahankan informasi yang masuk kedalam controller.
< VB.Net >
< VB.Net >
Untuk ASP.Net-Core BindAttribute berbeda. Hanya satu opsi saja dan parameter untuk include saja. Caranya kerjanya saja saja.
< C# >
Bisa saja BindAttribute ini digunakan pada Model di level class. Tentu ini akan bereffek pada semua yang menggunakan Model ini.
< VB.Net >
Sama juga terhadap BindAttribute di ASP.Net-Core. Bedanya hanya parameter saja dan cara kerjanya seperti yang digunakan pada method parameter.
< C# >
UpdateModel
Kita bisa juga memanfaatkan TryUpdateModel yang ada di Controller. Dan akan seperti pada gambar di bawah.
< VB.Net >
Sayang tersebut tidak berlaku di Controller pada ASP.Net-Core. Oleh karena itu kita buat interface seperti di bawah. Kita hanya menggunakan property Id dan property UserName.
< VB.Net >
< C# >
Dan itu di-implementasi-kan pada Model-nya.
< VB.Net >
< C# >
Bila kita mempunyai Model yang memiliki interface seperti ini. Maka kita bisa menggunakan override dari TryUpdateModel method.
< VB.Net >
ASP.Net-Core tidak memiliki method tersebut. Tapi ada persamaan untuk itu yang ada didalam Controller-nya. Method tersebut adalah TryUpdateModelAsync. Caranya hampir sama dengan yang di ASP.Net.
< C# >
Penutup
Demo ini hanya menggunakan Form saja, tapi kekreatifitasan cara kerja Mass Aassignment Vulnerability bisa beragam. Seperti pada tahun 2012, di mana GitHub (Ruby-on-Rails) terbukti memiliki kelemahan ini. Lebih parah lagi, yang dimasukkan berupa SSH-public-key yang menyebabkan repository dapat dikendalikan.
Mass Aassignment Vulnerability sudah lama ada dan seperti SQL-Injection masih saja programmer suka melupakan hal seperti ini. Tulisan ini dibuat sebagai pengingat, keamanan adalah fitur juga selain kecepatan dan kestabilan aplikasi.
Referensi
- ASP.Net
- AutoMapper
- GitHub
- Wikipedia: Exploit
- Wikipedia: Mass_assignment_vulnerability
- MSDN: BindAttribute Class
- MSDN: Controller.TryUpdateModel Method
- ASP.Net Core: ControllerBase Class
- ASP.Net Core: BindAttribute Class
Perhatian! Code yang ditampilkan dalam tulisan ini merupakan ilustrasi dari yang ingin dipaparkan dan bukan production ready code.
Sudah banyak kejadian karena asal meng-copy-and-paste tanpa mengerti code yang diambil itu ke dalam production.
Selain itu perlu ada tambahan code dan test sebelum siap untuk digunakan secara utuh.