Quelle: xkcd.com/327
Hier geht es zur Meldung der Leipziger unabhängigen Hochschulzeitung luhze.
Das Sitzplatzbuchsystem der Universitätsbibliothek Leipzig (UBL) glänzt leider weder im Design noch im Quellcode. Das zeigen mehrere Schwachstellen und ungesicherte Endpunkte. Es war möglich, alle Buchungen auszulesen, zu modifizieren und zu löschen. In den Daten: Bibliotheksnummern, Orte, Platznummern, Daten, Uhrzeiten und Buchungscodes. Laut einer Pressesprecherin der UBL gäbe es keine Anhaltspunkte, dass Daten dabei abgegraben wurden. Aber ausschließen wollte sie es nicht. Im folgenden eine Chronologie und Demonstration der Schwachstellen.
Das System wurde nach Beginn der Pandemie geschaffen, um das geregelte Arbeiten in den Bibliotheken zu ermöglichen. Dafür muss im Voraus ein Platz auf der Website gebucht werden. Dank der Quelloffenheit des Systems habe ich es mir am Wochenende (15./16.5) mal genauer angeschaut. Dabei ist mir ins Auge gesprungen, dass in der App wie wild SQL-Statements aus Strings und Parametern zusammen konkateniert wurden. Ich hab das System auf meinen Rechner aufgesetzt und ein paar geeignete Payloads für die POSTs kreiert, um den Angriff probeweise auszuprobieren. Dabei habe ich AND-Klauseln den SQL-Statements hinzugefügt, um nur meine Buchungen abzufragen und zu löschen.
Auch Buchungen zu löschen, war dabei problemlos möglich. Perfekt, wenn der Lieblingsplatz auf der Empore im historischen Lesesaal (Mitte) der Albi mal wieder belegt ist. Dafür musste aber der Startpunkt in der Zukunft liegen, denn ältere Buchungen konnten nicht mehr gelöscht werden. Dieser Angriff benötigte einen Token, das heißt man musste sich vorher anmelden.
Nachdem ich diese Schwachstelle am Sonntag den 16. gemeldet hatte, wurde sie, so eine Nachricht der stellvertretenden Direktorin, die ich am Dienstag erhielt, noch an ebendiesen Sonntag gefixt. Einen Commit ins Repo gab es allerdings nicht. Der POST zum Auslesen funktionierte danach nicht mehr. Nur beim POST zum Löschen bekam ich weiterhin eine E-mail, dass einer meiner Buchungen gelöscht wurde. Jedoch hatte das keine Auswirkung, denn die Einträge, die ich im Portal fand, waren die selben geblieben.
Das war aber schon einmal ein Anhaltspunkt. Nachdem ich den POST noch ein paar Mal ausprobiert hatte, bekam ich weitere E-mail mit immer den selben Einträgen die angeblich gelöscht worden sind. Auch war mir klar, dass die Injection noch passieren musste, sonst hätte ich einen 500 Internal Server Error bekommen. Das heißt, dass das grundlegende Problem der SQLi Schwachstelle, das ich in meiner E-mail auch genauso adressiert hatte, nicht behoben wurde.
Ich habe an das SQL noch ein "oder by RAND()" angefügt. Damit bekam ich nicht nur immer den selben Eintrag per E-mail sondern einen zufälligen. In der Mail: Bibliotheksnummer, Ort, Zeit und Platz. Das hieß, wenn ich zufällig die Einträge sortierte, bekam ich alle früher oder später an meine Mail-Adresse geliefert. Ich habe mir einen Exploit gebaut, der trackt, welche Einträge er schon bekommen hat und die wurden im SQL dann ausgeschlossen. "Leider" ist mir aufgefallen, dass immer meine Bibliotheksnummer in der Mail stand. Das lag daran, dass die Bibliotheksnummer für die Mail nicht aus der Tabelle entnommen wurde, sondern die benutzt wurde, welche ich im POST unter "readernumber" spezifiziert habe, die auch zur Authentifizierung genutzt wird.
Damit konnte ich mir zwar alle Einträge liefern lassen, aber keiner wäre einer Bibliotheksnummer zugeordnet. Aber was trotzdem möglich war, ist, dass man eine Bibliotheksnummer spezifizierte und sich zu dieser die Belegungen ausgeben lässt. Ich habe meinen Exploit dahingehend angepasst und wenige Minuten später hatte ich alle meine Buchungen in meinem E-mail Postfach. Der Exploit ist hier zu finden.
Beim Durchscrollen des Quellcodes sind mir dann noch ein weiterer Endpunkte aufgefallen: "api/booking/stats". Beim diesem POST-Endpoint konnte ich die Zweigstelle, Start und Endpunkt angeben und tada: Alle Buchungen mit Bibliotheksnummer, Ort, Platz, Zeit und Buchungscode.
Und nun der krönende Abschluss: "api/booking/counter". Ein großartiger GET-Endpunkt. Rief man diese URL auf, bekam man neben ein paar netten Statistiken, die aktuell angemeldeten Nutzer*innen und ihre Tokens. Session Hijacking war noch nie so einfach. Keine zehn Minuten nach meiner E-mail an die UBL (mittlerweile die dritte) war das System offline. Leider gibt es noch keinen Fix-Commit im Repo (Stand 14.10).
Niclas Stoffregen, 24.05.2021
UPDATE 23.06.2021:
Mir ist eine weitere Sicherheitslücke aufgefallen. Der Endpunkt "api/booking/admin" lies mit validen Token das Auslesen von Buchungen einer spezifizierten Bibliotheksnummer zu. Durch das iterative Hochzählen von Bibliotheksnummern konnten schnell große Teile der Buchungsliste heruntergeladen werden. Ein PoC-Exploit findet sich hier.
UPDATE 01.10.2021:
Das Buchsystem wurde durch eine 3G-Regelung der Universität ersetzt und ist deshalb offline.