#!/usr/bin/perl # # 0r4cl3.pl # An EASY-TO-USE Oracle Password Audit Script # # I made this automated script for an Oracle audit, and # a related control was about to check if wheter the # password was the default installed by the DBMS or is # too weak. # # If you use the the Default passwords audit feature (-d switch) # you must download the Oracle default password list in text format (.csv) # from http://www.petefinnigan.com/default/default_password_list.htm # # If you use the Bruteforce feature (-b switch) # you must download checkpwd 1.23 from # http://www.red-database-security.com/software/checkpwd.html # and your favorite wordlist. I also recomend to change the case of # the wordlist from lowercase to uppercase, unless you're going to audit an # Oracle 11g since this version added the case-sensitive passwords feature. # # Tested against user/pass list retrieved from Oracle 10g Release2 # # Alejandro Hernandez # Mexico/Feb-09 use Getopt::Std; # The complete path where checkpwd is located. I assume that is in # the same working directory, if not, change it ! use constant CHECKPWD => "./checkpwd"; sub hdr { print < \n"; print "\tAvailable Options:\n"; print "\t-d\tMatch against Pete Finnigan's default password list\n"; print "\t-b\tBruteforce with the help of Checkpwd and a Wordlist\n\n"; print "\t\tFile containing the output of \n"; print "\t\t\tSELECT username,password,account_status FROM dba_users;\n"; print "\t\tFor option -d: Pete Finnigan's default password list\n"; print "\t\t\tFor option -b: A wordlist for bruteforcing\n"; exit; } hdr; getopts("db"); sub hash_db_output { open ORACLE, $ARGV[0] or die "Cannot open $ARGV[0]: $!"; while(){ chomp; next if /USERNAME/ or /-/ or /^(\s)*$/ or /^#.*/; /(\w+)\s+(\w+)\s+(\w+ & \w+|\w+)/; $ORACLE{$1}{hash} = $2; $ORACLE{$1}{acc_status} = $3; } close ORACLE; } sub hash_default_pass { open DFLT_PASS, $ARGV[1] or die "Cannot open $ARGV[1]: $!"; # A hash of hashes that contain arrays while(){ ($dflt_user, $dflt_pass, $dflt_hash, $dflt_comm) = (split/,/)[2..5]; push @{ $DFLT_PASS{$dflt_user}{dflt_pass} }, $dflt_pass; push @{ $DFLT_PASS{$dflt_user}{dflt_hash} }, $dflt_hash; push @{ $DFLT_PASS{$dflt_user}{dflt_comm} }, $dflt_comm; } close DFLT_PASS; } if($opt_d){ hash_db_output; hash_default_pass; print "[ DEFAULT PASSWORDS FOUND]\n"; print "----------------------------------------------------------\n"; print "USERNAME PASSWORD ACCOUNT_STATUS\n"; print "----------------------------------------------------------\n"; foreach $user_db (sort keys %ORACLE){ $ndx = 0; foreach $user_dflt_hash (@{ $DFLT_PASS{$user_db}{dflt_hash}}){ $ndx++; if($ORACLE{$user_db}{hash} eq $user_dflt_hash){ printf "%-21s", $user_db; printf "%-23s", @{ $DFLT_PASS{$user_db}{dflt_pass} }[$ndx-1]; print "$ORACLE{$user_db}{acc_status}\n"; # print "Risk: $DFLT_PASS{$user_db}{dflt_comm}\n"; $dflt_cnt++; last; } } } print "\n-=[ DEFAULT PASSWORDS FOUND: $dflt_cnt !\n" if $dflt_cnt; } elsif($opt_b){ hash_db_output; if(! -e $ARGV[1]){ print "The wordlist \"$ARGV[1]\" doesn't exist !\n"; exit; } print "[ BRUTEFORCING PASSWORDS ]\n"; foreach $user_db (sort keys %ORACLE){ $cmd = CHECKPWD . " -quiet $user_db:$ORACLE{$user_db}{hash} $ARGV[1]"; $out = `$cmd 2> /dev/null | grep weak`; if($out){ chomp $out; $out .= " and the account is $ORACLE{$user_db}{acc_status}"; print "$out\n"; $crack_cnt++; } } print "\n-=[ WEAK OR GUESSED PASSWORDS: $crack_cnt !\n" if $crack_cnt; } else{ die "Invalid option!\n"; }