Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

XSS using javascript: URLs #167

Closed
wfinn opened this issue Nov 21, 2021 · 5 comments
Closed

XSS using javascript: URLs #167

wfinn opened this issue Nov 21, 2021 · 5 comments

Comments

@wfinn
Copy link

wfinn commented Nov 21, 2021

javascript: urls can cause cross site scripting

Steps to reproduce

  1. paste this in your editor [aaaa](javascript:alert(1))
  2. preview it
  3. click on aaaa

The fix would be only allowing https?:// urls or maybe a small whitelist.

@agusmakmun
Copy link
Owner

Thank you @wfinn for reporting this issue.
The same issue on official: Python-Markdown/markdown#976

Probably we should implement a bleach to handle that case.
but, I still struggle on rendering iframe and img.

@wfinn wfinn closed this as completed Nov 21, 2021
@agusmakmun
Copy link
Owner

agusmakmun commented Dec 21, 2021

@wfinn seems we have a solution for you netbox-community/netbox#4717 (comment)

import markdown
from html.parser import HTMLParser
from django.conf import settings
from django.utils.safestring import mark_safe

# https://en.wikipedia.org/wiki/List_of_URI_schemes
ALLOWED_URL_SCHEMES = getattr(
    settings, "ALLOWED_URL_SCHEMES",
    ['file', 'ftp', 'ftps', 'http', 'https', 'irc', 'mailto', 'sftp', 'ssh', 'tel', 'telnet', 'tftp', 'vnc', 'xmpp']
)


def render_markdown(value):
    # Render Markdown
    html = markdown.markdown(value, extensions=['fenced_code', 'tables'])

    class MyHTMLParser(HTMLParser):
        error = False
        def handle_starttag(self, tag, attrs):
            for key, val in attrs:
                if tag == 'a' and key == 'href':
                    for scheme in ALLOWED_URL_SCHEMES:
                        if val.startswith(scheme):
                            return
                    self.error = True
                
    parser = MyHTMLParser()
    parser.feed(html)
    if (parser.error):
        html = "A link with an invalid scheme was detected - see settings.ALLOWED_URL_SCHEMES"

    return mark_safe(html)


value = "[aaaa](javascript:alert(1))"
render_markdown(value)

Or also using this nice idea:

netbox-community/netbox@5af2b3c

agusmakmun pushed a commit that referenced this issue Dec 21, 2021
@agusmakmun
Copy link
Owner

@wfinn fixed on this version: https://pypi.org/project/martor/1.6.8/
please upgrade your martor;

pip install martor --upgrade

@wfinn
Copy link
Author

wfinn commented Jan 10, 2022

Hi,
I noticed while [aaaa](javascript:alert(1)) is filtered, [aaaa](javascript&colon;alert(1)) is not, it still results in <a href="javascript:alert(1)">aaaa</a>

@wfinn wfinn reopened this Jan 10, 2022
@agusmakmun
Copy link
Owner

agusmakmun commented Jan 11, 2022

@wfinn hmm challanging, the patterns should be:

pattern = fr"\[(.+)\]\((?!({schemes})).*(:|;)(.+)\)"

Here is the test:

import re


markdown_text = """
[aaaa](javascript:alert(1))

[aaaa](javascript&colon;alert(1))
"""

ALLOWED_URL_SCHEMES = [
    "file", "ftp", "ftps", "http", "https", "irc", "mailto",
    "sftp", "ssh", "tel", "telnet", "tftp", "vnc", "xmpp",
]

schemes = "|".join(ALLOWED_URL_SCHEMES)
pattern = fr"\[(.+)\]\((?!({schemes})).*(:|;)(.+)\)"
markdown_text = re.sub(
    pattern,
    "[\\1](\\3)",
    markdown_text,
    flags=re.IGNORECASE,
)

output:

\n[aaaa](:)\n\n[aaaa](;)\n

Any others?

agusmakmun pushed a commit that referenced this issue Jan 11, 2022
@wfinn wfinn mentioned this issue Jan 11, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants