在我的网站(服务器端是c#(中,我让用户提交这样的链接:
<a href="$">link text</a>
他们输入的内容将仅保留在"href"属性中。我想通过"href"URL阻止XSS。
现在我检查它是否是一个有效的url,即c#对象URI。
我的问题是:
- 使用URI验证url是否足以阻止url xss
- 如果没有,我应该如何防止这种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不够。我解决问题的方法:
- 不允许任何引号字符或换行,也许您可能需要在查询字符串中接受引号,但目前我已经完全禁止了它们。如果我真的需要的话,我可能会改变主意
- 如果检测到任何实体(例如
&
(,则不允许-拒绝url - 如果字符串解析为Uri-请检查是否接受该方案
此时url可能仍然类似于javascript:alert(1)
-浏览器将接受:
,而WebUtility.HtmlDecode
由于缺少分号而失败,因此:
- 如果字符串的查询字符串部分前面有一个与号或冒号,则拒绝它
这是代码。
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执行。如果你想办法打破它,请告诉我。