Wir haben uns, im Rahmen einer Craft Night der Academy, die Sicherheit eines unserer internen Produkte angeschaut. Das Projekt war noch nicht abgeschlossen, aber wir wollten gerne trotzdem vorab einen Blick darauf werfen. Mehr um selbst einen Blick für das Thema Security zu bekommen, als um eine abschließende Sicherheitsanalyse des Projektes zu machen. Dafür wäre ein 2 Stunden Workshop auch etwas knapp.
In diesem Artikel will ich aufzeigen, wie wir vorgegangen sind, was wir gelernt haben und welche Empfehlungen wir anderen geben können.
Vorbereitungen
Um zu verhindern, dass die Workshop Teilnehmer das Testsystem des Projektes lahmlegen haben wir beschlossen das Projekt lokal aufzusetzen und zu starten. So konnte jeder nach Herzenslust hacken, ohne dabei Rücksicht darauf zu nehmen, dass das System noch gebraucht wird. Es sollte im ersten Schritt vor allem darum gehen die Sicherheit der Anwendung anzuschauen. Die Infrastruktur konnten und wollten wir, auch aufgrund der kurzen Zeit, nicht mit in Augenschein nehmen.
Mit einigen erfahrenen Kollegen haben wir das Projekt aufgesetzt und eine kurze Dokumentation erstellt, die es den Teilnehmern ermöglicht hat, das Projekt schnell und unkompliziert aufzusetzen. Außerdem haben wir nach ersten Lücken geschaut, um sicherzugehen, dass die Workshopteilnehmer auch etwas finden können (ggf. mit etwas Hilfe).
Vorgehen im Workshop
Es handelt sich bei der Anwendung um eine Single Page Application, die JWT für die Authentifizierung benutzt. Zunächst haben wir den Teilnehmern daher vorgestellt, wie man ein JWT über jwt.io decodieren kann, um Einsicht in die enthaltenen Daten zu erhalten. Hier sollte nichts Vertrauliches gespeichert sein, aber die eine oder andere Information kann man manchmal abgreifen. In unserem Fall z. B. die Namen der Rollen, die ein „normaler“ Benutzer hat. Informationen zu sammeln ist immer ein guter Plan, also haben wir die Namen der Rollen vermerkt. Als nächstes haben wir gezeigt, wie man mit den Entwicklungstools von Firefox HTTP Requests editieren und erneut absenden kann.
Anschließend haben die Teilnehmer versucht gemeinsam Informationen zu sammeln und Sicherheitslücken zu identifizieren. Da der Workshop virtuell statt fand haben wir das auf einem virtuellen Whiteboard gemacht. So konnten wir kollaborativ vorgehen. Komplexere Sachverhalte wurden dabei von den Teilnehmern in der Videokonferenz diskutiert.
Findings
Welche Sicherheitslücken haben wir entdeckt? Zunächst wurde eine generierte API Dokumentation gefunden, die ebenfalls das Ausführen einzelner Requests ermöglichte. Damit waren viele Details der API bereits enthüllt, aber zunächst noch keine Sicherheitslücke entdeckt. Für ein produktives System würde man diese Dokumentation vermutlich abschalten, wenn es sich nicht um eine public API handelt. Dies sollte eigentlich der Fall sein, doch scheinbar lag hier eine Fehlkonfiguration vor.
Es war relativ schnell klar, dass es sich hier um eine PHP/Symphony Anwendung handelt. Auch solche Informationen können hilfreich sein und sollten gesammelt werden. Was haben wir noch gefunden?
SQL Injection (kind of)
In einem Suchfeld konnte man ein % eingeben und damit alle im System befindlichen Entitäten einsehen. Eine darüber hinausgehende SQL injection war allerdings nicht möglich. Trotzdem sollte das so natürlich nicht sein.
Broken Authorization
Es fiel auf, dass der Endpunkt für den Upload bestimmter Bilder nicht in der API Dokumentation abgebildet war. Hatte hier jemand etwas vorbei am Framework gebaut? Und wenn ja, wie wurde der Endpoint gesichert? Ein genauerer Blick schien lohnenswert. Und tatsächlich: man konnte Bilder anderer Nutzer überschreiben. Hierfür war es ausreichend, selbst ein Bild hochzuladen, “Edit and resend” auszuführen und die URL anzupassen. Hier wurde nur die Nutzer-ID ausgetauscht. Es stellte sich heraus, dass für den Upload nicht einmal ein gültiges JWT notwendig war, sondern nur die Kenntnis der Ziel-URL.
Validation
Der Versuch ein svg mit Schadcode hochzuladen gelang zwar, allerdings lieferte der GET Request danach nur noch einen 500er, vermutlich weil das Dateiformat nicht erwartet wurde. Hier hätte man beim Upload bereits prüfen müssen, ob das Dateiformat zulässig ist oder nicht. Eine Validierung wurde nur im Frontend gemacht, nicht aber auf Backend-Seite.
Noch einmal Validierung
Die Anwendung bietet den Export von Daten in verschiedenen Formaten an. Die Dateinamen werden aus Daten generiert, die der User im UI nicht ändern kann. Wenn man aber das UI umgeht und den Request manipuliert, so ist die Änderung dieser Daten möglich. Eine Backend seitige Validierung war nicht vorhanden. Der Export läuft dann auf einen Fehler, wenn man z. B. null für bestimmte Felder hinterlegt oder Sonderzeichen einschleust.
Stacktrace exposure
Einem der Teilnehmer gelang es über die fehlende Validierung einen Error zu provozieren, dessen Stacktrace es bis in den Browser schaffte. Zur Überraschung aller Teilnehmer handelte es sich um einen Java Stacktrace. Wir versuchten über canarytokens.org einen jog4shell Angriff, der allerdings nicht zu einem Erfolg führte.
Noch einmal Broken Authorization und Privilege Escalation
In der API Dokumentation war unter anderem eine Schnittstelle für die im System verwendeten Rollen verfügbar. Man konnte sich die Liste der Rollen holen. Der Versuch, eine eigene Rollen zu ändern, schlug zunächst fehl. Allerdings nicht, weil uns als nicht privilegierte Benutzer das Recht dazu fehlte, sondern weil es bereits eine Rolle ROLE_ADMIN gab. Wir haben diese also zunächst umbenannt und den Administratoren damit ihre Rechte entzogen, um dann eine der Rollen, die wir aus dem JWT kannten, umzubenennen. Und schwupps hatten wir Administratorrechte auf dem System.
Was haben wir gelernt?
Das systematische Sammeln von Informationen hilft dabei das zu untersuchende System besser zu verstehen und verschiedene Informationen zu verknüpfen. Dies gilt natürlich insbesondere, wenn man mit einem ganzen Team an der Untersuchung arbeitet. Eine weitere große Hilfe war das „Edit & Resend“ Feature von Firefox.
Gute Ansatzpunkte sind Authentication und Authorization. Hier, aber auch in anderen Bereichen, lohnt ein genaues Hinschauen. Das gilt insbesondere für die Teile eines Systems, die anders sind, von den vorhandenen Mustern abweichen. Überall dort, wo es nach einer Bastellösung aussieht, nach etwas, das nicht mit dem gewählten Framework gebaut wurde, sind Sicherheitslücken wahrscheinlicher.
Empfehlungen
Follow your Framework. Bastellösungen sollten vermieden werden, wo immer es möglich ist. Das bedeutet natürlich auch, dass man den Best Practices folgen sollte. Validierung, Authentication oder Authorization sollten selbstverständlich sein, werden aber allzu oft vernachlässigt. Features müssen fertiggestellt, Bugs gefixt werden und für das Refactoring war keine Zeit. Was kann also helfen?
Business
Die Businessseite versteht IT Security oftmals nicht oder nur schlecht. Das ist auch gar nicht die Aufgabe von Project Ownern, Projektmanagern oder anderen Rollen, die die Businesseite vertreten. Natürlich wollen die Stakeholder ein sicheres System, aber ihnen fehlt meist das Verständnis darüber, was zu tun ist, warum bestimmte Maßnahmen notwendig sind oder welche Folgen ein bestimmtes Sicherheitsproblem haben kann. Es kann also hilfreich sein, mögliche Angriffsvektoren festzuhalten und mit einem möglichen Schaden und dem nötigen Aufwand zur Behebung anzureichern. So werden z. B. Product Owner in die Lage versetzt die Sicherheitsprobleme der von Ihnen verantworteten Software besser einzuschätzen. Eine Priorisierung wird möglich und durch das Verständnis der Situation entsteht eine Motivation für die Behebung der Probleme.
Best Practices
Es macht immer Sinn den Best Practices der Branche zu folgen. Dazu gehören unter anderem:
- Nutzung eines automatisierten Audits, in der Regel über das Build Tool (z. B. über das OWASP plugin für gradle, cargo audit oder npm audit)
- Die Nutzung von Dependabot
- Automatisierte dependency updates
- Prüfung der Software auf die Top 10 der OWASP
- Nutzung von Security Frameworks
Der letzte Punkt ist von entscheidender Bedeutung. Security ist kein triviales Feld und wer sich nicht primär damit beschäftigt, sollte keine Verschlüsselungen oder Algorithmen zum Password hashen selber bauen, sondern fertige Lösungen dafür verwenden. Für die meisten Anwendungsfälle sind diese verfügbar und besser als das meiste, was man selber baut.
Weitere Maßnahmen
Eine Schulung des Teams, z. B. unter Zuhilfenahme des Juice Shops von Björn Kimmenich kann helfen ein besseres Verständnis für das Thema Security zu entwickeln. Teilnehmen können dabei auch Mitarbeiter, die nicht direkt an der Technik arbeiten. Auch für POs oder Abteilungsleiter ist ein besseres Verständnis des Themas hilfreich. Zu diesem Zweck haben wir bereits ein Security KHC durchgeführt, die typische Probleme und Best Practices aufzeigt. Die Zusammenfassung davon könnt ihr hier nachlesen.