Penetrationtesting für PHP
Ein Penetrationtest ist ein umfassender Sicherheitstest einer Webanwendung und erstreckt sich über die Überprüfung der Sicherheit möglichst aller Bestandteile. Als Penetration-Tester versucht man systematisch die Anwendung anzugreifen um so Sicherheitslücken wie beispielsweise SQL-Injections oder Cross-Site-Scripting-Schwachstellen frühzeitig zu identifizieren. Ein Penetrationtest kann sehr aufwendig werden und viel Erfahrung benötigen. Aber ein paar kleine Prozeduren des Penetrationtestings sollte jeder PHP-Entwickler kennen und nutzen.
Diese Artikel richtet sich eher an kleinere bis mittlere Webanwendungen ohne dezidierte Security-Experten bzw. ohne die Beauftragung externer Security-Berater. Ein Penetrationtest lässt sich im Umfang beliebig steigern.
Solltet ihr mehr Informationen zu dem Thema wünsche, kann ich euch das Buch The Web Application Hacker's Handbook empfehlen. Der häufige Verweis auf die eigene Software und die eigene Website ist zwar nervig, aber es bietet einen guten Überblick über das Thema.
Ziele des Penetrationtesting
Ein Penetrationtest ist eine systematische Vorgehensweise zur Überprüfung von Validierung der Sicherheitseigenschaften von Webanwendungen. Der Penetrationtest umfasst dabei oftmals die Überprüfung der gesamten Anwendung auf jede mögliche Sicherheitsschwachstelle. Jede gefundene Schwachstelle sollte dabei dokumentiert und im Nachgang behoben werden.
Ein Penetrationtest kann deutliche Sicherheitslücken in der Webanwendung offenbaren, die, sollte ein Angreifer diese identifizieren, zu erheblichen finanziellen Schäden führen können. Nachfolgend präsentiere ich euch 10 Schritte des Penetrationtestings, die ihr zum Teil auch ohne große Expertise erfolgreich umsetzen könnt. Bei wirklich kritischen Anwendungen sollten aber weiterhin Experten die Sicherheit eurer Website überprüfen.
Die 10 Schritte des Penetrationtestings
Schritt 1: Vorbereitung
Als aller erstes solltet ihr Sicherstellen, dass durch den Penetrationtest keine Daten verloren gehen oder der Betrieb eurer Webanwendung gestört wird. Es kann passieren, dass ihr eine Sicherheitslücke findet die zum Löschen der Datenbank führt und ich denke nicht, dass ihr für die Löschung verantwortlich sein möchtet.
Deswegen sollte der Penetrationtest in einer sicheren Umgebung passieren, beispielsweise auf eurem lokalen Webserver und nicht auf eurem Produktivsystem.
Ebenfalls lassen sich zwischen White-Box-, Grey-Box- und Back-Box-Testing unterscheiden. Bei Back-Box-Testing habt ihr überhaupt keinen Einblick in den Programmcode, bei Grey-Box-Testing habt ihr gewisse Einblicke und bei White-Box-Testing kennt ihr den kompletten Programmcode. Den Programmcode zu kennen kann hilfreich sein.
Schritt 2: Identifizierung der kritischen Assets
Im zweiten Schritt solltet ihr definieren, welche Assets besonders kritisch für eure Webanwendung sind. Sind dies beispielsweise eure Benutzerdaten? Oder die Zahlungsdaten? Oder gewisser Programmcode, der nicht offenbart werden darf?
Schreibt nieder was die wichtigsten Daten & Software sind. Im nachfolgenden Penetrationtesting solltet ihr auf das wichtigste Asset besonders viel Zeit verbringen. Wenn euer Besucherzähler gehackt wird ist es vermutlich weniger schlimm als wenn alle Kundendaten gelöscht werden.
Ihr könnt auch einen gezielten Penetrationtest durchführen, beispielsweise möchtet ihr diesmal nur den Bestellvorgang eurer Website evaluieren.
Schritt 3: Dokumentation
Bereitet eure Dokumentation vor. Ihr solltet eine Liste mit den wichtigsten Assets und den Zielen des Penetrationtests besitzen, eine Checkliste mit abgearbeiteten Test sowie eine Form um gefundene Sicherheitslücken zu dokumentieren.
Schritt 4: Angriffsziele identifizieren
Geht eure Website systematisch durch und notiert potentielle Angriffsziele. Jede Benutzereingabe ist ein potentielles Angriffsziel, beispielsweise die Registrierung, bei benutzergenerierten Inhalten (Foren, Kommentare, Produkt-Reviews etc.). Auch die Abfrage von sensitiven/sensiblen Daten ist ein Angriffsziel. Viele Websites kann man zur Preisgabe sensibler Daten veranlassen, indem man die ID im GET-Parameter verändert.
Schritt 5: Überprüfung auf typische Schwachstellen
Ihr solltet eure Website / alle identifizierten Angriffsziele systematisch auf folgende Schwachstellen überprüfen:
- SQL-Injections
Ihr solltet jede Eingabemöglichkeit, ob GET-Parameter in der URL oder POST-Parameter in Formularen auf SQL-Injections überprüfen. Ein einfacher Test ist den String ' OR 1=1 -- zu übermittel und sich die Ausgabe und das Fehlerprotokoll anzuschauen. Auch könnt ihr mal einen String probieren der einen SQL-Error hervorruft wie beispielsweise ' SELECT und dann eure SQL-Error-Log inspizieren.
Vergesst bei Formulareingaben auch nicht Felder zu überprüfen, die versteckt sind. Eine Validierung der Eingaben mittels JavaScript, z.B. dass das Feld nur Zahlenwerte enthalten darf, ist nicht ausreichend. Ein Angreifer kann JavaScript einfach deaktivieren. - Cross Site Scripting (XSS)
Überprüft wie bei SQL-Injections alle Benutzereingaben, egal ob GET oder POST, auf Cross Site Scripting. Oftmals funktioniert das Maskieren von Benutzerdaten nicht, beispielsweise beim Namen des Benutzers, bei der Anschrift, beim der E-Mail-Adresse usw.
Gebt bei jedem Parameter den ihr findet den folgenden Code ein: <script>alert('XSS erfolgreich');</script>. Sollte irgendwann ein Popup auftauchen, so ist eure Anwendung entsprechend verwundbar. - Cross-Site-Request-Forgery (CSRF)
Überprüft eure Formular sowie auch Links die gewisse Aktionen ausführen (z.B. Logout-Link) auf Cross-Site-Request-Forgery. Schaut dass der CSRF-Token korrekt vorhanden ist und ihr ohne bzw. mit falschem Token das Formular nicht absenden könnt / den Link nicht aufrufen könnt. - Code Injection
Wie in dem Artikel beschrieben solltet ihr insbesondere eure Datei-Uploads überprüfen (Sicherer Dateiupload), dass dort ein Angreifer keinen PHP-Code hochladen kann. Ebenfalls solltet ihr keine includes verwenden, die Code dynamisch von anderen Quellen laden.
Schritt 6: Authentifizierung und Authorisierung
Der sichere Login ist für viele Webanwendung kritisch. Keiner möchte, dass sich unbefugte in das eigene Konto einloggen können. Überprüft eure Funktionen zur Registrierung, zum Login und zur Passwort-vergessen-Funktion. Fallen euch dort Sicherheitsstellen auf?
Ebenfalls sollten interne Seiten nur nach einem erfolgreichen Login aufrufbar sein. Überprüft, ob dies auch wirklich der Fall ist. Und den potentiellen Administrationsbereich eurer Website solltet ihr nicht vergessen: Ist dieser ausreichend abgesichert?
Schritt 7: Error-Handling
Wie werden Fehlermeldungen in eurem System ausgegeben? Ihr solltet vermeiden, dass durch eine Fehlermeldung der Angreifer weitere Informationen über euer System erhält. Klopft euer System deswegen darauf ab, dass bei einer Fehlermeldung möglichst wenig hilfreiche Informationen für einen Angreifer dabei sind. Geht ein SQL-Query beispielsweise schief, so kann es euch als Entwickler helfen den SQL-Query auszugeben, der fehlgeschlagen ist. Für einen Angreifer ist so etwas aber gefundenes Fressen.
Überprüft ebenso "aufbereitete Fehlermeldungen". Ihr habt einen Login-Bereich und bei einer falschen/unbekannten E-Mail-Adresse gebt ihr die Meldung "Falsche E-Mail-Adresse" aus? Dies lässt sich von einem Angreifer wunderbar nutzen um zu überprüfen ob eine gewisse E-Mail-Adresse bei euch registriert ist. So könnte ein Mitbewerber beispielsweise eure Kundenstruktur ausspähen.
Schritt 8: Schadensminimierung
Eine 100% Sicherheit ist leider nicht zu erreichen, jede Anwendung hat irgendwo Schwachstellen die ausgenutzt werden könnten. In diesem Schritt solltet ihr also vom schlimmsten Fall ausgehen und schauen welche Strategien ihr besitzt zur Schadensminimierung.
Was passiert, wenn ein Benutzerkonto z.B. gehackt wurde? Oder einer eurer Benutzer sich einfach vergessen hat auszuloggen und jemand mit bösen Hintergedanken danach den Rechner nutzt? Kann dieser dann beispielsweise sämtliche Daten des Nutzers löschen?
Ebenfalls solltet ihr schauen, was passiert wenn mittels SQL-Injections sensible Daten aus eurer Datenbank abrufbar sind. Eure Passwörter solltet z.B. sicher abgespeichert sein, sensible Daten wie Zahlungsdaten ggf. sogar verschlüsselt abgespeichert sein.
Schritt 9: Überprüfung des Backups
Es gibt nicht wenige Fälle, bei denen ein Angreifer in das System eindringen konnte (z.B. durch einen gestohlenes Administrationspasswort) und dann beispielsweise die gesamte Datenbank gelöscht hat. Ein Backup ist daher kritisch und kann vor massivem Schaden schützen. Überprüft eure Backup-Strategie, d.h. überprüft ob die Datenbank und die Dateien auf eurem Server regelmäßig gesichert werden (am Besten täglich). Überprüft ebenfalls, dass das Backup in Ordnung ist und ihr damit die Daten wiederherstellen können. Nicht wenigen ist es bereits passiert, dass die Backupsoftware nicht richtig funktioniert hat und im Fall der Fälle es deswegen kein Backup mehr gab.
Auch solltet ihr in diesem Schritt sicherstellen, dass das Backup nicht von einem Angreifer gelöscht werden kann. Die Hinterlegung des Backups auf einem anderen Rechner/Server ist zu empfehlen.
Mehr Infos: Datenbankbackup per PHP
Schritt 10: Überprüfung der Verfügbarkeit
Die Verfügbarkeit und Nutzbarkeit besitzt einen hohen Wert, denn jede Sekunde die eure Website nicht erreichbar ist kann entsprechend hohen Schaden produzieren.
Im letzten Schritt solltet ihr überprüfen, wie ein Angreifer eure Verfügbarkeit schaden kann. Gegen einen Denial of Service von einem großen Botnet gegen euren Webserver könnt ihr als PHP-Entwickler wenig tun. Aber es existieren auch andere Angriffsmöglichkeiten.
Eine Möglichkeit wäre das Zuspammen eurer System. Ein Spam-Bot, der euer Formular zum Schreiben von Kommentaren tausendfach absendet ist schnell geschrieben. Normale Nutzer können dann euer System nicht mehr nutzen. Eine andere Gefahr sind besonders rechenintensive Operationen, z.B. sehr komplexe Suchfunktionen in der Datenbank. Ein Angreifer könnte diese Operation massenhaft auf eurem Webserver ausführen und diesen schnell in die Knie zwingen.
Überprüft im letzten Schritt, dass eure Anwendung möglichst schwer zuzuspammen ist bzw. falls es dazu kommt, ihr einfach Gegenmaßnahmen ergreifen könnt und z.B. alle Einträge vom Nutzer löschen könnt.
Autor: Nils Reimers