如何在服务器端防止href属性的xss?

时间:2018-07-13 19:10:20

标签: c# asp.net .net security xss

在我的网站(服务器端为c#)中,我让用户提交如下链接:

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

他们输入的任何内容仅保留在“ href”属性内。我想通过“ href” URL阻止XSS。

现在,我检查c#对象URI是否为有效网址。

我的问题是:

  1. 使用URI验证URL是否足以阻止url xss?
  2. 如果没有,我应该如何防止这种xss?

例如,如何防止有效网址的XSS网络钓鱼攻击为:     “ http://xss.rocks/xss.css

2 个答案:

答案 0 :(得分:0)

作为URI进行验证是一个好的开始。之后,确认scheme是白名单选项,例如http / https。之后,请确保在输出之前对其进行编码(请参阅OWASP链接)。基本上,您可以对任何html属性编码进行完全相同的操作,除了您还需要注意恶意方案。

要注意的事情:javascript:alert(1);(验证方案),https://example.com?xss=" onclick=alert(1);//(转义输出)。

请参阅:

对于问题的第二部分,一旦用户单击链接并转到新站点,该站点就不再是XSS。允许用户添加任何URL仍然很危险,即使它不是XSS漏洞也是如此。它们仍然可以链接到恶意站点,非法内容等。对于这些站点,您也许可以针对site reputation API like Google provides进行验证,但即使这样也不是防弹的。

答案 1 :(得分:0)

要回答您的问题-验证为System.Uri是不够的。我的解决方法:

  1. 不允许使用任何引号字符或换行符,也许您可​​能需要接受查询字符串中的引号,但目前我完全禁止使用它们。如果我真的需要,我可能会改变主意。
  2. 如果检测到则不允许任何实体(例如&amp;)-拒绝网址
  3. 如果字符串解析为Uri,请检查该方案是否被接受

此时,URL仍然可能类似于javascript&#58alert(1)-浏览器将接受&#58,而WebUtility.HtmlDecode由于缺少分号而失败,因此:

  1. 如果字符串的查询字符串部分前面有“&”号,请拒绝

这是代码。

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

我认为,不应以任何方式切换URL的上下文以执行javascript。如果您找到打破它的方法,请告诉我。