Half a years worth of pull requests with great features have finally been baked into an official release of Kentor.AuthServices which is now available on Nuget. The most important fixes are improved active/passive handling for the Owin middleware and full support for SHA256/384/512 as it is time to leave SHA1.
First of all I would like thank all contributors and users that have had to wait for this while I’ve been on parental leave. A special thanks to Explunit who has made a lot of valuable contributions as well as reviewing pull requests and taken part in design discussions.
The public API of AuthServices is getting more and more stable, but nevertheless there are some breaking changes.
- The Owin Middleware is now once again Passive by default
- The Owin Middleware will act as Active during Logout, even if it is configured as passive. This can be disabled with the
StrictOwinAuthenticationMode compatibility setting.
- On .NET 4.6.2 and later AuthServices now by default generates SHA256-based signatures and only accepts SHA256 or stronger signatures.
- The “clever” ReturnUrl expansion has been removed as it proved to create more problems than it solved.
- ReturnUrl open redirect issue fixed.
For some times there’s been bug reports to Kentor.AuthServices, IdentityServer3 and System.IdentityModel.Tokens.Jwt about enabling SHA256 XML signature support sometimes breaks JWT signing. It fails with an error of System.Security.Cryptography.CryptographicException: Invalid algorithm specified.
This has been one of those annoying bugs where everyone’s solution works perfectly by itself, but combined they fail. I closed this issue in AuthServices with a comment that “works for us, has to be IdentityServer3/System.IdentityModel.Tokens doing something strange.”. I’ve finally had some time to look deeper into this thanks to IRM that asked me to do this as a consultancy service. Without someone paying for the time, it’s hard to spend the hours needed to find the root cause of a problem like this. When I started out on this I looked at all three systems/components involved to try to understand what triggers the problem. I ended up fixing this in Kentor.AuthServices for now. The fix could also have been done in the .NET Framework, IdentityServer3 or System.IdentityModel.Tokens.Jwt. Doing it in Kentor.AuthServices was mostly a matter of convenience because I control it myself.
That means that the TL;DR of all of this is that if you update to Kentor.AuthServices 0.19.0 or later this problem is solved. If you’re interested on how to solve it if you add SHA256 support yourself, please read on.
.NET offers the simple
string.Join() methods for joining and splitting separated strings. But what if there is no suitable separator character that may not occur in the string? Then the separator character must be escaped. And then the escape character must be escaped too… And this turns out to be quite an interesting algorithm to write.
I thought that this functionality would be built in, but as far as I could find out it isn’t. If there is a built in way, please leave a comment to educate me. This being a string manipulation, there is a possibility to use Regular Expressions too, but…
Some people, when confronted with a problem, think “I know, I’ll use regular expressions.” Now they have two problems.
Solving this through a Regular Expression would require some black magic double look-behind assertion which I wouldn’t understand even when I wrote the code, much less later when I came back to fix some bug. So I went for implementing it myself.
Earlier this month, Microsoft released MS16-035 that addresses issues I previously reported in SignedXml. They did not only fix the duplicate Id vulnerability I reported though, they also fixed a number of other issues – introducing some breaking changes. This post is an effort to document those and changes and the registry switches that can be used to revert back to the old behaviour.
These are the breaking changes I know about. If you know of any more issues, please leave a comment or drop a mail and I’ll try to update the post.
- Duplicate Ids for reference elements no longer allowed (applies to both
- Id values must be a well formed NCName (which is required by the XML standard, applies to both
- External references disabled by default
- XPath Transform disabled by default
- XSLT Transform disabled by default
.NET’s SignedXML class
has had a risky implementation for lookup of XML elements by id in
GetIdElement() when resolving signed xml references. The lookup validated only the first element if there are several with the same id. This opens up for XML Signature Wrapping attacks in any library that is using the default implementation without taking necessary precautions. For SAML2 libraries signature wrapping is a well known attack class with very severe implications.
I reported this privately to Microsoft on December 3rd 2015. They responded (as promised within 24 hours) that they would investigate. The vulnerability was assigned ids CVE-2016-0132 and MS16-035. A fix was released on “patch Tuesday” in March 2016 (and yes, I’m proud to be listed in the acknowledgement section). The fix also contains a number of related breaking changes.
This is an example of a signed XML document with data that might be incorrectly trusted.
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<data>Some false data</data>
The document demonstrates how two elements have the same id. The unpatched
SignedXml.GetIdElement() method will only find and validate the first occurrence of the id, but code that loops all nodes and checks that the id is present in the signature’s references will trust both