SignalR - Decryption key specified has invalid hex characters - c#

I am using SignalR 2.2.0 and MVC 4. When I load my page in Chrome, I receive an error in the console:
http://localhost:8180/signalr/negotiate?clientProtocol=1.5&connectionData=%5B%7B%22name%22%3A%22chathub%22%7D%5D&_=1467627883530 500 (Internal Server Error)
Upon further inspection using Fiddler I can view the stacktrace:
[ConfigurationErrorsException]: Decryption key specified has invalid hex characters. (C:\Users\Foo\web.config line 66)
at System.Web.Security.Cryptography.MachineKeyMasterKeyProvider.GenerateCryptographicKey(String configAttributeName, String configAttributeValue, Int32 autogenKeyOffset, Int32 autogenKeyCount, String errorResourceString)
at System.Web.Security.Cryptography.MachineKeyMasterKeyProvider.GetEncryptionKey()
at System.Web.Security.Cryptography.Purpose.GetDerivedEncryptionKey(IMasterKeyProvider masterKeyProvider, KeyDerivationFunction keyDerivationFunction)
at System.Web.Security.Cryptography.AspNetCryptoServiceProvider.GetNetFXCryptoService(Purpose purpose, CryptoServiceOptions options)
at System.Web.Security.Cryptography.AspNetCryptoServiceProvider.GetCryptoService(Purpose purpose, CryptoServiceOptions options)
at System.Web.Security.MachineKey.Protect(ICryptoServiceProvider cryptoServiceProvider, Byte[] userData, String[] purposes)
at System.Web.Security.MachineKey.Protect(Byte[] userData, String[] purposes)
at Microsoft.Owin.Host.SystemWeb.DataProtection.MachineKeyDataProtector.Protect(Byte[] userData)
at Microsoft.Owin.Security.DataProtection.AppBuilderExtensions.CallDataProtectionProvider.CallDataProtection.Protect(Byte[] userData)
at Microsoft.AspNet.SignalR.Infrastructure.DataProtectionProviderProtectedData.Protect(String data, String purpose)
at Microsoft.AspNet.SignalR.PersistentConnection.ProcessNegotiationRequest(HostContext context)
at Microsoft.AspNet.SignalR.PersistentConnection.ProcessRequest(HostContext context)
at Microsoft.AspNet.SignalR.Hubs.HubDispatcher.ProcessRequest(HostContext context)
at Microsoft.AspNet.SignalR.PersistentConnection.ProcessRequest(IDictionary`2 environment)
at Microsoft.AspNet.SignalR.Owin.Middleware.HubDispatcherMiddleware.Invoke(IOwinContext context)
at Microsoft.Owin.Infrastructure.OwinMiddlewareTransition.Invoke(IDictionary`2 environment)
at Microsoft.Owin.Mapping.MapMiddleware.<Invoke>d__0.MoveNext()
From what I've gathered, SignalR is using the machine key to perform some encryption/decryption.
This is what the machine key looks like:
<machineKey decryptionKey="5E329ED7DE2786FCD906E717C97A09BE26B3564BBE0A2B28,IsolateApps" validationKey="A64F709FB47B282CB8331205BC423D63450B4FFC92FE06EC1E00B3AE8B5B1F529A5CD1064F66C08545FC13B013F84153598B29213D5494DD5EC348B537A51DAE,IsolateApps"/>
I'm guessing it's seeing the "IsolateApps" in the decryptionKey/validationKey and throwing an exception ("...invalid hex characters").
If I remove the "IsolateApps" from the keys, I can't log in anymore since I'm using FormsAuthentication which in turn makes use of the keys to encrypt/decrypt. So removing the "IsolateApps" does not seem to be a solution.
PS. The code I'm using is from this tutorial.
I have already looked at this answer but it does not solve the problem. I have also tried to add compatibilityMode="Framework20SP1" to the machine key but that does not work either.
Is there way to fix this issue without removing the "IsolateApps" value from the keys in the web config?

I have fixed the issue. I decided to remove the ",IsolateApps" attribute from the machine key which stopped giving this exception:
Decryption key specified has invalid hex characters
Removing this attribute meant I could not log in anymore (since the machine key has technically changed) which forced me to reset my account password. Once I reset the password I could continue with logging in.
Once I was able to log in I was receiving this error:
ws://xxxxx/signalr/connect?transport=webSockets&clientProtocol=1.5&connectionToken=xxxxx'
failed: Connection closed before receiving a handshake response.
This exception was only being thrown in Chrome.
SignalR fell back onto server sent events because the web socket handshakes weren't successful. After many hours of debugging I solved the issue by adding this to the web config:
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" />
<pages controlRenderingCompatibilityVersion="4.0" />
</system.web>
Once that was added, SignalR was functioning as excepted.

Related

Getting error Menu_HoverStatic is null or undefined, not a function object, while using asp.net SiteMap control for menu items

Ours is ASP.net application which we recently migrated from Windows 2008 to Windows 2016 server IIS 10.
In Windows 7 OS in IE 11, we face the issue where menu items are not accessible and is throwing error on hover over:(Chrome and Win 10 IE 11 application is working good)
The value for property 'Menu_HoverStatic' is null or undefined, not a function object.
Event Logs are registering a different error:
Event message: An error occurred processing a web or script resource request. The resource identifier failed to decrypt.
<Data>w3wp.exe</Data>
<Data>IIS APPPOOL\SDMS3AppPool</Data>
<Data>HttpException</Data>
<Data>Unable to validate data.
at System.Web.Configuration.MachineKeySection.EncryptOrDecryptData(Boolean fEncrypt, Byte[] buf, Byte[] modifier, Int32 start, Int32 length, Boolean useValidationSymAlgo, Boolean useLegacyMode, IVType ivType, Boolean signData)
at System.Web.UI.Page.DecryptString(String s, Purpose purpose)
at System.Web.Handlers.AssemblyResourceLoader.System.Web.IHttpHandler.ProcessRequest(HttpContext context)
</Data>
<Data>https://yourdomain.com/WebResource.axd?d=4008OIcfpQF6_PTcMUk_uuvjlbvBEPqjv3TH_Vnn6L3r0AEZJ8Q033KeIIkTHLC_AKyJ_c9JpdqPlJLfGOrxCpK--hZQ1gp-BXe8XbRP_6g1&t=636511268826842555</Data>
<Data>/WebResource.axd</Data>
We call SiteMap in master page:
<div class="NavigationContent">
<asp:Menu ID="Menu1" runat="server" Orientation="Horizontal" DataSourceID="SiteMapDataSource"
CssClass="Menu"
StaticEnableDefaultPopOutImage="false"
DynamicEnableDefaultPopOutImage="false"
StaticMenuItemStyle-CssClass="MenuItem"
StaticHoverStyle-CssClass="MenuItemHover"
StaticSelectedStyle-CssClass="MenuItemSelected"
DynamicMenuItemStyle-CssClass="MenuItem"
DynamicHoverStyle-CssClass="MenuItemHover"
DynamicSelectedStyle-CssClass="MenuItemSelected"
OnDataBound="Menu1_DataBound"
/>
<asp:SiteMapDataSource ID="SiteMapDataSource" runat="server" ShowStartingNode="false" />
</div>
Going through google, this error seems to be due to webresource.axd.
I tried following suggestions among many:
App pool mode set to Integrated, .net 4
Set browser security level to low
Add webresource.axd in IIS handler mapping for application virtual directory.
Thanks for all the help!!
I tried a lot of suggestions and at last this issue was resolved by machine key.
If your server is a web farm, make sure you have same key in all servers.
<system.web>
<machineKey validationKey="2488181654410AFDA27F6A1F4855B75E4E3BD4C7A18969D151A7524CEBE432583762F430B31D86AEEFD368CD2104616C38EABFCBC7C658DA3A553******" decryptionKey="30DC1CA2BD1BDDAB7BFA18DE02B0059443EC656B39FAB179E38CBD82CCF4E***" validation="SHA1" decryption="Auto"/>
</system.web>
you can follow below article to generate machine key:
Generate Machine Key In IIS

ASP MVC Url Encode double escape sequence

I want to encrypt the Id part of a given url and I used SHA-1 for that. This algorithm convert the id to the following string:
NxVhIhrfbZNzyxqtudUZdiv4DdQA9nF1Zn7CueGUiT8=|h1bCRiN5zxexiIhHp+qNEQ0jVh/8fMGiIkeTf30LVdU=
Therefore, my final url would be something like this:
http://localhost:9432/Product/Edit/NxVhIhrfbZNzyxqtudUZdiv4DdQA9nF1Zn7CueGUiT8=|h1bCRiN5zxexiIhHp+qNEQ0jVh/8fMGiIkeTf30LVdU=
This url has some character which cause the request fail. For example ‘+’ is not allowed in url. So I used HttpUtility.UrlEncode() on the encrypted Id and got this string as a result:
NxVhIhrfbZNzyxqtudUZdiv4DdQA9nF1Zn7CueGUiT8%3d%7ch1bCRiN5zxexiIhHp%2bqNEQ0jVh%2f8fMGiIkeTf30LVdU%3d
Now my url is:
http://localhost:9432/Product/Edit/NxVhIhrfbZNzyxqtudUZdiv4DdQA9nF1Zn7CueGUiT8%3d%7ch1bCRiN5zxexiIhHp%2bqNEQ0jVh%2f8fMGiIkeTf30LVdU%3d
However using the above url cause the following error:
The request contained a double escape sequence and request filtering is configured on the Web server to deny double escape sequences.
I can ignore that by inserting the below code in web.config:
<system.webServer>
<security>
<requestFiltering allowDoubleEscaping="true" />
</security>
</system.webServer>
Now I have two questions:
Why the result of HttpUtility.UrlEncode() causes any kind of error. As I noticed, the result of that doesn’t contain any illegal character for a url?
As I understood putting <requestFiltering allowDoubleEscaping="true" /> is not a good solution, since it will create a security hole in the application, so what would be the best solution in this case?
the result of HttpUtility.UrlEncode() doesn't contain errors, it is just encoding the + sign with will be detected on IIS level. IIS rejects "+" in URLs by default. Your work around will work:
<requestFiltering allowDoubleEscaping="true" />
but as you said, it will create some security problems because this makes your site more vulnerable to malicious URLs.
What i suggest, either you use another encryption algorithm that doesn't generate these "IIS" sensetive characters, or if you wanna use the above workaround, you need to implement proper URL/User-Input validations in order to make sure that you catch and prevent all suspecious entries.

Federated Authentication - two cookies, first cookie has closing xml tag

I am creating the authentication cookies for a site using the code FederatedAuthentication.SessionAuthenticationModule.WriteSessionTokenToCookie(token);
The token is quite big, so the cookie is split across two cookies. 99% of the time everything works correctly, here is an example of the two cookies from a successful login once they have been Base64 decoded:
WebSiteAuth:
<?xml version="1.0" encoding="utf-8"?><SecurityContextTokenp1:Id="_e00ce4ab-> 2439-48d3-a1cd-f6a31180d02f-B99934A3DBEDB9B3EA191AB595FA8011" xmlns:p1="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns="http://docs.oasis-open.org/ws-sx/ws-secureconversation/200512"><Identifier>urn:uuid:adbfc4e1-c4a1-4882-9980-aa59431cdf48</Identifier><Cookie xmlns="http://schemas.microsoft.com/ws/2006/05/security">ENCRYPTED_COOKIE_VALUE
WebSiteAuth1:
ENCRYPTED_COOKIE_VALUE</Cookie></SecurityContextToken>
But sometimes the user is encountering the following error:
Exception information:
Exception type: FormatException
Exception message: The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or
an illegal character among the padding characters. at
System.Convert.FromBase64_Decode(Char* startInputPtr, Int32
inputLength, Byte* startDestPtr, Int32 destLength) at
System.Convert.FromBase64CharPtr(Char* inputPtr, Int32 inputLength)
at System.Convert.FromBase64String(String s) at
System.IdentityModel.Services.SessionAuthenticationModule.TryReadSessionTokenFromCookie(SessionSecurityToken&
sessionToken) at
System.IdentityModel.Services.SessionAuthenticationModule.OnAuthenticateRequest(Object
sender, EventArgs eventArgs) at
System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step,
Boolean& completedSynchronously)
I logged the user's cookies at the time that the error was thrown, and here is what the cookies looked like after I Base64 decoded them.
WebSiteAuth:
<?xml version="1.0" encoding="utf-8"?><SecurityContextToken p1:Id="_3518f851-bbec-4bb3-b7bb-c4c9bd9165e2-978AD0895E2683747B7CAFF4F1C7131B" xmlns:p1="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns="http://docs.oasis-open.org/ws-sx/ws-secureconversation/200512"><Identifier>urn:uuid:dd9a6856-9bd1-486c-9f5c-e980fbcc3b02</Identifier><Cookie xmlns="http://schemas.microsoft.com/ws/2006/05/security">ENCRYPTED_COOKIE_VALUE</Cookie></SecurityContextToken>
WebSiteAuth1:
ENCRYPTED_COOKIE_VALUE</Cookie></SecurityContextToken>
As you can see, the difference is that the first cookie has closing tags </Cookie></SecurityContextToken>which should not be there, because the xml is closed in the second cookie.
I think that this is what is causing the error.
Does anyone have experience of this problem? Or any ideas how I can fix this?
My solution was to reduce the size of the cookie.
There is a setting on the SessionSecurityToken which is called IsReferenceMode. So I set this to be true. This means that the cookie is stored on the server and only a reference to this 'server cookie' is stored on the user's machine. This means that the cookie is much smaller, and is not split into two cookies, which avoids the problem I had where the first cookie chunk sometimes randomly included closing xml tags.
The downside to this approach is that when the application pool is restarted, then the customer loses their cookie, even if they set that the cookie should be persistant. To work around this I was able to inherit from the SessionSecurityTokenCache class and override the AddOrUpdate, Get and Remove methods to use the database as a backup store, so the token can be retrieved even if the session is cleared.
I adapted the thinktecture model which is here:
https://github.com/identitymodel/Thinktecture.IdentityModel
There is a good blog explaining the basics here:
https://brockallen.com/2013/02/21/server-side-session-token-caching-in-wif-and-thinktecture-identitymodel/

Reading cookie value : Using URL Rewrite Provider module - Unable to validate at System.Web.Configuration.MachineKeySection.EncryptOrDecryptData

I have requirement to append USERNAME to the URL in server side using URL Rewrite module.
Why?:
I have website site1, when USER logs in to site1, he will see a link to site2., This link is URL or reports. (Tableau).
Authenticated ticket has been created using FormAuthentication in site1.
When USER clicks the link, authenticated username should be passed to site2.
I could append username from client side, but due to security issues I have to append username to URL in server side before it gets executed.
So I have decided to use URL rewrite provider, which grabs the username by decrypting the cookie value as shown below
namespace PlatformAnalysisUrlProvider.PlatformAnalysisProvider
{
class AnalysisRewriteProvider: IRewriteProvider, IProviderDescriptor
{
public void Initialize(IDictionary<string, string> settings,
IRewriteContext rewriteContext)
{
}
public string Rewrite(string value)
{
string[] cookievalues = value.Spli('=');
FormAuthentication ticket = FormAuthentication.Decrypt(cookievalues[1]);
//Decrypt throws error as shown below
}
}
}
Cookie Values
cookievalues [0] = has the key
cookievalues [1] = has the value
Example:
233AWJDKSHFHFDSHFJKDFDKJFHDKJFKDJFHDHFDHFKJHDFKJHDFJHDKJFHDSKJFHDF
It's a cookie value. But decrypt is not happening
I am getting following error
Unable to validate data.
at System.Web.Configuration.MachineKeySection.EncryptOrDecryptData(
Boolean fEncrypt, Byte[] buf, Byte[] modifier, Int32 start,
Int32 length, IVType ivType, Boolean useValidationSymAlgo,
Boolean signData)
Here is my settings in IIS for URL Rewrite
Requested URL: Matches the Patterns
Using: Regular Expression
Ignore Case - Checked
Conditions -
Input : {HTTP_COOKIE}
Type : Matches the Pattern
Pattern : .*
Action Type - Rewrite
Rewrite URL - http://11.155.011.123{HTTP_URL}&USERNAME={PlatformAnalysisUrlProvider:{C:0}}
I have also set up MACHINE KEY as suggested by this forum
I have referred this post for development
One of the stack overflow post suggested that it might be firewall or antivirus issue. But I do not have antivirus installed or firwall enabled.
It really helps if someone direct me to code sample where web site hosted in IIS and URL Rewrite provider is used.
Updating Error Log
MODULE_SET_RESPONSE_ERROR_STATUS
Notification - "PRE_BEGIN_REQUEST"
HttpReason - "URL Rewrite Module Error"
Updating post with Machine Key Info
<MachineKey Description="AES" validation="SHA1"
descriptionKey="******"
validationKey="******" CompatibilityMode="Framework20SP2">
Reason May be - The website where cookie getting created is developed using .NET Framework 4.5. The provider where we reading the cookie is Framework 3.5. Is this may be the cause? OR Do we need config file for Provider project?
Updates - I have added machine key to Machine.config , but it still did not work :(
Alternative Solution
Add App.config to class Library
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<!-- ... -->
<add key="SecurityKey" value="somevalue"/>
<!-- ... -->
</appSettings>
</configuration>
Copy config to GAC
Follow this blog - http://techphile.blogspot.in/2007/02/2.html
Encrypt the value (refer here) and create custom cookie during Login
Use the Decrption logic inside custom rewrite provider
The good thing about this is that the error is a general decryption error and not one with URL Rewrite itself, so that gives you a wider area to search for help. The mechanics of URL Rewrite seem to be right.
Decrypting means that it must be encrypted by the same method as you're decrypting it. So it has to be the right cookie and the right decryption method.
Since you're not checking which cookie that you're reading from, you could get unexpected results if the wrong cookie is first in the list of cookies.
Here are some steps that I recommend to troubleshoot this:
Create a simple URL Rewrite rule that will give you the value of your cookie. I created a rule to do that in my example below. You can test it by going to yoursite.com/getcookie. It should redirect to yoursite.com/?Cookie={cookievalue}
Then you can test your code outside of the URL Rewrite provider. You can create a simple console app or winforms app to test the rest of the code.
I recommend adding a check for the existence of the cookie and then a check again for the 2nd value. For example: if (cookievalues[1] != null).
When developing the decryption method, you don't have to worry about URL Rewrite. As long as it works in a test app in .NET then you should be set.
<rule name="Get cookie value" stopProcessing="true">
<match url="^getcookie" />
<action type="Redirect" url="/?Cookie={HTTP_COOKIE}" appendQueryString="false" redirectType="Found" />
</rule>

Azure Cache ErrorCode<ERRCA0017>:SubStatus<ES0006>

Im trying to access MS Azure Cache service and pretty often I get this error:
Microsoft.ApplicationServer.Caching.DataCacheException: ErrorCode<ERRCA0017>:SubStatus<ES0006>:There is a temporary failure. Please retry later. (One or more specified cache servers are unavailable, which could be caused by busy network or servers. For on-premises cache clusters, also verify the following conditions. Ensure that security permission has been granted for this client account, and check that the AppFabric Caching Service is allowed through the firewall on all cache hosts. Also the MaxBufferSize on the server must be greater than or equal to the serialized object size sent from the client.). Additional Information : The client was trying to communicate with the server: net.tcp://remoto.cache.windows.net: line 23233.
at Microsoft.ApplicationServer.Caching.DataCache.ThrowException(ErrStatus errStatus, Guid trackingId, Exception responseException, Byte[][] payload, EndpointID destination)
at Microsoft.ApplicationServer.Caching.SocketClientProtocol.Get(String key, ref DataCacheItemVersion version, ref TimeSpan timeout, ref ErrStatus err, String region, IMonitoringListener listener)
at Microsoft.ApplicationServer.Caching.DataCache.InternalGet(String key, ref DataCacheItemVersion version, String region, IMonitoringListener listener)
at Microsoft.ApplicationServer.Caching.DataCache.<>c__DisplayClass53.<Get>b__52()
at Infrastructure.Azure.Cache.AzureCacheServiceClient.<>c__DisplayClass6`1.<Get>b__5() in AzureCacheServiceClient.cs: line 88
at Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling.RetryPolicy.ExecuteAction(Func`1 func)
It happens when Im trying to access some object in cache like this:
public T Get<T>(string key)
{
retryPolicy.ExecuteAction(() =>(T) (_cache.Get(key)));
}
Here is my initialization code:
var cacheFactory = new DataCacheFactory();
_cache = cacheFactory.GetDefaultCache();
var retryStrategy = new FixedInterval(15, TimeSpan.FromSeconds(2));
_retryPolicy = new RetryPolicy<CustomCacheTransientErrorDetectionStrategy>(retryStrategy);
And app.config:
<configSections>
<section name="dataCacheClients" type="Microsoft.ApplicationServer.Caching.DataCacheClientsSection, Microsoft.ApplicationServer.Caching.Core" allowLocation="true" allowDefinition="Everywhere" />
<section name="cacheDiagnostics" type="Microsoft.ApplicationServer.Caching.AzureCommon.DiagnosticsConfigurationSection, Microsoft.ApplicationServer.Caching.AzureCommon" allowLocation="true" allowDefinition="Everywhere" />
</configSections>
<dataCacheClients>
<dataCacheClient channelOpenTimeout="1000" requestTimeout="45000" name="default">
<autoDiscover isEnabled="true" identifier="[some.host.name]" />
<securityProperties mode="Message" sslEnabled="true">
<messageSecurity authorizationInfo="***" />
</securityProperties>
</dataCacheClient>
</dataCacheClients>
It happend at least three times already while the Azure Health Status (https://azure.microsoft.com/en-us/status/) said everything was fine at that time.
As the exception message says - there are some 'temporary' failures on MS side still maybe I'm doing smth wrong in my code?
Do you get the error a few times, and then things start working again? If so, this is expected behavior and your application should have a policy where you retry some number of times before falling back to the persistent data store.
If you get the error consistently (more than a few seconds), it's likely the DataCacheFactory has gotten into a bad state. You can either restart your client process, or else refresh the DataCacheFactory as described in this blog post.

Categories