The error I am getting is:
Identity check failed for outgoing message. The expected DNS identity of the remote endpoint was 'MYSERVER' but the remote endpoint provided DNS claim 'myserver.mycompany.com'. If this is a legitimate remote endpoint, you can fix the problem by explicitly specifying DNS identity 'myserver.mycompany.com' as the Identity property of EndpointAddress when creating channel proxy.
I have googled and found lots of problem getting this but none of the solutions have worked for me.
My questions 1) where exactly does the 'expected DNS identity' come from and 2) where is the DNS claim coming from?
From what I can tell the answer to question #2 is the with the element.
One thing that is different from the other posts I have seen is that this only broken on one of our servers so I am thinking this might be a DNS issue with this particular server.
Related
Let's assume that the client wants to authenticate himself to a HTTP proxy. The proxy is configured with kerberos, and has clearly the service name HTTP/proxy.foo.bar set in it's configs. How does the client know which service name to request the ticket to ? Does it request the ticket to the domain name he's making request to (in this case it is proxy.foo.bar indeed), or does it receive the name in the authentication sequence, in a 407 reply in this case (which doest contain the negotiate challenge, but I just don't know if there's a way to look into it) ?
I'm trying to debug the kerberos errors on a proxy which suddenly stopped authenticating some clients. The thing is, that looking in the Wireshark, I see that the client is requesting a ticket not for a service name configured on a proxy (same name he's instructed to use), HTTP/proxy.foo.bar, but for a name that the proxy IP resolves to, HTTP/host.foo.bar (well, at least it's the name that the proxy resolves to, may be though the client gets it some other way), and TGS just cannot find one, thus an error happens.
So you’ve got two questions in here (you didn't ask how to actually solve the problem, to do that more details would be needed - see comments).
You asked "The proxy is configured with kerberos, and has clearly the service name HTTP/proxy.foo.bar set in it's configs. How does the client know which service name to request the ticket to?"
A. It works pretty much like this. The client types in a URL in the web browser or clicks on a hyperlink. It looks up the IP host in DNS domain which matches the host name in the URL. Then it goes to that IP host, looking for the service defined in the URL, in this case it is the HTTP service. If it receives an HTTP 401 Negotiate challenge (it's 401, not 407) from the web server, due to it being Kerberos-protected, it goes to its KDC and requests a Kerberos service ticket for HTTP/proxy.foo.bar, zips back to proxy.foo.bar and presents the ticket to that host for the HTTP service running on it. The host validates this ticket and if all is well and the client web browser renders the HTML. You've seen the Kerberos ticket ticket when you ran klist on the client. I don't have any web references for you, this is all off the top of my head.
You also asked “Does it request the ticket to the domain name he's making request to (in this case it is proxy.foo.bar indeed), or does it receive the name in the authentication sequence, in a 407 reply in this case (which doest contain the negotiate challenge, but I just don't know if there's a way to look into it) ?”
A. Your question was a bit hard to follow but if I am understanding you correctly, the answer is the web client requests a ticket as a result of the HTTP 401 Negotiate authentication challenge from the web server (see above).
There’s many diagrams sequencing this process on the web, including here: http://www.zeroshell.org/kerberos/Kerberos-operation/
We have a HTTP endpoint where a form request is posted containing transaction data from a 3rd party https website.
We are investigating ways that our HTTP endpoint can contain code to check that the host that posted the request is the 3rd party website and no-one else (i.e. a hacker).
Is there any way our HTTP endpoint can authenticate with the website where the posted form request originated? Maybe by SSL Certificate Authentication?
Many thanks in advance.
To guarantee that the server on the other side is who they say they are the safest way is to have them use an SSL Certificate. If the they also need to trust who you are then each side should have their own SSL Certificate.
The IP Range solution provided in the comment could be a possible hack but it's quite brittle and it couldn't be applied in a very serious environment.
The Shared Key solution will work and it's reliable but you have to change keys from time to time depending on the volume of traffic between the two servers.
Hope this helps.
It might be better to use message-level security instead of transport-level security (SSL/TLS).
The third party website would sign the message using its certificate (or to be precise, using the private key matching its certificate), and your website would verify this signature.
This could allow for that message to be relayed by the user's browser, without needing a direct connection between the two servers.
This sort of mechanism already exists in the Identity Management world, for example with SAML and Shibboleth. (You can still have direct connections between the servers to get additional information too.)
I'm working on a project which requires delegation in a double-hop scenario. We have a desktop client, connecting to a WCF service using a net.tcp binding, connecting to a SQL database on another server. Our goal is to use the user's credentials to access the SQL database.
Both the WCF service and SQL database are running under the same domain user, which has delegation enabled for the SQL database. The instructions here have been followed, with no success.
Now, some details recorded in our logs:
The login used on the SQL database appears as the user the WCF service is running under, and uses Kerberos.
The login used on the WCF server appears as the client's user, but uses NTLM.
Using either [OperationBehavior(Impersonation = ImpersonationOption.Allowed)] or using (ServiceSecurityContext.Current.WindowsIdentity.Impersonate()) results in commands being run as the client, on the WCF server. This leads me to believe impersonation is working fine.
So, what could be causing the first hop to fall back to NTLM? We suspect it's a SPN issue, but we've registered the SPNs of both the WCF service and SQL service to the shared domain user. Also, as per the instructions listed above, we've set the SQL service as trusted for delegation on the domain user.
We've used EndpointIdentity.CreateSpnIdentity on the WCF service to set the SPN, and this is the SPN we've registered to the domain user.
Any suggestions? Thanks in advance!
Edit:
We've found something that may have been an issue - We had not used EndpointIdentity.CreateSpnIdentity on the client. After setting this we receive the error
“call to SSPI failed” with an inner exception of “target principle name is incorrect”. But the SPN we've set in the client and the server match, and both match the hostname of the service. If we set both the client and the server SPN to something completely different, or if the client's specified SPN does not match the server's SPN, authentication falls back to NTLM as it did before. We've done research into the error, but cannot find its cause. Any suggestions?
We've also performed packet captures of both cases - falling back to NTLM and when we receive the "call to SSPI failed" error. In both cases, similar packets are sent and received until, on one, NTLM is mentioned. On the other, a "TURN CHANNEL" packet is sent from the client to the server. The packets contain nothing human readable except the IP address of the server until either NTLM is mentioned, and the username and computer names are sent, or the "TURN CHANNEL" packet is sent, which contains what appears to be the SPN, and possibly the hostname. There doesn't appear to be any human readable error codes or error messages. Any suggestions on what to look for in the packets?
We found our error - the client was creating the connection using the IP address of the server. After switching the IP to a fully qualified domain name, the first hop consistently authenticates using Kerberos.
The IP address resolves to the same string we used in both SPNs, but I suppose the client checks if the connection string matches the portion of the SPN following the slash before performing any other checks.
We tested our results using both Network Service and our domain user, and as long as the SPN was registered to the computer or user respectively, there were no issues.
Hopefully this answer will save others some time and hassle!
Additional Note: While this enabled Kerberos authentication for all connections, we later discovered that this was unnecessary in our situation. Part of our connection to the database was not inside the impersonation using block, which was causing the table read to fail. We have since removed all delegation and SPN related code, and the database connection continued to work correctly. Our first hop is using NTLM. We're not exactly sure how the credentials are being used at the SQL server, as our connection appears to be exactly what is described as the double hop scenario, which should require Kerberos and delegation, but it's hard to argue with what's working. I suspect it may have something to do with the note located under delegation in this document:
When a client authenticates to the front-end service using a user name and password that correspond to a Windows account on the back-end service, the front-end service can authenticate to the back-end service by reusing the client’s user name and password. This is a particularly powerful form of identity flow, because passing user name and password to the back-end service enables the back-end service to perform impersonation, but it does not constitute delegation because Kerberos is not used. Active Directory controls on delegation do not apply to user name and password authentication.
If anyone has any other suggestions for the reason it's working, I'd love to hear them. However, I don't feel it's worth opening another question for.
I'm confused about what the identity element on a client endpoint really does. I've understood that a identity dns value like is supposed to tell WCF to assert that the service's certificate is issued to myserver.local. And that this should allow me to point the endpoint address to https://localhost/MyService.svc instead of https://myserver.local/MyService.svc.
But this fails I don't understand why. I have myserver.local pointing to 127.0.0.1 in my host file and I have self-created certificate issued to myserver.local. It works fine with myserver.local but when I change the endpoint address to localhost it stops working because it "can't establish a SSL/TLS trust".
Can anyone explain why?
Thanks
If you want to know what the WCF Identity DNS value is for, and what to put in it, see this question:
WCF client endpoint identity - configuration question
It helped me to understand what it's for.
I am creating a secure web based API that uses HTTPS; however, if I allow the users to configure it (include sending password) using a query string will this also be secure or should I force it to be done via a POST?
Yes, it is. But using GET for sensitive data is a bad idea for several reasons:
Mostly HTTP referrer leakage (an external image in the target page might leak the password[1])
Password will be stored in server logs (which is obviously bad)
History caches in browsers
Therefore, even though Querystring is secured it's not recommended to transfer sensitive data over querystring.
[1] Although I need to note that RFC states that browser should not send referrers from HTTPS to HTTP. But that doesn't mean a bad 3rd party browser toolbar or an external image/flash from an HTTPS site won't leak it.
From a "sniff the network packet" point of view a GET request is safe, as the browser will first establish the secure connection and then send the request containing the GET parameters. But GET url's will be stored in the users browser history / autocomplete, which is not a good place to store e.g. password data in. Of course this only applies if you take the broader "Webservice" definition that might access the service from a browser, if you access it only from your custom application this should not be a problem.
So using post at least for password dialogs should be preferred. Also as pointed out in the link littlegeek posted a GET URL is more likely to be written to your server logs.
Yes, your query strings will be encrypted.
The reason behind is that query strings are part of the HTTP protocol which is an application layer protocol, while the security (SSL/TLS) part comes from the transport layer. The SSL connection is established first and then the query parameters (which belong to the HTTP protocol) are sent to the server.
When establishing an SSL connection, your client will perform the following steps in order. Suppose you're trying to log in to a site named example.com and want to send your credentials using query parameters. Your complete URL may look like the following:
https://example.com/login?username=alice&password=12345)
Your client (e.g., browser/mobile app) will first resolve your domain name example.com to an IP address (124.21.12.31) using a DNS request. When querying that information, only domain specific information is used, i.e., only example.com will be used.
Now, your client will try to connect to the server with the IP address 124.21.12.31 and will attempt to connect to port 443 (SSL service port not the default HTTP port 80).
Now, the server at example.com will send its certificates to your client.
Your client will verify the certificates and start exchanging a shared secret key for your session.
After successfully establishing a secure connection, only then will your query parameters be sent via the secure connection.
Therefore, you won't expose sensitive data. However, sending your credentials over an HTTPS session using this method is not the best way. You should go for a different approach.
Yes. The entire text of an HTTPS session is secured by SSL. That includes the query and the headers. In that respect, a POST and a GET would be exactly the same.
As to the security of your method, there's no real way to say without proper inspection.
SSL first connects to the host, so the host name and port number are transferred as clear text. When the host responds and the challenge succeeds, the client will encrypt the HTTP request with the actual URL (i.e. anything after the third slash) and and send it to the server.
There are several ways to break this security.
It is possible to configure a proxy to act as a "man in the middle". Basically, the browser sends the request to connect to the real server to the proxy. If the proxy is configured this way, it will connect via SSL to the real server but the browser will still talk to the proxy. So if an attacker can gain access of the proxy, he can see all the data that flows through it in clear text.
Your requests will also be visible in the browser history. Users might be tempted to bookmark the site. Some users have bookmark sync tools installed, so the password could end up on deli.ci.us or some other place.
Lastly, someone might have hacked your computer and installed a keyboard logger or a screen scraper (and a lot of Trojan Horse type viruses do). Since the password is visible directly on the screen (as opposed to "*" in a password dialog), this is another security hole.
Conclusion: When it comes to security, always rely on the beaten path. There is just too much that you don't know, won't think of and which will break your neck.
Yes, as long as no one is looking over your shoulder at the monitor.
I don't agree with the statement about [...] HTTP referrer leakage (an external image in the target page might leak the password) in Slough's response.
The HTTP 1.1 RFC explicitly states:
Clients SHOULD NOT include a Referer
header field in a (non-secure) HTTP
request if the referring page was
transferred with a secure protocol.
Anyway, server logs and browser history are more than sufficient reasons not to put sensitive data in the query string.
Yes, from the moment on you establish a HTTPS connection everyting is secure. The query string (GET) as the POST is sent over SSL.
You can send password as MD5 hash param with some salt added. Compare it on the server side for auth.