如何确保这是一个安全的 LDAP 连接并写入 AD 的 unicodePwd 属性?

问题描述 投票:0回答:1

我正在使用带有 Ubuntu 24.04 Noble 的 Vagrant VM 来开发一个项目。我正在使用 Node 20.18.0 和 NestJs 10.4.5。

在其中一条路线中,我尝试使用 NodeJs 的 ldapts 库访问安全的 ldap 服务器。安全连接的目的是在AD中写入unicodePwd字段。

Microsoft 有 此文档 与编写 unicodePwd 属性相关。基本上,密码必须用双引号括起来,并且必须采用 UTF-16 编码。那么该属性应该写入安全连接中。

最初我尝试通过这种方式连接:

const client = new Client({
    url: 'ldaps://<ldapip>',
    timeout: 0,
    connectTimeout: 0,
});
const bindDN = 'CN=Administrator,CN=Users,DC=myproject,DC=local';
const password = 'mypdw';

try {
    console.log('D1');
    let cert = fs.readFileSync('/vagrant/backend/certs/mycert.crt');

    console.log(cert.toString('base64'));
    await client.startTLS({
      ca: [cert],
    });
    
    console.log('D2');
    await client.bind(bindDN, password);
    
    console.log('D3');
    (...)
} catch (error) {
    return { status: 500, msg: 'LDAP fail', error }
} finally {
    await client.unbind();
}

当我运行此代码时,D0、D1 和证书打印正确,但未到达 D2 点。它失败并出现以下错误:

{"code":"UNABLE_TO_VERIFY_LEAF_SIGNATURE"}}

我确信该证书是由 AD 的 CA 发出的。我正在使用 Chromium 并且 CA 已正确导入其中。 我还尝试创建一个包含用户证书和 CA 证书的文件,但它也不起作用。

然后我对代码做了一些更改,现在它可以连接了,但我不确定我是否有安全连接,因为我无法用它做我需要做的事情(编写 unicodePwd 属性)。有没有办法检查安全连接是否到位?或者只是连接并绑定到 ldaps://myserver:636 就足以保证安全连接?

这是代码的当前版本:

// I tried the line below both with ca and client certs with equal results
let cert = fs.readFileSync('/vagrant/backend/certs/client-cert.crt');
let opts = {
    ca: [cert],
    host: 'myurl.myproject.local',
    rejectUnauthorized: false,
    secure: true         
};  
const client = new Client({
    url: 'ldaps://myurl.myproject.local:636',
    timeout: 0,
    tlsOptions: {
        ...opts, 
        minVersion: 'TLSv1.1'
    },
    connectTimeout: 0,
});
const bindDN = 'CN=Administrator,CN=Users,DC=myproject,DC=local';
const password = 'mypdw';
    
try {
    console.log('D1');
    console.log(cert.toString('base64'));
        
    console.log('D2');
    await client.bind(bindDN, password);
        
    console.log('D3', client.isConnected);
        
    let passwdUtf16 = this.encodePassword("mypwd");
        
    var newUser = {
        sn: 'teste',
        objectClass: ["organizationalPerson", "person", "user"],
        unicodePwd: passwdUtf16
    }       

    await client.add('cn=test,ou=MyCompany,ou=Organizations,dc=myproject,dc=local', newUser);
        
    console.log('D4');

我还尝试添加不带 unicodePwd 属性的用户(它有效),然后执行以下操作:

let change = new Change({ operation: 'replace', modification: new Attribute({ type: 'unicodePwd;binary', values: [passwdUtf16] }) });

await client.modify('cn=test,ou=MyCompany,ou=Organizations,dc=myproject,dc=local', change);

在这两种情况下,我都会收到 UnwillingToPerformError 错误,这让我认为我没有建立安全连接。

这是encodePassword函数:

encodePassword(str) {
  const text = '"' + str + '"';
  let byteArray = new Uint8Array(text.length * 2);
  for (let i = 0; i < text.length; i++) {
    byteArray[i * 2] = text.charCodeAt(i); // & 0xff;
    byteArray[i * 2 + 1] = text.charCodeAt(i) >> 8; // & 0xff;
  }
  return String.fromCharCode.apply(String, byteArray);
}

现在我有问题:

  1. 如何断言这是一个安全连接以便正确写入 unicodePwd 属性?

  2. 我写密码有什么错误吗?

javascript node.js active-directory nestjs ldap
1个回答
0
投票
  1. 根据以下声明,需要 SASL 层加密而不是 SSL/TLS。

“在 Windows Server 2003 操作系统及更高版本上,DC 还允许修改受 128 位(或更好)简单身份验证和安全层 (SASL) 层加密而不是 SSL/TLS 保护的连接上的 unicodePwd 属性。” 参考:https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/6e803168-f140-4d23-b2d3-c3a8ab5917d2

我认为该属性的特殊之处在于文档中说:

“为了使密码更改操作成功,服务器强制要求要更改密码的用户或 inetOrgPerson 对象必须拥有自身的“用户更改密码”控制访问权限,并且 Vdel 必须是当前密码在物体上。”

您可以通过此链接提高 LDAP 日志记录级别 https://learn.microsoft.com/en-us/troubleshoot/windows-server/active-directory/configure-ad-and-lds-event-logging。本文中引用的诊断子项可以选择为 16 或 27,分别检查 LDAP 接口事件或 PDC 密码更新通知。日志记录级别可以选择 4(详细)。

© www.soinside.com 2019 - 2024. All rights reserved.