Sicherheit von Web-Applikationen ist eines meiner Lieblingsthemen. So habe ich vor einigen Jahren ein Papier zum Thema SQL Injection und Cross-Site Scripting geschrieben. Dieses diente damals einem Firmen-internen Vortrag bei meiner Lehrfirma. Der Schwerpunkt dieses Papiers lag auf der Verhinderung der Angriffe mit Active Server Pages.

Das Thema ist nach wie vor aktuell, und nach wie vor gibt es da viel zu tun. Bei der Evaluation von Ruby on Rails ist es für mich auch wichtig, wie ich da SQL Injection und Cross-Site Scripting verhindern kann. Das Manual Securing your Rails ist prominent auf der Startseite des Bereiches Dokumentation verlinkt und gibt Auskunft.

Erstmal kümmert sich Rails um sehr viele Dinge selber. So werden ja viele Funktionen für den Datenbank-Zugriff der Daten automatisch generiert und diese sind gegen SQL Injection Probleme geschützt. Um bei einer eigenen Query (find_all heisst die Funktion dazu) keine Probleme damit zu erhalten, müssen die Benutzer-Eingaben bereinigt werden. Dazu kann man eine Methode verwenden, welche der Möglichkeit von “Prepared Statements” in anderen Frameworks nicht unähnlich ist. Ein Beispiel:

Customer.find_all [ "company = ?", company ]

Dies gibt mir alle Kunden zurück, deren Firmenname mit dem Wert der Variable company übereinstimmt. (Diese Funktion muss seit Rails 0.9.3 dank den "dynamic finders" nicht mehr mit find_all implementiert werden.)

Eine Schwierigkeit, die ich hatte, war eine LIKE Abfrage. Ich hatte eine Suchabfrage mit einer WHERE company LIKE '%eingabe%' Bedingung. Erster Versuch war dann so etwas:

Customer.find_all [ " company LIKE '%?%' ", company ]

Doch das führt nicht zum gewünschten Resultat. Denn da herauskommt, wenn company z.B. den Wert "test" enthält: company LIKE '%'test'%'. Um die Variable company werden als Hochkommas eingefügt, so dass ich mit dieser Variante zwei Hochkommas zu viel in der Abfrage haben werde. Dann habe ich im #rubyonrails IRC Channel nachgefragt und präsentiert wurde mir die Antwort, auf die ich eigentlich selber hätte kommen sollen. Und so macht man's richtig:

Customer.find_all [ " company LIKE ? ", '%#{company}%' ]

Der Ausdruck #{company} ist eine Möglichkeit, in einem String den Wert der Variable zu verwenden. Die beiden Prozentzeichen werden also aus der Anfrage rausgenommen und direkt in den Abfrage-Wert reingepackt. So kommen die Hochkommas um den ganzen Ausdruck mit den Prozenten und alles ist in Ordnung.

Also nochmals die Kurzfassung. Für normale Abfragen verwende man
Customer.find_all [ "company = ?", company ]
und wenn man eine LIKE '%xx%' Abfrage erstellen möchte, kommt
Customer.find_all [ " company LIKE ? ", '%#{company}%' ]
zum Zuge.