Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reading the local password policy programmatically

Are there Windows API functions that allows reading what the current password policy is? For instance, minimum length, complexity etc.

If not reading, is there a way to verify a password against the policy programmatically?

like image 288
Maltrap Avatar asked Nov 24 '08 10:11

Maltrap


3 Answers

See Security Watch Windows Domain Password Policies. You can hit AD using ADSI or its wrappers. I found a VBScript sample. You can translate it to any language you want:

Sub ListPasswordPolicyInfo( strDomain )
    Dim objComputer
    Set objComputer = GetObject("WinNT://" & strDomain )
    WScript.Echo "MinPasswordAge: " &  ((objComputer.MinPasswordAge) / 86400)
    WScript.Echo "MinPasswordLength: " &  objComputer.MinPasswordLength
    WScript.Echo "PasswordHistoryLength: " &  objComputer.PasswordHistoryLength
    WScript.Echo "AutoUnlockInterval: " &  objComputer.AutoUnlockInterval
    WScript.Echo "LockOutObservationInterval: " &  objComputer.LockOutObservationInterval
End Sub

Dim strDomain
Do
    strDomain = inputbox( "Please enter a domainname", "Input" )
Loop until strDomain <> ""

ListPasswordPolicyInfo( strDomain )

As a bonus, check out LDAP Admin. It's an open source LDAP directory editor, which you can use to test things, and also checkout the code written in Delphi.

like image 53
Eugene Yokota Avatar answered Sep 22 '22 02:09

Eugene Yokota


Eugene's answer is helpful, but not quite what I needed. The password complexity filter can actually be customized, and what would be good would be a way of asking Windows, does this password meet the requirements?

It took me a while to locate it, but the function is NetValidatePasswordPolicy. The MSDN docs for this function are awful; check out this MSDN blog entry instead.

like image 26
Nicholas Wilson Avatar answered Sep 22 '22 02:09

Nicholas Wilson


Querying ActiveDirectory only works for computers joined to a domain; and where the user has the ability to query the domain controller (which is something that can be un-granted).

@NicholasWilson's answer of using NetValidatePasswordPolicy is a good one; as it can do a lot of heavy lifting for you. It can even perform password quality checks that you would have to re-implement yourself. But NetValidatePasswordPolicy does fail as examining your custom password history when you use salted hashes to store passwords (e.g. BCrypt or Scrypt).

But the real question is how to query for the current machine's (even an non-domain joined machine's) password policy. You can query that using:

NetUserModalsGet

struct USER_MODALS_INFO_0
{
    DWORD usrmod0_min_passwd_len;
    DWORD usrmod0_max_passwd_age;
    DWORD usrmod0_min_passwd_age
    DWORD usrmod0_force_logoff; 
    DWORD usrmod0_password_hist_len;
}
PUSER_MODALS_INFO_0 = ^USER_MODALS_INFO_0;    

PUSER_MODALS_INFO_0 info0;

NET_API_STATUS res = NetUserModalsGet(nil, 0,  out info0);

if (res <> NERR_Success)
   RaiseWin32Error(res);
try
   //Specifies the minimum allowable password length. 
   //Valid values for this element are zero through PWLEN.
   Log(info0.usrmod0_min_passwd_len);

   //Specifies, in seconds, the maximum allowable password age. 
   //A value of TIMEQ_FOREVER indicates that the password never expires. 
   //The minimum valid value for this element is ONE_DAY. 
   //The value specified must be greater than or equal to the value for the usrmod0_min_passwd_age member.
   Log(info0.usrmod0_max_passwd_age);

   //Specifies the minimum number of seconds that can elapse between the time
   //a password changes and when it can be changed again. 
   //A value of zero indicates that no delay is required between password updates. 
   //The value specified must be less than or equal to the value for the usrmod0_max_passwd_age member.
   Log(info0.usrmod0_min_passwd_age);

   //Specifies, in seconds, the amount of time between the end of the valid
   // logon time and the time when the user is forced to log off the network. 
   //A value of TIMEQ_FOREVER indicates that the user is never forced to log off. 
   //A value of zero indicates that the user will be forced to log off immediately when the valid logon time expires.
   Log(info0.usrmod0_force_logoff);

   //Specifies the length of password hi'+'story maintained. 
   //A new password cannot match any of the previous usrmod0_password_hist_len passwords. 
   //Valid values for this element are zero through DEF_MAX_PWHIST
   Log(info0.usrmod0_password_hist_len);
finally
   NetApiBufferFree(info0);
end;
like image 29
Ian Boyd Avatar answered Sep 21 '22 02:09

Ian Boyd