Big Binary Files Upload (PostgreSQL)

Unterstützen Sie HackTricks

PostgreSQL Large Objects

PostgreSQL bietet eine Struktur, die als Large Objects bekannt ist, die über die Tabelle pg_largeobject zugänglich ist und zum Speichern großer Datentypen wie Bilder oder PDF-Dokumente konzipiert wurde. Dieser Ansatz ist vorteilhaft gegenüber der Funktion COPY TO, da er die Exportation von Daten zurück ins Dateisystem ermöglicht und sicherstellt, dass eine exakte Kopie der Originaldatei erhalten bleibt.

Um eine komplette Datei innerhalb dieser Tabelle zu speichern, muss ein Objekt in der Tabelle pg_largeobject erstellt werden (identifiziert durch eine LOID), gefolgt von der Einfügung von Datenchunks, die jeweils 2KB groß sind, in dieses Objekt. Es ist entscheidend, dass diese Chunks genau 2KB groß sind (mit der möglichen Ausnahme des letzten Chunks), um sicherzustellen, dass die Exportfunktion korrekt funktioniert.

Um Ihre binären Daten in 2KB große Chunks zu unterteilen, können die folgenden Befehle ausgeführt werden:

split -b 2048 your_file # Creates 2KB sized files

Um jede Datei in Base64 oder Hex zu kodieren, können die folgenden Befehle verwendet werden:

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

Wichtig: Bei der Automatisierung dieses Prozesses sicherstellen, dass 2KB große Blöcke von Klartext-Bytes gesendet werden. Hexadezimal codierte Dateien benötigen aufgrund der Verdopplung der Größe 4KB Daten pro Block, während Base64 codierte Dateien der Formel ceil(n / 3) * 4 folgen.

Die Inhalte der großen Objekte können zu Debugging-Zwecken mit folgendem Befehl angezeigt werden:

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

Verwendung von lo_creat & Base64

Um binäre Daten zu speichern, wird zuerst ein LOID erstellt:

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

In Situationen, die präzise Kontrolle erfordern, wie zum Beispiel beim Ausnutzen einer Blind SQL Injection, wird lo_create bevorzugt, um eine feste LOID anzugeben.

Datenchunks können dann wie folgt eingefügt werden:

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

Um das große Objekt nach der Verwendung zu exportieren und möglicherweise zu löschen:

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

Verwendung von lo_import & Hex

Die Funktion lo_import kann verwendet werden, um einen LOID für ein großes Objekt zu erstellen und anzugeben:

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

Nach der Objekterstellung werden die Daten seitenweise eingefügt, wobei sichergestellt wird, dass jeder Block 2KB nicht überschreitet:

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;

Um den Prozess abzuschließen, werden die Daten exportiert und das große Objekt wird gelöscht:

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

Einschränkungen

Es wird darauf hingewiesen, dass große Objekte ACLs (Access Control Lists) haben können, die den Zugriff selbst auf von Ihrem Benutzer erstellte Objekte einschränken. Ältere Objekte mit großzügigen ACLs können jedoch weiterhin für die Inhaltsexfiltration zugänglich sein.

Support HackTricks

Last updated