how to prevent xss of href attribute at the server

2019-08-15 01:53发布

In my website ( server side is c# ) , I let users submit links like this:

<a href="$">link text</a>

Whatever they input will stay inside the "href" attribute only. i want to prevent XSS through the "href" URL.

Right now i check if it's a valid url the c# object URI.

My questions are:

  1. Is using URI for validate a url is enough to prevent url xss?
  2. if not, how should i prevent this kind of xss?

For example how can i prevent XSS phishing attack of a valid url as: "http://xss.rocks/xss.css"

2条回答
淡お忘
2楼-- · 2019-08-15 02:17

Validating as a URI is a good start. After that, verify the scheme is a white-listed option such as http/https. After that, make sure that you encode it before outputting it (see OWASP link). Basically, you do exactly what you do for any html attribute encoding, except you also need to be aware of malicious schemes.

Things to look out for: javascript:alert(1); (validate scheme), https://example.com?xss=" onclick=alert(1);// (escape output).

See:

As for the second part of your question, once the user clicks the link and goes to the new site, it isn't XSS on your site anymore. Letting users add any URL can still be dangerous, even if it isn't an XSS vulnerability though. They can still link to malicious sites, illegal content, etc. For those, you can perhaps validate against a site reputation API like Google provides, but even that is not bulletproof.

查看更多
爱情/是我丢掉的垃圾
3楼-- · 2019-08-15 02:24

To answer your question - validating as System.Uri is not enough. My approach to the problem:

  1. Do not allow any quote character or new-lines, perhaps you might need to accept quotes in the query strings but for now I have banned them altogether. I might change my mind if I actually need it.
  2. Do not allow any entities (e.g. &amp;) if detected - reject the url
  3. If the string parses as Uri - check the scheme is accepted

At this point the url could still be something like javascript&#58alert(1) - the browsers will accept the &#58 while WebUtility.HtmlDecode fails because of missing semicolon so:

  1. If there is an ampersand or a colon before the query string part of the string - reject it

Here is the code.

    private static readonly string[] acceptedSchemes = { Uri.UriSchemeHttp, Uri.UriSchemeHttps, Uri.UriSchemeMailto, Uri.UriSchemeFile };
    private static readonly char[] forbiddenHrefChars = { '"', '\'', '`', (char)10, (char)13 };
    private static readonly char[] forbiddenBeforeQueryString = { ':', '&', '\\' }; // the colon may look surprising, but if we deal with a colon we expect something which parses as URI

    /// <summary>
    /// Returns true if the specified string is considered XSS safe href attribute value.
    /// </summary>
    public static bool IsSafeHref(string input)
    {
        if (input.Any(c => forbiddenHrefChars.Contains(c)))
            return false;

        // do not accept any entities
        string href = WebUtility.HtmlDecode(input);
        if (href != input)
            return false;

        // check if the scheme is valid, if specified
        bool isUri = Uri.TryCreate(input, UriKind.Absolute, out Uri uri);
        if (uri != null)
            return acceptedSchemes.Contains(uri.Scheme ?? "");

        int qsIdx = href.IndexOf('?');
        string partBeforeQueryString = qsIdx < 0 ? href : href.Substring(0, qsIdx);

        if (forbiddenBeforeQueryString.Any(c => partBeforeQueryString.Contains(c)))
            return false;

        return true;
    }

I believe it should not allow any way to switch the context of the URL to execute as javascript. Please let me know if you find a way to break it.

查看更多
登录 后发表回答