Contents

绕过域策略的强制密码历史

Contents

前言

域策略通常会设置强制密码历史,比如多少次密码不允许重复。

但对于Email、OA、SVN、Git等各种用到LDAP域认证来实现SSO的服务来说,密码都要重新改一遍,确实很麻烦。

安全上去,便利下来。

于是曾几何时,写了个ps脚本,通过不断设置随机密码,来绕过密码历史的次数限制,这样就可以继续沿用以前的密码了。

使用步骤

  • 对于未加域的用户,cmd输入:runas /netonly /noprofile /user:YourCorp.com\YourUserName powershell
  • 保存下面的代码到ecp.ps1,然后调用:Import-Module ecp.ps1; ECP YourUserName NewPassword
  • 提示:这里可以使用AdFind工具来查看域策略,例如:AdFind.exe -h YourCorp.com -s base -b DC=YourCorp,DC=com ,pwdHistoryLength就是强制密码历史次数
$LDAP_ROOT = 'LDAP://DC=YourCorp,DC=com'  //这里改成你所在的域

function GetUserLdapPath([string]$user)
{
    $searcher = New-Object DirectoryServices.DirectorySearcher;
    $searcher.Filter = "(&(objectCategory=Person)(sAMAccountName=$user))";
    $searcher.SearchRoot = $LDAP_ROOT;
    return $searcher.FindAll()[0].Path;
}

function GenRandomPassword()
{
    Add-Type -AssemblyName System.Web;
    $PasswordLength = 12;     //这是生成的密码长度,对大多数域策略来说12位够了,也可以通过AdFind查询
    $SpecialCharCount = 0;    //特殊字符数量
    return [System.Web.Security.Membership]::GeneratePassword($PasswordLength, $SpecialCharCount);
}

function ChangePassword([int]$rotation, [string]$user, [string]$old_psw, [string]$new_psw)
{
    $ldap_user = GetUserLdapPath($user);
    Write-Output "[User] $user [Ldap] $ldap_user";
    if ([String]::IsNullOrEmpty($ldap_user)) {
        Write-Output "[UserLdap] err";
        return '';
    }

    $last_psw = $old_psw;
    for ($i = 0; $i -lt $rotation; $i++) {
        $rand_psw = GenRandomPassword;
        ([ADSI]$ldap_user).ChangePassword($last_psw, $rand_psw);
        Write-Output "[Phase$i Password] $last_psw => $rand_psw";
        $last_psw = $rand_psw;
    }
    ([ADSI]$ldap_user).ChangePassword($last_psw, $new_psw);
    Write-Output "[End Phase] $last_psw => $new_psw successfully.";
}

function ECP([string]$user, [string]$password)
{
    ChangePassword 5 $user $password $password;  //强制密码历史次数
}