Securing WCF Services - c#

I have WCF services hosted on a console application and a web application accessing its operations. I have searched for WCF security and in most cases the web services were hosted on IIS. What points should I follow in order to implement WCF transport layer security in my case?
What I want is
Using username and password to execute WCF operations
Use SSL to encrypt data.
If my WCF services are hosted on a console application. Are there any IIS configurations that I should make?

If you want to expose WCF service over HTTP you can use BasicHttpBinding with custom configuration:
<bindings>
<basicHttpBinding>
<binding name="secured">
<security mode="TransportWithMessageCredential">
<message clientCredentialType="userName" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="securedService">
<serviceMetadata httpsGetEnabled="true" />
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="Namespace.Type, assembly" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="Namespace.Type" behaviorConfiguration="securedService">
<host>
<baseAddresses>
<!-- some url -->
<baseAddress baseAddress="https://localhost:8088/Service" />
</baseAddresses>
</host>
<endpoint address="" contract="Namespace.Type" binding="basicHttpBinding" bindingConfiguration="secured" />
<endpoint address="mex" contract="IMetadataExchange" binding="mexHttpsBinding" />
</service>
</services>
This will create SOAP 1.1 service using HTTPS and UserName token profile for transporting credentials in the message. It will also expose metadata (WSDL) over HTTPS and user name and password will be validated by custom validator. Default validation validates windows accounts but it can also be reconfigured to use ASP.NET membership provider.
The last thing you need to do is allowing HTTPS on used port (8088 in the example). For this you need a certificate with private key installed in certificate store on the machine (should be in My / Personal store in LocalMachine). You can create self signed certificate for test purposes.
Once you have a certificate you must assign the certificate to the port by using netsh. You should also allow application to listen on the port by using netsh otherwise your console application will have to run as admin (UAC - Windows Vista, 7, 2008, 2008 R2).

If your WCF Services are hosted in a console app, IIS has nothing to do with them, so you don't need to configure IIS or anything.
In order to have transport-layer security, you can use WsHttp or NetTcp binding in combination with SSL.
Have a look at http://www.dotnetspark.com/kb/1502-security-wcf--transport-level.aspx, http://www.packtpub.com/article/microsoft-wcf-security and http://dotnetrobert.com/?q=node/140.

Related

WebHttpBinding with Http and Https

I am trying to use https & http for the website. The website has .svc files which act as REST service and called from JavaScript.
My Config:
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="AjaxBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="MyServiceBehaviour">
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceMetadata httpGetEnabled="True" httpsGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
<services>
<service behaviorConfiguration="MyServiceBehaviour" name="MyService.Lookups">
<endpoint address="" behaviorConfiguration="AjaxBehavior"
binding="webHttpBinding" bindingConfiguration="httpWebBinding" contract="MyService.Lookups" >
</endpoint>
<endpoint address="" behaviorConfiguration="AjaxBehavior"
binding="webHttpBinding" bindingConfiguration="httpsWebBinding" contract="MyService.Lookups" >
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<bindings>
<webHttpBinding>
<binding name="httpsWebBinding">
<security mode="Transport">
<transport clientCredentialType="None" proxyCredentialType="None" />
</security>
</binding>
<binding name="httpWebBinding">
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None" />
</security>
</binding>
</webHttpBinding>
</bindings>
</system.serviceModel>
Browsing https://myserver/services/Lookups.svc/Hello gives
Could not find a base address that matches scheme http for the endpoint with binding WebHttpBinding. Registered base address schemes are [https]
Browsing http://myserver/services/Lookups.svc/Hello gives
Could not find a base address that matches scheme https for the endpoint with binding WebHttpBinding. Registered base address schemes are [http]
If I remove any one endpoint it works. Example removing endpoint configured with bindingConfiguration="httpWebBinding" works for HTTPS ,
How can I make it work with HTTP and HTTPS? As of now, I can able to use either http or https by removing one endpoint.
Referred How can I combine the WCF services config for both http and https in one web.config? and How do you setup HTTP and HTTPS WCF 4 RESTful services?
Note: In IIS, it is two web sites one listen on http and another on
https. Both sharing same code in physical folder
UPDATE: As of now, I removed endpoints and it works. But my concern is removing endpoing configured with behaviourConfiguration doesnt look great solution to me.
This works for both http & https
<services>
<service behaviorConfiguration="MyServiceBehaviour" name="MyService.Lookups">
</service>
</services>
I've recreated your scenario and used your web.config to configure endpoints for my test service. Your configuration is ok and works correctly. The part that don't works for you is probably your https configuration in IIS. Make sure you have enabled https access to your service. If you test it with IISExpress from Visual Studio then left click on your project and in the properties window (View -> Properties Window ) select for SSL Enabled = True.
As #Lesmian pointed out in his answer, the issue is in your IIS configuration.
More specifically in:
Note: In IIS, it is two web sites one listen on http and another on https. Both sharing same code in physical folder
The reason is that IIS can not handle endpoints on a schema which it does not support.
You have two sites, and one of them has HTTP binding but does not has HTTPS, and the other has HTTPS but not HTTP.
So when you browse to http:// URL, IIS directs you to the (surprise!) http-enabled site, reads web.config, sees that it registers https endpoint (which is not supported by the site) and throws the exception telling that there is no https scheme support on the http-enabled-only site.
When you browse to the https:// URL the situation is similar - IIS does not allow you to use http endpoint on the https-enabled-only site.
To handle the issue you better use a single site with two bindings.
Another (and more complex) option would be using different web.configs for sites: set up separate sites (pointed to separate folders) and use the publishing and web.config transforming tools of the Visual Studio
Add This Code.
<protocolMapping>
<add scheme="http" binding="webHttpBinding" bindingConfiguration="httpWebBinding"/>
<add scheme="https" binding="webHttpBinding" bindingConfiguration="httpsWebBinding"/>
</protocolMapping>
I dont't know this query is still active or not but as i checked Please
Add binding="mexHttpsBinding" also
with binding="mexHttpBinding" with different endpoint
This helps me.

Configure WCF Service to enable HTTPS and Transport Credential with User Name and Password

I have created a WCF Service and it works fine. Now I need to configure it to enable Transport Credentials with User Name and Password, and use HTTPS instead of HTTP. (Without using and certificates)
This is my existing configuration
<services>
<service name="MySAPService">
<endpoint address=""
binding="wsHttpBinding"
contract="MyService.IMyService" />
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
I googled about this and did not manage to find exact article appropriate for my scenario.
What are the changes I have to make to enable HTTPS and use User Name, Password authentication?
To enable Https, change
<serviceBehaviors>
<behavior>
<serviceMetadata httpsGetEnabled="true"/>
</behavior>
</serviceBehaviors>
and add <security mode="Transport"/> in the <webHttpBinding>.
for User Name, Password authentication use the following link:
link
When you say HTTPS it implies SSL, SSL requires Certificate (Now a certificate can be any certificate, self signed, untrusted CA etc.).
Now coming to the second part username & password, for that you need to set clientCredentialType="Basic" if you want to send them in plain text.
HTTPS/SSL/Certificates is over and above Username/Password authentication.

WCF in IIS, http basic authentication - Windows User "security" implications

I created a WCF Service, using http Basic Authentication and SSL. (Temporary certificate in IIS atm)
Here is the relevant configuration.
<services>
<service name="MyNamespace.MyService">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="basicHttps"
name="MyEndPoint" contract="MyNamespace.IMyService" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="">
<!-- These will be false when deployed -->
<serviceMetadata httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
<!-- This doesn't do anything in IIS -->
<behavior name="CustomUsernameValidatorBehavior">
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="MyNamespace.CustomUserNameValidator" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="basicHttps">
<security mode="Transport">
<transport clientCredentialType="Basic" />
</security>
</binding>
</basicHttpBinding>
</bindings>
Due to the fact I am hosting in IIS, I can't use my customUsernameValidator, and IIS Basic authentication tries the username and password against Windows.
I created a new user, disabled logon locally, and put it in a new group (without rights). The only purpose of the user is to ensure they are allowed to access the service, nothing else. The service will be online, not internal e.g. in an Intranet etc.
My question boils down to this, is there security risks/implications due to the fact I am using a real windows user? What can be done to secure this service/IIS if so?
Should something be done to prevent 'phishing' of information, could they for example try different usernames and passwords to find credentials?
Btw this is a working binding (minus some other endpoints etc.) for WCF using Http Basic Authentication in IIS and SSL. It requires IIS has Basic Authentication installed, as well as a Windows User to authenticate against. I would prefer not to authenticate against a Windows user.
IIS 5.0 and below version has IP address disclosure vulnerability if Basic Authentication (with no realm defined) is used.
Please have a look at this site:
http://www.juniper.net/security/auto/vulnerabilities/vuln1499.html

Is TransportWithMessageCredential without certificate secure enough for a WCF service?

I have developed a WCF self-hosted service, for which I have two basic security requirements as it will be accessed over the Internet:
The transport layer should prevent tampering and sniffing, especially the retrieval of authentication credentials. This is what SSL does, but from what I have seen setting up SSL requires the installation of certificates (except maybe through this hack that uses plain certificate files), which I prefer not to have to do.
The authentication layer should consist of a username/password validator.
I configured my service to use:
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName" />
<transport clientCredentialType="Basic" />
</security>
Even if the transport layer is HTTP (not HTTPS), does this make WCF create another security layer that is equivalent to SSL? If not, what is the difference in terms of security strength?
Also, is there any way to secure the meta data endpoint without using a SSL certificate (not essential but would be appreciated)?
Here is my full configuration code for the self-hosted service:
<?xml version="1.0"?>
<configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup>
<system.serviceModel>
<services>
<service name="MyService">
<host>
<baseAddresses>
<add baseAddress = "http://localhost:8000/Services" />
</baseAddresses>
</host>
<endpoint address ="MyService" binding="wsHttpBinding" contract="IMyService">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="Binding1" maxReceivedMessageSize="2147483647">
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName" />
<transport clientCredentialType="Basic" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="True"/>
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="CR.Common.Services.CustomValidator, Common" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
Thank you!
By default, all secure WCF bindings (like wsHttpBinding) will encrypt and sign messages.
SSL mandatory use a certificate, and the hack in the link you give is hacking wcf, not SSL. Because without SSL WCF forbid the use of the basicHttpBinding (which send xml in clear) and UserNamePasswordValidator, because in this case anyone that intercept the message can get the username/password.
With WSHttpBinding you could avoid SSL and put the security on the message level.
I strongly advise you to read this article, especially the Service Credentials and Negotiation chapter:
To support mutual authentication and message protection, services must
provide credentials to the caller. When transport security is used
(SSL), service credentials are negotiated through the transport
protocol. Service credentials for message security can also be
negotiated when Windows credentials are used; otherwise a service
certificate must be specified
With the UserNamePasswordValidator, you must configure a certificate on the server to allow the client the sign and encrypt each message (using the certificate's public key).
If you were using Windows authentication, it'll not be needed.
Why are you so worried about certificate ?

WCF trying to expose a nettcp endpoint; TCP error code 10061: No connection could be made because the target machine actively refused it

I don't understand what the problem is here. My wsHttpBinding works fine. Here is my configuration. Any help most appreciated.
<?xml version="1.0"?>
<configuration>
.....
<system.serviceModel>
<services>
<service behaviorConfiguration="DataService.Service1Behavior"
name="ODHdotNET.DataService">
<endpoint
address=""
binding="wsHttpBinding"
bindingConfiguration="largeTransferwsHttpBinding"
contract="ODHdotNET.IDataService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint
address="net.tcp://139.149.141.221:8001/DataService.svc"
binding="netTcpBinding"
contract="ODHdotNET.IDataService"/>
<endpoint
address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://139.149.141.221:8000/DataService.svc" />
</baseAddresses>
</host>
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="largeTransferwsHttpBinding2"
maxReceivedMessageSize="5000000" maxBufferPoolSize="5000000">
<security mode ="Message">
<message clientCredentialType="UserName"/>
</security>
</binding>
<binding name="largeTransferwsHttpBinding"
maxReceivedMessageSize="5000000" maxBufferPoolSize="5000000" />
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="DataService.Service1Behavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
edit: I am self-hosting in a Windows Service; I am not using IIS.
do you mean that a WCF client throws this error ?
if so:
please run the follwing at the command prompt:
netstat -ona | find "8001"
if this returns data, please post it
You need to add TCP support to your IIS.
To enable TCP, MSMQ, or named pipes communication specifically, perform the additional step of configuring support for the associated protocol. For TCP communication, bind the default Web site to a net.tcp port by using the Appcmd command-line utility. Appcmd is an IIS utility that enables you to administer virtual sites, directories,applications, and application pools.
%windir%\system32\inetsrv\appcmd.exe set site "Default Web Site" -
+bindings.[protocol='net.tcp',bindingInformation='808:*']
To support the other protocols, run additional commands that enable those protocols for the default Web site. At this point, you have configured the net.tcp protocol at the site level.
%windir%\system32\inetsrv\appcmd.exe set app "Default Web Site/OrderServiceHost"
/enabledProtocols:http,net.tcp
Please look at these for more detail: Extend Your WCF Services Beyond HTTP With WAS
Hosting WCF Services in Windows Activation Service
Make sure the port is open in windows firewall
Make sure your host is running when you invoke methods in client application.

Categories

Resources