Aktualisiert am: 2023-12-06
SQL Injection
Enumeration
-
Im Quellcode finden wir einen Kommentar, der uns auf die Beschaffenheit der Tabelle
users
hinweist. Dabei werden auch die Feldlängen definiert/* CREATE TABLE `users` ( `username` varchar(64) DEFAULT NULL, `password` varchar(64) DEFAULT NULL ); */
-
Jegliche SQL-Abfragen gehen durch
mysql_real_escape_string
, um SQL Injection zu verhindern -
Jeglicher Output wird durch
htmlentities
geschickt, um XSS zu verhindern. Das ist aber ohnehin nicht unser Ziel -
Wenn der User existiert, werden bei korrektem Kennwort die Zugangsdaten ausgegeben. Wenn der User nicht existiert, wird er erstellt
if(validUser($link,$_REQUEST["username"])) { //user exists, check creds if(checkCredentials($link,$_REQUEST["username"],$_REQUEST["password"])){ echo "Welcome " . htmlentities($_REQUEST["username"]) . "!<br>"; echo "Here is your data:<br>"; $data=dumpData($link,$_REQUEST["username"]); print htmlentities($data); } else{ echo "Wrong password for user: " . htmlentities($_REQUEST["username"]) . "<br>"; } } else { //user doesn't exist if(createUser($link,$_REQUEST["username"],$_REQUEST["password"])){ echo "User " . htmlentities($_REQUEST["username"]) . " was created!"; } }
Exploitation
- Die Funktion
mysql_real_escape_string
war (ist?) unzuverlässig bei fehlerhafter Konfiguration des Encodings. Dieser Artikel von 2006 geht auf das Ausnutzen der Schwachstelle mittels Multibyte Encoding ein. Es wird dort auch darauf hingeweisen, dass man besser Prepared Statements verwendet, was der OWASP-Empfehlung entspricht.
-
Wie ich gelernt habe, definiert SQL im Standard ein unerwartetes Verhalten bei der Überprüfung auf Gleichheit (
=
) von Strings- Trailing Spaces werden bei einem
SELECT
Statement abgeschnitten - Trailing Spaces werden bei einem
INSERT
Statement berücksichtigt,- soweit dies die Feldlänge zulässt
- Trailing Spaces werden bei einem
-
SQL bietet uns hier einen Angriffsvektor, der sich mit einem besonders langen Benutzernamen ausnutzen lässt. Beachtet den Punkt am Ende – das kann auch ein anderes Zeichen wie ein Buchstabe oder eine Ziffer sein
kali@kali:~$ python3 -c "print('natas28' + ' ' * 64 + '.')" natas28 .
- Der Punkt (
.
) am Ende sorgt dafür, dass invalidUser
dieSELECT
-Abfrage fehlschlägt, gleichwohl der Benutzernatas28
bereits existiert. Entsprechend wirdcreateUser
aufgerufen - Die 64 Spaces (
INSERT
. Der Punkt am Ende wird abgeschnitten - Ab nun geben
SELECT
-Abfragen aufnatas28
mehrere Ergebnisse zurück
- Der Punkt (
-
Mit dem überlangen Benutzernamen können wir uns einen Benutzer mit beliebigem Kennwort erstellen und uns damit als
natas28
Anmelden, um die (bzw. alle) Zugangsdaten zu erhaltenJWwR438wkgTsNKBbcJoowyysdM82YjeF
Best Practices
- Definiere identifizierende Felder mit einem
UNIQUE
Constraint, um dadurch keine weiterenINSERT
Statements zuzulassen, die sich bloss in der Anzahl an Trailing Spaces unterscheiden
Links
- Lösungsbeschreibung einer anderen Challenge mit ähnlicher Problemstellung