我有一个Apache PHP服务器,我试图使用现有的活动目录实现权限。
我们选择了NTLM来自动验证Windows用户,这部分似乎工作,我正在检索用户名和NTLM挑战的答案。
我正在使用PHP ldap函数与Active Directory通信(使用服务帐户),到目前为止,我可以检索用户组并检查用户名是否存在,但我无法以用户身份连接以验证密码:$success = @ldap_bind($ad, "$username@$domain}", $password) or die('Could not bind to AD.');
在这里,我可以用明文密码连接,但只有所谓的“NTLM响应安全缓冲区”。
可以链接NTLM和LDAP吗?如何链接?PHP ldap_bind
是否不支持NTLM?
我读到here可以将挑战和用户NTLM响应作为“NETLOGON_NETWORK_INFO”进行传输,但我找不到任何有关此方法的文档。
我还发现a laravel library声称可以做到这一点,但查看代码时,我发现了我已经测试过的内容:@ldap_bind
需要明文密码。
我的问题可能类似于this unanswered question,但除此之外,很少有结果将LDAP和NTLM关联起来。
下面是我接手该项目时服务器上的NTLM实现:
$headers = apache_request_headers();
if (@$_SERVER['HTTP_VIA'] != NULL) {
//echo "Proxy bypass!";
}
elseif(!isset($headers['Authorization']) || $headers['Authorization'] == NULL) {
header( "HTTP/1.0 401 Unauthorized" );
header( "WWW-Authenticate: NTLM" );
exit;
}
if(isset($headers['Authorization']) && substr($headers['Authorization'],0,5) == 'NTLM ') {
$chaine = substr($headers['Authorization'], 5);
$chained64 = base64_decode($chaine);
if(ord($chained64[8]) == 1) {
$retAuth = "NTLMSSP".chr(000).chr(002).chr(000).chr(000).chr(000).chr(000).chr(000).chr(000);
$retAuth .= chr(000).chr(040).chr(000).chr(000).chr(000).chr(001).chr(130).chr(000).chr(000);
$retAuth .= chr(000).chr(002).chr(002).chr(002).chr(000).chr(000).chr(000).chr(000).chr(000);
$retAuth .= chr(000).chr(000).chr(000).chr(000).chr(000).chr(000).chr(000);
$retAuth64 = trim(base64_encode($retAuth));
header( "HTTP/1.0 401 Unauthorized" );
header( "WWW-Authenticate: NTLM $retAuth64" );
exit;
}
if(ord($chained64[8]) == 3) {
//LM Response Security Buffer:
$lenght_LMRSB = (ord($chained64[15])*256 + ord($chained64[14]));
$offset_LMRSB = (ord($chained64[17])*256 + ord($chained64[16]));
$LMRSB = str_replace("\0","",substr($chained64, $offset_LMRSB, $lenght_LMRSB));
//NTLM Response Security Buffer:
$lenght_NTLMRSB = (ord($chained64[23])*256 + ord($chained64[22]));
$offset_NTLMRSB = (ord($chained64[25])*256 + ord($chained64[24]));
$NTLMRSB = str_replace("\0","",substr($chained64, $offset_NTLMRSB, $lenght_NTLMRSB));
//Domain:
$lenght_domain = (ord($chained64[31])*256 + ord($chained64[30]));
$offset_domain = (ord($chained64[33])*256 + ord($chained64[32]));
$domain = str_replace("\0","",substr($chained64, $offset_domain, $lenght_domain));
//Login:
$lenght_login = (ord($chained64[39])*256 + ord($chained64[38]));
$offset_login = (ord($chained64[41])*256 + ord($chained64[40]));
$login = str_replace("\0","",substr($chained64, $offset_login, $lenght_login));
echo "$LMRSB<br>";
echo "$NTLMRSB<br>";
//HERE i would like to verify credentials against my active directory before accepting the username as a real logged user
$_SESSION["utilisateur"] = $login;
}
}
1条答案
按热度按时间ddrv8njm1#
我们选择了NTLM来自动验证Windows用户,这部分似乎工作,我正在检索用户名和NTLM挑战的答案。
无法通过LDAP绑定验证NTLM响应。
我的意思是,从技术上讲,您可能可以将挑战和响应中继到SASL NTLM绑定,但这实际上与您的安全团队通常希望防止发生的“NTLM中继攻击”相同。如果启用了必要的强化选项,则将为特定服务SPN发出NTLM响应,并且该响应将被LDAP服务器拒绝。因此,即使在理论上是可能的,依赖于它继续是可能的也是非常不明智的(甚至比首先使用NTLM更不明智)。
我在这里读到一个可以传输挑战和用户NTLM响应作为“NETLOGON_NETWORK_INFO”,但我找不到任何文档的方式这样做。
是的,但这样做需要现有的“Netlogon安全通道”,并且 that 需要计算机帐户。
通常的方法是安装桑巴舞(特别是Winbind组件)并将Web服务器加入域(这是建立Netlogon通道的地方),此时您将能够使用
ntlm_auth
CLI工具以“官方”方式验证NTLM挑战,方法是让Winbind通过Netlogon协议将它们中继到DC。(You实际上不需要在你的web服务器上安装“用户身份验证”部分(pam_winbind/nsswitch),以防你担心用户会通过SSHing进入服务器;你只需要守护进程。)
但是,我强烈建议不要做任何涉及NTLM的事情。你有 Active Directory, Active Directory从2000年起就有Kerberos**。**HTTP支持Kerberos身份验证,就像它支持NTLM一样,你甚至不需要自己滚动它-你所需要的只是mod_auth_gssapi Apache模块(或旧的mod_auth_kerb)和一个keytab,Web服务器将完成所有工作;你可以在PHP脚本中从
$_SERVER["REMOTE_USER"]
中获取用户名。(Kerberos票据的验证甚至不需要联系KDC,也没有任何服务运行,也没有特殊的特权通道;只是一个keytab,其中包含webapp的服务用户帐户的密码。)