Model Binding è una funzionalità piuttosto interessante e può aggiungere un vantaggio alla sicurezza generale se viene utilizzata correttamente.
Ecco come funziona (il codice e le funzionalità si applicano a ASP.NET MVC ma potrebbe essere lo stesso in Ruby):
Supponiamo di avere un modulo in una pagina web:
<form action="/SendData">
Email: <input type="text" name="email" id="email"><br>
Address:<input type="text" name="address" id="address"><br>
<input type="submit" value="Submit">
</form>
Scrivi una classe come questa:
class Contact{
String Email{get;set;}
String Address{get;set;}
}
Con l'associazione modello la funzione che riguarda la richiesta dell'utente può essere:
public ActionResult SendData(Contact contact){
//do something with contact.Email and contact.Address
}
Come puoi vedere, il binding di modelli inserisce automaticamente i dati ricevuti nella richiesta HTML in un oggetto di tipo Contact.
Inoltre, è possibile definire le funzioni di convalida utilizzando DataAnnotations.
class Contact{
[Required(ErrorMessage="Input email please!")]
[RegularExpression("^some_regex"),ErrorMessage ="Error"]
String Email{get;set;}
[Required(ErrorMEssage="Input address please!")]
String Address{get;set;}
}
e controlla in questo modo:
public ActionResult SendData(Contact contact){
if(ModelState.IsValid)
{
//do something with contact.Email and contact.Address
}
}
Come puoi vedere, è facile aggiungere la convalida e alcuni errori comuni (come le query SQL scritte male possono essere evitate).
Ora spieghiamo il problema che ha portato all'hack di GitHub (binding di massa):
Che cosa accade se nella classe sono presenti proprietà che non compaiono nel modulo:
<form action="/SendData">
Email: <input type="text" name="email" id="email"><br>
<input type="submit" value="Submit">
</form>
Se un utente malintenzionato invia anche una variabile con il nome indirizzo , il framework lo vincolerà automaticamente, senza sapere che nel modulo originale non era presente tale input.
Nel caso GitHub , gli sviluppatori probabilmente hanno utilizzato un oggetto con una proprietà che si differenziava tra amministratori e utenti normali (ad esempio isAdmin ). Inviando questo parametro nel modulo di login (o in un'altra pagina), insieme all'utente e alla password, l'utente malintenzionato avrebbe potuto accedere alla funzionalità amministrativa.
Ci sono diversi modi per risolvere questo problema (blacklist binding, whitelist binding), ma io raccomando l'uso di interfacce e classi che contengono solo le proprietà del modulo (o l'altro attribuito contrassegnato come di sola lettura ).
Whitelist esempio di bind:
public ActionResult SendData(
[Bind(Include="Email")]Contact contact)
{
//...
}
Riguardo ai framework interessati, probabilmente la maggior parte di essi sono interessati (Ruby e ASP lo sono), ma questa non è una vulnerabilità in sé, è solo una cattiva programmazione. Finché i programmatori affrontano questa funzionalità correttamente, tutto dovrebbe essere OK.
Non penso che uno strumento automatico possa rilevare questo tipo di problemi, ma una revisione approfondita del codice dovrebbe risolverlo.