Freitag, 27. Dezember 2013

AppFuse - Security

Im letzten Post wurde bereits eine kleine Projektverwaltung begonnen. Nach dem erfolgreichen Auflisten von Projekten fehlt jetzt noch das Anlegen, Bearbeiten und Löschen. Darüber hinaus soll die Sicherheit einer AppFuse-Anwendung untersucht werden. Wer darf welche Seiten sehen und wie schlägt sich Appfuse bei den "OWASP Top 10 2013 vulnerabilities".

Also zuerst wird das Formular zum Anlegen und Bearbeiten eines Projektes erstellt. Auch das Löschen erfolgt auf dieser Seite. Dieses Formular entspricht in weiten Teilen dem Beispiel aus dem AppFuse-JSF-Tutorial - mit Ausnahme der Navigation. Das Turorial verwendet die Navigation Rules in der faces-config.xml. In diesem Beispiel hingegen erfolgt die Navigation direkt an der Komponente, z.B. beim Cancel-Button wird als action direct auf die projectList.jsf verwiesen.



Für die Navigation muss auch die ProjectAction ein wenig angepasst werden. Die Methoden bekommen einen String als Rückgabeparameter, der JSF dazu veranlasst, nach der Aktion auf die betreffende Seite zu navigieren. Und ein wenig Nutzerfeedback ist auch nicht verkehrt. Dazu wird jeweils eine Message hinzugefügt. Weiterhin stellt sich die Methode "getProject(String projectName)" als überflüssig heraus, da alle Aktionen über die Id des Projekts stattfinden. Sie kann entfallen. Dafür kommen die Membervariablen Project und Id hinzu.



Die Tests müssen entsprechend angepasst werden.



Und in der projectList.xhtml hatte sich im letzten Post ein Fehler eingeschlichen. Im Tag "h:commandButton" für das Hinzufügen eines neuen Projekts muss der Parameter "action" statt "#{projectAction.addProject}" jetzt "projectForm.jsf" lauten. Mit diesen Änderungen sollte es jetzt möglich sein, Projekte hinzuzufügen, zu bearbeiten und zu löschen. Das Formular öffnet sich:



Und auch das Speichern funktioniert:



Jetzt geht es daran, die Sicherheit zu ergründen. Zuerst soll definiert werden, wer das neue Projektmenü verwenden darf. AppFuse verwendet für das Menü die Taglib "Struts-Menu". Obwohl im Namen Struts vorkommt, kann diese Taglib auch ohne Struts eingesetzt werden. Nur das letzte Update ist vom 1.6.2007 und dieses Projekt kann wohl als nicht mehr aktiv bezeichnet werden.

Zur Konfiguration des Menüs müssen zwei Dateien angepasst werden:
  • menu-config.xml
  • menu.jsp


In der "menu-config.xml" werden die möglichen Menüpunkte definiert. Dafür gibt es die Tags "Menu" und "Item". In beiden Tags kann über das Attribut "roles" festgelegt werden, welche Rollen den jeweiligen Menüpunkt sehen dürfen.

Die "menu.jsp" legt die Reihenfolge der angezeigten Menüpunkte über das Tag <menu:displayMenu name="MyMenu"/> fest. Hierbei muss nur der Hauptmenüpunkt angegeben werden. Durch das Item-Tag definierte Untermenüs werden automatisch präsentiert. Die Präsentation des Menüs erledigt Velocity. Auf der Projektseite stehen einige vorgefertigte Templates zur Verfügung.

In der "menu.jsp" wird auch festgelegt, welche Klasse für die Rechteprüfung verwendet werden soll. Im Attribut "permissions" des Tags "menu:useMenuDisplayer" wird der Instanzname der entsprechenden Prüfklasse definiert. Diese Klasse muss das Interface "PermissionsAdapter" implementieren und einzig die Methode "boolean isAllowed(MenuComponent menu)" überschreiben. Der mitgelieferte "rolesAdapter" wird laut dem AppFuse Security Model auf "magische Art" verwendet.

Die Liste der Aktionen auf der Hauptseite "mainMenu.xhtml" hat nichts mit der Menükonfiguration zu tun. Das hat zur Folge, dass man an den eigentlich nicht erwünschten Menüpunkt herankommt. Deshalb muss hier eine andere Form der Absicherung greifen.

Nachdem mich die Seite "Apply Security to Managers and DAOs" ziemlich in die Irre geführt hat bin ich letztendlich durch Probieren auf die wirklich einfach Lösung gekommen. In der security.xml befinden sich bereits folgende Zeilen vorgefertigt:



Somit war meine Erwartungshaltung, dass die Liste der Nutzer aus dem Adminmenu durch "getUsers(..)" bereits gesichert ist. Also habe ich den Menüpunkt als Link auf der Hauptseite ergänzt und ihn als user angeklickt. Und nichts, d.h. als user wurden alle Nutzer aufgelistet, obwohl das eigentlich zum Adminmenü gehört.

Also in die Implementierung geschaut und erkannt, dass statt der Methode "getUsers()" die Methode "search()" zum Anzeigen der Nutzer verwendet wird. Also habe ich diese Methode in der security.xml ergänzt und nach einem Neustart tatsächlich die gewünschte SecurityException erhalten.



Jetzt sollte auch noch die Projektliste nur durch den Admin einsehbar sein. Dazu fügte ich eine Zeile mit der Methode "ProjectManager.getAll()" ein. Die führte aber nicht zum gewünschten Ergebnis. Erst als ich den ProjectManager durch den GenericManager ersetzte funktionierte es. Somit sieht der komplette Abschnitt der security.xml jetzt so aus:



Und wie verhält sich die Appfuse-Anwendung jetzt bzgl. der "OWASP Top 10 2013 vulnerabilities". Die Nummer 1 der Bedrohungen sind nach wie vor die Injections. Dabei ist hier jede Form von Daten gemeint, die ungeprüft an einen Interpreter weitergereicht werden. Der Interpreter kann hier SQL oder der Kommandozeileninterpreter des Betriebsystems, LDAP oder weitere sein. Für AppFuse trifft hier insbesondere die SQL-Injection zu. Hierbei können Kommandos zum Holen und zum Speichern von Daten injiziert werden.

Das Holen von Daten wird über JSF gekapselt, d.h. für einen Link wird aus einem h:commandLink ein a-Tag gerendert dessen href-Attribut nur aus einem '#' besteht. Die eigentliche Aktion erfolgt via JavaScript im onClick-Event: "onclick="return myfaces.oam.submitForm('editProject','editProject:projects:0:j_id7',null,[['id','-2'],['from','list']]);""

Das Speichern der Formulardaten übernimmt Hibernate. Und das schluckt klaglos meinen Versuch einer SQL-Injection und speichert einfach das SQL-Statement inkl. führendem Anführungszeichen, dass den zugrundeliegenden Befehl beenden sollte. Auch ein Semikolon half nichts. Also scheint SQL-Injection schon mal kein Problem von AppFuse zu sein.

Nummer 2 der Bedrohungen ist "Broken Authentication and Session Management". Hierzu zählen auch so einfach Dinge, wie ein sinnvoll konfiguriertes Session Timeout in der web.xml. Hier ist die AppFuse-WebApp bereits vorbildlich mit 15 Min. vorkonfiguriert. Alle anderen Sicherheitsaspekte werden nicht selbst implementiert, sondern es kommt Spring Security zum Einsatz. Und das ist der Quasi-Standard auf diesem Gebiet. Wenn nicht dem vertrauen, wem dann ;-)

Auch die 3. Bedrohung "Cross Site Scripting" schluckt AppFuse klaglos. Der Versuch, das JavaScript-Snippet
 '><script>alert("bla")</script>'. 
in einem Eingabefeld zur Ausführung zu bringen führte nur dazu, dass es klaglos gespeichert wurde. Eine Bedrohung ist dadurch nicht entstanden.

Das soll es für diesen Post gewesen sein. Die anderen Bedrohungsszenarien kann jeder selbst ausprobieren.

Keine Kommentare:

Kommentar veröffentlichen