使用 CredSpec 的经典 ASP/MSSQL 身份验证问题
Classic ASP/MSSQL Authentication Issue using CredSpec
我目前正在尝试对一些旧的(很快将被淘汰的)基础设施进行一些改进,以准备迁移到 .NET 核心。我们有一个小的反馈表,它使用 SQLOLEDB 连接字符串写入 SQL table。这些字符串与以明文定义的 username/password 配合使用时效果很好,但我希望放弃这种方法以支持集成身份验证。
我已经做了很多工作才能到达现在的位置:
- 基于安装了 ASP 功能的 IIS 构建了 docker 容器。
- 运行 Windows 主机上群中的容器 - 加入了我们的 AD 域。
- 设置 gMSA 以提供对数据库的域帐户访问权限。
目前,我已经 运行 完成了 Windows 容器指南中 MS 的 gMSA 中的所有步骤(https://docs.microsoft.com/en-us/virtualization/windowscontainers/manage-containers/manage-serviceaccounts). The tests check out, I'm able to run all the tests in https://docs.microsoft.com/en-us/virtualization/windowscontainers/manage-containers/gmsa-troubleshooting#check-the-container 没有任何问题,但是当我尝试使用我的连接字符串,我在日志中收到错误显示:
2020-09-28 19:36:43 172.17.173.120 POST /Default.asp |42|80040e4d|Login_failed_for_user_'NT_AUTHORITY\ANONYMOUS_LOGON'.
这对我来说没有多大意义,因为应用程序池标识设置为网络并且测试在容器上检出。
现在我尝试了一些操作,例如编辑 web.config 以将模拟设置为 true/false,通过 Windows 进行身份验证,但我仍然有点难过。我已将主机设置为允许通过 Kerberos 委托任何服务。
我还尝试使用以下方式登录:
docker exec -it --user "NT AUTHORITY\NETWORK SERVICE" cb4 powershell
然后 运行:
$connectionString = 'Data Source=serverhostname.domain.local;database=databasename;Integrated Security = True;'
$sqlConnection = New-Object System.Data.SqlClient.SqlConnection $connectionString
$sqlConnection.Open()
$sqlConnection | select *
这导致数据库连接处于打开状态。
应用程序池是使用 NetworkService 身份设置的
Get-ItemProperty IIS:\AppPools\domain.co.uk\ -Name processModel
identityType : NetworkService
userName :
password :
loadUserProfile : False
setProfileEnvironment : True
logonType : LogonBatch
manualGroupMembership : False
idleTimeout : 00:20:00
idleTimeoutAction : Terminate
maxProcesses : 1
shutdownTimeLimit : 00:01:30
startupTimeLimit : 00:01:30
pingingEnabled : True
pingInterval : 00:00:30
pingResponseTime : 00:01:30
logEventOnProcessModel : IdleTimeout
PSPath : WebAdministration::\413E8843BBEF\AppPools\domain.co.uk\
PSParentPath : WebAdministration::\413E8843BBEF\AppPools
PSChildName : domain.co.uk\
PSDrive : IIS
PSProvider : WebAdministration
Attributes : {identityType, userName, password, loadUserProfile...}
ChildElements : {}
ElementTagName : processModel
Methods :
Schema : Microsoft.IIs.PowerShell.Framework.ConfigurationElementSchema
如有任何建议,我们将不胜感激!
连接数据库需要注意以下几点
- 应用程序池的身份应该有一个域帐户。
- 域帐户具有读取或更改数据库的权限。
- IIS 服务器和 sql 服务器应在同一个 Intranet 中并使用同一个域。
更多细节可以参考这篇。
好的,所以我弄明白了并将我的发现发布在 public 要点中:
https://gist.github.com/jimbo8098/48fa8d1cd05a61b35534aa107decb3e3
基本上,问题是当应用程序池标识设置为网络时,站点不是,它使用的似乎是 IUSR。鉴于此,我没有将 gMSA 帐户中继到 ASP 的脚本,因此我无法使用集成身份验证。解决方案是 运行:
Set-WebConfigurationProperty system.webServer/security/authentication/anonymousAuthentication -Name "userName" -Value ""; if ($?) {
Set-WebConfigurationProperty system.webServer/security/authentication/anonymousAuthentication -Name "password" -Value ""; if ($?) {
Set-WebConfigurationProperty system.webServer/security/authentication/anonymousAuthentication -Name "logonMethod" -Value 2;}}
这样做是将用户名和密码设置为空白,并将登录方法设置为网络。这是完美的,因为这意味着应用程序池和站点都使用了预期的帐户,即 gMSA 帐户。
我发现一个非常有用的方法是制作一个测试脚本:
<%
Set objNetwork = CreateObject("WScript.Network")
strNAME = objNetwork.computername
response.write("Value of strNAME variable: " & strNAME & "<br>")
response.write("Domain = " & objNetwork.UserDomain & "<br/>")
response.write("ComputerName = " & objNetwork.ComputerName & "<br/>")
response.write("UserName = " & objNetwork.UserName & "<br/>")
%>
在解决方案之前,这显示了 IUSR,这是我解决问题的重要线索。解决方案后,用户名读取 app$
(其中 app 是 gMSA 的名称)以及预期的域。
我目前正在尝试对一些旧的(很快将被淘汰的)基础设施进行一些改进,以准备迁移到 .NET 核心。我们有一个小的反馈表,它使用 SQLOLEDB 连接字符串写入 SQL table。这些字符串与以明文定义的 username/password 配合使用时效果很好,但我希望放弃这种方法以支持集成身份验证。
我已经做了很多工作才能到达现在的位置:
- 基于安装了 ASP 功能的 IIS 构建了 docker 容器。
- 运行 Windows 主机上群中的容器 - 加入了我们的 AD 域。
- 设置 gMSA 以提供对数据库的域帐户访问权限。
目前,我已经 运行 完成了 Windows 容器指南中 MS 的 gMSA 中的所有步骤(https://docs.microsoft.com/en-us/virtualization/windowscontainers/manage-containers/manage-serviceaccounts). The tests check out, I'm able to run all the tests in https://docs.microsoft.com/en-us/virtualization/windowscontainers/manage-containers/gmsa-troubleshooting#check-the-container 没有任何问题,但是当我尝试使用我的连接字符串,我在日志中收到错误显示:
2020-09-28 19:36:43 172.17.173.120 POST /Default.asp |42|80040e4d|Login_failed_for_user_'NT_AUTHORITY\ANONYMOUS_LOGON'.
这对我来说没有多大意义,因为应用程序池标识设置为网络并且测试在容器上检出。
现在我尝试了一些操作,例如编辑 web.config 以将模拟设置为 true/false,通过 Windows 进行身份验证,但我仍然有点难过。我已将主机设置为允许通过 Kerberos 委托任何服务。
我还尝试使用以下方式登录:
docker exec -it --user "NT AUTHORITY\NETWORK SERVICE" cb4 powershell
然后 运行:
$connectionString = 'Data Source=serverhostname.domain.local;database=databasename;Integrated Security = True;'
$sqlConnection = New-Object System.Data.SqlClient.SqlConnection $connectionString
$sqlConnection.Open()
$sqlConnection | select *
这导致数据库连接处于打开状态。
应用程序池是使用 NetworkService 身份设置的
Get-ItemProperty IIS:\AppPools\domain.co.uk\ -Name processModel
identityType : NetworkService
userName :
password :
loadUserProfile : False
setProfileEnvironment : True
logonType : LogonBatch
manualGroupMembership : False
idleTimeout : 00:20:00
idleTimeoutAction : Terminate
maxProcesses : 1
shutdownTimeLimit : 00:01:30
startupTimeLimit : 00:01:30
pingingEnabled : True
pingInterval : 00:00:30
pingResponseTime : 00:01:30
logEventOnProcessModel : IdleTimeout
PSPath : WebAdministration::\413E8843BBEF\AppPools\domain.co.uk\
PSParentPath : WebAdministration::\413E8843BBEF\AppPools
PSChildName : domain.co.uk\
PSDrive : IIS
PSProvider : WebAdministration
Attributes : {identityType, userName, password, loadUserProfile...}
ChildElements : {}
ElementTagName : processModel
Methods :
Schema : Microsoft.IIs.PowerShell.Framework.ConfigurationElementSchema
如有任何建议,我们将不胜感激!
连接数据库需要注意以下几点
- 应用程序池的身份应该有一个域帐户。
- 域帐户具有读取或更改数据库的权限。
- IIS 服务器和 sql 服务器应在同一个 Intranet 中并使用同一个域。
更多细节可以参考这篇
好的,所以我弄明白了并将我的发现发布在 public 要点中:
https://gist.github.com/jimbo8098/48fa8d1cd05a61b35534aa107decb3e3
基本上,问题是当应用程序池标识设置为网络时,站点不是,它使用的似乎是 IUSR。鉴于此,我没有将 gMSA 帐户中继到 ASP 的脚本,因此我无法使用集成身份验证。解决方案是 运行:
Set-WebConfigurationProperty system.webServer/security/authentication/anonymousAuthentication -Name "userName" -Value ""; if ($?) {
Set-WebConfigurationProperty system.webServer/security/authentication/anonymousAuthentication -Name "password" -Value ""; if ($?) {
Set-WebConfigurationProperty system.webServer/security/authentication/anonymousAuthentication -Name "logonMethod" -Value 2;}}
这样做是将用户名和密码设置为空白,并将登录方法设置为网络。这是完美的,因为这意味着应用程序池和站点都使用了预期的帐户,即 gMSA 帐户。
我发现一个非常有用的方法是制作一个测试脚本:
<%
Set objNetwork = CreateObject("WScript.Network")
strNAME = objNetwork.computername
response.write("Value of strNAME variable: " & strNAME & "<br>")
response.write("Domain = " & objNetwork.UserDomain & "<br/>")
response.write("ComputerName = " & objNetwork.ComputerName & "<br/>")
response.write("UserName = " & objNetwork.UserName & "<br/>")
%>
在解决方案之前,这显示了 IUSR,这是我解决问题的重要线索。解决方案后,用户名读取 app$
(其中 app 是 gMSA 的名称)以及预期的域。