Wednesday, December 30, 2009

Security Gotcha: Nonrepudiation

@YaronNaveh

An important web services security requirement is nonrepudiation. This requirement prevents a party from denying it sent or received a message. The way to implement this is using Xml Digital Signatures. For example, if I sent a message which is signed with my private key, I cannot later deny that I sent it.

A common mistake is to think that every web service that require an X.509 certificate ensures nonrepudiation. This goes without say for web services that only require server certificate - in these services clients are either anonymous or username/password identified, which is considered weak cryptographically material.

However, also when a client X.509 is involved, nonrepudiation is not always guaranteed.
For example, let's examine a Wcf service which uses WsHttpBinding with TransportWithMessageCredential and clientCredentialType="Certificate":


<wsHttpBinding>
   <binding name="WSHttpBinding_IService" >
     <security mode="TransportWithMessageCredential">
       <transport clientCredentialType="None" proxyCredentialType="None"
        realm="" />
       <message clientCredentialType="Certificate" negotiateServiceCredential="true"
        algorithmSuite="Default" establishSecurityContext="false" />
     </security>
   </binding>
</wsHttpBinding>


This is how the client request looks like:


<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing">
  <soap:Header>
  ...
   <To soap:mustUnderstand="1" u:Id="_1" xmlns="http://www.w3.org/2005/08/addressing" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">https://www.someService.co.il/</To>
   ...
   <o:Security soap:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
    <u:Timestamp u:Id="_0" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
     <u:Created>2009-12-30T18:19:03.538Z</u:Created>
     <u:Expires>2009-12-30T18:24:03.538Z</u:Expires>
    </u:Timestamp>
    <o:BinarySecurityToken u:Id="uuid-b29856c4-1be8-4cf6-94ef-b3e2818b9924-1" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">...</o:BinarySecurityToken>
    <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
     <SignedInfo>
      <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
      <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
      <Reference URI="#_0">
       <Transforms>
        <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
       </Transforms>
       <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
       <DigestValue>ExzPg2kUjOQz2nFBMlhm+OT3GNY=</DigestValue>
      </Reference>
      <Reference URI="#_1">
       <Transforms>
        <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
       </Transforms>
       <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
       <DigestValue>mN+2rmNLmjSJxbO4x+n/V6gGAb4=</DigestValue>
      </Reference>
     </SignedInfo>
     <SignatureValue>...</SignatureValue>
     <KeyInfo>
      <o:SecurityTokenReference>
       <o:Reference URI="#uuid-b29856c4-1be8-4cf6-94ef-b3e2818b9924-1" />
      </o:SecurityTokenReference>
     </KeyInfo>
    </Signature>
   </o:Security>
  </soap:Header>
  <soap:Body>
   <EchoString xmlns="http://tempuri.org/">
    <s>abcde</s>
   </EchoString>
  </soap:Body>
</soap:Envelope>


The message body is not signed!
This practically means anyone who has this message (for example the server) can extract the signed parts and resend them with a bogus body.

@YaronNaveh

What's next? get this blog rss updates or register for mail updates!

Saturday, December 26, 2009

When your unit test is not implemented...

@YaronNaveh

When your unit test is not implemented yet you want to make sure everybody knows about it. One bad way is to throw an exception in the test first line:


[Test]
public void MyNewTest()
{
   throw new NotImplementedException();
}


The reason is that when you see in the report this failure you can never tell if the error comes from the unit test or the application under test...

The good solution is to use a build in feature of your unit test framework. For example, the Ignore attribute in NUnit. If for some reason you have to throw an exception (so the test will be red) at least throw some better error class like "new UnitTestNotImplementedException()".

@YaronNaveh

What's next? get this blog rss updates or register for mail updates!

Unit Test Legitimic Failures

@YaronNaveh

Our unit tests are expected to pass every time. When they fail we are expected to fix the regression. But in some cases it is ok for a test to temporarily not pass. For example, if the test is a small regression in a minor feature and we are currently employed with other critical missions. But while the test is failing we should at least make sure it will not cause any noise like spamming out the team.

When we use NUnit, the solution is the Ignore attribute:


[Test]
[Ignore]
public void SomeTest()
{
//...
}


The test is not red any more:

@YaronNaveh

What's next? get this blog rss updates or register for mail updates!

The XmlReader state should be Interactive

@YaronNaveh

Recently I was parsing Xml in c# from an XmlReader to an XElement:


MemoryStream m = GetMemoryStream();
XmlReader r = XmlReader.Create(m);
XElement e = XElement.ReadFrom(r) as XElement;


The last line threw this exception:


System.InvalidOperationException
The XmlReader state should be Interactive.


In MSDN ReadState.Interactive state is described as:


The Read method has been called. Additional methods may be called on the reader.


But why should I call read? It is the XElement responsibility to do it.

The solution is pretty simple though:


MemoryStream m = GetMemoryStream();
XmlReader r = XmlReader.Create(m);
//This is how we make the XmlReader interactive
r.MoveToContent();

XElement e = XElement.ReadFrom(r) as XElement;

@YaronNaveh

What's next? get this blog rss updates or register for mail updates!

Wednesday, December 9, 2009

Not all errors are red

@YaronNaveh

Here's some WCF service trace log. Is there a problem with the service the log belongs too?



Of course, we see an error in the red line.

What about this service?




Well, nothing red here. Let's drill down into the "warning" details:



It seems WCF errors come in more than one color.

@YaronNaveh

What's next? get this blog rss updates or register for mail updates!