Mein erstes Rails-Gem: Ein möglicher Fix für das Massassignment-Problem in Rails
Montag, 02. April 2012 um 17:12 von Christian Eichhorn in Webentwicklung
Ich muss mich erstmal kurz vorstellen: ich bin einer der Entwickler hinter der IT-Infrastruktur, die ihr als Fernstudenten und Präsenzteilnehmer hier tagtäglich nutzt; wenn etwas mal nicht funktioniert (selten), oder der Kunde sagt: "genauso, wie ihr das anbietet, will ich das, bloß ein bisschen anders!" (schon ein wenig häufiger), dann heißt es immer: "Christian!!!!". Manche Fernstudenten kennen mich auch schon aus dem Onlinecampus.
Zur Sache: Ich habe gerade mein erstes Rails-Gem veröffentlicht. Ein Gem ist eine kleine Erweiterung, um eine Ruby- bzw. Rails-Applikation um bestimmte Funktionen zu erweitern.
Der Hintergrund: unter bestimmten Bedingungen können in sich Anwender in Rails-Anwendungen wie unserer hier Admin-Rechte erschleichen, und das will man natürlich nicht. In der Rails-Gemeinde hat es da in letzter Zeit ein wenig Aufregung deshalb gegeben. Ich habe mir das Problem angesehen und eine Lösung dafür gefunden, die gut funktioniert, zumindest für uns; hier ist sie.
Also, ab jetzt bitte nur Rails-Entwickler weiterlesen; alle anderen kriegen sonst, glaube ich, glasige Augen...
Da die Daten-Objekte in einer Rails-Applikation im Front- und im Backend verwendet werden, ist es schwierig, die Attribute über die Modelle zu schützen.
Kurze Problem-Beschreibung:
Mittels record.update_attributes(params[:record]) ist es möglich, die Attribute des records aus einem Formular zu aktualisieren. Dadurch ist es aber auch möglich, dass ein verändertes Formular im Browser andere Attribute setzt als die, die vom Entwickler gedacht waren.
Beispiel:
Um einen User als Admin zu markieren, genügt es das Attribute admin auf true zu setzen (User ist ein Admin!).
Fügt nun ein User in seinem Profil-Formular im Browser durch diverse Tools ein Formular-Feld hinzu
<input type="hidden" value="1" name="user[admin]" id="user_admin">
und im Controller wird folgender Ruby-Code verarbeitet
# Code zum Auslesen des Users aus der Datenbank user.update_attributes(params[:user]) # Code zum Rendern der Anzeige
ist es möglich sich Admin-Rechte zu erschleichen!
Mögliche Lösung:
Das Formular übermittelt der Controller-Action, welche Attribute erlaubt sind. Hierfür wurde folgendes GEM entwickelt: massassignment_security_form
Hierdurch werden die form_helper in Rails erweitert. Das Formular übermittelt dem Controller, welche Attribute erlaubt waren:
<% form_tag({:action => "update"}) do %> <%= error_messages_for :user %> <table> <tr> <td><label for="user_title">Title:</label></td> <td><%= text_field :user, :title %></td> </tr> <tr> <td><label for="user_first_name">Vorname:</label></td> <td><%= text_field :user, :first_name %></td> </tr> <tr> <td><label for="user_name">Name:</label></td> <td><%= text_field :user, :name %></td> </tr> <tr> <td colspan="2"> <%= submit_tag 'Speichern' %> </td> </tr> </table> <% end %>
Hierdurch wird folgendes Formular in HTML erzeugt:
<form method="post" action="/route/to/users/update"> <table> <tr> <td><label for="user_title">Titel:</label></td> <td><input type="text" value="" size="30" name="user[title]" id="user_title"></td> </tr> <tr> <td><label for="user_first_name">Vorname:</label></td> <td><input type="text" value="Christian" size="30" name="user[first_name]" id="user_first_name"></td> </tr> <tr> <td><label for="user_name">Name:</label></td> <td><input type="text" value="Eichhorn" size="30" name="user[name]" id="user_name"></td> </tr> <tr> <td> <input type="submit" value="Speichern" name="commit"> </td> </tr> </table> <input type="hidden" value="VerschluesselterHashMitDenAttributenFuerDenUser" name="massassignment_fields"> </form>
Die erlaubten Attribute im Formular werden im Hidden-Field (massassignment_fields) verschlüsselt hinterlegt und beim Absenden übertragen!
Nach dem Absenden sorgt ein before-Filter dafür, dass nur die Attribute in params[:user] erhalten bleiben, die in diesem Formular erlaubt sind.
Das Formular kann zwar im Browser manupuliert werden, aber es werden nur noch die vorher definierten Attribute übernommen.
Wenn der verschlüsselte Hash nicht verarbeitet werden kann, werden keine Attribute aus dem Formular übernommen!
In der README wird erklärt, wie Ihr das Gem bei Euch nutzen könnt!
Tags: Ruby , Rails , Massassignment fix