Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

XML Signatures and References

DZone's Guide to

XML Signatures and References

Last week I showed a peculiar XML Signature that validates even though the containing document was changed. The reason is that the signature lacks References. Read on to learn more.

· Web Dev Zone
Free Resource

Get deep insight into Node.js applications with real-time metrics, CPU profiling, and heap snapshots with N|Solid from NodeSource. Learn more.

Last week I showed a peculiar XML Signature that validates even though the containing document was changed. The reason is that the signature lacks References. Before explaining what’s wrong with the signature, and with the validation code, we’ll have a look at how XML Signatures work.

XML DSig Primer

XML in general is a powerful beast, with so many options available that it quickly gets really complex. The XML Digital Signatures standard is no exception to that. The extra  features  complexity of XML DSig compared to other signature standards is that one or more different blocks of data can be signed by the same signature block. That data can be the containing XML Document, part of an XML document, or some other resource such as a web page. In this post we’ll only look at signing resources in the document containing the signature.

Consider a simple XML document.

<Document>
  <Colour ID = "yellow">
    <Item>Sun</Item>
    <Item>Lemon</Item>
  </Colour>
  <Colour ID = "green">
    <Item>Grass</Item>
    <Item>Cucumber</Item>
  </Colour>
  <Colour ID = "black">
    <Item>Hackerz</Item>
  </Colour>
</Document>

Adding a signature to it can be done in two ways:

  • An Enveloped Signature is a signature that is inserted into the data that is signed.
  • An Enveloping Signature is a signature that is sitting side-by-side with the data that is signed.

Either way, a signature contains one or more references that identifies the element signed and a hash of the element’s contents. I’ve added a signature to the above element, containing two references.

Xml-DSig

The first reference has URI="yellow". This is an enveloped signature as the signature element is stored within the data that has been signed. The actual signature is excluded when calculating the hash.

The second reference has URI="green". This is an enveloping signature. It signs an element that is side-by-side by the signature.

Although this document contains a signature, which is valid, only part of the document is protected. The black section can be altered without the signature detecting it or new elements can be added as siblings to the <colour> elements. This is what makes XML signature so  powerful  dangerous. It is not enough to validate an XML signature. The references must be checked too, to ensure that it’s the right data that has been signed. And that brings us to the answer to the XML signature in my previous post. That signature contains no references, so it doesn’t sign any data at all! Creating such a signature is normally not allowed in the .NET framework. To create it I used an old unit test that uses shims to avoid the check for references.

Always Check References and the Key

Did I mention that the references of an XML signature must always be checked? I hope so, because that is the most common mistake of XML signature validation. It is so common, that just about every well known SAML2 implementation was hacked through it a few years ago (OWASP has an overview slide deck about it).

The second thing besides checking the references (I did mention that, didn’t I?) is that the key must be checked. The most simple overloaed ofSignedXml.CheckSignature() with no arguments just checks that the data is signed by a certificate that is trusted by operating system. The signature in my previous post will validate because I signed it with a certificate of mine issued by a trusted root. To be sure that the data actually came from the real sender, the information about the key must be checked. Or even better, the expected key should be supplied as an argument toSignedXml.CheckSignature() to bypass the entire certificate storage.

The Complete Signature

In the image I excluded some parts of the XML signature for brevity. Here is the complete one, that can be validated. Please note that it is signed by an RSA Key, with the key values included in the signature. The only thing proven by this signature is that the creator of the signature is a holder of the private key. But there is no identity information on the holder of the key attached. So the signature is actually quite worthless.

<Document>
   <Colour ID="yellow">
      <Item>Sun</Item>
      <Item>Lemon</Item>
      <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
         <SignedInfo>
            <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
            <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
            <Reference URI="#yellow">
               <Transforms>
                  <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
                  <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
               </Transforms>
               <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
               <DigestValue>sRhgxVLVLVNQwFV+DvjIgbcIoeU=</DigestValue>
            </Reference>
            <Reference URI="#green">
               <Transforms>
                  <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
               </Transforms>
               <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
               <DigestValue>WfbY1xs4jWohgPF/eboGDahJqXM=</DigestValue>
            </Reference>
         </SignedInfo>
         <SignatureValue>sJQG9uukmyMXT42WJ+lMSCQLehGXamikavXw0Ty0nrTf+laQbrsorTv84vgW253VQ6VEdeIJ4AYyks0olgusEEq8x2Cm43XtnEJCcYe9n1+XDeloil60EOahJOyZp9dFORmPrEVnanR10LQWmHTjMN1itnRsSHwtzKrs57fhTPc=</SignatureValue>
         <KeyInfo>
            <KeyValue>
               <RSAKeyValue>
                  <Modulus>srhYx87VpBrsftyteXe0FJIIPlGukuGxRHtjcQPwrttxEXkfqlZKahzgyeWlCQoMTFmvAqXZAB7eSVQyo6V/fEGtMXZ31q8ORY6q+G/u1L7XTJ18zVO/pkP7j+++QuMivoiPCJAsmqC5NS71IjJ6h5YTy677UVOcR215ukjq10E=</Modulus>
                  <Exponent>AQAB</Exponent>
               </RSAKeyValue>
            </KeyValue>
         </KeyInfo>
      </Signature>
   </Colour>
   <Colour ID="green">
      <Item>Grass</Item>
      <Item>Cucumber</Item>
   </Colour>
   <Colour ID="black">
      <Item>Hackerz</Item>
   </Colour>
</Document>


Node.js application metrics sent directly to any statsd-compliant system. Get N|Solid

Topics:
xml ,security ,integration ,web dev

Published at DZone with permission of Anders Abel, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}