XSS-Protection in Rails 3

Für mein „altes“ Rails 2 Projekt habe ich mir – zum Schutz vor Cross-Site-Scripting (XSS) Attacken – ein kleines Modul geschrieben, das gefährliche HTML-Tags aus jedem Attribut eines Models mittels h() Methode entfernt. In der neuen Version kann ich darauf komplett verzichten.

In Rails 3 werden standardmäßig alle Ausgaben von unerwünschtem Code gesäubert. Ein einfaches aber sehr wirkungsvolles Feature.

Es kann Fälle geben, bei denen man bewusst auf diese Funktion verzichten will. Hierfür steht die raw() Methode zur Verfügung:

  1. < %= raw article.content %>

Die raw() Methode macht nichts anderes, als dass sie das Attribut html_safe des String-Objekts (bzw. ActiveSupport::SafeBuffer) setzt. Dieses wird beim Rendering des Views abgefragt und entscheidet letztendlich darüber, ob der auszugebende HTML-Code gesäubert wird oder nicht.

In meinen Helper-Methoden ziehe ich es vor auf die raw() Methode zu verzichten und html_safe selbst aufzurufen:

  1. def article_head(article)
  2.   "<h1>#{article.title}</h1>
  3.   <span class='date'>#{article.date}</span>".html_safe
  4. end
Share

ActiveRecord: Vorsicht bei der Massenänderung von Attributen

Rails bietet einfache Möglichkeiten um einem Objekt alle benötigten Attribute zuzuweisen. Einem ActiveRecord Model können z.B. schon bei der Instanziierung alle gewünschten Attribute aus den Request-Parametern (z.B. aus einem Formular) übergeben werden. Dieses Vorgehen nennt sich im Rails-Jargon „Mass-assignment“.

Nehmen wir an wir haben ein Model „Comment“, dass die Kommentare von Benutzern einer Webseite speichert. Um Spam vorzubeugen, sollen alle Kommentare erst nach redaktioneller Überprüfung angezeigt werden, weshalb das Model ein Attribut „reviewed“ besitzt. Nur wenn dieses den Wert „1“ hat, wird der Kommentar öffentlich angezeigt.
In der Methode für die Speicherung eines neuen Kommentars steht nun folgender Code:

  1. @comment = Comment.new(params[:comment])

Würde der Anwender den Request nun so manipulieren (z.B. durch das Einfügen eines weiteren Feldes im HTML-Formular), dass dem Host der Parameter params[:comment][:reviewed] mit dem Wert „1“ übergeben wird, wäre die redaktionelle Prüfung umgangen.

Um das zu verhindern, gibt es in ActiveRecord die Methode attr_accessible. Mit dieser kann eine Whitelist der Attribute erstellt werden, die durch Mass-assignment verändert werden dürfen. Die Methode attr_protected bietet die selbe Funktionalität, jedoch mit einem Blacklist-Verfahren, d.h. es werden Attribute definiert, die nicht verändert werden dürfen.

Im Beispiel der Kommentare, müsste man also im Model „Comment“ diesen Code hinterlegen:

  1. attr_protected(:reviewed)

Dann kann das Attribut nur noch mit dem direkten Zugriff manipuliert werden z.B:

  1. comment.reviewed = true

Ich persönlich bevorzuge übrigens das Whitelist-Verfahren, da somit Flüchtigkeitsfehler bei der Entwicklung vermieden werden können ;-)

Share