#!/usr/bin/perl
#
# win_login.saint
# Check Windows accounts for guessable passwords
#
# Copyright (C) 2001 World Wide Digital Security, Inc.
# by Sam Kline, WWDSI, 6/01

require 'perllib/netbios.pl';
require 'perllib/getopts.pl';
require 'perl/misc.pl';

print "BEGIN\n";
$usage = "$0 [-v] [-g guesses] [-n number of accounts] <target>";
Getopts("g:n:v") || die $usage;
die $usage if $#ARGV < 0;
$target = $ARGV[0];
$opt_g = 2 if !$opt_g;

$max = $opt_n ? 1000 + $opt_n : 1100;
@account_ids = (500, 501, 1000..$max);
@guesses = ("", "%login%", "password", "%nigol%", "%login%1");
$#guesses = $opt_g - 1;
#
# Get NetBios name
#
&open_socket($target, udp, 0);
$nb_name = &netbios_name_request($target);
&close_socket;

die "cannot determine netbios name" unless $nb_name;
print "Netbios name: $nb_name\n" if $opt_v;

&netbios_init;
#
# Get list of account names
#
&open_socket($target, tcp, 139);

if (!&session_request($nb_name)) {
    print "Session request failed\n" if $opt_v;
    goto CLOSE;
}
if (!&session_negotiate) {
    print "Session negotiate failed\n" if $opt_v;
    goto CLOSE;
}
# Establish null session
if (!&session_setup($nb_name)) {
    print "Session setup failed\n" if $opt_v;
    goto CLOSE;
}
if (!&tree_connect($nb_name)) {
    print "Tree connect failed\n" if $opt_v;
    goto CLOSE;
}
# Connect to \lsarpc
if (!(&nt_create("\\lsarpc") &&
      &bind_pipe("\\lsarpc") &&
      &lsa_open)) {
	print "LSA open failed\n" if $opt_v;
	goto CLOSE;
}
# Get Domain Member SID
if (!(&lsa_query(3,3) &&
      &init_read(92))) {
	print "Get Domain Member SID failed\n" if $opt_v;
	goto CLOSE;
}
# Get Domain Controller SID
if (!(&lsa_query(4,5) &&
      &init_read(92))) {
	print "Get Domain Controller SID failed\n" if $opt_v;
	goto CLOSE;
}
# Close
if (!(&lsa_close &&
      &init_read(4) &&
      &nt_close)) {
	print "Close failed\n" if $opt_v;
	goto CLOSE;
}
if (!(&nt_create("\\lsarpc") &&
      &bind_pipe("\\lsarpc") &&
      &lsa_open_sec)) {
	print "LSA open failed\n" if $opt_v;
	goto CLOSE;
}
# Get account name for each account ID
@login = ();
for $account_id (@account_ids) {
  if (&lookup_sid($account_id) &&
      &init_read(112)) {
	print "Found login $login_name\n" if $opt_v;
	push @login, $login_name;
  }
}
# Disconnect from \lsarpc
if (!(&lsa_close &&
      &init_read(4) &&
      &nt_close)) {
	print "LSA Close failed\n" if $opt_v;
	goto CLOSE;
}

&close_socket;

$service = "netbios-ssn";
$status = "a";
$trusted = "ANY\@$target";
$trustee = "ANY\@$target";
#
# Guess account passwords
#
&netbios_init;
&open_socket($target, tcp, 139);

if (!&session_request($nb_name)) {
    print "Session request failed\n" if $opt_v;
    goto CLOSE;
}
if (!&session_negotiate) {
    print "Session negotiate failed\n" if $opt_v;
    goto CLOSE;
}

# Check for LDAP_Anonymous default password (MS Site Server)

# First check that we don't alarm on non-existent accounts
# (Apparently some non-existent accounts as treated as
# null users, either due to NT misconfiguration or a bug
# in netbios.pl)
if (!&session_setup($nb_name,"n0n_ex1stant","")) {
    print "trying LDAP_Anonymous/LdapPassword_1\n" if $opt_v;
    if (&session_setup($nb_name,"LDAP_Anonymous","LdapPassword_1")) {
	$severity = "ns";
	$service_output = "Microsoft Site Server";
	$text = "MS Site Server default account";
	&saint_print;
    }
}

# Attempt log-in
$service_output = "guessed account password";
for $login_name (@login) {
    for (@guesses) {
	($guess = $_) =~ s/%login%/$login_name/;
	if ($guess =~ /%nigol%/) {
	    # Check the login backwards
	    $backward = "";
	    $forward = $login_name;
	    while($forward) { $backward .= chop $forward; }
	    $guess =~ s/%nigol%/$backward/;
	}
	print "trying $login_name/$guess\n" if $opt_v;
	if (&session_setup($nb_name,$login_name,$guess)) {
	    if ($login_name eq $login[0]) {
		# administrator account (id 500)
		$severity = "rs";
	    } elsif ($login_name eq $login[1]) {
		# guest account (id 501)
		$severity = "ns";
	    } else {
		$severity = "us";
	    }
	    if ($guess eq "") {
		$text = "Windows account $login_name has no password";
	    } else {
		$text = "Guessed password to windows account ($login_name:$guess)";
	    }
	    &saint_print;
	    last;
	}
    }
}

CLOSE: &close_socket;

