SQL-Injection für Einsteiger

Es gibt viele Internetdienste, bei denen man sich mit Benutzernamen und Passwort anmelden muss. Das Formular sieht dann zum Beispiel so aus:

Eine handelsübliche Loginmaske.

Eine handelsübliche Loginmaske.

Total einfach: Man trägt seinen Benutzernamen (z. B. hszemi) und sei Passwort (z. B. geheim) ein, klickt auf “Anmelden” und wird auf die Startseite des “internen” Bereichs weitergeleitet.

Basics

Im Hintergrund läuft dabei in der Regel Folgendes ab:

Es gibt einen Datenbankserver mit einer Datenbank, in der sich eine Tabelle befindet, in der alle Benutzerkonten eingetragen sind: In der Spalte “benutzername” steht der jeweilige Benutzername und in der Spalte “passwort” jeweils das dazugehörige Passwort – allerdings nicht im Klartext1, sondern in der Regel wird eine Einwegfunktion verwendet (zum Beispiel MD5), die aus dem Passwort eine Prüfsumme berechnet, und lediglich die wird in der Datenbank gespeichert.

Das hat den Vorteil, dass jemand, der Zugriff auf die Datenbank hat, nicht die Passwörter sieht, sondern theoretisch so lange Wörter durch die Einwegfunktion jagen muss, bis zufällig einmal die richtige Prüfsumme herauskommt.

Die Benutzertabelle in der Datenbank sieht also etwa so aus:

ID benutzername passwort
1 Safura 4fdf7cf087cbf024d2e50a14256016f7
2 Erna 908fc4942e1f629d4c6629808da70165
3 Hans ccd5cc2741cd6347ac791e76e3062528
4 Jean b195d8b5aee9b903334bc8360099a90f

Zurück zum Login-Formular. Wird auf den “Anmelden”-Knopf geklickt, so werden an den Webserver die Inhalte der beiden Textfelder gesendet. Dort wird dann geprüft, ob es eine Zeile in der Benutzertabelle gibt, in der in der Spalte “benutzername” der Text aus dem Formularfeld “Benutzername” steht UND in deren Passwortfeld der Wert steht, der herauskommt, wenn man die Einwegfunktion auf den Inhalt des Formularfelds “Passwort” anwendet.

Solche Datenbankabfragen werden gemeinhin in einer eigenen Sprache formuliert, der “Structured Query Language” oder kurz “SQL”. Das ist eine Art sehr einfaches Englisch. Eine einfache SQL-Anfrage hat folgende Struktur:

SELECT (Liste von Tabellenspalten oder einfach * für alle Spalten)
FROM (Liste von Tabellen, aus denen die Spalten kommen)
WHERE (Bedingungen, um die Zeilen auszuwählen)

Wenn sich nun also Hans mit dem Passwort hanspasswort anmelden will, müsste folgende Anfrage ausgeführt werden:

SELECT *
FROM benutzer
WHERE benutzername = ‘Hans’ AND passwort = MD5(‘hanspasswort’)2

Wenn die Anfrage eine Zeile als Ergebnis zurückliefert, hat Hans das richtige Passwort eingegeben und darf in den “internen” Bereich. Falls es keine Zeile in der Tabelle gibt, die beide Bedingungen erfüllt, hat Hans ein falsches Passwort eingegeben und muss draußen bleiben.

Der Angriff

Die SQL-Abfrage muss nun allerdings für jeden Anmeldevorgang dynamisch zusammengebastelt werden. Nehmen wir an, der eingegebene Benutzername steckt immer in der Variable $BENUTZER und das eingegebene Passwort in der Variable $PASSWORT. Dann könnte man folgende SQL-Abfrage ausführen:

SELECT *
FROM benutzer
WHERE benutzername = ‘$BENUTZER‘ AND passwort = MD5(‘$PASSWORT‘)

Das blöde dabei: So eine SQL-Abfrage ist erstmal nur ein gewöhnlicher String (heißt eine Zeichenkette). Man könnte jetzt als Benutzernamen folgendes eingeben:

Safura’ OR ‘1’ = ‘1

Dann wird aus dem WHERE-Teil (der die Auswahl der Zeilen bestimmt) folgendes:

WHERE benutzername = ‘Safura’ OR ‘1’ = ‘1’ AND passwort = MD5(‘…’)

Da in SQL eine UND-Verknüpfung (AND) vor einer ODER-Verknüpfung (OR) ausgewertet wird und ‘1’ = ‘1’ logischerweise immer den Wert WAHR hat, werden plötzlich alle Zeilen zurückgeliefert, in denen entweder der Benutzername gleich Safura oder das eingegebene Passwort hinterlegt ist, oder beides.

Das heißt, mit diesem Trick kann man sich als jeder beliebige Nutzer anmelden, ohne das Passwort zu kennen. Alternativ kann man auch einen Quatsch-Benutzernamen angeben und als Passwort häufig genutzte Passwörter durchraten und wird bei einem Treffer als der Benutzer angemeldet, dessen Passwort man erraten hat – ohne zuvor den Benutzernamen zu kennen.

Warum funktioniert das?

Beim Zusammenbasteln der Anfrage oben wurden die Benutzereingaben direkt verwendet. Der eingegebene Benutzername wurde dann so gewählt, dass er zur Grundstuktur der SQL-Anfrage passt, aber ein anderes (vom Angreifer gewünschtes) Ergebnis zurückgeliefert wird. Durch die Anführungszeichen wird der eigentliche Benutzername beendet und das folgende OR wird als SQL-Schlüsselwort (statt als Inhalt des Benutzernamens) behandelt – mit fatalen Folgen.

Was tut man dagegen?

Eine der wichtigsten Regeln beim Programmieren: Vertraue gar niemals nicht irgendwelchen Benutzereingaben. Dass im obigen Beispiel der eingegebene Benutzername ohne vorherige Prüfung einfach so in die SQL-Abfrage eingebaut wird, ist grob fahrlässig – was leider nicht heißt, dass so etwas in der freien Wildbahn nicht vorkommt.

Für Datenbankabfragen die Variablen enthalten sollte man wo möglich Prepared Statements verwenden, die sich darum kümmern, dass eine Zahl wirklich eine Zahl und ein String wirklich ein String bleibt, und entsprechende problematische Zeichen zuverlässig herausfiltern.

Falls dafür ein Umbau der gesamten Webanwendung nötig und dieser zu aufwändig wäre, sollte man als Sofortmaßnahme auf jeden Fall die Benutzereingaben vorfiltern. PHP bietet hier zum Beispiel die Funktion mysqli_real_escape_string() an, die das übernimmt.

Die “abgehärtete” Datenbankabfrage sähe dann so aus:

SELECT *
FROM benutzer
WHERE benutzername = ‘mysqli_real_escape_string($BENUTZER)
AND passwort = MD5(‘mysqli_real_escape_string(
$PASSWORT)‘)

Fazit

Nun gut, diese Sicherheitslücke ist also bei uns drin.
Die Reparatur würde aber Geld und/oder Zeit kosten, deshalb machen wir da nix. Das weiß schließlich keiner dass die Lücke da ist und wie man sie ausnutzt weiß außer Ihnen auch niemand.

Ääh ja. SQL-Injections gehören zum kleinen 1×1 eines jeden Skriptkiddies. Gutes Gelingen 🙂

  1. Wobei es das auch gibt. Sollte man das machen?
  2. MD5(‘hanspasswort’) berechnet in diesem Fall den Wert der Einwegfunktion für die Eingabe ‘hanspasswort’

Das Ding mit der UniApp

So ziemlich jede politische Hochschulgruppe an der Uni Bonn hat so ihr ganz persönliches Steckenpferd. Die Piraten kümmern sich in Theorie und Praxis um die IT, die LUST ist kritisch, der RCDS will die UniCard, die Jusos sind gegen Anwesenheitspflichten und die GHG eröffnet “nächste Woche” die Fahrradwerkstatt – und das schon seit gefühlt mehreren Jahren.

Die LHG, die jüngste der im SP vertretenen Gruppen, fordert die UniApp. Im Gegensatz zum RCDS, der für “seine” UniCard mittlerweile zum dritten Mal einen eigenen SP-Ausschuss spendiert bekam, muss sich die UniApp ohne einen solchen durchschlagen. Dafür bietet die LHG auch außerhalb des Wahlkampfs auf ihrer Internetseite grundlegende Informationen dazu, wie eine solche UniApp denn aussehen können sollte1.

Was machen die Anderen

Gerne wird hier auf die “preisgekrönte” App der Ruhr-Uni Bochum verwiesen. Natürlich habe ich mir diese App2 mal näher angesehen. So sieht der Einstiegsbildschirm der App aus:

Das Ding mit der UniApp
Das Ding mit der UniApp

Hübsch, hübsch. Wenn ihr mit dem Mauszeiger über die Bildchen fahrt (bzw. auf mobilen Endgeräten darauf tatscht), tauchen allerdings so Kreuze auf. Das sind dann die Funktionen, bei denen sich einfach ein Webbrowser (rotes Kreuz) oder eine andere App (blaues Kreuz) öffnet. Wir haben es hier also letztlich mit einer hübschen Linksammlung mit ein paar Extras zu tun.

Das App-Team der Ruhr-Uni Bochum meinte dazu über Twitter, dass eine Einbettung wohl derzeit techisch nicht anders realisierbar sei:

Schade. Doch zurück zur UniApp für die Rheinische Friedrich-Wilhelms-Universität Bonn.

Was kann die Uni Bonn

Sorry, falsche Überschrift. Haha.

Was könnte man für die Uni Bonn basteln

Die LHG macht ja bereits eine Reihe von Vorschlägen, was so eine UniApp können könnte.

Uni-Mailaccount

Man kann den Uni-Mail-Account bereits problemlos mit dem normalen Mail-Account der regulären E-Mail-App des Smartphones nutzen. Es handelt sich dabei schließlich um ein stinknormales E-Mail-Konto. Für Personen, deren technisches Verständnis für die Einrichtung eines Mail-Accounts nicht ausreicht, bietet das Hochschulrechenzentrum extra detaillierte Anleitungen an. Ich persönlich habe auch lieber alle meine Mailkonten in einer App versammelt, als für die Uni-Mails noch eine eigene App öffnen zu müssen. Insgesamt scheint mir die Entwicklung eines vollwertigen E-Mail-Clients in der UniApp verlorene Liebesmüh zu sein. Wenn man natürlich direkt aus dem integrierten Adress- und Personenverzeichnis der App Nachrichten per E-Mail versenden könnte, ohne die App zu wechseln, wäre das schon ganz nett. Fügen wir das Verzeichnis von Kontaktadressen mal zur Liste der gewünschten Funktionalitäten hinzu.

Mensaspeisepläne (mit einer echten Bewertungsfunktion)

Mensaspeisepläne sind zunächst Sache des Studentenwerks, nicht der Universität. Nichtsdestotrotz könnte man so etwas thematisch gut in eine UniApp integrieren. Das Studentenwerk bietet derzeit eine Web-App zum Abruf der Mensaspeisepläne an. Kommentieren oder bewerten kann man die angebotenen Speisen da allerdings nicht. Was jedoch eine “echte” Bewertungsfunktion von einer “nicht-echten” unterscheidet, erschließt sich mir nicht ganz. Grundsätzlich aber eine gute Idee, die entsprechenden Schnittstellen müsste dann wohl das Studentenwerk bereitstellen.

Onlinelernplattformen (eCampus)

Eine kurze Internetrecherche ergab, dass es wohl noch keine ILIAS-App gibt3, sondern nur ein paar Ansätze, eine mobilgerätefreundliche Oberfläche zu schaffen. Man müsste also innerhalb der Uni-App den Zugriff auf eCampus realisieren und dieses gegebenenfalls noch dafür anpassen. Aufwand, aber machbar, da ILIAS Open-Source-Software ist.

Bibliotheksverzeichnisse (OPAC)

Hier gilt vermutlich das gleiche wie für die Integration von eCampus, nur dass es hier bereits auch Open-Source-Apps gibt, die zweitverwertet werden könnten.

BASIS (Vorlesungsverzeichnis, Notenübersicht, …)

BASIS ist eigentlich ein QIS-Server und ist ein Produkt der HIS GmbH. HIS steht für “Hochschul Informations System” und QIS steht für “Qualitätssteigerung der Hochschulverwaltung im Internet durch Selbstbedienung”. Kannste dir nicht ausdenken, aber damit sind sie wohl Marktführer in Deutschland4. Wenn man die mit genug Geld bewirft, basteln die sicherlich die erforderlichen Schnittstellen, die die UniApp benötigen würde. Es gibt bereits Uni-Apps, die das können (siehe unten).

Hochschulsportverzeichnis

Das Hochschulsportverzeichnis der Uni scheint eine selbstgebastelte Lösung zu sein. Schnittstelle dafür bereitstellen und gut is.

Gebäudepläne zur Orientierung (insb. Toiletten)

Die Navigation innerhalb von Gebäuden ist derzeit eins der großen Probleme, das die Drohnen-Community beschäftigt – GPS funktioniert in geschlossenen Räumen eher so semi-gut. Man muss derzeit also immer noch selbst anhand des Gebäudeplans herausfinden, wo man sich momentan überhaupt befindet. Ein paar mehr Schilder aufhängen scheint mir die billigere Alternative zu sein.

Da sich Gebäudepläne jedoch relativ selten ändern, könnte man diese sogar statisch in die App integrieren. Das ist so ein Feature, das vermutlich eher wenig Aufwand verursacht und das man deshalb einfach mitnehmen könnte.

Wichtige News zur Hochschulpolitik und besonderen Veranstaltungen der Uni

Hier stellt sich die Frage: Wer betreut das? Die Pressestelle der Uni? Aber warum nicht. Das dürfte ebenfalls ziemlich einfach zu implementieren sein.

Terminkalender (bspw. mit Unipartys)

Hahaha. Unipartys. Haha.

Auch hier stellt sich die Frage: Wer betreut das? So ein gemeinsamer Terminkalender wäre aber grundsätzlich mal eine gute Idee, vorausgesetzt, das wird auch anständig gefüllt. Da sehe ich derzeit eher das größere Problem als in der Implementierung in eine UniApp.

Augmented reality

Ääh, watt? Entschuldigt bitte, aber mir fällt keine sinnvolle Anwendung für Augmented Reality in einer UniApp ein. Klärt mich auf, liebe LHG. Oder habt ihr nur Buzzword-Bingo gespielt?

Sonst noch was?

Ich habe mir auf gut Glück eben die App der Otto-von-Guericke-Universität Magdeburg (OVGU) heruntergeladen. Die sieht sehr cool aus. Erster Schritt bei der Einrichtung ist übrigens die Auswahl eines Farbschemas *grins*.

Neben Stundenplan- und Notenübersicht, Mensa-Speiseplan, Bibliotheksverwaltung und Personensuche beinhaltet die App noch ein Feedback-Formular, einen Twitter-Feed5 und einen integrierten Player für das Uniradio Magdeburg. Alles6 in der App integriert. Geiler Scheiß. Liebe LHG, verweist doch lieber mal auf die App der Uni Magdeburg als Referenz.

  1. Die UniCard-Pläne werden vom RCDS stets nur auf Wahlkampfplakaten und in der Wahlzeitung verkündigt. Nicht Wahlkampf-bezogene Informationen zur UniCard findet man auf der Webseite des RCDS anscheinend nicht.
  2. für Android, ein iOS-Testgerät ist nicht verfügbar. I’m not even sorry.
  3. Die Software, mit der eCampus läuft, heißt ILIAS.
  4. Das ist zumindest mein Eindruck.
  5. Wenn ihr mal in der App der Uni Magdeburg erwähnt werden sollt, twittert was mit dem Hashtag #ovgu. Viele türkische Twitterer nutzen diese Möglichkeit bereits rege.
  6. Die Elemente zur Studiums- und Bibliotheksverwaltung konnte ich mangels Account nicht ausprobieren.

Analyse: Wann werden wir vom Rüngler-Problem kalt erwischt?

Für kommenden Mittwoch ist zu einer SP-Sitzung geladen, auf der die Ausschüsse des Studierendenparlaments der Uni Bonn nach einem entsprechenden Ältestenratsbeschluss neu besetzt werden sollen; derweil streiten sich die Größen der Bonner Hochschulpolitik munter weiter bis in die nächste Instanz.

Doch ignorieren wir das alles mal und wenden uns der eigentlichen Frage zu: Wie problematisch ist das Rüngler-Problem?

Die Fakten

Das Studierendenparlament hat 43 Sitze. Die Ausschüsse des Studierendenparlaments werden auf Basis dieser Sitzverteilung besetzt, nach dem Sainte-Laguë/Schepers-Verfahren. Die Anzahl der Ausschussmitglieder ist zunächst einmal sinnigerweise ungerade. Die Satzung der Studierendenschaft sieht Ausschussgrößen von 3, 5, 7 und 9 vor. Eine SP-Mehrheit hat also mindestens 22 Sitze, eine Ausschussmehrheit entsprechend 2, 3, 4 oder 5.

Das Problem (Wiederholung)

In der aktuellen Besetzung hat das Studierendenparlament das Problem, dass die SP-Mehrheit von RCDS und Jusos mit 22 Sitzen in einem Fünferausschuss nur 2 Sitze besetzen kann, also keine Mehrheit in diesem Ausschuss hätte. Entsprechendes gilt für einen Neunerausschuss. Erklärbärartikel zum sog. “Rüngler-Problem”

Was tun?

Zunächst einmal wollen wir die Frage beantworten, mit welchen Wahlergebnissen wir eigentlich rechnen müssen. Da für unser Problem nicht die Identität der Listen, sondern nur das Verhältnis ihrer Sitzzahlen interessant ist, genügt es, die Sitzverteilungen absteigend sortiert zu berechnen. Ein kleines Python-Skript mit einer zehnfach verschachtelten For-Schleife erledigt dies für 2 bis 10 antretende Listen in erstaunlicherweise weniger als einer Sekunde1. Wen diese Ergebnisse interessieren: klick.

Doch damit beginnt der große Spaß ja erst. Nun wird jede dieser Sitzverteilungen darauf geprüft, für welche Ausschussgrößen das Rüngler-Problem auftritt. Alternativ kann natürlich auch das Sainte-Laguë/Schepers-Verfahren zu viele Sitze zuteilen, was ebenfalls nicht wünschenswert, aber hier nicht primärer Gegenstand unserer Betrachtung ist.

Resultate

Ei, ei, ei.

Nehmen wir mal an, der RCDS hätte einen Sitz weniger und die Piraten-Hochschulgruppe einen Sitz mehr im Studierendenparlament. Abstrakt sieht das ganze also so aus:

Unsere Beispielverteilung.

Unsere Beispielverteilung.

Nun bilden wir unsere Ausschüsse mit dem bewährten Sainte-Laguë/Schepers-Verfahren. In den folgenden Grafiken markiert die gestrichelte Linie die Mitte. Alle Listen links und auf dieser Linie besitzen zusammen eine Mehrheit im Ausschuss.

Dreierausschuss

B+C: 21 SP-Sitze, haben jedoch Ausschussmehrheit

B+C: Nur 21 SP-Sitze, haben jedoch Ausschussmehrheit → Rüngler-Problem

Fünferausschuss

majority-05

A+D: Nur 16 SP-Sitze, haben jedoch Ausschussmehrheit → Rüngler-Problem

Siebenerausschuss

majority-07

B+C: Nur 21 SP-Sitze, haben jedoch Ausschussmehrheit → Rüngler-Problem

Neunerausschuss

majority-09

C+D+E+F: Nur 20 SP-Sitze, haben jedoch Ausschussmehrheit → Rüngler-Problem

Aber hey, es ist Karneval! Versuchen wir es doch mal mit einem Elferrat, dat hätt noch emmer joot jejange!

Elferausschuss (nicht satzungskonform)

majority-11

B+D+E+F: Nur 21 SP-Sitze, haben jedoch Ausschussmehrheit → Rüngler-Problem

Wat fott es, es fott. *hust*

 Herr Doktor, wie schlimm isset?

Schlimmstenfalls treten bei der nächsten Wahl 8 Listen an und es ergibt sich folgendes Ergebnis:

Können wir das machen? Bitte?

Können wir das machen? Bitte?

Dann haben wir das Rüngler-Problem bei einer Ausschussgröße von 3. Und bei 5. Und bei 7. Und 9. Und 11. Und 13. Überhaupt bei jeder ungeraden Zahl zwischen 2 und 42 – außer bei 23: Da schlägt dann das Sainte-Laguë/Schepers-Verfahren fehl, weil fünf Listen gleichzeitig die letzten vier Sitze zugeteilt bekämen. Die Rüngler-Lösung, bei der einfach die Ausschussgröße so weit nach oben korrigiert wird, bis das Problem nicht mehr auftritt, würde also zu 43er-Ausschüssen führen – da kann man dann eigentlich gleich eine SP-Sitzung einberufen.

Nun haben wir Extrembeispiele gesehen. Blicken wir nun auf einen Graphen, der die Wahrscheinlichkeit abbildet, dass bei einer der vier von der Satzung vorgesehenen Ausschussgrößen das Rüngler-Problem auftritt, oder das Sainte-Laguë/Schepers-Verfahren (STLGS) nicht die gewünschte Zahl an Sitzen zuteilen kann.

Aufgeteilt wird das ganze nach der Anzahl der im SP vertretenen Listen.

Aufgeteilt wird das ganze nach der Anzahl der im SP vertretenen Listen.

Wir sehen: Je mehr Listen im SP sitzen, desto wahrscheinlicher wird es, dass das Sainte-Laguë/Schepers-Verfahren für eine der Ausschussgrößen fehlschlägt, und noch stärker steigt die Wahrscheinlichkeit, dass das Rüngler-Problem auftritt.

Eine Grafik hab ich noch: Wie wahrscheinlich ist es, dass für alle vier vorgesehenen Ausschussgrößen entweder das Rüngler-Problem auftritt oder das Sainte-Laguë/Schepers-Verfahren nicht die gewünschte Zahl an Sitzen zuteilen kann?

Sieht verschmerzbar aus. Wobei: 10 % sind dann doch ganz schön viel.

Sieht verschmerzbar aus. Wobei: 10 % sind eigentlich doch ganz schön viel. Anscheinend konvergiert das gegen 25 %, also jedes vierte Wahlergebnis wäre höchstproblematisch. Gegen zu viele Listen im SP könnte ja eine Sperrklausel bei der Wahl helfen *diabolisches Grinsen*

Fazit

Wenn das Rüngler-Problem ein Problem ist, ist es tatsächlich ein Problem.

So, für heute habe ich nun mit genug Zahlen und Bildern um mich geworfen. Das gesamte Team von hszemi.de wünscht allen Beteiligten viel Vergnügen bei der Lösung dieses Problems!

Disclaimer: Menschen machen Fehler. Falls ihr in den obigen Zahlen und Grafiken einen Fehler bemerkt, freue ich mich über einen Hinweis, zum Beispiel in den Kommentaren.

  1. Für eine einzige Liste ist dies trivial. Beweis durch scharfes Hinschauen. (Für 2 Listen eigentlich ja auch.)