【问题标题】:Selecting the AD ntSecurityDescriptor Attribute as a Non-Admin选择 AD ntSecurityDescriptor 属性作为非管理员
【发布时间】:2017-04-07 21:04:33
【问题描述】:

我正在为 Active Directory ACL/ACE 开发 SDDL/安全描述符解析器。我几乎完成了,当我使用管理帐户连接到 LDAP 时一切正常。

但是,当我尝试以非管理帐户的身份查询 ntSecurityDescriptor 时,它不会返回任何值。用户帐户本身有权读取该属性。当我开始对此进行调查时,我遇到了以下 LDAP 服务器控件:

https://msdn.microsoft.com/en-us/library/cc223323.aspx

LDAP_SERVER_SD_FLAGS_OID 控件与 LDAP 搜索一起使用 请求控制 Windows 安全描述符的一部分以 取回。 DC 仅返还证券的指定部分 描述符。它还与 LDAP 添加和修改请求一起使用,以 控制要修改的 Windows 安全描述符部分。华盛顿特区 仅修改安全描述符的指定部分。

当将此控件发送到 DC 时,controlValue 字段设置为 以下ASN.1结构的BER编码。

 SDFlagsRequestValue ::= SEQUENCE {
     Flags    INTEGER
 }

Flags 值具有以下格式,以大端字节表示 命令。 X 表示客户端应该设置为 0 的未使用位,并且 服务器必须忽略它。

指定未设置位或不使用 LDAP_SERVER_SD_FLAGS_OID 控件的标志等效于将标志设置为 (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION)。将此控件发送到 DC 不会导致服务器在其响应中包含任何控件。

文档中该语句的最后一部分似乎不正确,至少在非管理用户的上下文中不正确。

我的问题:我应该如何使用标准的 PHP LDAP 库函数将此控件发送到 LDAP?我知道我必须设置服务器控件,但我不确定如何对值进行编码。我已将其范围缩小为最简单的示例:

$user = 'user@example.local';
$pass = 'secret';
$server = 'dc1.example.local';

$ldap = ldap_connect($server);
ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);

ldap_bind($ldap, $user, $pass);
$ctrl1 = array(
    "oid" => "1.2.840.113556.1.4.801",
    "iscritical" => true,
    // How should this value be set???
    "value" => sprintf("%c%c%c%c%c", 48, 3, 2, 1, 15)
);
if (!ldap_set_option($ldap, LDAP_OPT_SERVER_CONTROLS, array($ctrl1))) {
    echo "Failed to set server controls";
}

$searchUser = "user";
$dn = "dc=example,dc=local";
$filter="(sAMAccountName=$searchUser)";
$attr = array("ntsecuritydescriptor");

$sr = ldap_search($ldap, $dn, $filter, $attr);
$info = ldap_get_entries($ldap, $sr);

// Should contain ntSecurityDescriptor...but it does not.
var_dump($info);

我知道控件的值需要进行 BER 编码,但我不确定如何实现文档中定义的值。我能够找到以下 Java 示例:

https://github.com/Tirasa/ADSDDL/blob/master/src/main/java/net/tirasa/adsddl/ntsd/controls/SDFlagsControl.java

但我无法将那里发生的事情翻译成 PHP。有什么想法吗?

【问题讨论】:

    标签: php active-directory ldap


    【解决方案1】:

    问题似乎是非特权 AD 用户帐户将无权访问安全描述符的 SACL。要解决这个问题并仍然检索ntSecurityDescriptor(减去 SACL),请发送设置了所有其他标志值的控件(其值为 7):

    // OWNER_SECURITY_INFORMATION + GROUP_SECURITY_INFORMATION + DACL_SECURITY_INFORMATION
    $sdFlags = 7;
    
    $ctrl1 = array(
        "oid" => "1.2.840.113556.1.4.801",
        "iscritical" => true,
        "value" => sprintf("%c%c%c%c%c", 48, 3, 2, 1, $sdFlags)
    );
    if (!ldap_set_option($ldap, LDAP_OPT_SERVER_CONTROLS, array($ctrl1))) {
        echo "Failed to set server controls";
    }
    

    我的猜测是 MS 文档没有错,LDAP_SERVER_SD_FLAGS_OID 的默认值用于设置 all 标志(包括 SACL)。由于大多数普通帐户无权访问该 SACL,因此 AD 可能决定不返回安全描述符的任何部分,因此即使您选择了查询也不会返回 ntSecurityDescriptor 值。

    另一个重要注意事项,如果您使用 LDAP 分页,它似乎会干扰此控制。您不能同时使用分页和此控件。我不确定这是否是此控件的一般副作用,或者是 PHP 的 LDAP 模块中如何完成服务器控件的问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-19
      • 2013-06-19
      • 1970-01-01
      相关资源
      最近更新 更多