Mass Assignment

Indice dei contenuti

    Il mass assignment è una vulnerabilità che si manifesta quando un framework o un’applicazione associa automaticamente i parametri di una richiesta HTTP agli attributi di un oggetto del modello dati, senza filtrare quali campi possono essere modificati dall’utente. Un attaccante che conosce (o indovina) il nome di un attributo privilegiato può includerlo nella richiesta e modificarlo, bypassando i controlli di autorizzazione.

    La vulnerabilità è strettamente legata alla caratteristica di model binding automatico di molti framework web (Rails, Laravel, Django, Spring, ASP.NET MVC).

    Meccanismo

    Un’applicazione espone un endpoint di aggiornamento del profilo utente:

    PUT /api/utenti/42
    Content-Type: application/json
    
    {
      "nome": "Mario",
      "email": "mario@esempio.it"
    }

    Il controller associa automaticamente tutti i campi JSON all’oggetto utente:

    # Codice vulnerabile — Rails / Python analogy
    utente = Utente.find(42)
    utente.update(request.json)   # bind di TUTTI i campi presenti
    utente.save()

    Il modello Utente ha anche i campi ruolo, admin, credito, email_verificata. L’attaccante invia:

    {
      "nome": "Mario",
      "email": "mario@esempio.it",
      "ruolo": "admin",
      "credito": 99999
    }

    Se il binding è indiscriminato, tutti i campi — inclusi quelli privilegiati — vengono aggiornati.

    Caso storico: GitHub (2012)

    La vulnerabilità fu resa celebre da Egor Homakov, che nel 2012 aggiunse la propria chiave SSH pubblica al repository del progetto Rails su GitHub sfruttando mass assignment. Il campo public_key[user_id] non era nella lista nera e veniva accettato direttamente. L’incident portò Rails a cambiare il comportamento di default verso il whitelisting.

    Varianti

    Nested mass assignment: gli oggetti annidati nel JSON possono esporre attributi di modelli correlati:

    {
      "nome": "Mario",
      "indirizzo": {
        "via": "Roma 1",
        "validato": true
      }
    }

    Array injection: in alcune implementazioni, array o hash aggiuntivi vengono mappati a relazioni o attributi non previsti.

    Parameter pollution combinata: usare HTTP Parameter Pollution per aggirare un filtro che opera sul primo parametro ma il binding usa il secondo.

    Contromisure

    Whitelisting esplicito (approccio consigliato): specificare esplicitamente quali campi possono essere aggiornati dall’utente — tutto il resto viene ignorato:

    # Sicuro — solo i campi consentiti vengono usati
    CAMPI_MODIFICABILI = {'nome', 'email', 'bio'}
    
    def aggiorna_utente(utente_id, dati):
        utente = Utente.find(utente_id)
        dati_filtrati = {k: v for k, v in dati.items() if k in CAMPI_MODIFICABILI}
        utente.update(dati_filtrati)

    In Rails: params.require(:utente).permit(:nome, :email). In Laravel: $request->only(['nome', 'email']).

    Data Transfer Object (DTO): separare il modello esposto dall’API dal modello dati interno. Il DTO definisce esplicitamente i campi accettabili in input; la mappatura verso il modello è esplicita e controllata.

    Blacklisting (sconsigliato): escludere solo i campi sensibili. Approccio fragile: ogni nuovo attributo privilegiato aggiunto al modello deve essere ricordato nella lista nera — un’omissione espone immediatamente il campo.

    Readonly attributes: molti ORM supportano attributi dichiarabili come non modificabili via mass assignment a livello di modello.

    Test espliciti: includere nei test di sicurezza tentativi di aggiornamento di campi privilegiati per verificare che vengano rifiutati.

    Relazione con altri argomenti

    • OWASP Top 10 — A01 Broken Access Control.
    • BOLA — mentre mass assignment riguarda quali campi si possono modificare, BOLA riguarda quali oggetti si può accedere.
    • Secure SDLC — la difesa efficace richiede una revisione del design API in fase precoce.
    • Vulnerabilità Informatica — classificata CWE-915 (Improperly Controlled Modification of Dynamically-Determined Object Attributes).

    Ultimo aggiornamento: