Big Binary Files Upload (PostgreSQL)
PostgreSQL Large Objects
PostgreSQL exposes a structure called large object (pg_largeobject
table), which is used for storing data that would be difficult to handle in its entirety (like an image or a PDF document). As opposed to the COPY TO
function, the advantage of large objects lies in the fact that the data they hold can be exported back to the file system as an identical copy of the original imported file.
In order to save a complete file inside this table you first need to create an object inside the mentioned table (identified by a LOID) and then insert chunks of 2KB inside this object. It's very important that all the chunks have 2KB (except possible the last one) or the exporting function to the file system won't work.
In order to split your binary in chunks of size 2KB you can do:
In order to encode each of the files created to Base64 or Hex you can use:
When exploiting this remember that you have to send chunks of 2KB clear-text bytes (not 2KB of base64 or hex encoded bytes). If you try to automate this, the size of a hex encoded file is the double (then you need to send 4KB of encoded data for each chunk) and the size of a base64 encoded file is ceil(n / 3) * 4
Also, debugging the process you can see the contents of the large objects created with:
Using lo_creat & Base64
First, we need to create a LOID where the binary data is going to be saved:
If you are abusing a Blind SQLinjection you will be more interested on using lo_create
with a fixed LOID so you know where you have to upload the content.
Also, note that there is no syntax error the functions are lo_creat
and lo_create
.
LOID is used to identify the object in the pg_largeobjec
t table. Inserting chunks of size 2KB into the pg_largeobject
table can be achieved using:
Finally you can export the file to the file-system doing (during this example the LOID used was 173454
):
Note the in newest versions of postgres you may need to upload the extensions without indicating any path at all. Read this for more information.
You possible may be interested in delete the large object created after exporting it:
Using lo_import & Hex
In this scenario lo_import is going to be used to create a large object object. Fortunately in this case you can (and cannot) specify the LOID you would want to use:
After creating the object you can start inserting the data on each page (remember, you have to insert chunks of 2KB):
The HEX must be just the hex (without 0x
or \x
), example:
Finally, export the data to a file and delete the large object:
Note the in newest versions of postgres you may need to upload the extensions without indicating any path at all. Read this for more information.
Limitations
After reading the documentation of large objects in PostgreSQL, we can find out that large objects can has ACL (Access Control List). It's possible to configure new large objects so your user don't have enough privileges to read them even if they were created by your user.
However, there may be old object with an ACL that allows current user to read it, then we can exfiltrate that object's content.
Last updated