So I get extremely frustrated having to change my password every 60 days because the security department has this belief that somehow that is going to prevent the nightmare at Sony from coming down upon our company. Without getting too deep into the politics around security I am a firm believer that it is far better for people to have a password that is highly complex and never changes or better yet high entropy and very simple to remember as opposed to forced rotations of passwords. My reasoning is simple. If I were a hacker and I got your password, I wouldn’t wait 60 days to use it. I would own you in the immediate… as in right now. 

Anyways to the point, I wrote a script years back that someone had asked me to share with them, so I figured I would make it available to everyone. It’s pretty straight forward. If you want to keep your password you simply have to flush the passwords out of the historical storage in Active Directory/LDAP. This little powershell scriptlet performs this function for you. It also reports each iteration of passwords used (in case the script is interrupted or fails so you can still login to your account and change the password.

Keep in mind that your account will take time to populate to all of the domain controllers in the domain as well as the forest and could result in you getting locked out during the timeframe when the domain is not quite synced. I highly suggest running the script while only logged into one device. I power down my cellphone and wireless on my tablet and shutdown my laptop and do this from my workstation right before I go to lunch. This gives the world an hour or so to get back in sync.

Now for the love:

########################################################################################################
Function Roll-DomainPassword()
{
  $Iterations = 15
  $PasswordLength = 15

  $DomainController = [string]([ADSI]”LDAP://RootDSE”).dnshostname.ToString()
  $CurrentUser = [Environment]::UserName 
  
  # PRINTS INPUTS
  
  Write-Host Generating $Iterations Passwords of $PasswordLength Characters in Length 
  Write-Host  for User $CurrentUser on $DomainController
  
  $OriginalPassword = Read-Host -Prompt "Password" -AsSecureString
  $LastPassword = $OriginalPassword
  
  For ($PassIteration = 0; $PassIteration -lt ($Iterations - 1); $PassIteration++) {
  
    $RandomPass = CreatePassword($PasswordLength)
  
    # OUTPUT CURRENT GENERATED PASSWORD TO USER FOR PROBLEM 
    # RESOLUTION IF SCRIPT FAILS TO COMPLETE.
    Write-Host Password$( $PassIteration + 1 ): "$RandomPass"
    
    # CONVERT PLAIN-TEXT STRING TO PASSWORD
    $NewPassword = $RandomPass | ConvertTo-SecureString `
      -AsPlainText -Force
    
    # SET DOMAIN PASSWORD TO NEW ITERATION TEMP PASSWORD
    Set-AdAccountPassword -Identity $CurrentUser -Server $DomainController `
                          -NewPassword $NewPassword -OldPassword $LastPassword
    
    $LastPassword = $NewPassword
    
    # RANDOMIZES TIME BETWEEN RANDOM INTEGER GENERATION REQUESTS 
    # TO PREVENT DUPLICATE STRINGS
    $betterSeed = Get-Random
    foreach ($char in $RandomPass) {
      $intChar = [int][char]$char[1]
      if ($intchar % 2 -eq 0) {
        $betterSeed = $betterSeed + $intchar
      } else {
        $betterSeed = $betterSeed - $intchar
      }
    }
    Start-Sleep -Milliseconds $( Get-Random -Maximum 999 -Minimum 11 -SetSeed $betterSeed )
  }
  
  Write-Host Setting Password back to original...
  
  # SET DOMAIN PASSWORD BACK TO ORIGINAL PASSWORD
  Set-AdAccountPassword -Identity $CurrentUser -Server $DomainController `
                        -NewPassword $OriginalPassword -OldPassword $LastPassword
}

function CreatePassword([int]$length) {

  # GENERATE RANDOM PASSWORD BASED ON LIMITED CHARACTER SET TO MAKE 
  # FOR EASY READING BY USER PREFERING NUMBERS AND SYMBOLS TO ALPHA
  # CHARACTERS WHEN VISUAL RESEMBLANCE OF DIGIT MAKES FOR DIFFICULT 
  # INTERPRETATION.
  #
  # Special thanks to Brent Challis on powershell.com forums for 
  # providing this wonderful snippit.
  # http://powershell.com/cs/members/bchallis/default.aspx

  $specialCharacters = "~!@#$%^&*()-_+=[]{};:,.<>/\"
  $lowerCase = "abcdefghkmnpqrtuvwxyz"
  $upperCase = "ABCDEFGHKLMNPQRTUVWXYZ"
  $numbers = "1234567890"

  $res = ""
  $rnd = New-Object System.Random

  do   {
    $flag = $rnd.Next(4); 
    
    if ($flag -eq 0) {
      $res += $specialCharacters[$rnd.Next($specialCharacters.Length)];
    } elseif ($flag -eq 1) {
      $res += $lowerCase[$rnd.Next($lowerCase.Length)];
    } elseif ($flag -eq 2) {
      $res += $upperCase[$rnd.Next($upperCase.Length)];
    } else {
      $res += $numbers[$rnd.Next($numbers.Length)];
    }
  } while ( 0 -lt $length-- )

  return $res
}

 

Advertisements