如何以编程方式获取 Enforce Password History 组策略设置? [英] How to programatically get the Enforce Password History group policy setting?

查看:58
本文介绍了如何以编程方式获取 Enforce Password History 组策略设置?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我如何以编程方式获取 强制执行密码历史 组策略设置?

How can i programatically get the Enforce Password History group policy setting?

您可以在以下位置找到组策略选项:

You can find the Group Policy option under:

**计算机配置\Windows 设置\安全设置\帐户策略\密码策略**

**Computer Configuration\Windows Settings\Security Settings\Account Policies\Password Policy**

强制执行密码历史

此安全设置决定了在可以重复使用旧密码之前必须与用户帐户关联的唯一新密码的数量.该值必须介于 0 到 24 个密码之间.

This security setting determines the number of unique new passwords that have to be associated with a user account before an old password can be reused. The value must be between 0 and 24 passwords.

此政策使管理员能够通过确保旧密码不被不断重复使用来增强安全性.

This policy enables administrators to enhance security by ensuring that old passwords are not reused continually.

与所有组策略选项一样,它存储在注册表中.不幸的是,它存储在一个未记录的注册表位置:

Like all group policy options, it is stored in the registry. Unfortunately it is stored in an undocumented registry location:

HKEY_LOCAL_MACHINE\SAM\SAM\Domains\Account\F

HKEY_LOCAL_MACHINE\SAM\SAM\Domains\Account\F

采用 未记录的二进制 blob 格式.

有一个 WMI 类 RSOP_SecuritySettingBoolean,但没有任何上下文,它只是一个挂在那里的名字 - 我不知道如何通过 COM/native 读取.

There is a WMI class RSOP_SecuritySettingBoolean, but without any context, it's just a name hanging out there - which i have no idea how to read through COM/native.

Windows 确实提供了一个 NetValidatePasswordPolicy API 允许它验证您的密码,例如:

Windows does provide an NetValidatePasswordPolicy API that will allow it to validate your password for things like:

  • 失败的尝试太多
  • 帐户锁定
  • 锁定自动重置
  • 密码最短使用期限
  • 密码最长使用期限
  • 密码重复使用

并且它将按照在计算机上生效的组策略执行所有这些操作.除了密码历史记录外,一切都很好.

and it will do all these things following the group policy in effect on the computer. And it all works great, except for password history.

该函数要求您传递密码哈希列表,例如:

The function requires you to pass a list of password hashes, e.g.:

  • $2a$14$mACnM5lzNigHMaf7O1py1OLCBgGL4tYUF0N/4rS9CwDsI7ytwL4D6
  • $2a$14$mACnM5lzNigHMaf7O1py1O3vlf6.BA8k8x3IoJ.Tq3IB/2e7g61Km
  • $2a$12$.TtQJ4Jr6isd4Hp.mVfZeuh6Gws4rOQ/vdBczhDx.19NFK0Y84Dle
  • $2a$12$Ro0CUfOqk6cXEKf3dyaM7OhSCvnwM9s4wIX9JeLapehKK5YdLxKcm

以及新候选密码的哈希值,例如:

as well as the hash of the new candidate password, e.g.:

  • $2a$10$1JsBs47iuMNsV166PKV.u.56hlT5/tRe9V5t5FIdfA0axpDSQuNN

这将导致 NetValidatePasswordPolicy 检查您当前的哈希值是否与任何现有的哈希值匹配.不幸的是,检查以前的密码哈希的整个概念只有在您使用弱密码算法时才有效(例如 Windows 使用的 PBKDF2).

This will cause NetValidatePasswordPolicy to check if your current hash matches any of the existing hashes. Unfortunately, the entire concept of checking previous password hashes only works when you use a weak password algorithm (such as PBKDF2 that Windows uses).

因为我使用现代的、昂贵的salted、密码散列算法 (BCrypt/SCrypt),所以不能仅从密码确定性地生成散列 - 我可以't 只需检查旧列表.我将不得不针对每个以前存储的盐重新散列用户的新密码.

Because i use a modern, expensive, salted, password hashing algorithm (BCrypt/SCrypt), a hash cannot be deterministically generated from a password alone - i can't simply check the old list. I would have to rehash the user's new password against every previously stored salt.

  • 这不仅是一项昂贵的操作;检查所有 24 个存储的哈希值可能需要 12 秒
  • 我不知道什么时候停止,因为我不知道密码历史记录组策略值(例如,当我只需要检查零时,我会检查所有 24 个存储的哈希值).

我考虑过使用包含 24 个存储密码哈希的虚拟列表调用 NetValidatePasswordPolicy,例如:

I have considered calling NetValidatePasswordPolicy with a dummy list of 24 stored password hashes, e.g.:

  • a
  • b
  • c
  • d
  • ...
  • v
  • w
  • x

API 然后会告诉我它的密码与 n 历史中的任何密码都不匹配.但 API 也旨在将您必须保留的东西返还给您.它可能然后返回:

The API will then tell me that it password has did not match any in the n history. But the API is also designed to return to you what you have to keep. It might then return:

  • $2a$10$1JsBs47iuMNsV166PKV.u.56hlT5/tRe9V5t5FIdfA0axpDSQuNN
  • a
  • b
  • c

由此我可以推断出密码历史长度为.

And from that i might be able to infer that the password history length is four.

但我还没有到达那里.

我已经三天了,失去了耐心.

I'm three days into this, and losing patience.

  • 为什么 Microsoft 会混淆组策略?
  • 为什么微软不允许人们阅读它?
  • 为什么它没有记录?
  • 我如何才能获得相同的结果?

推荐答案

事实证明,使用 RSOP_SecuritySettingBoolean(策略的结果集)是一个坏主意;因为它只适用于加入域的机器.

Turns out that using RSOP_SecuritySettingBoolean (resultant set of policy) is a bad idea; as it only works on domain-joined machines.

查询 Active Directory 同样仅适用于加入域的计算机;并且适用于有能力查询域控制器的用户(这是不可授权的).

Querying Active Directory likewise only works for computers joined to a domain; and on works for users who have the ability to query the domain controller (which is something that can be un-granted).

真正的解决方案是使用 NetUserModalsGet,它可以返回如下结构:

The real solution is to use NetUserModalsGet, which can return you structures like:

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; //Specifies the length of password history 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.
}

struct USER_MODALS_INFO_3 
{
   DWORD usrmod3_lockout_duration;
   DWORD usrmod3_lockout_observation_window;
   DWORD usrmod3_lockout_threshold;
}

示例代码为:

Int32 GetPasswordHistoryLength()
{
   PUSER_MODALS_INFO_0 info0;

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

   if (res <> NERR_Success)
      RaiseWin32Error(res);
   try
   {
      return info0.usrmod0_password_hist_len;
   }
   finally
   {
      NetApiBufferFree(info0);
   }
}

文档说最大值是 DEF_MAX_PWHIST,在 Lmaccess.h 中定义为:

The documentation says the max value is DEF_MAX_PWHIST, which is defined in Lmaccess.h as:

//
// user modals related defaults
//

#define MAX_PASSWD_LEN      PWLEN
#define DEF_MIN_PWLEN       6
#define DEF_PWUNIQUENESS    5
#define DEF_MAX_PWHIST      8

#define DEF_MAX_PWAGE       TIMEQ_FOREVER               // forever
#define DEF_MIN_PWAGE       (unsigned long) 0L          // 0 days
#define DEF_FORCE_LOGOFF    (unsigned long) 0xffffffff  // never
#define DEF_MAX_BADPW       0                           // no limit
#define ONE_DAY             (unsigned long) 01*24*3600  // 01 day

但事实并非如此.该策略允许用户最多设置 24 个.

But that's not true. The policy allows a user to set a maximum of 24.

注意:任何发布到公共领域的代码.无需署名.

Note: Any code released into public domain. No attribution required.

这篇关于如何以编程方式获取 Enforce Password History 组策略设置?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆