Die fünf Stufen zur sicheren Webapplikation mit ColdFusion

Mischa Sameli, Geschäftsführer & Leiter Entwicklung

Webapplikationen sind so lange sicher, bis etwas Unerwartetes geschieht. Eine Phrase, klar. Aber so wahr wie nur irgendetwas, leider. Denn selten werden alle möglichen und bekannten Sicherheitsvorkehrungen bei der Erstellung einer Webapplikation getroffen, meistens natürlich aus Zeitmangel. Im Folgenden werde ich auflisten, welche Massnahmen ich weshalb bei der Konzipierung einer ColdFusion-Applikation berücksichtigt und schliesslich integriert habe.

Im Voraus soll gleich einmal festgehalten werden, dass dies nicht eine abschliessende Liste der Möglichkeiten darstellt. Denn ich werde mich rein auf Massnahmen beschränken, die mir als Programmierer zur Verfügung stehen. Als Webmaster oder Hosting-Anbieter stehen mir logischerweise weitere Tools (Firewall, Url-Rewriting, Einstellungen am ColdFusion-Server) zur Verfügung, als Entwickler kann ich den Zugang zu diesen Möglichkeiten aber nicht voraussetzen und habe folglich eigene Massnahmen zu treffen. Nun aber zurück zum Thema. Und den fünf Stufen zur sicheren Webapplikation mit ColdFusion. Kurz zusammengefasst ergibt sich für mich folgender Ablauf:

  1. Schaden verhindern
  2. Müll entfernen
  3. User bei Angaben unterstützen und Eingaben Client-seitig überprüfen
  4. Benutzereingaben Server-seitig validieren
  5. sicher ist sicher

So betrachtet kein grosser Aufwand, würde man meinen. Und trotzdem scheut man oft die Arbeit. Nicht so, wenn man die richtigen Tools einsetzt. Und zwar effizient. Aber wiederum eins nach dem anderen.

  1. Schaden verhindern In unserem Fall bedeutet dies, Hacking-Angriffe abzuwehren. Und wir sprechen dabei von SQL-Injections und Cross-Site-Scripting (XSS). Diesen Job erledigen grundsätzlich Firewalls am effizientesten. Aber wie bereits erwähnt, kann man nicht davon ausgehen, dass diese auch dafür konfiguriert worden sind oder werden. Eine bekannte Open-Source-Lösung für ColdFusion ist Portcullis von John Mason. Die Bibliothek läuft und Adobe ColdFusion 6 bis 8 und Railo, mit ziemlicher Sicherheit auch mit BlueDragon, was ich aber nicht getestet habe. Die Integration von Portcullis ist denkbar einfach. Im einfachsten Fall sieht der Code dafür etwa so aus:
    1<!--- Komponente in den Application-Scope laden, sofern nicht bereits vorhanden ---><cfif isdefined("application.Portcullis") >
    2<cfset application.Portcullis = createObject("component","com.fusionlink.Portcullis").init()/>
    3</cfif><!--- Scopes durchtesten ---><cfset application.Portcullis.scan(url,"url",cgi.remote_addr)>
    4<cfset application.Portcullis.scan(form,"form",cgi.remote_addr)>
    5<cfset application.Portcullis.scan(cookie,"cookie",cgi.remote_addr)>
    6<!--- Bei Verdacht, Uebung abbrechen und auf Fehlerseite umleiten --->
    7<cfif application.Portcullis.isBlocked(cgi.remote_addr) eq true>
    8<!--- umleiten oder was auch immer --->
    9<cfabort>
    10</cfif>
    Simpel, und ohne Probleme in bestehende Applikationen einzubauen. Die Konfiguration der einzelnen Prüfmechanismen ist direkt in die Komponente integriert. Das ist natürlich nett, wenn man Portcullis bei vielen Applikationen mit der gleichen Konfiguration verwenden und jeweils updaten möchte. Für individuelle Einstellungen ist dies natürlich nicht allzu optimal. Deshalb habe ich für unser Demo-Projekt die Komponente so angepasst, dass die Konfiguration ausgelagert werden kann. Sprich, es mussten getter- und setter-Funktionen erstellt und die init()-Funktion angepasst werden. Somit war ich bereits in der Lage, die Konfiguration von Portcullis über ColdSpring anzupassen, und kann trotzdem noch die Standard-Werte für alle Applikationen global anpassen, indem ich die Komponente aktualisiere. Wenn ich ColdSpring für ein Projekt nicht verwende, muss natürlich auch nichts am Code geändert werden. Im Falle des Demo-Projekts mit Model-Glue habe ich die Scan-Funktionen im Event onRequestStart() untergebracht; bei CF-Projekten ab Version 7 in der Datei application.cfc. Somit werden die Scans bei allen Request durchgeführt, sollte ich sie aus irgendwelchen Gründen nicht mehr benötigen, kann ich sie an diesem einen Ort im zentralen Controller-File entfernen. Auf jeden Fall haben wir damit schon eine grosse Gefahrenquelle elimiert.
  2. Müll entfernen Damit ist natürlich Spam gemeint, klar. Spam richtet zwar in den meisten Fällen keinen direkten Schaden an, ist aber trotzdem ärgerlich und verursacht einmal primär Kosten. Eine kostengünstige Variante habe ich mit der Open-Source-Bibliothek cfFormProtect gefunden. Die Integration habe ich im gestrigen Beitrag bereits beschrieben. Auch diese Komponente habe ich übrigens geringfügig angepasst, sodass sie nun über Getter- und Setter-Funktionen verfügt und einfach via ColdSpring konfiguriert werden kann. cfFormProtect lässt sich leicht erweitern, bietet aber bereits in der Grundausstattung ausreichend Schutzfunktionalitäten. Und selbstverständlich hätte man auch hier Methoden zur Verhinderung von SQL-Injections und XSS integrieren können. Aber die Aufgabentrennung, wie sie nun integriert ist, gefällt mir von der Logik her besser.
  3. User bei der Eingabe unterstützen und Client-seitige Validierung Eine grosse Fehlerquelle sind Benutzereingaben. Denn Benutzer verstehen auch heute noch nicht, in welchem Format sie zum Beispiel Datumseingaben tätigen müssen – weils keine Regel gibt und in der Regel auch zuwenig Hilfen. In diesem Sinne möchte ich hier gar nicht gross auf Usability bei Formularen eingehen – dazu gibt's ausgezeichnete Quellen wie zum Beispiel http://www.jasonbartholme.com/101-resources-to-help-you-build-a-better-web-form/. Die wenigen Prinzipien die ich für das Projekt verfolgt habe: Code, der validiert, ein Layout, das nett aussieht und sinnvolle sowie einfache Validierungen. Diese Anforderungen haben mich schliesslich zu cfUniForm geführt, einer Open-Source-Bibliothek, die auf Uni-Form beruht. Die Bibliothek unterstützt eine live-Validierung, also onBlur() mit Hilfe des jQuery-Plugins Validation. Die Kombination ist extrem flexibel und ebenfalls wirklich einfach integrieren.
  4. Benutzereingaben Server-seitig validieren Selbstverständlich reicht die Client-Seitige Validierung der Benutzereingaben nicht aus. Die Server-seitige Lösung stammt in diesem Fall von der Open-Source-Bibliothek ValidateThis. Und das coole an dieser Bibliothek ist, dass sie Client- und Server-seitige Validierungen über eine einzige Konfiguration anbietet und ebenfalls das jQuery-Plugin Validation verwendet. Eine Kombination mit cfUniForm ist folglich kein Problem.
  5. sicher ist sicher Die letzte Massnahme betrifft das Speichern der Daten in der Datenbank. Auch wenn ja eigentlich nichts Schadhaftes bis zu diesem Schritt mehr vorhanden sein dürfte – sicher ist sicher, und kostet eigentlich auch nichts. Deshalb wird konsequent der cfqueryparam-Tag verwendet. Und weil ich mir bei meinem Projekt alles ein wenig einfach gestalten möchte, verwendet ich ein ORM-Tool, in diesem Fall reactor. Wow, um den 5. Punkt muss ich mich also nicht mehr wirklich kümmern…

Mit diesen 5 Schritten, die standardisiert verwendet werden können, kann die Sicherheit von Webapplikationen massiv erhöht werden – man muss es nur tun. Aber es tut nicht weh, versprochen.