How to accept a self-signed SSL certificate in a WCF client? - wpf

This may be a stupid question but I just can't find the answer.
What I would like to do:
I have a WCF service hosted by IIS. It is working perfectly, I can access the wsdl, I have a self-signed certificate for the server etc. I would like to call this service from a WPF client.
The problem is, since I have a self-signed certificate, I get the following exception when calling the service:
Could not establish trust relationship for the SSL/TLS secure channel with authority 'localhost'.
If I access the site (or the service) from a browser, it is no problem, because the browser warns me about the certificate, and gives me the choice of viewing the page anyway. But the WPF client just throws an exception.
I don't want to completely turn off the authentication process, I simply would like to give the users the option of ignoring this warning (as browsers do).
Can anyone provide some code for this? If you ran into a good, detailed tutorial about this, it would be awesome too. (See, my problem with the tutorials I've found is the lack of details)

Here's the minimum amount of code you need to make WCF client accept an arbitrary certificate. This is not secure. Use for testing only. Don't blame me if this code goes berserk and eats your little kitten.
ServicePointManager.ServerCertificateValidationCallback +=
new System.Net.Security.RemoteCertificateValidationCallback(EasyCertCheck);
The call back:
bool EasyCertCheck(object sender, X509Certificate cert,
X509Chain chain, System.Net.Security.SslPolicyErrors error)
{
return true;
}
Code shamelessly lifted from the least helpful answer to Is it possible to force the WCF test client to accept a self-signed certificate?

You can register the certificate yourself. If load the certificate in the client as well, and then register the it as trusted you shouldn't get that warning.
You need to find a X509CertificateCollection and add the certificate to that collection. I had this kind of problem with a SmtpClient running over Ssl.
By hooking the System.Net.ServicePointManager.ServerCertificateValidationCallback or implementing System.Net.ICertificatePolicy and identify my own installed certificate as valid/trusted (attached to the System.Net.ServicePointManager.CertificatePolicy).
This is not WCF stuff per se, but from what I could tell, this should translate to WCF as well. It all depends what WCF is uses under the hood.

Related

Decrypting HTTPS traffic with a proxy

I am implementing a Web proxy (in C), with the end goal of implementing some simple caching and adblocking. Currently, the proxy supports normal HTTP sites, and also supports HTTPS sites by implementing tunneling with HTTP CONNECT. The proxy works great running from localhost and configured with my browser.
Despite all of this, I'll never be able to implement my desired features as long as the proxy can not decrypt HTTPS traffic. The essence of my question is: what general steps do I need to take to be able to decrypt this traffic and implement what I would like? I've been researching this, and there seems to be a good amount of information on existing proxies that are capable of this, such as Squid.
Currently, my server uses select() and keeps all client ids in an fd_set. When a CONNECT request is made, it makes a TCP connection to the specified host, and places the file descriptor of both the client and the host into the fd_set. It also places the tuple of fd's into a list, and the list is scanned whenever more data is ready from select() to see if data is coming from an existing tunnel. The data is then read and forwarded blindly. I am struggling to see how to intercept this data at all, due to the nature of the CONNECT verb requiring opening a simple TCP socket to the desired host, and then "staying out of it" while the client and host set up their own SSL sockets. I am simply asking for the right direction for how I can go about using the proxy as a MITM attacker in order to read and manipulate the data coming in.
As a brief aside, this project is solely for my own use, so no security or advanced functionality is needed. I just need it to work for one browser, and I am happy to get any warnings from the browser if certificate-spoofing is the best approach.
proxy can not decrypt HTTPS traffic
You are trying to mount a man-in-the-middle attack. SSL is designed to prevent that. But - there is a weak point - a list of trusted certificate authorities.
I am simply asking for the right direction for how I can go about using the proxy as a MITM attacker in order to read and manipulate the data coming in.
You can get inspiration from Fiddler. The Fiddler has its own CA certificate (certification authority) and once you add this CA certificate as trusted, then Fiddler generates server certificates for each connection you use on the fly.
It comes with serious security consideration, your browser will trust any site. I've even seen using the Fiddler core inside a malware, so be careful

silverlight accept invalid certificate

I'm doing https web requests in silverlight using "WebRequest"/"WebResponse" framework classes.
Problem is: I do a request to an url like: https://12.34.56.78
I receive back a versign signed certificate which has as subject a domain name like: www.mydomain.com.
Hence this results in a remote certificate mismatch error.
First question: Can I somehow accept the invalid certificate, and get the WebBresponse content ? (even if it involves using other libraries, I'm open to it)
Additional details: (for those interested on why I need this scenario)
I'm trying to give a client access to a silverlight app deployed on a test server.
Client accesses the silverlight app at: www.mydomain.com/app
Then I do some rest requests to: https://xx.mydomain.com
Problem is I don't want to do requests on https://xx.mydomain.com, since that is on our productive server. For this reason I use https://12.34.56.78 instead of https://xx.mydomain.com.
Client has some firewalls/proxies and if I simply change his hosts file and map https://xx.mydomain.com to 12.34.56.78, web requests don't resolve to the mapped IP.
I say this because on his network webrequests fail if I try that, on my network I can use the hosts changing without problems.
UPDATE: Fixed the problem by deploying test releases to an alternative: https://yy.domain.com and allowing the user to configure for test purposes, the base url to which I do requests to be: https://yy.domain.com.
Using an certificate that contained the IP in the subject or an alternative subject would've probably worked too, but would have cost some money to be issued by a certified provider and would not be so good because IP's might change.
After doing more research looks like Microsoft won't add this feature too soon, unless there's a scenario for non-testing/debugging uses.
See: http://connect.microsoft.com/VisualStudio/feedback/details/368047/add-system-net-servicepointmanager-servercertificatevalidationcallback-property

Making a WP7 HttWebRequest POST with an untrusted cert?

I'm working on a Windows Phone 7 application that makes a REST service call. The third party that hosts the web services has an invalid certificate in the current environment. When I hit the URL in Firefox, I get a warning about the cert and I am asked if I want to continue. I'm also using the Poster FF extension to test the call. It works with Poster if I first accept the invalid cert in Firefox. If I don't, then POSTER wont make the request.
In my WP7 Emulator, I can't make the request at all. I get a 404 at the EndGetResponse method. I making the same request as in Poster, so I know there is nothing wrong with the request. I have successfully hit another web service using the same code (no certs involved), so I don't think it's the code. The only thing I can think of is that WP7 doesn't allow requests to an invalid cert. Has anyone had experience with this situation? Is there any way around it?
Is there a way I can tell my app to accept all communication, even if there is an invalid cert?
There is sadly no way to do this on the phone. Ordinarily, i.e. on the desktop this simple line of code will disable certificate checking.
System.Net.ServicePointManager.ServerCertificateValidationCallback = (se, cert, chain, sslError) => { return true; };
If you look at the ServicePointManager on the phone, there's no callback to hook into. It's a massive pain in the arrrrse.
Have you considered writing to the service owner and asking why they're being bad internet citizens? (essentially, what you're seeing here is web security in action, for better or worse)
As Matt says, you might be able to code a simple relay on a web server. It doesn't have to be a special service, but maybe just a web page that does the call for you and spits out RAW text or XML. Your phone client just GETs this page and picks through the response manually.
Where there's a will there's a way.
Luke
You need to install the root CA cert of the issuing party on the phone.
You can do this by emailing the RootCA to the user of the phone. They click on the attachement and it will prompt them to ask if they want to install the certificate on the phone.
Once you have done that your requests should go through.
I dont believe there is a way to do this programatically in your app however.
I'm not aware of a way to install additional certificates on the phone.
In this situation I'd create a proxy service between your app and the 3rd party site and have your app call that. If you need to, you could put the proxy behind a valid cert.

Windows Phone 7 - Cookies not sent to WCF service

I have a bunch of WCF services at a domain:
AuthenticationService (the standard MS one, over HTTPS)
AppService (HTTP)
Usually, I call the Authentication Service and a cookie is returned. For desktop applications, I detach the cookie and reattach it with every new service call to the AppService which exposes the meat of my API.
Silverlight in the browser automatically attaches the cookie in all calls to the domain. I expected the phone to do the same.
It doesn't.
Access to the headers is not supported on the phone, so manual manipulation is out. I wonder if its because some bright spark at MS thought that the phone should enforce that cookies are only reattached to HTTPS endpoints at the same domain or something...
Help!!
This is a nightmare to troubleshoot since the phone doesn't support the other major major helpful setting; ignoring self-signed certificates.
Thanks,
Luke
** UPDATE **
While I'm following up the method using CookieContainer I must point out that even though the Add method on the Headers collection is missing in Silverlight, one can still add headers using the indexer.
See http://cisforcoder.wordpress.com/2010/12/01/how-to-implement-basic-http-authentication-in-wcf-on-windows-phone-7/
** UPDATE 2 **
CookieContainer can be set as per Lex answer. I'm now stuck and continuing to investigate an ArgumentNullException thrown from within the WCF client upon References.cs EndInvoke. My server shows no sign of receiving the call.
Two key calls on the stack are:
System.Net.Browser.HttpWebRequestHelper.ParseHeaders
And
MS.Internal.InternalWebRequest.OnDownloadFailed
FINAL UPDATE
The ArgumentNullException seems to be thrown when called against a server with a self-signed certificate.
However, there's something odd with the emulator/SDK. I have had this exception against all my servers, even those with no SSL, and one with an issued certificate.
I've also had problems that have been resolved only by a local reboot. So I think my problems have been a result of having the right code, but thinking it was wrong because of other problems in the SDK.
Not sure what advice to give, except to be mistrusting of exceptions stemming from the WP7 WCF stack, particularly EndpointNotFoundException and ArgumentNullException, and to have a full framework test client app around as a sanity check.
Luke
In desktop SL, I do it by sharing cookie container between service proxies in client http stack. Did not try this on WP7, but you may check this out.
First, you need to insert <httpCookieContainer/> in your client-side binding configuration (usually in ServiceReferences.ClientConfig).
In code, switch to client http stack.
WebRequest.RegisterPrefix("http://", WebRequestCreator.ClientHttp);
WebRequest.RegisterPrefix("https://", WebRequestCreator.ClientHttp);
Then you need to create a CookieContainer instance and assign it to all service proxies.
var cc = new CookieContainer();
var service1 = new ServiceReference1.MyService1Client { CookieContainer = cc };
var service2 = new ServiceReference2.MyService2Client { CookieContainer = cc };
Now, when your cookie container receives cookie, it will reuse it for all web services. Make sure, that cookie comes with correct Path setting.

WCF security between WinForms client and Shared Host webserver

Ok,
I have developed this WinForms client, which interacts with a server (ASPX Application) by means of WCF calls. I would now like to deploy the server to my shared webhost, but I'm kinda new to WCF and especially the security possibilities behind it.
The goal is to kind of secure the WCF service, so that not everybody that knows or finds out the endpoint address can call it. Rather, only my WinForms client must be able to call the WCF service.
I do not need authentication on a user basis, so no authentication is required from the user of the client. But I want only instances of this WinForms client to be able to interact with the service. The information passed between server and client is not very sensitive, so it's not really required to secure it, but it's a plus if it can easily be done.
Is this possible with a Shared Host (IIS) environment (no HTTPS at disposal) ? What bindings and options should I use ? I suppose wsHttpBinding, but how would I setup the security options ?
Using .NET 4.0
Thanks
From what I understand, you have an internet-facing service which you want to limit to only your client app to be able to call - correct? Or do you envision other clients (like PHP, Ruby etc.) also wanting to call into your service at some point?
To secure your message, you have two options in WCF - message or transport security. Over the internet, with an unknown number of hops between your client and your service, transport security doesn't work - you're left with message security (encrypting the message as it travels across the 'net). For this to work, you typically add a digital certificate to your service (only server-side) that the client can discover and use to encrypt the messages with. Only your service will be able to decrypt them - so you're safe on that end.
The next point is: who can call your service? If you want to be totally open to anyone, then yes, you need wsHttpBinding (or the RESTful variant - webHttpBinding). If you want to allow non-.NET clients, you're typically limited to no authentication (anyone can call), or username/password schemes which you will validate on the server side against a database of valid users.
If you only want to allow your own .NET client in, then you can do several things:
disable metadata on your service; with this, you would "hide" your endpoints and the services they provide - someone using a "metadata scanner" (if that exists) wouldn't be able to just stumble across your service and find out what methods it provides etc. This however also makes it impossible for another developer outside your organization to do an Add Service Reference to your service.
you could define and use a custom binary http binding - only other clients with this setup could even call your service. The binary http binding would bring some speed improvements, too. See this blog post on how to do this.
you need to somehow identify those callers that are allowed in - one possible method would be to put an extra header into your WCF messages that you then check for on the server side. This would simply make sure that a casual hacker who discovers your service and figures out the binary http binding would still be rejected (at least for some time). See this blog post here on how to implement such a message inspector extension for WCF.
the ultimate step would be to install a digital certificate on the client machine along with your service. You would then set up your client side proxy to authenticate with the service using that certificate. Only client machine that have that certificate could then call into your service.
It really depends on how far you want to go - WCF gives you a lot of options, but you need to decide how much effort you want to put into that .
The first thing you need to ask your self is: "What can someone do to your WCF service if they connected their own customized client?" Look at all of the functionality that is being exposed via WCF and assume that it could be accessed at will. You have absolutely no control over the client, and you will never have this ability.
HTTPS is beautiful, its a damn shame that your forced to be vulnerable to OWASP A9: Insufficient Transport Layer Protection. If it where up to me, I would move to a different host that cared about security. If you are throwing usernames and passwords over the network, then your putting your users in danger.
One of the biggest problems I have seen with a WCF service is that they had a "executeQuery()" function that was exposed. The developer allowing the client to build queries to be executed by the server. This approach is fundamentally flawed as you are just handing your database over to an attacker. This type of vulnerability isn't SQL Injection, it falls under CWE-602: Client-Side Enforcement of Server-Side Security.
Along the same lines as CWE-602 is OWASP A4: Insecure Direct Object References. Could an attacker fool your WCF service into thinking its another user by providing a different user id? Are you trusting the client to tell the truth?
The next classification of vulnerabilities that you must take into consideration is OWASP A1: Injection, other wise known as "Taint and Sink". For instance if you are exposing a function where one of its parameters is being used in a CreateProcess() which is invoking cmd.exe. This parameter could be controlled by the attacker, and there for this variable is "tainted", the call to CreateProcess() is a "sink". There are many types of vulnerabilities along these lines, including but not limited to; SQL Injection, LDAP Injection, XPATH Injection. These types of vulnerabilities affect all web applications.

Resources