企业内部AD脆弱密码审计
by 云舒
2008-07-09
http://www.ph4nt0m.org
这个是前段时间做的个小脚本,没什么用,审计内部AD脆弱密码的。做这样一些简单的工作,脚本语言确实挺合适的。需要一个普通的AD账号,导出账户名,过滤掉禁用的,然后开始扫描。密码字典按照自己公司的实际情况写就好了,支持%USERNAME%123这样的格式。
脚本里面的各种参数我写死了,因为自己用,不必要敲参数。如果想要用用看,自己改就是了,perl这种东西简单的学一下的话,一个上午就够了。下午不行,这种天气下午只适合睡觉,或者吃点冰绿豆汤之类的东西,反正是不适合看代码。
#!/usr/bin/perluse warnings;
use strict;
use Win32::OLE;
use Data::Dumper;
use Authen::Simple::ActiveDirectory;
use constant ADS_UF_ACCOUNTDISABLE => 2;
use constant ADS_SCOPE_SUBTREE => 2;
my $server = 'bj.microsoft.com';
my $domain = 'bj.microsoft.com';
my %users;
my @pwds;
select( STDOUT );
$| = 1;
print "Loading account from ad";
&LoadUser( );
print "done!n";
print scalar(keys(%users))." users loaded!n";
print "Loading password from dic";
&LoadPwd( );
print "done!n";
open( REPORT, ">report.txt" ) || die "create report error: $!n";
select( REPORT );
$| = 1;
select( STDOUT );
foreach my $user( keys(%users) )
{
foreach my $pwd( @pwds )
{
$pwd =~ s/%USERNAME%/$user/;
my $ret = &TestPwd( $user, $pwd );
if( $ret == 1 )
{
print "cracked! username=$user,password=$pwd,mail=".$users{$user}."n";
print REPORT "cracked! username=$user,password=$pwd,mail=".$users{$user}."n";
last;
}
#print "testing [$user/$pwd] n";
}
}
close( REPORT );
sub LoadUser
{
my $objConnection = Win32::OLE->new( "ADODB.Connection" );
my $objCommand = Win32::OLE->new( "ADODB.Command" );
# open ad
$objConnection -> open( "Provider=ADsDSOObject;" );
$objCommand -> {"ActiveConnection"} = $objConnection;
# search what and how
my $cmd = "select userAccountControl,distinguishedName,mail from 'GC://dc=bj,dc=microsoft,dc=com' where objectCategory='user'";
$objCommand -> {"CommandText"} = $cmd;
# import all users
$objCommand -> Properties -> {"Page Size"} = 1000;
# search all subtree
$objCommand -> Properties -> {"searchscope"} = ADS_SCOPE_SUBTREE;
my $objRecordSet = Win32::OLE->new( "ADODB.Recordset" );
$objRecordSet = $objCommand->Execute( ) || die "query data from active directory error,exitn";
while( not $objRecordSet -> eof )
{
my $intUAC = $objRecordSet -> Fields("userAccountControl") -> value;
# remove diable account
if( not ( $intUAC & ADS_UF_ACCOUNTDISABLE ) )
{
my $longName = $objRecordSet -> Fields("distinguishedName") -> value;
my $mail = $objRecordSet -> Fields("mail") -> value;
if( (!defined($mail)) or $mail eq "" )
{
$mail = "null";
}
if( $longName =~ /^CN=([w.-_]+),/ )
{
#print ."n";
my $userName = $1;
chomp( $mail );
chomp( $userName );
$users{$userName} = $mail;
}
}
$objRecordSet -> MoveNext();
}
}
sub LoadPwd
{
open( FH, "<pass.txt" ) || die "Open password dict error,exit!n";
@pwds = <FH>;
chomp( @pwds );
}
sub TestPwd
{
my $username = shift;
my $password = shift;
my $ad = Authen::Simple::ActiveDirectory -> new( host => $server, principal => $domain ) || die "Connected error: $!";
if ( $ad->authenticate( $username, $password ) )
{
return 1;
}
else
{
return 0;
}
}