پرش به محتوای اصلی
آسیب‌پذیری‌های سایت

Mass Assignment چیست؟ بررسی آسیب‌پذیری تخصیص انبوه و روش‌های جلوگیری از تغییر غیرمجاز داده‌ها در API

آسیب‌پذیری Mass Assignment زمانی رخ می‌دهد که API داده‌های دریافتی از کاربر را بدون محدودسازی دقیق به ویژگی‌های Object یا Model داخلی متصل کند و در نتیجه امکان تغییر Propertyهای غیرمجاز ایجاد شود. این ضعف می‌تواند Propertyهای مربوط به سطح دسترسی، مالکیت، وضعیت حساب یا منطق مالی را تحت تأثیر قرار دهد و در طبقه‌بندی فعلی امنیت API با کنترل مجوز در سطح ویژگی‌های Object ارتباط مستقیم دارد.

تیم امنیت رخنه‌کاو ۴۳ دقیقه مطالعه انتشار:

آسیب‌پذیری Mass Assignment یا «تخصیص انبوه» زمانی ایجاد می‌شود که برنامه ورودی دریافت‌شده از کاربر را بدون کنترل دقیق، مستقیماً به ویژگی‌های یک Object، Model یا Entity داخلی متصل کند. در چنین شرایطی ممکن است کاربر بتواند ویژگی‌هایی را تغییر دهد که هرگز قرار نبوده از طریق API قابل ویرایش باشند؛ برای مثال سطح دسترسی، وضعیت تأیید حساب، مالکیت یک رکورد یا ویژگی‌های مدیریتی.

راهکار اصلی جلوگیری از Mass Assignment این است که سرور دقیقاً مشخص کند کدام فیلدها اجازه ورود و تغییر دارند، ورودی API مستقیماً به مدل پایگاه داده متصل نشود و برای هر عملیات از DTO، Schema Validation و کنترل مجوز در سطح Property استفاده شود.

Mass Assignment چیست؟

Mass Assignment یک ضعف امنیتی در نحوه تبدیل داده ورودی کاربر به اشیای داخلی برنامه است.

در بسیاری از Frameworkها، توسعه‌دهنده می‌تواند داده‌های یک درخواست HTTP را به‌صورت خودکار به یک Object یا Model متصل کند. این قابلیت سرعت توسعه را افزایش می‌دهد و مقدار زیادی کد تکراری را حذف می‌کند، اما اگر بدون محدودیت استفاده شود می‌تواند مرز امنیتی بین «داده‌ای که کاربر اجازه تغییر آن را دارد» و «داده‌ای که فقط سیستم باید کنترل کند» را از بین ببرد.

فرض کنید مدل داخلی یک کاربر شامل ویژگی‌های زیر باشد:

  • name
  • email
  • phone
  • role
  • account_status
  • email_verified
  • credit_balance
  • owner_id

کاربر عادی ممکن است از طریق صفحه تنظیمات حساب فقط اجازه تغییر نام، ایمیل و شماره تلفن خود را داشته باشد.

مشکل زمانی ایجاد می‌شود که Backend به‌جای استخراج همین سه فیلد، تمام داده دریافتی را مستقیماً به مدل User منتقل کند.

در این معماری، امنیت API وابسته به این فرض اشتباه می‌شود که «کلاینت فقط فیلدهایی را ارسال خواهد کرد که در رابط کاربری نمایش داده شده‌اند».

اما رابط کاربری یک مرز امنیتی نیست.

کاربر می‌تواند درخواست HTTP را مستقل از رابط وب یا اپلیکیشن ایجاد یا تغییر دهد. بنابراین سرور باید فرض کند تمام داده‌های دریافتی از Client غیرقابل‌اعتماد هستند.

OWASP این رفتار را Mass Assignment می‌نامد و توصیه می‌کند تنها ویژگی‌هایی که واقعاً باید از طرف Client قابل تغییر باشند به‌صورت صریح مجاز شوند.

چرا Mass Assignment در APIها اهمیت زیادی دارد؟

APIها معمولاً مستقیماً با ساختارهای داده برنامه تعامل دارند.

در یک رابط سنتی ممکن است یک فرم HTML فقط سه ورودی مشخص داشته باشد، اما API معمولاً داده را در قالب‌هایی مانند JSON دریافت می‌کند و آن را به لایه‌های داخلی برنامه انتقال می‌دهد.

اگر Backend فیلدهای ورودی را دقیقاً محدود نکند، اختلافی میان «قابلیت‌هایی که UI نمایش می‌دهد» و «قابلیت‌هایی که API واقعاً قبول می‌کند» ایجاد می‌شود.

این اختلاف همان جایی است که Mass Assignment می‌تواند به یک آسیب‌پذیری جدی تبدیل شود.

موضوع فقط اضافه کردن یک Property ناشناخته نیست. خطر واقعی زمانی شکل می‌گیرد که یک Property معتبر در مدل داخلی وجود داشته باشد، اما کاربر اجازه تغییر آن را نداشته باشد.

برای نمونه:

یک API ویرایش پروفایل ممکن است از نظر فنی فیلد role را بشناسد، زیرا این فیلد در User Model وجود دارد؛ ولی تصمیم‌گیری درباره مقدار آن باید فقط توسط سیستم مدیریت دسترسی انجام شود.

Mass Assignment زمانی رخ می‌دهد که لایه API میان «Property موجود» و «Property قابل ویرایش توسط این کاربر در این عملیات» تفاوت قائل نشود. Mass Assignment چگونه به وجود می‌آید؟

Mass Assignment چگونه به وجود می‌آید؟

ریشه این آسیب‌پذیری معمولاً استفاده بیش از حد از قابلیت‌های Automatic Binding یا Object Mapping است.

بسیاری از Frameworkها برای راحتی توسعه‌دهنده مکانیزم‌هایی دارند که داده ورودی را به‌صورت خودکار به ویژگی‌های یک Object متصل می‌کنند.

این قابلیت‌ها ممکن است با نام‌هایی مانند موارد زیر شناخته شوند:

Mass Assignment

Auto Binding

Automatic Binding

Model Binding

Object Binding

Over-posting

Object Injection

نام دقیق بسته به زبان برنامه‌نویسی و Framework متفاوت است، اما ایده تقریباً یکسان است: تبدیل خودکار مجموعه‌ای از پارامترهای ورودی به ویژگی‌های یک Object.

خود این قابلیت لزوماً آسیب‌پذیری نیست.

مشکل زمانی ایجاد می‌شود که کنترل امنیتی مشخصی درباره Propertyهایی که اجازه Bind شدن دارند وجود نداشته باشد.

یک مثال ساده از Mass Assignment

یک فروشگاه اینترنتی را تصور کنید که کاربران می‌توانند آدرس حساب خود را ویرایش کنند.

مدل داخلی Customer ممکن است شامل این داده‌ها باشد:

Customer
--------
id
name
email
address
phone
customer_type
discount_level
account_status
credit_limit
created_at

رابط کاربری فقط اجازه تغییر موارد زیر را می‌دهد:

name
address
phone

اگر Backend همین سه Property را به‌صورت صریح استخراج و بررسی کند، ساختار مناسبی داریم.

اما اگر منطق برنامه تقریباً به این شکل باشد:

customer.update(request.body)

امنیت عملیات کاملاً وابسته به نحوه رفتار Framework و تنظیمات مدل خواهد شد.

در چنین شرایطی ممکن است Propertyهای داخلی دیگری نیز قابل تغییر شوند.

بنابراین تفاوت اصلی میان طراحی امن و ناامن در این نیست که Frontend چه فیلدهایی را نمایش می‌دهد؛ بلکه در این است که Backend دقیقاً چه Propertyهایی را مجاز می‌داند.

چرا مخفی کردن فیلد در Frontend راهکار امنیتی نیست؟

یکی از اشتباهات رایج در طراحی API این است که توسعه‌دهنده تصور می‌کند چون فیلدی در HTML، JavaScript یا اپلیکیشن موبایل نمایش داده نشده، کاربر به آن دسترسی ندارد.

این فرض اشتباه است.

کلاینت تحت کنترل کاربر قرار دارد.

کاربر می‌تواند:

درخواست‌های شبکه را مشاهده کند.

ساختار API را بررسی کند.

درخواست معتبر برنامه را بازسازی کند.

Client سفارشی بنویسد.

از ابزارهای تست API استفاده کند.

یا مستقیماً با Endpoint ارتباط برقرار کند.

بنابراین هر تصمیم امنیتی باید در Backend گرفته شود.

Frontend می‌تواند تجربه کاربری را مدیریت کند، اما نمی‌تواند مجوز دسترسی را enforce کند.

Property حساس چیست؟

هر Property که تغییر آن بتواند بر امنیت، مجوزها، مالکیت، وضعیت مالی یا منطق کسب‌وکار تأثیر بگذارد باید حساس در نظر گرفته شود.

نمونه‌های متداول عبارت‌اند از:

role

is_admin

permissions

owner_id

user_id

account_status

verified

email_verified

phone_verified

credit

balance

discount

price

subscription_level

approved

blocked

internal_status

created_by

organization_id

البته حساس بودن یک Property وابسته به Context است.

مثلاً status در یک سیستم ممکن است وضعیت ظاهری پروفایل باشد و حساسیت خاصی نداشته باشد، اما در سامانه دیگر تعیین کند که یک تراکنش مالی تأیید شده است یا خیر.

بنابراین نمی‌توان فقط براساس نام فیلد تصمیم گرفت.

مجوز باید براساس Business Logic تعیین شود.

ارتباط Mass Assignment با Broken Object Property Level Authorization

در نسخه ۲۰۱۹ OWASP API Security Top 10، Mass Assignment به‌عنوان API6:2019 یک ریسک مستقل معرفی شده بود.

در طبقه‌بندی OWASP API Security Top 10 سال ۲۰۲۳، Mass Assignment همراه با Excessive Data Exposure در دسته گسترده‌تری با عنوان:

Broken Object Property Level Authorization یا BOPLA

قرار گرفته است.

دلیل این تغییر این است که ریشه هر دو مشکل در کنترل ناکافی دسترسی به Propertyهای یک Object قرار دارد.

در یک حالت کاربر Propertyای را مشاهده می‌کند که نباید ببیند.

در حالت Mass Assignment کاربر Propertyای را تغییر می‌دهد که نباید اجازه تغییر آن را داشته باشد.

به همین دلیل Mass Assignment را می‌توان یکی از شکل‌های مهم ضعف مجوزدهی در سطح ویژگی‌های Object دانست. تفاوت Mass Assignment با BOLA چیست؟

تفاوت Mass Assignment با BOLA چیست؟

Mass Assignment و BOLA یا Broken Object Level Authorization هر دو با Access Control ارتباط دارند، اما یکسان نیستند.

در BOLA مسئله اصلی این است که:

«آیا این کاربر اجازه دسترسی به این Object را دارد؟»

در Mass Assignment مسئله اصلی این است که:

«اگر کاربر به این Object دسترسی دارد، دقیقاً اجازه تغییر کدام Propertyهای آن را دارد؟»

فرض کنید کاربری اجازه ویرایش پروفایل خودش را دارد.

بنابراین دسترسی او به Object خودش قانونی است.

اما این موضوع به این معنی نیست که باید بتواند تمام Propertyهای User Object را تغییر دهد.

مثلاً ممکن است اجازه تغییر name را داشته باشد اما نباید قادر به تغییر role باشد.

بنابراین حتی وقتی Object Level Authorization به‌درستی پیاده‌سازی شده باشد، Property Level Authorization همچنان ضروری است.

تفاوت Mass Assignment با IDOR چیست؟

IDOR معمولاً زمانی مطرح می‌شود که کاربر با تغییر یک شناسه بتواند به Resource متعلق به کاربر دیگری دسترسی پیدا کند.

برای مثال، اگر Endpoint مشخصی Object شماره 100 را دریافت کند و تغییر ID به 101 باعث دسترسی به داده شخص دیگری شود، مشکل به کنترل دسترسی در سطح Object مربوط است.

اما Mass Assignment لزوماً نیازمند تغییر ID نیست.

ممکن است کاربر کاملاً قانونی به Object خودش دسترسی داشته باشد ولی بتواند Property غیرمجازی از همان Object را تغییر دهد.

بنابراین:

IDOR یا BOLA درباره «کدام Object» است.

Mass Assignment درباره «کدام Property از Object» است.

البته یک API ممکن است هم‌زمان هر دو ضعف را داشته باشد که در این صورت تأثیر امنیتی می‌تواند بسیار بیشتر شود.

تفاوت Mass Assignment با Broken Function Level Authorization

Broken Function Level Authorization یا BFLA زمانی رخ می‌دهد که کاربر بتواند Function یا Endpointای را اجرا کند که اساساً نباید در اختیار نقش او قرار داشته باشد.

برای مثال ممکن است Endpoint مدیریتی برای غیرفعال کردن کاربران وجود داشته باشد و یک کاربر عادی بتواند آن را فراخوانی کند.

در Mass Assignment ممکن است همان Endpoint عادی و قانونی باشد، اما Propertyهای بیشتری از چیزی که باید قابل تغییر باشند قبول کند.

این تمایز در طراحی تست‌های امنیتی بسیار مهم است.

تیم امنیت باید سه سؤال جداگانه بپرسد:

آیا کاربر اجازه اجرای این Function را دارد؟

آیا کاربر اجازه دسترسی به این Object را دارد؟

آیا کاربر اجازه تغییر این Property را دارد؟

اگر هر سه کنترل مستقل بررسی نشوند، بخشی از سطح حمله API ممکن است پنهان باقی بماند.

تفاوت Validation و Authorization در Mass Assignment

یکی از مهم‌ترین مفاهیم در این آسیب‌پذیری تفاوت میان Validation و Authorization است.

Validation می‌پرسد:

«آیا این مقدار از نظر ساختار و نوع داده معتبر است؟»

Authorization می‌پرسد:

«آیا این کاربر اجازه تغییر این Property را دارد؟»

فرض کنید Property زیر در مدل وجود داشته باشد:

account_status = "active"

ممکن است Schema Validation فقط اجازه مقادیر زیر را بدهد:

active
disabled
pending

اگر کاربر عادی مقدار active را ارسال کند، مقدار از نظر Schema کاملاً معتبر است.

اما سؤال امنیتی این است که آیا کاربر عادی اصلاً اجازه تعیین account_status را دارد؟

بنابراین Validation به‌تنهایی Mass Assignment را حل نمی‌کند.

یک API امن به هر دو نیاز دارد:

Input Validation

Property-Level Authorization

Authentication نیز Mass Assignment را حل نمی‌کند

وجود Authentication قوی نیز به‌تنهایی کافی نیست.

ممکن است API از:

JWT

OAuth 2.0

Session Cookie

API Token

2FA

یا مکانیزم احراز هویت بسیار قدرتمندی استفاده کند.

با این حال کاربر احراز هویت‌شده همچنان می‌تواند تلاش کند Propertyهایی را تغییر دهد که خارج از سطح دسترسی او هستند.

Authentication فقط مشخص می‌کند درخواست‌کننده چه کسی است.

Authorization مشخص می‌کند او چه کاری اجازه دارد انجام دهد.

Mass Assignment معمولاً یک مشکل Authorization و Data Binding است، نه صرفاً Authentication.

چرا Mass Assignment می‌تواند خطرناک باشد؟

شدت آسیب‌پذیری کاملاً به نوع Propertyهایی بستگی دارد که از طریق API قابل تغییر هستند.

در ساده‌ترین حالت ممکن است یک ویژگی کم‌اهمیت تغییر کند.

اما اگر Propertyهای امنیتی، مالی یا مدیریتی تحت تأثیر باشند، پیامد می‌تواند بسیار جدی باشد.

افزایش سطح دسترسی

اگر نقش یا Permission یک حساب در همان Object ذخیره شده باشد و API اجازه تغییر ناخواسته آن را بدهد، مرز میان کاربر عادی و نقش‌های دارای دسترسی بیشتر ممکن است از بین برود.

تغییر مالکیت منابع

Propertyهایی مانند:

owner_id

user_id

organization_id

ممکن است مشخص کنند یک Resource متعلق به چه کسی است.

نباید اجازه داد مقدار چنین Propertyهایی صرفاً براساس داده دریافتی از Client تعیین شود.

دور زدن فرآیند تأیید

Propertyهایی مانند:

verified

approved

reviewed

email_verified

اغلب باید فقط توسط Workflow داخلی برنامه تغییر کنند.

اگر Client بتواند مستقیماً آن‌ها را کنترل کند، یک فرآیند چندمرحله‌ای امنیتی ممکن است عملاً بی‌اثر شود.

دستکاری منطق مالی

در سامانه‌های مالی و فروشگاهی، Propertyهایی مانند قیمت، اعتبار، تخفیف یا موجودی حساب باید با حساسیت بسیار بیشتری مدیریت شوند.

مقادیر مالی مهم بهتر است در سمت Server و براساس منطق معتبر محاسبه شوند، نه اینکه از Client به‌عنوان حقیقت پذیرفته شوند.

تغییر وضعیت داخلی

بعضی Propertyها برای مدیریت Workflow طراحی شده‌اند و اصلاً نباید بخشی از قرارداد عمومی API باشند.

برای مثال:

fraud_review_status
internal_risk_score
manual_approval
moderation_status

افشای امکان تغییر چنین Propertyهایی می‌تواند مرز میان منطق داخلی و API عمومی را از بین ببرد.

چرا معماری CRUD عمومی مستعد Mass Assignment است؟

یکی از الگوهایی که ریسک Mass Assignment را افزایش می‌دهد طراحی APIهای بسیار Generic است.

برای مثال یک Endpoint عمومی مانند:

PATCH /users/{id}

ممکن است تقریباً تمام User Model را به‌عنوان ورودی قبول کند.

این طراحی در ابتدا ساده است، اما به مرور زمان مدل User بزرگ‌تر می‌شود.

فرض کنید ابتدا User فقط شامل موارد زیر باشد:

name
email
phone

بعداً ویژگی‌های زیر اضافه می‌شوند:

role
status
organization_id
risk_level
verified

اگر Endpoint قبلی همچنان تمام Model را Bind کند، اضافه شدن هر Property جدید می‌تواند بدون تغییر واضح در Controller، سطح حمله API را افزایش دهد.

به همین دلیل Contract یک API بهتر است مستقل از Domain Model طراحی شود. Domain Model نباید همان API Model باشد

Domain Model نباید همان API Model باشد

یکی از مهم‌ترین اصول طراحی امن این است که Object داخلی برنامه الزاماً نباید همان Objectای باشد که API دریافت یا بازمی‌گرداند.

Domain Model ممکن است شامل ده‌ها Property داخلی باشد.

اما Request DTO یک عملیات شاید فقط به سه Property نیاز داشته باشد.

برای مثال:

User Domain Model
-----------------
id
name
email
phone
role
status
verified
credit
organization_id
created_at
updated_at

در مقابل:

UpdateProfileRequest
--------------------
name
phone

این جداسازی یک مرز امنیتی واضح ایجاد می‌کند.

توسعه‌دهنده به‌جای اینکه بپرسد:

«کدام فیلدها را نباید قبول کنیم؟»

می‌پرسد:

«این عملیات دقیقاً به چه فیلدهایی نیاز دارد؟»

این تغییر دیدگاه، طراحی را از Blocklist به Allowlist منتقل می‌کند.

Allowlist بهتر از Blocklist است

دو رویکرد کلی برای کنترل Propertyها وجود دارد.

Blocklist:

فیلدهایی که خطرناک هستند مشخص می‌شوند و سایر فیلدها مجاز هستند.

Allowlist:

فقط فیلدهایی که برای عملیات لازم هستند مجاز شناخته می‌شوند و بقیه به‌صورت پیش‌فرض رد یا نادیده گرفته می‌شوند.

در Mass Assignment معمولاً Allowlist امن‌تر است.

دلیل آن ساده است.

فرض کنید امروز مدل ۱۰ Property دارد و دو Property در Blocklist قرار می‌گیرند.

شش ماه بعد توسعه‌دهنده Property امنیتی جدیدی اضافه می‌کند.

اگر فراموش شود آن را به Blocklist اضافه کنند، Endpoint قدیمی ممکن است بلافاصله Property جدید را قبول کند.

اما در Allowlist، Property جدید به‌صورت پیش‌فرض اجازه ورود ندارد.

این دقیقاً با اصل Secure by Default هماهنگ است. استفاده از DTO برای جلوگیری از Mass Assignment

استفاده از DTO برای جلوگیری از Mass Assignment

Data Transfer Object یا DTO یکی از بهترین روش‌ها برای جدا کردن ورودی API از Object داخلی برنامه است.

برای هر عملیات می‌توان یک DTO مشخص تعریف کرد.

برای نمونه:

UpdateUserProfileDTO
--------------------
display_name
phone
timezone

در این حالت حتی اگر User Entity دارای ده‌ها Property دیگر باشد، آن Propertyها بخشی از قرارداد Update Profile نیستند.

سپس Mapping میان DTO و Domain Model به‌صورت کنترل‌شده انجام می‌شود:

user.display_name = dto.display_name
user.phone = dto.phone
user.timezone = dto.timezone

این روش ممکن است چند خط کد بیشتر نیاز داشته باشد، اما مرز اعتماد را بسیار شفاف‌تر می‌کند.

Schema Validation چه نقشی دارد؟

Schema Validation مشخص می‌کند Request باید چه ساختاری داشته باشد.

برای مثال Schema می‌تواند تعیین کند:

چه Propertyهایی وجود داشته باشند.

نوع هر Property چیست.

چه Propertyهایی اجباری هستند.

حداقل و حداکثر طول رشته چقدر است.

مقادیر مجاز Enum کدام‌اند.

آیا Additional Properties مجاز هستند یا خیر.

Schema Validation زمانی در برابر Mass Assignment بسیار مفید است که API فیلدهای ناشناخته یا خارج از قرارداد را Reject کند.

برای مثال Contract مربوط به Update Profile نباید هر Property اضافی را به Backend انتقال دهد.

با این حال Schema Validation جایگزین Authorization نیست.

ممکن است یک Property از نظر Schema معتبر باشد اما فقط Administrator اجازه تغییر آن را داشته باشد.

Property-Level Authorization چیست؟

در بسیاری از سامانه‌ها فقط تعیین Allowed Fields کافی نیست.

ممکن است یک Property برای بعضی نقش‌ها قابل تغییر باشد و برای بعضی دیگر نباشد.

فرض کنید Endpoint مدیریت اعضای یک سازمان اجازه تغییر اطلاعات زیر را داشته باشد:

display_name
department
role

یک مدیر سازمان شاید اجازه تغییر role را داشته باشد، اما خود کاربر عادی فقط بتواند display_name را تغییر دهد.

بنابراین Allowlist می‌تواند Context-Aware باشد.

برای مثال:

Member:
display_name

Manager:
display_name
department

Administrator:
display_name
department
role

این تصمیم باید در سمت Server و براساس Identity و Policy معتبر اتخاذ شود.

نقش اصل Least Privilege

اصل Least Privilege می‌گوید هر کاربر، سرویس یا جزء سیستم فقط باید حداقل دسترسی لازم برای انجام وظیفه خود را داشته باشد.

این اصل فقط درباره Permissionهای سیستم‌عامل یا Database نیست.

در طراحی API نیز می‌توان آن را اعمال کرد.

اگر یک Endpoint فقط برای تغییر نام پروفایل طراحی شده است، نباید توانایی Update کردن تمام User Model را داشته باشد.

هرچه Scope عملیات محدودتر باشد، احتمال تغییر ناخواسته داده نیز کاهش می‌یابد.

رویکرد توسعه امن نیز توصیه می‌کند کنترل‌های امنیتی در خود چرخه طراحی و توسعه نرم‌افزار ادغام شوند، نه اینکه صرفاً پس از انتشار و در مرحله تست به آن‌ها فکر شود.

نقش HTTP PUT و PATCH در Mass Assignment

گاهی تصور می‌شود استفاده از PUT یا PATCH به‌تنهایی باعث ایجاد یا جلوگیری از Mass Assignment می‌شود.

این برداشت درست نیست.

آسیب‌پذیری به نحوه پردازش داده در Backend بستگی دارد، نه صرفاً HTTP Method.

PUT معمولاً برای جایگزینی کامل Representation یک Resource به‌کار می‌رود.

PATCH معمولاً تغییر بخشی از Resource را بیان می‌کند.

اما در هر دو حالت سرور باید مشخص کند چه Propertyهایی قابل تغییر هستند.

حتی یک PATCH بسیار کوچک نیز می‌تواند ناامن باشد اگر Property-Level Authorization وجود نداشته باشد.

PUT کامل و خطر اعتماد به Representation

در APIهایی که PUT یک Object کامل را دریافت می‌کند، توسعه‌دهندگان باید دقت بیشتری داشته باشند.

فرض کنید Client نسخه‌ای از User Object را دریافت کرده، بخشی از آن را تغییر داده و کل Object را دوباره ارسال می‌کند.

اگر Backend تمام Representation را به Model Bind کند، Propertyهای داخلی ممکن است ناخواسته وارد مسیر Update شوند.

راهکار بهتر این است که حتی در PUT نیز Contract مشخص و محدود تعریف شود.

PATCH و فیلدهای پویا

PATCH معمولاً برای به‌روزرسانی انتخابی Propertyها استفاده می‌شود.

اما اگر Backend منطق مشابه زیر داشته باشد:

for every received property:
    object[property] = value

ریسک Mass Assignment همچنان وجود دارد.

قبل از اعمال هر Property باید مشخص شود:

آیا نام Property معتبر است؟

آیا این Endpoint اجازه تغییر آن را دارد؟

آیا این User اجازه تغییر آن را دارد؟

آیا مقدار آن معتبر است؟

آیا تغییر آن با Business Rule سازگار است؟

بنابراین وجود یک لیست عمومی از فیلدهای Model کافی نیست.

Mass Assignment در APIهای REST

REST APIها معمولاً Resource-Oriented هستند و Objectها را در قالب JSON منتقل می‌کنند.

این ساختار طبیعی باعث می‌شود Domain Object و API Representation به‌راحتی با یکدیگر مخلوط شوند.

اگر Serializer یا ORM به‌صورت خودکار داده ورودی را روی Entity اعمال کند، Propertyهای اضافی ممکن است ناخواسته قابل تغییر شوند.

برای جلوگیری از این وضعیت باید میان مراحل زیر تفکیک ایجاد شود:

دریافت Request

Parse کردن JSON

Schema Validation

Authentication

Authorization

Property Filtering

Business Logic

Domain Update

Database Persistence

هر مرحله مسئولیت خاص خود را دارد.

Mass Assignment در GraphQL

GraphQL نیز ذاتاً در برابر Mass Assignment ایمن نیست.

در GraphQL نوع Input معمولاً به‌صورت مشخص تعریف می‌شود که یک مزیت امنیتی محسوب می‌شود، اما اگر Input Type بیش از حد گسترده باشد همچنان مشکل باقی می‌ماند.

برای مثال اگر Mutation ویرایش کاربر از همان Input Type عمومی مدل استفاده کند و Propertyهای مدیریتی نیز در آن وجود داشته باشند، مسئله Property-Level Authorization حل نشده است.

Schema دقیق می‌تواند سطح حمله را کاهش دهد، اما Resolver نیز باید Authorization مناسب را اجرا کند.

Mass Assignment در اپلیکیشن‌های موبایل

گاهی Backend براساس این فرض طراحی می‌شود که API فقط توسط اپلیکیشن رسمی موبایل استفاده خواهد شد.

این فرض نباید مبنای امنیت باشد.

اپلیکیشن موبایل در سمت Client اجرا می‌شود و ارتباط آن با API قابل مشاهده و تحلیل است.

حتی اگر رابط برنامه هیچ گزینه‌ای برای تغییر Property حساس نداشته باشد، Backend باید تمام درخواست‌ها را مستقل از Client بررسی کند.

API باید فرض کند Client ممکن است دستکاری شده باشد.

آیا WAF می‌تواند Mass Assignment را متوقف کند؟

Web Application Firewall یا WAF می‌تواند یکی از لایه‌های دفاعی باشد، اما راهکار اصلی Mass Assignment نیست.

WAF ممکن است برخی الگوهای مشکوک را شناسایی کند، ولی معمولاً اطلاعات کافی درباره Business Logic ندارد.

برای مثال WAF الزاماً نمی‌داند:

آیا role باید توسط User تغییر کند؟

آیا discount_level برای این Endpoint قانونی است؟

آیا Manager اجازه تغییر department_id را دارد؟

آیا approved فقط باید توسط سیستم داخلی تنظیم شود؟

این تصمیم‌ها وابسته به منطق برنامه هستند.

بنابراین اصلاح اصلی باید در Application Layer انجام شود.

WAF فقط می‌تواند Defense in Depth ایجاد کند.

چرا فیلتر کردن نام‌های معروف کافی نیست؟

یک راهکار ضعیف این است که توسعه‌دهنده فقط نام‌هایی مانند:

admin

role

is_admin

را مسدود کند.

این کار دو مشکل دارد.

اول اینکه نام Propertyها در هر برنامه متفاوت است.

دوم اینکه Property حساس جدید ممکن است در آینده اضافه شود.

برای مثال:

access_level
moderator
tier
approved
internal_flag

هرکدام می‌توانند همان اثر امنیتی را داشته باشند.

بنابراین امنیت نباید براساس حدس زدن نام فیلدهای خطرناک طراحی شود.

Allowlist عملیات‌محور روش قابل‌اعتمادتری است.

چگونه Mass Assignment را در مرحله طراحی پیشگیری کنیم؟

امن‌ترین روش این است که جلوگیری از آسیب‌پذیری پیش از نوشتن Endpoint آغاز شود.

برای هر عملیات باید مشخص شود:

چه Actorی عملیات را انجام می‌دهد؟

روی چه Resourceای؟

کدام Propertyها قابل مشاهده هستند؟

کدام Propertyها قابل تغییر هستند؟

چه Propertyهایی فقط توسط سیستم تغییر می‌کنند؟

چه Roleهایی مجاز به تغییر هر Property هستند؟

چه Validationهایی لازم است؟

چه Business Ruleهایی باید بررسی شوند؟

این اطلاعات بهتر است بخشی از API Contract و Security Requirements باشند.

طراحی Endpointهای محدود و هدفمند

به‌جای ایجاد یک Endpoint عمومی که هر نوع تغییر را قبول می‌کند، گاهی Endpointهای هدفمند امنیت بهتری ایجاد می‌کنند.

برای مثال به‌جای:

PATCH /account

که ده‌ها Property را قبول می‌کند، می‌توان عملیات منطقی را تفکیک کرد.

مانند:

PATCH /account/profile
POST /account/change-email
POST /account/change-password

این طراحی باعث می‌شود هر عملیات Contract، Validation و Policy امنیتی مخصوص خود را داشته باشد.

البته تعداد بیشتر Endpointها همیشه به معنی امنیت بیشتر نیست، اما مرزهای روشن‌تر معمولاً بررسی و تست را آسان‌تر می‌کنند.

Propertyهای Server-Controlled

بعضی Propertyها باید کاملاً Server-Controlled باشند.

یعنی Client نه‌تنها اجازه تغییر آن‌ها را نداشته باشد، بلکه اساساً لازم نباشد آن‌ها را ارسال کند.

برای نمونه:

created_at
updated_at
created_by
internal_score
verification_status
fraud_status
balance
server_signature

مقدار چنین Propertyهایی باید توسط Backend، Database یا سرویس مسئول تعیین شود.

اگر Client آن‌ها را ارسال کرد، بسته به طراحی API می‌توان درخواست را Reject کرد یا فیلد را نادیده گرفت.

برای APIهای حساس، Reject کردن فیلدهای خارج از Contract معمولاً شفافیت بیشتری ایجاد می‌کند.

جلوگیری از Mass Assignment در لایه Database

کنترل اصلی باید در Application Layer باشد، اما Database نیز می‌تواند Defense in Depth ایجاد کند.

برای مثال:

محدود کردن دسترسی Database User

استفاده از Constraints

استفاده از Trigger فقط در موارد ضروری

تفکیک عملیات حساس

استفاده از Stored Procedure در معماری‌هایی که مناسب است

و محدود کردن دسترسی سرویس‌ها به Tableها یا Columnهای خاص

می‌تواند تأثیر یک خطای Application را کاهش دهد.

با این حال Database نباید جایگزین Property-Level Authorization برنامه شود.

ثبت رویدادهای تغییرات حساس

هر تغییر در Propertyهای حساس بهتر است Audit شود.

برای مثال اگر موارد زیر تغییر می‌کنند:

Role

Permission

Status

Ownership

Financial Limit

Verification State

ثبت اطلاعاتی مانند موارد زیر مفید است:

چه کسی تغییر را انجام داده؟

چه زمانی؟

روی چه Resourceای؟

Property قبلی چه بوده؟

مقدار جدید چیست؟

درخواست از کدام Session یا Service آمده؟

آیا عملیات موفق بوده؟

Audit Log هم برای Incident Response و هم برای کشف رفتار غیرعادی اهمیت دارد.

Logging نباید اطلاعات حساس را افشا کند

هنگام ثبت Requestها باید مراقب بود خود سیستم Logging به منبع نشت اطلاعات تبدیل نشود.

ذخیره کامل Body تمام درخواست‌ها ممکن است باعث ثبت موارد حساسی مانند:

Password

Access Token

Session Token

API Key

اطلاعات مالی

یا داده‌های شخصی شود.

بنابراین Logging نیز باید براساس Data Classification طراحی شود.

تست امنیت Mass Assignment

تست Mass Assignment باید در محیط دارای مجوز و با داده‌های آزمایشی انجام شود.

هدف اصلی تست این است که مشخص شود آیا Endpoint فقط Propertyهای مورد انتظار را قبول می‌کند یا خیر.

روش امن تست می‌تواند شامل مقایسه موارد زیر باشد:

API Documentation

Request Schema

DTO

Domain Model

Response Model

Authorization Policy

و رفتار واقعی Endpoint.

اگر Domain Model دارای Propertyهایی باشد که در Request Schema دیده نمی‌شوند، باید بررسی شود آیا Backend واقعاً آن‌ها را از Request رد می‌کند یا خیر.

بررسی API Schema

وجود OpenAPI Specification می‌تواند تست را آسان‌تر کند.

برای هر Endpoint می‌توان بررسی کرد:

کدام Propertyها در Request Body تعریف شده‌اند؟

آیا additionalProperties کنترل شده است؟

کدام فیلدها Read-Only هستند؟

کدام فیلدها Write-Only هستند؟

آیا Schema ورودی با Domain Entity یکی شده است؟

آیا یک Schema واحد برای Create، Update و Response استفاده می‌شود؟

استفاده از یک Schema واحد برای تمام عملیات معمولاً باید با دقت بررسی شود.

Create و Update نباید الزاماً یک Schema داشته باشند

یکی از الگوهای مستعد خطا استفاده از یک Model مشترک برای همه عملیات است.

اما Propertyهای قابل استفاده هنگام Create ممکن است با Update متفاوت باشند.

برای مثال هنگام ساخت حساب، ممکن است Email لازم باشد.

پس از ایجاد حساب، تغییر Email شاید نیازمند فرآیند جداگانه تأیید هویت باشد.

بنابراین Schemaهای زیر می‌توانند متفاوت باشند:

CreateUserRequest
UpdateProfileRequest
ChangeEmailRequest
AdminUpdateUserRequest
UserResponse
AdminUserResponse

هرکدام یک هدف و سطح دسترسی متفاوت دارند.

Response Model نیز مهم است

Mass Assignment عمدتاً درباره Write Operation است، اما Responseها نیز باید محدود باشند.

اگر API تمام Propertyهای Domain Object را Serialize کند، اطلاعات داخلی می‌تواند افشا شود.

این افشا ممکن است شناخت ساختار Backend و Propertyهای حساس را آسان‌تر کند.

به همین دلیل طراحی امن API باید دو جهت را کنترل کند:

چه چیزی وارد API می‌شود؟

چه چیزی از API خارج می‌شود؟

OWASP نیز در راهنمای API3:2023 توصیه می‌کند تنها Propertyهای مورد نیاز در پاسخ ارائه شوند و ساختار داده خروجی به حداقل مورد نیاز Business Requirement محدود شود.

استفاده از Read-Only Property

بعضی Frameworkها و ابزارهای Schema اجازه علامت‌گذاری Property به‌عنوان Read-Only را می‌دهند.

این قابلیت مفید است، اما تیم توسعه باید مطمئن شود Backend واقعاً آن را enforce می‌کند.

صرفاً اینکه Documentation یک Property را Read-Only نمایش دهد به معنی تضمین امنیت نیست.

Server باید هنگام Runtime نیز از تغییر آن جلوگیری کند.

جداسازی Command و Query

در معماری‌های پیچیده، جداسازی مدل‌های خواندن و نوشتن می‌تواند ریسک را کاهش دهد.

یک Object ممکن است برای Response شامل ۲۰ Property باشد، اما Command مربوط به Update فقط دو Property دریافت کند.

این تفکیک باعث می‌شود توسعه‌دهنده مجبور نباشد همان Object بزرگ را در هر دو جهت استفاده کند.

این اصل با الگوهایی مانند CQRS نیز هم‌راستا است، هرچند برای پیاده‌سازی امن Mass Assignment الزامی نیست.

Mass Assignment در Microserviceها

در معماری Microservice، خطر فقط در API عمومی وجود ندارد.

Internal APIها نیز باید بررسی شوند.

یکی از اشتباهات متداول این است که تیم‌ها فرض کنند چون Endpoint فقط از شبکه داخلی قابل دسترسی است، نیازی به محدودسازی Propertyها ندارد.

اما سرویس داخلی ممکن است از طریق:

یک سرویس دیگر

Gateway

Queue Consumer

Job Worker

یا حساب سرویس

داده دریافت کند.

هر مرز اعتماد باید دقیق تعریف شود.

استفاده از Microservice به‌خودی‌خود مشکل Mass Assignment را حل نمی‌کند.

API Gateway چه کمکی می‌کند؟

API Gateway می‌تواند:

Authentication

Rate Limiting

Routing

Schema Validation

و برخی Policyهای مشترک

را مدیریت کند.

اما معمولاً تصمیم نهایی درباره اینکه «این کاربر اجازه تغییر این Property خاص از این Object را دارد یا خیر» وابسته به Business Logic داخل سرویس است.

بنابراین Gateway می‌تواند یک لایه دفاعی مفید باشد، ولی Application Authorization همچنان ضروری است.

نقش API Schema در معماری امن

Schema دقیق باعث می‌شود قرارداد Client و Server روشن باشد.

بهتر است برای هر عملیات مشخص شود:

Propertyهای مجاز

نوع داده

Constraintها

Propertyهای Required

Propertyهای Read-Only

و رفتار در برابر Unknown Fields

Schema همچنین می‌تواند برای تولید Automated Test استفاده شود.

اگر API Contract بخشی از CI/CD باشد، تغییر ناخواسته در سطح Propertyها راحت‌تر شناسایی می‌شود.

تست خودکار برای جلوگیری از بازگشت آسیب‌پذیری

اصلاح Mass Assignment نباید فقط به یک Patch دستی محدود شود.

برای Endpointهای حساس باید Regression Test نوشته شود.

یک تست مناسب بررسی می‌کند که:

فیلد مجاز قابل تغییر باشد.

فیلد غیرمجاز تغییر نکند.

Unknown Property رد شود یا طبق Policy نادیده گرفته شود.

کاربر با Role متفاوت رفتار مناسب دریافت کند.

تغییر Model داخلی باعث گسترش خودکار Request Contract نشود.

این تست‌ها اهمیت زیادی دارند، زیرا مدل‌های داده در طول عمر نرم‌افزار دائماً تغییر می‌کنند.

Secure Defaults در Binding

اگر Framework مورد استفاده قابلیت تنظیم Binding دارد، بهتر است Default به سمت محدودیت باشد.

به بیان دیگر:

همه چیز ممنوع باشد مگر آنچه صریحاً مجاز شده است.

نه اینکه:

همه چیز مجاز باشد مگر آنچه صریحاً ممنوع شده است.

این اصل احتمال خطا در آینده را کاهش می‌دهد.

Code Review برای شناسایی Mass Assignment

در Code Review باید الگوهای مربوط به Mapping و Binding بررسی شوند.

Reviewer می‌تواند به‌دنبال مواردی باشد که:

Request Body مستقیماً وارد ORM می‌شود.

Request Object مستقیماً به Entity تبدیل می‌شود.

تمام Propertyها در حلقه روی Object نوشته می‌شوند.

Controller بدون DTO کار می‌کند.

Update Generic بدون Field Allowlist وجود دارد.

Schema ورودی و Database Model یکی هستند.

Propertyهای امنیتی در Model کنار Propertyهای قابل ویرایش قرار گرفته‌اند.

این موارد الزاماً آسیب‌پذیری نیستند، اما نقاط مناسبی برای بررسی بیشتر هستند.

Threat Modeling و Mass Assignment

Mass Assignment را می‌توان پیش از پیاده‌سازی نیز در Threat Modeling شناسایی کرد.

برای هر Data Flow سؤال کنید:

داده از کجا وارد می‌شود؟

چه Entityهایی را تغییر می‌دهد؟

Client روی کدام Propertyها کنترل دارد؟

چه Propertyهایی Trust Boundary را عبور می‌کنند؟

چه تصمیم امنیتی براساس داده Client گرفته می‌شود؟

چه داده‌ای باید Server-Controlled باشد؟

این نوع بررسی مخصوصاً برای سیستم‌هایی مانند:

فروشگاه اینترنتی

سامانه مالی

SaaS چندسازمانی

پنل مدیریت

سامانه احراز هویت

Marketplace

و APIهای B2B

اهمیت بیشتری دارد.

نقش Business Logic در جلوگیری از آسیب‌پذیری

امنیت Mass Assignment صرفاً یک مسئله Framework نیست.

گاهی Property از نظر فنی قابل Update است و حتی Role کاربر نیز اجازه تغییر آن را دارد، اما تغییر موردنظر با Business Rule سازگار نیست.

فرض کنید مدیر یک تیم اجازه تغییر Role کاربران را داشته باشد، ولی نباید بتواند نقش کاربری را از سطح خودش بالاتر ببرد.

در این حالت Allowlist ساده کافی نیست.

Business Authorization باید Context تغییر را نیز بررسی کند.

بنابراین تصمیم امنیتی می‌تواند شامل موارد زیر باشد:

Who؟

What Object؟

Which Property؟

From What Value؟

To What Value؟

Under What Conditions؟

چرا Client-Side Validation کافی نیست؟

Validation سمت Client برای تجربه کاربری خوب است.

برای مثال می‌تواند مانع ارسال فرم ناقص شود یا Format ورودی را بررسی کند.

اما این Validation قابل دور زدن است.

تمام قوانین مهم باید در Server نیز اجرا شوند.

قاعده ساده این است:

هر چیزی که فقط در Frontend enforce شده، از دید امنیتی enforce نشده است.

آیا Hidden Input امن است؟

خیر.

Hidden Input فقط باعث می‌شود فیلد در رابط معمولی دیده نشود.

مقدار آن همچنان بخشی از Client است و نباید برای تصمیم‌های حساس بدون بررسی Server استفاده شود.

به‌خصوص Propertyهایی مانند:

user_id

price

role

permission

status

نباید صرفاً به دلیل Hidden بودن قابل اعتماد در نظر گرفته شوند.

جلوگیری از تغییر Ownership

Ownership یکی از حساس‌ترین حوزه‌هاست.

اگر یک Resource متعلق به User یا Organization خاصی است، Backend بهتر است مالکیت را از Context معتبر استخراج کند.

برای مثال Owner ممکن است از:

Authenticated User

Session

JWT Claims معتبر

Organization Membership

یا Policy داخلی

تعیین شود.

پذیرفتن مستقیم Owner Identifier از Request در شرایطی که Client حق تعیین مالک ندارد، معماری پرریسکی ایجاد می‌کند.

جلوگیری از تغییر Role و Permission

Role و Permission بهتر است در Workflowهای اختصاصی مدیریت دسترسی تغییر کنند.

Endpoint عمومی ویرایش Profile نباید چنین مسئولیتی داشته باشد.

تفکیک این عملیات چند مزیت دارد:

Authorization ساده‌تر می‌شود.

Audit واضح‌تر می‌شود.

تست آسان‌تر است.

کنترل‌های اضافی قابل اعمال هستند.

و احتمال Mass Assignment کاهش می‌یابد.

جلوگیری از تغییر وضعیت‌های سیستمی

Propertyهای مرتبط با Workflow باید با دقت زیادی طراحی شوند.

فرض کنید Order دارای وضعیت‌های زیر است:

pending
paid
processing
shipped
completed
cancelled

همه Actorها نباید اجازه انتقال Order بین تمام این Stateها را داشته باشند.

حتی اگر Property status در مدل وجود داشته باشد، بهتر است تغییر وضعیت از طریق Business Operation مناسب انجام شود.

برای مثال:

cancelOrder()
markAsPaid()
shipOrder()

این طراحی امکان اعمال Precondition و Authorization مناسب را فراهم می‌کند.

تأثیر Mass Assignment بر سیستم‌های چندسازمانی

در Multi-Tenant Applicationها Propertyهایی مانند:

tenant_id

organization_id

workspace_id

بسیار حساس هستند.

اگر کاربر بتواند Context Tenant یک Object را تغییر دهد، جداسازی منطقی میان مشتریان سیستم ممکن است آسیب ببیند.

بنابراین Tenant Context باید تا حد امکان از Identity معتبر و Context سرور تعیین شود، نه از یک Property قابل اعتماد Client.

Mass Assignment در پنل مدیریت

حتی Admin APIها نیز باید Allowlist داشته باشند.

این تصور که «Administrator به همه چیز دسترسی دارد» اغلب بیش از حد ساده است.

ممکن است چند سطح مدیریت وجود داشته باشد:

Support

Moderator

Organization Admin

Security Admin

Super Admin

هر Role باید فقط Propertyهای مورد نیاز خود را تغییر دهد.

همچنین حساب مدیریتی نیز ممکن است Compromise شود؛ محدود کردن Capability می‌تواند Blast Radius را کاهش دهد.

اشتباهات رایج در جلوگیری از Mass Assignment

اعتماد به Frontend

عدم نمایش یک Property در UI هیچ تضمین امنیتی ایجاد نمی‌کند.

استفاده از Blocklist محدود

مسدود کردن چند نام معروف ممکن است Propertyهای جدید را بدون حفاظت باقی بگذارد.

استفاده مستقیم از Request Body در ORM

اتصال مستقیم ورودی به Entity می‌تواند مرز میان API Contract و Data Model را از بین ببرد.

استفاده از یک Model برای همه عملیات

Create، Update، Admin Update و Response الزاماً نیازهای یکسانی ندارند.

اتکا به Validation بدون Authorization

معتبر بودن یک مقدار به معنی مجاز بودن کاربر برای تغییر آن نیست.

اعتماد به Authentication

کاربر Authenticated نیز ممکن است تلاش کند داده خارج از Permission خود را تغییر دهد.

اتکا به WAF

WAF معمولاً Context کافی برای تصمیم‌گیری درباره Property-Level Authorization ندارد.

نداشتن Regression Test

اگر اصلاح امنیتی بدون تست باقی بماند، تغییر بعدی در Model می‌تواند آسیب‌پذیری را دوباره ایجاد کند.

نادیده گرفتن Internal API

API داخلی نیز یک Trust Boundary دارد و باید Contract مشخص داشته باشد.

استفاده از Client برای محاسبه مقادیر حساس

مقادیر مالی، Ownership و وضعیت‌های امنیتی بهتر است در Backend تعیین شوند. چک‌لیست جلوگیری از آسیب‌پذیری Mass Assignment

چک‌لیست جلوگیری از آسیب‌پذیری Mass Assignment

برای هر Endpoint نوشتنی بررسی کنید:

آیا Request Body مستقیماً به Entity یا ORM داده می‌شود؟

آیا DTO مجزا وجود دارد؟

آیا فهرست Propertyهای مجاز صریح است؟

آیا Unknown Propertyها کنترل می‌شوند؟

آیا Propertyهای حساس Server-Controlled هستند؟

آیا Authorization در سطح Object انجام می‌شود؟

آیا Authorization در سطح Property نیز انجام می‌شود؟

آیا Roleهای مختلف Allowlist متفاوت دارند؟

آیا Create و Update Schema جدا هستند؟

آیا User و Admin از Request Model یکسان استفاده می‌کنند؟

آیا Ownership از Context معتبر تعیین می‌شود؟

آیا Validation سمت Server وجود دارد؟

آیا تغییر Property حساس Audit می‌شود؟

آیا تست منفی برای Propertyهای غیرمجاز وجود دارد؟

آیا تغییرات Domain Model در Code Review از نظر API بررسی می‌شوند؟

اگر پاسخ چند مورد از این سؤالات منفی باشد، Endpoint باید با دقت بیشتری بررسی شود. یک معماری امن برای Update کردن داده

یک معماری امن برای Update کردن داده

یک Flow مناسب برای عملیات Update می‌تواند به این صورت باشد:

HTTP Request
      ↓
Authentication
      ↓
Request Schema Validation
      ↓
DTO Creation
      ↓
Object-Level Authorization
      ↓
Property-Level Authorization
      ↓
Business Rule Validation
      ↓
Explicit Mapping
      ↓
Domain Model
      ↓
Database
      ↓
Audit Log

در این معماری هیچ مرحله‌ای به‌تنهایی مسئول تمام امنیت نیست.

Authentication هویت را مشخص می‌کند.

Schema Validation ساختار داده را بررسی می‌کند.

DTO سطح داده ورودی را محدود می‌کند.

Authorization دسترسی را کنترل می‌کند.

Business Logic صحت عملیات را بررسی می‌کند.

Explicit Mapping مشخص می‌کند دقیقاً چه چیزی تغییر کند.

این همان مفهوم Defense in Depth است.

پاسخ API در برابر Property غیرمجاز چگونه باشد؟

دو رویکرد رایج وجود دارد:

نادیده گرفتن Property ناشناخته

یا

Reject کردن Request

هرکدام مزایا و معایب خود را دارند.

نادیده گرفتن ممکن است Compatibility بیشتری داشته باشد، اما خطاهای Client را پنهان کند.

Reject کردن معمولاً Contract را شفاف‌تر می‌کند.

برای APIهای حساس، Fail Closed و Schema سخت‌گیرانه اغلب انتخاب مناسبی است.

مهم‌تر از انتخاب یکی از این دو رفتار، ثابت و مستند بودن Policy است.

وضعیت HTTP مناسب

Response Code نیز باید با رفتار API هماهنگ باشد.

برای ورودی نامعتبر ممکن است 400 Bad Request مناسب باشد.

در برخی طراحی‌ها 422 Unprocessable Content برای داده‌ای که از نظر Syntax معتبر است اما با قواعد Request سازگار نیست استفاده می‌شود.

برای عدم مجوز نیز پاسخ باید مطابق مدل Authorization سیستم طراحی شود.

با این حال نباید فقط به Status Code تکیه کرد؛ مسئله اصلی این است که تغییر غیرمجاز هرگز اعمال نشود.

Secure Coding در برابر Mass Assignment

توسعه امن در این حوزه چند اصل ساده ولی مهم دارد:

ورودی Client را Untrusted در نظر بگیرید.

API Contract را مستقل از Database Model تعریف کنید.

Allowlist را به Blocklist ترجیح دهید.

DTOهای کوچک و عملیات‌محور بسازید.

Propertyهای امنیتی را Server-Controlled نگه دارید.

Authorization را در Backend اجرا کنید.

Business Rule را از Client نپذیرید.

برای Propertyهای حساس Audit ایجاد کنید.

تست‌های منفی بنویسید.

این اصول وابسته به زبان برنامه‌نویسی خاصی نیستند.

نقش DevSecOps

Mass Assignment فقط مسئولیت برنامه‌نویس Backend نیست.

تیم DevSecOps می‌تواند کنترل‌هایی در Pipeline قرار دهد.

برای مثال:

Static Analysis

API Schema Review

Security Unit Tests

Integration Tests

Contract Tests

SAST

DAST

و Code Review Security Checklist

می‌توانند احتمال ورود دوباره ضعف را کاهش دهند.

البته ابزار خودکار معمولاً Business Logic را به‌طور کامل درک نمی‌کند؛ بنابراین بررسی انسانی همچنان اهمیت دارد.

چرا ابزارهای خودکار همیشه Mass Assignment را پیدا نمی‌کنند؟

برای تشخیص کامل این آسیب‌پذیری باید بدانیم چه Propertyهایی «نباید» برای کاربر قابل تغییر باشند.

این موضوع یک سؤال Business Logic است.

Scanner ممکن است متوجه شود API Property اضافی قبول می‌کند، اما الزاماً نمی‌داند آن Property حساس است یا خیر.

به همین دلیل بهترین روش ترکیبی است:

Automated Testing

Code Review

API Contract Review

Threat Modeling

و Manual Security Testing مجاز.

اهمیت مستندسازی Propertyهای حساس

در پروژه‌های بزرگ بهتر است تیم توسعه فهرستی از Data Classification داشته باشد.

برای مثال Propertyها می‌توانند به گروه‌هایی مانند زیر تقسیم شوند:

Public

User Editable

User Read-Only

Administrative

System Internal

Financial

Security Sensitive

PII

Secret

چنین دسته‌بندی‌ای تصمیم‌گیری هنگام طراحی DTO و Authorization را آسان‌تر می‌کند.

تغییر مدل داده باید یک رویداد امنیتی محسوب شود

هر بار که Property جدیدی به Entity حساس اضافه می‌شود باید این سؤال مطرح شود:

آیا این Property از API قابل مشاهده خواهد بود؟

آیا قابل نوشتن خواهد بود؟

چه Roleهایی اجازه دسترسی دارند؟

آیا Serializer آن را خودکار منتشر می‌کند؟

آیا Binding آن را خودکار قبول می‌کند؟

آیا Log آن را ذخیره می‌کند؟

این بررسی ساده می‌تواند از تبدیل یک تغییر معمولی Database به آسیب‌پذیری API جلوگیری کند.

چه Endpointهایی باید در اولویت بررسی باشند؟

Endpointهایی که عملیات Create یا Update انجام می‌دهند معمولاً اولویت بیشتری دارند.

خصوصاً:

ویرایش Profile

مدیریت User

مدیریت Organization

پرداخت و Billing

Subscription

Order

Wallet

Permission Management

Admin API

Moderation

Verification

KYC Workflow

و تنظیمات Account

هرچه Propertyهای امنیتی یا مالی بیشتری در Entity وجود داشته باشد، بررسی باید دقیق‌تر باشد.

تأثیر Mass Assignment بر E-Commerce

در فروشگاه اینترنتی Propertyهای زیادی وجود دارند که نباید مستقیماً تحت کنترل Client باشند.

برای مثال:

Final Price

Discount

Payment Status

Order Status

Seller ID

Commission

Refund Status

Credit

مقادیر نهایی باید براساس Business Logic سمت Server محاسبه و تأیید شوند.

اعتماد به داده Client در این بخش‌ها می‌تواند علاوه بر ضعف امنیتی، مشکل مستقیم مالی ایجاد کند.

تأثیر Mass Assignment بر سیستم‌های احراز هویت

در سیستم Identity، Propertyهایی مانند موارد زیر بسیار حساس‌اند:

Role

MFA Status

Email Verification

Account Lock

Password Reset State

Recovery Configuration

Trusted Device Status

تغییر چنین Propertyهایی باید از Workflowهای اختصاصی عبور کند.

برای مثال وضعیت Email Verification نباید صرفاً از یک Update Profile عمومی تغییر کند.

تأثیر Mass Assignment بر SaaS

در SaaSهای چندسازمانی موارد زیر اهمیت زیادی دارند:

Workspace Ownership

Organization Role

Billing Plan

Seat Count

Subscription State

Tenant ID

Feature Entitlement

این Propertyها معمولاً بخشی از منطق Business هستند و نباید مستقیماً به داده Client اعتماد کنند.

رابطه Mass Assignment با Zero Trust

یکی از اصول Zero Trust این است که اعتماد ضمنی براساس محل یا Client ایجاد نشود.

همین دیدگاه در API نیز قابل استفاده است.

اینکه درخواست:

از اپلیکیشن رسمی آمده،

از شبکه داخلی آمده،

دارای Token معتبر است،

یا متعلق به کاربر شناخته‌شده است،

به معنی مجاز بودن تمام داده‌های داخل Request نیست.

هر عملیات باید براساس Identity، Resource، Property و Policy بررسی شود.

Defense in Depth برای Mass Assignment

هیچ کنترل واحدی نباید تنها سد امنیتی باشد.

یک طراحی قوی می‌تواند چند لایه داشته باشد:

Schema محدود

DTO

Explicit Mapping

Property Authorization

Business Validation

Database Constraints

Audit Logging

Automated Tests

Monitoring

API Gateway

WAF

اگر یک لایه اشتباه کند، لایه دیگر ممکن است از تأثیر کامل خطا جلوگیری کند.

پایش رفتار غیرعادی API

Monitoring می‌تواند نشانه‌هایی از تلاش برای دستکاری Propertyها را مشخص کند.

برای مثال:

تعداد زیاد Requestهای دارای Unknown Property

تلاش برای ارسال فیلدهای خارج از Schema

تغییرات غیرعادی Role

تغییر Ownership

تغییر Status در زمان غیرمنتظره

یا تکرار خطاهای Authorization

می‌تواند ارزش بررسی داشته باشد.

البته Alert باید براساس رفتار واقعی سیستم طراحی شود تا False Positive بیش از حد ایجاد نکند.

فرآیند مناسب اصلاح آسیب‌پذیری Mass Assignment

اگر Mass Assignment در یک API شناسایی شد، اصلاح صرفاً مسدود کردن Property کشف‌شده کافی نیست.

بهتر است مراحل زیر انجام شود.

ابتدا Scope مشخص شود.

تمام Endpointهایی که از همان Model، Serializer، DTO یا Binding Mechanism استفاده می‌کنند بررسی شوند.

سپس Root Cause مشخص شود.

آیا مشکل Generic Update است؟

آیا DTO وجود ندارد؟

آیا Allowlist ناقص است؟

آیا Authorization Property-Level وجود ندارد؟

بعد از اصلاح، Regression Test نوشته شود.

در نهایت Logها و داده‌های قبلی بررسی شوند تا مشخص شود آیا تغییر غیرمنتظره‌ای رخ داده است یا خیر.

چرا Patch موضعی کافی نیست؟

فرض کنید آسیب‌پذیری روی Property role پیدا شده است.

اگر توسعه‌دهنده فقط همین Property را Block کند، Property دیگری مانند account_type ممکن است همان اثر را داشته باشد.

اصلاح امن باید معماری Binding را تغییر دهد.

به همین دلیل Root Cause Analysis اهمیت دارد.

هدف باید این باشد که هیچ Property خارج از Contract بدون تصمیم صریح توسعه‌دهنده قابل تغییر نباشد.

معیار یک API مقاوم در برابر Mass Assignment

یک API سالم باید بتواند پاسخ روشنی برای این سؤال داشته باشد:

«برای این Endpoint، این Role، این Resource و این Operation دقیقاً کدام Propertyها قابل تغییر هستند؟»

اگر پاسخ این سؤال از روی Code، Policy یا Schema مشخص نباشد، احتمالاً طراحی بیش از حد ضمنی است.

هرچه تصمیم‌های امنیتی Explicitتر باشند، نگهداری سیستم در آینده آسان‌تر خواهد شد.

سؤالات متداول درباره Mass Assignment

Mass Assignment چیست؟

Mass Assignment آسیب‌پذیری‌ای است که در آن Backend مجموعه داده دریافت‌شده از Client را بدون محدودسازی کافی به Object یا Model داخلی متصل می‌کند. در نتیجه ممکن است Propertyهایی که کاربر اجازه تغییر آن‌ها را ندارد نیز قابل ویرایش شوند.

آیا Mass Assignment فقط در APIهای REST رخ می‌دهد؟

خیر. این مشکل می‌تواند در هر معماری‌ای رخ دهد که داده Client به شکل خودکار یا بیش از حد عمومی به Object داخلی متصل شود. REST، GraphQL و حتی برخی فرم‌های سنتی وب می‌توانند تحت تأثیر قرار بگیرند.

آیا Mass Assignment همان BOLA است؟

خیر. BOLA بیشتر درباره مجوز دسترسی به یک Object است، در حالی که Mass Assignment درباره مجوز تغییر Propertyهای آن Object است. هر دو بخشی از مشکلات Access Control هستند ولی سطح کنترل آن‌ها متفاوت است.

Mass Assignment در OWASP کدام دسته است؟

در OWASP API Security Top 10 سال ۲۰۱۹، Mass Assignment تحت عنوان API6:2019 معرفی شده بود. در نسخه ۲۰۲۳ این موضوع همراه با Excessive Data Exposure در API3:2023 یا Broken Object Property Level Authorization ادغام شده است.

بهترین روش جلوگیری از Mass Assignment چیست؟

مهم‌ترین روش این است که ورودی Client مستقیماً به Domain Model متصل نشود و فقط Propertyهای موردنیاز هر Operation به‌صورت Allowlist تعریف شوند. استفاده از DTO، Schema Validation، Explicit Mapping و Property-Level Authorization نیز بسیار مؤثر است.

آیا Validation برای جلوگیری کافی است؟

خیر. Validation بررسی می‌کند مقدار معتبر است یا نه، اما Authorization تعیین می‌کند کاربر اجازه تغییر آن Property را دارد یا خیر. API امن به هر دو نیاز دارد.

آیا JWT جلوی Mass Assignment را می‌گیرد؟

خیر. JWT می‌تواند بخشی از Authentication یا Authorization باشد، اما جلوی Binding ناامن Propertyها را به‌صورت خودکار نمی‌گیرد.

آیا WAF می‌تواند این آسیب‌پذیری را رفع کند؟

WAF می‌تواند یک لایه دفاعی اضافه ایجاد کند، اما معمولاً Business Context لازم برای تشخیص Property مجاز و غیرمجاز را ندارد. اصلاح اصلی باید در Application Code و API Contract انجام شود.

آیا استفاده از DTO ضروری است؟

از نظر فنی تنها راه‌حل نیست، اما DTO یکی از بهترین الگوها برای جدا کردن ورودی API از Domain Model و کاهش احتمال Mass Assignment است.

آیا Unknown Fieldها باید رد شوند؟

در APIهای حساس، رد کردن Propertyهای خارج از Schema معمولاً Contract را شفاف‌تر می‌کند. با این حال رفتار دقیق باید براساس طراحی سیستم انتخاب و به‌صورت ثابت enforce شود.

آیا Admin API به Property-Level Authorization نیاز دارد؟

بله. Administratorها نیز ممکن است سطوح دسترسی متفاوت داشته باشند. علاوه بر این، محدودسازی Capability می‌تواند تأثیر Compromise شدن یک حساب مدیریتی را کاهش دهد.

آیا Mass Assignment فقط مشکل برنامه‌نویسی Backend است؟

خیر. طراحی API، Data Model، Authorization Policy، Testing، DevSecOps، Logging و Threat Modeling همگی در پیشگیری از این آسیب‌پذیری نقش دارند.

جمع‌بندی

Mass Assignment در ظاهر می‌تواند یک خطای ساده در Data Binding باشد، اما در APIهایی که Propertyهای حساس، مالی یا مدیریتی دارند ممکن است به یکی از مهم‌ترین ضعف‌های کنترل دسترسی تبدیل شود.

مشکل اصلی زمانی ایجاد می‌شود که Backend به‌جای تعریف دقیق داده‌های مجاز، تمام یا بخش بزرگی از ورودی Client را مستقیماً به Domain Model، ORM Entity یا Object داخلی متصل کند. در چنین شرایطی Propertyای که هرگز در رابط کاربری نمایش داده نشده ممکن است همچنان از طریق API قابل تغییر باشد.

اصل اساسی این است که Client نباید تعیین کند چه چیزی اجازه تغییر دارد.

Backend باید برای هر Operation مشخص کند کدام Propertyها قابل دریافت هستند، چه کسی اجازه تغییر آن‌ها را دارد و تغییر هر Property تحت چه Business Ruleهایی مجاز است.

استفاده از DTOهای اختصاصی، Allowlist، Schema Validation، Explicit Mapping، Object-Level Authorization و Property-Level Authorization می‌تواند احتمال Mass Assignment را به‌شدت کاهش دهد.

در کنار این کنترل‌ها، تست خودکار، Code Review، Threat Modeling، Audit Logging و Monitoring باعث می‌شوند آسیب‌پذیری در تغییرات بعدی نرم‌افزار دوباره ظاهر نشود.

مهم‌ترین نکته این است که امنیت API فقط در سطح Endpoint یا Object تعریف نمی‌شود. حتی وقتی کاربر اجازه دسترسی به یک Resource را دارد، این موضوع به معنی اجازه مشاهده یا تغییر تمام Propertyهای آن Resource نیست.

طراحی امن زمانی شکل می‌گیرد که این مرزها به‌صورت صریح، قابل تست و قابل نگهداری تعریف شوند.

در یک API امن، سؤال فقط این نیست که «کاربر به چه Objectای دسترسی دارد؟»؛ بلکه باید مشخص باشد «روی آن Object، دقیقاً چه Propertyهایی و تحت چه شرایطی قابل تغییر هستند؟»

همین تفکیک می‌تواند مرز میان یک API قابل اعتماد و سامانه‌ای باشد که یک قابلیت ساده Automatic Binding در آن به مسیر تغییر غیرمجاز داده‌های حساس تبدیل شده است.

مطالب مرتبط