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



在我的网站(服务器端是c#(中,我让用户提交这样的链接:

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

他们输入的内容将仅保留在"href"属性中。我想通过"href"URL阻止XSS。

现在我检查它是否是一个有效的url,即c#对象URI。

我的问题是:

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

例如,如何防止有效url的XSS网络钓鱼攻击:"http://xss.rocks/xss.css">

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

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

参见:

  • https://www.owasp.org/index.php/XSS_(交叉_站点_脚本(_事件_备忘单
  • https://msdn.microsoft.com/en-us/library/system.web.security.antixss.antixssencoder.xmlattributeencode(v=vs.110(.aspx

至于问题的第二部分,一旦用户点击链接并转到新网站,你的网站上就不再是XSS了。允许用户添加任何URL仍然是危险的,即使它不是XSS漏洞。他们仍然可以链接到恶意网站、非法内容等。对于这些网站,你可能可以根据像谷歌提供的API网站声誉进行验证,但即使这样也不是防弹的。

回答您的问题-验证为系统。Uri不够。我解决问题的方法:

  1. 不允许任何引号字符或换行,也许您可能需要在查询字符串中接受引号,但目前我已经完全禁止了它们。如果我真的需要的话,我可能会改变主意
  2. 如果检测到任何实体(例如&amp;(,则不允许-拒绝url
  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执行。如果你想办法打破它,请告诉我。

最新更新