Статьи

XML-подписи и ссылки

На прошлой неделе я показал  своеобразную подпись XML,  которая проверяет, хотя содержащийся документ был изменен. Причина в том, что в подписи отсутствуют  ссылки . Прежде чем объяснить, что не так с подписью и кодом проверки, мы посмотрим, как работают подписи XML.

XML DSig Primer

XML в целом — мощный зверь с таким количеством доступных опций, что он быстро становится действительно сложным. Стандарт XML Digital Signatures не является исключением из этого. Экстра 

функции
 Сложность XML DSig по сравнению с другими стандартами подписи заключается в том, что один или несколько различных блоков данных могут быть подписаны одним и тем же блоком подписи. Этими данными могут быть содержащий XML-документ, часть XML-документа или какой-либо другой ресурс, такой как веб-страница. В этом посте мы рассмотрим только ресурсы подписи в документе, содержащем подпись.

Рассмотрим простой XML-документ.

<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>

Добавить подпись к нему можно двумя способами:

  • Enveloped Подпись  является подпись , которая вставляется  в  данные , которые подписаны.
  • Enveloping Подпись  является подпись , которая сидит бок о бок с данными , которые подписаны.

В любом случае, подпись содержит одну или несколько  ссылок,  которые идентифицируют подписанный элемент и хэш содержимого элемента. Я добавил подпись к вышеуказанному элементу, содержащему две ссылки.

Xml-DSig

Первая ссылка имеет  URI="yellow". Это  конвертная подпись, так  как элемент подписи хранится в данных, которые были подписаны. Фактическая подпись исключается при вычислении хэша.

Вторая ссылка имеет  URI="green". Это  обволакивающая подпись . Он подписывает элемент, который находится рядом с подписью.

Хотя этот документ содержит подпись, которая является действительной, защищена только часть документа. Черный раздел может быть изменен без обнаружения сигнатуры, или новые элементы могут быть добавлены в <colour> элементы как родные  элементы. Это то, что делает подпись XML так 

мощный
 опасно. Недостаточно проверить подпись XML. Ссылки также должны быть проверены, чтобы убедиться, что это правильные данные, которые были подписаны. И это подводит нас к ответу на подпись XML в моем  предыдущем посте . Эта подпись не содержит ссылок, поэтому она вообще не подписывает никаких данных! Создание такой подписи обычно не допускается в .NET Framework. Для его создания я использовал  старый модульный тест,  который использует прокладки, чтобы избежать проверки ссылок.

Всегда проверяйте ссылки и ключ

Я упоминал, что ссылки на подпись XML всегда должны проверяться? Я надеюсь на это, потому что это самая распространенная ошибка проверки подписи XML. Это настолько распространено, что почти каждая известная реализация SAML2  была взломана несколько лет назад  (в OWASP есть обзорная слайд-карта об этом ).

Во-вторых, помимо проверки ссылок (я упоминал об этом, не так ли?), Необходимо проверить ключ. Самое простое перекрытие SignedXml.CheckSignature() без аргументов просто проверяет, что данные подписаны сертификатом, которому доверяет операционная система. Подпись в моем предыдущем посте будет подтверждена, потому что я подписал ее своим сертификатом, выданным доверенным рутом. Чтобы быть уверенным, что данные действительно пришли от реального отправителя, необходимо проверить информацию о ключе. Или, что еще лучше, ожидаемый ключ должен быть указан в качестве аргумента SignedXml.CheckSignature() для обхода всего хранилища сертификатов.

Полная подпись

Для краткости я исключил некоторые части подписи XML. Вот полный, который можно проверить. Обратите внимание, что он подписан ключом RSA, а значения ключей включены в подпись. Единственное, что подтверждается этой подписью, это то, что создатель подписи является владельцем закрытого ключа. Но нет никакой идентификационной информации о владельце ключа прилагается. Так что подпись на самом деле совершенно бесполезна.

<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>