There might be a problem in many applications based on XML signature verification (provided I am not wrong, of course).
Let's have a simple XML message with an enveloped XML signature:
<?xml version="1.0" encoding="UTF-8"?>
<message>
<msgenvelope id="SIGNED_DATA">some signed data</msgenvelope>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
...
<Reference URI="#SIGNED_DATA">
...
</Reference>
</SignedInfo>
<SignatureValue>naUY...+xZbEA=</SignatureValue>
</Signature>
</message>
According to this MSDN article, you should verify such a XML document with the SignedXml
class:
SignedXml signedXml = new SignedXml(Doc); //Doc is my message
XmlNodeList nodeList = Doc.GetElementsByTagName("Signature");
signedXml.LoadXml((XmlElement)nodeList[0]);
bool ok = signedXml.CheckSignature(Key);
if (ok) {
string signedData = Doc.SelectSingleNode("/message/msgenvelope").InnerText;
//do something with the signed data
} else {
//throw error or something
}
I think there is a problem: the CheckSignature
method verifies if the signature value is correct, but not if the signed data is really the data which are expected to be signed.
An evil guy could modify the message this way:
<?xml version="1.0" encoding="UTF-8"?>
<message>
<msgenvelope id="anotherid">FAKE DATA!!</msgenvelope>
<evil_envelope>
<msgenvelope id="SIGNED_DATA">some signed data</msgenvelope>
</evil_envelope>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
...
<Reference URI="#SIGNED_DATA">
...
</Reference>
</SignedInfo>
<SignatureValue>naUY...+xZbEA=</SignatureValue>
</Signature>
</message>
This message is verified correctly, because the signed element and the signature are still the same. However, resulting data string contains "FAKE DATA!!".
There are a few ways to avoid this attack - using schema verification against XSD, checking the id
attribute of the trusted element etc. What is the recommended approach to get rid of this risk? Should the MSDN article be improved? Is there any reference implementation that handles this problem correctly?