I have an ASP.NET application that executes a WMI call to a remote system. The application Web.config contains <identity impersonate="true"> and <authentication mode="Windows"> options which, as I understand, should force the application code to be executed on behalf of the application user.
The problem is that I get "Access is denied" error, despite the fact I can successfully execute the my WMI request from PowerShell console on the same host under the same user to the remote server in question.
// this doesn't work
ManagementScope scope = new ManagementScope();
scope.Path.NamespacePath = "root\\virtualization";
scope.Path.Server = "vs01";
scope.Connect(); // <-- here comes exception
# this works just fine
Get-WmiObject -Namespace 'root\virtualization' -Class Msvm_ComputerSystem -ComputerName vs01
Dumping HttpContext.Current.User.Identity.Name, System.Security.Principal.WindowsIdentity.GetCurrent().Name, System.Threading.Thread.CurrentPrincipal.Identity.Name properties suggest that impersonation works as expected.
Ideas? Could the issue be some kind of .NET or IIS security?
You need to have a domain administrator enable Delegation for your web server machine. This is a security feature of Kerberos. By default an intermediate server (in this case your web server) is not allowed to pass the impersonation context of a client to the remote server unless it has been given Delegation permission. If you don't do this the remote target server will see the request coming in as Anonymous User... which if its properly secured will be denied access.
Note its a common policy to only allow an intermediate server to delegate to specific target servers (called constrained delegation), so if your web app needs to be able to call WMI on any server in your network you may have problem. Talk to your domain admin.
Related
I have asp.net core 3.1 web api. When I run the project locally in Visual studio, it works fine. But when I publish it to IIS and run it, I get the error.
500 Internal Server Error","error": "A connection was successfully established with the server, but then an error occurred during the pre-login handshake. (provider: TCP Provider, error: 0 - An existing connection was forcibly closed by the remote host.)"}
Or Login failed for user domain_name\machine_name.
connection string looks like this
"ConnectionStrings": {
"ABCDB": "Server=xxx-test,80;Database=abc;Integrated Security=true;MultipleActiveResultSets=true;"
},
I have the hosting bundle installed for .net core 3.
my app runs under ApplicationPoolIdentity which is added to the database and has the permissions. My application pool is set to No Managed Code with ApplicationPoolIdentity.
The endpoints for the api which are not connecting to the database work just fine on published version but anything that is connecting to the database gives the error.
I referred to couple of links but hard luck.
https://www.loganfranken.com/blog/1345/why-your-web-application-cant-connect-to-sql-server/
IIS fails to pass windows credentials through to SQL Server for ASP.NET Core app
Why asp.net core app uses different user than AppPool identity for Windows Authentication when connecting to SQL Server?
Any help is appreciated.
Edit: The only things that works for me running the appPool under custom account(my credentialis) but does not work under appPoolIdentity on IIS
It seem that your environment needs a reset.
1- Manually check your app folder under IIS to see if any cached files or similar ones could be deleted.
2- Ideally, install it in a new folder under IIS
3- Reset the IIS
4- Make a hard refresh of the web browser
your connection string should be like this:
"ABCDB": "Data Source=xxx-test;Initial Catalog=abc;Integrated Security=SSPI;Persist Security Info=True;"
and add application pool name of your published application of security/users folder of your DB:
IIS APPPOOL\<apppool name>
Or add a new user account to you DB with user name and password. In this case you will also have to change the connection string.
I was having the same issue.
Other .NET Core 3.1 web apps are running just fine with the same authentication method (anonymous authentication) on the same IIS instance on the same server using the same connection string to the same MS SQL DB.
With this one particular .NET Core 3.1 web app, IIS is causing the app to try to authenticate to MSSQL DB with the username {DOMAIN}\{Computer Name}
The issue for me was that the connection string for the one app with the issue had "Trusted_Connection=True".
I knew that I would get this authentication interception from IIS with Integrated_Security but did not realize that Integrated_Security is synonymous with Trusted_Connection.
So the fix is to remove Trusted_Connection = True or Integrated_Security = True from the DB connection string in the app. If you need either of these two for your code to work (but are providing a username and password in the DB connection string), you should probably re-evaluate your code. Otherwise, the behavior OP and I observed should be what you want to happen and this isn't a problem.
I have the following setup:
IIS 8.0
a web handler call it test.ashx
Impersonation & Windows Authentication are both configured. Kerberos is showing as the authentication type.
test.ashx uses the unmanaged API: CreateProcessAsUser() method to run "cmd.exe /c myScript.cmd"
I put statements in myScript.cmd and see that it is running as the requesting user as I need it to. The problem I am experiencing is that the script cannot reference network files (either mapped drives or UNC path)
I need myScript.cmd to run as the requesting user and to be able to access network file resources. How do I get this to work?
I found one item that made a big difference on getting kerberos authentication to work, which is required to do impersonation and delegation. In IIS Manager I had to choose the web site, then run the Configuration Editor. Once it opened I had to choose the as from: DefaultWebSiteWeb.Config, and as the section: system.webServer/security/authentication/windowsAuthentication. Then set: useAppPoolCredentials = True. Note: useKernelMode was already set to true.
Additionally, for the web site I have the following set for Authentication:
ASP.NET: Enabled
Windows Authentication: Enabled, Provider: Negotiate, Kernel mode enabled.
Now my ASHX web handler (in C#) can start a process as the user, run a .cmd file that accesses network resources.
BACKGROUND:
IIS is on One Server (7)
SQL is on another server
Active Directory is on another server (this may or may not make a difference but from what I have read it may)
We have a brand new MVC site that is using AD Permissions to grant access to the site and then to run the SP's within SQL
The site access is working correctly, but I am getting the error Login failed for user 'NT AUTHORITY\ANONYMOUS LOGON' which I believe means I have fallen fowl to the double hop issue.
Within IIS I have an App Pool of V4.0 Integrated and Application Pool Identity
within my Application I have settings of ASP.net Impersonation Enabled and Windows Authentication Enabled all else is Disabled
And within the Delegation settings of the SQL Server and the IIS Server I have set 'Trust this computer for delegation to any service (Kerberos only)'
also if I run the following statement within SQL
SELECT auth_scheme
FROM sys.dm_exec_connections
WHERE session_id = ##SPID;
I get KERBEROS.
What am I missing? or doing wrong? Thanks
There are number of things you may want to check, do you have SPN setup on the SQL Box, these can be added via the following command:
setspn -a "<SQL_SERVER_Server_Name>:1433" "<SQL_SERVER_Service_Account>"
You may want to add both the FQDN as well as the short name. Once this is complete you will need to restart the SQL Server, not just the service.
If this does not work, can you run the following commands:
setspn -l "<AppPool Account Name>"
and
setspn -l "<SQL Server Account Name>"
I have an ASP.NET web application that is trying to read a remote share with the impersonated user. Specifically, I am trying to use the following code to read the directories on the remote share..
DirectoryInfo rootDir = new DirectoryInfo(strPath);
foreach (DirectoryInfo dir in rootDir.EnumerateDirectories())
{
TreeNode folderNode = new TreeNode(dir.Name, dir.FullName);
folderNode.PopulateOnDemand = true;
folderNode.ImageUrl = "~/img/Folder.png";
nodeList.Add(folderNode);
}
When the webpage runs this code, I get the following error message...
Access to the path '\remoteserver\remoteshare\' is denied.
Here is my web.config...
<authentication mode="Windows"/>
<identity impersonate="true" />
<authorization>
<deny users="?"/>
</authorization>
When I log onto the website, I know that impersonation is working because I can do an HttpContext.Current.User.Identity.Name and see my username. I am running this application on a domain under IIS 7.5. I also know that this can't be a Kerberos "double-hop" issue because I can connect to a remote SQL server (from the web server) and pass the Windows Authenticated credentials through just fine and return results from a query.
I am using Process Monitor on the web server to figure out which credentials are being passed over to the remote share. When I look at the capture where the ACCESS DENIED is showing, it gives me this description...
Desired Access: Read Data/List Directory, Synchronize, Disposition: Open, Options: Directory, Synchronous IO Non-Alert, Open For Backup, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a, Impersonating: DOMAIN\username
Where DOMAIN\username is my impersonated username from the web server.
Process Monitor is also showing that NT AUTHORITY\NETWORK SERVICE is the user on the web server that is making the request, which makes me think that the web server is NOT, in fact, passing over the impersonated user to read the remote file share. It's almost like there is a "double hop" issue for remote file share access specifically.
I have also configured the web server to "Trust this computer for delegation to any service (Kerberos only)". Again, this can't be a double-hop issue if I can access a remote SQL server from the web server, or can it? Any help or pointers would be greatly appreciated, I have spent 2 days looking at possible solutions and nothing works.
I can not seem to get sql server to recognize my credentials.
Asp.net recognizes me when I login but when I execute a sql command I get a login failed message.
The IIS server and SQL server are on different machines.
There are other applications the IIS server which are able to authenticate to the sql server. I believe the Active Directory settings are correct. I am investigating what I am doing differently.
I must be missing something.
I check the IIS settings
The web config is set to impersonate.
Below is the relevant information. If anyone has any idea as to what I missed or am doing wrong I would appreciate some help.
IIS Settings:
'Integrated Windows authentication' is checked
'Enable anonymous access" is not checked
Web Config
<authentication mode="Windows"/>
<identity impersonate="true"/>
<authorization>
<deny users="?" />
</authorization>
Page_Load Code:
Dim winId As IIdentity = HttpContext.Current.User.Identity
TextBoxMessage.Text = winId.Name + Environment.NewLine
Dim cnn As SqlClient.SqlConnection
Try
Dim sql As String = "*****"
cnn = New SqlClient.SqlConnection("Data Source=*****;Initial Catalog=****;Integrated Security=True")
cnn.Open()
Dim cmd As New SqlClient.SqlCommand(sql, cnn)
cmd.ExecuteNonQuery()
cnn.Close()
Catch ex As Exception
TextBoxMessage.Text += ex.Message
cnn.Close()
End Try
Output:
Domain\UserName
Login failed for user 'NT AUTHORITY\ANONYMOUS LOGON'.
This is key = The IIS server and SQL server are on different machines. You're facing the classic double hop issue. Think of it in this way:
You access the web application under your credentials
IIS in this case has to present who you say you are to the SQL Server
IIS says, "Why hello SQL Server, I'm passing on Tony's kerberos creds, they are legit"
SQL Server says, "Hmmm, IIS I'm not sure I trust you, I need proof that you are trusted to present these credentials to me".
Thus once you enable delegation as mentioned by Remus, your SQL Server will trust the credentials your IIS server is presenting on your behalf.
In terms of security, under delegation, it would be wise to choose:
Trust this computer for delegation for specified services only | Use Kerberos only | and then underneath the "Services to which this account can present delegated credentials" make sure you explicitly set only the server/port you need.
You also need to enable constrained delegation:
Enabling Constrained Delegation
How To: Use Protocol Transition and Constrained Delegation in ASP.NET 2.0
Windows Server 2003 Constrained Delegation (IIS 6.0)
Are your ISS server and SQL Server running on the same machine?
If not, Active Directory has to be configured to allow your IIS server to impersonate your accout towards the SQL Server. See How To: Use Protocol Transition and Constrained Delegation in ASP.NET 2.0.
Long story short: IIS server should have "trusted for delegation" checkbox checked in Active Directory.
You need to set you credentials in Application Pool.
- Open IIS
- Select Application Pools
- Enter the name, select .Net framework version and click OK
- Select the new added application pool and click on Advanced Settings..
- In the Process Model section click on Identity - choose custom account and enter the AD username, password, confirm password and click OK
- Select your application and in the Basic settings choose your application pool just created.
Hope this helps