C# 如何在服务器端防止href属性的xss?
在我的网站(服务器端是c#),我允许用户提交如下链接:C# 如何在服务器端防止href属性的xss?,c#,asp.net,.net,security,xss,C#,Asp.net,.net,Security,Xss,在我的网站(服务器端是c#),我允许用户提交如下链接: <a href="$">link text</a> 他们输入的任何内容都将仅保留在“href”属性中。我想通过“href”URL阻止XSS 现在我检查它是否是一个有效的url,即c#对象URI 我的问题是: 使用URI验证url是否足以防止url xss 如果没有,我应该如何防止这种xss 例如,如何防止有效url的XSS钓鱼攻击,如下所示: “验证为URI是一个良好的开端。之后,验证是否为白名单选项,例如ht
<a href="$">link text</a>
他们输入的任何内容都将仅保留在“href”属性中。我想通过“href”URL阻止XSS
现在我检查它是否是一个有效的url,即c#对象URI
我的问题是:
“验证为URI是一个良好的开端。之后,验证是否为白名单选项,例如
http
/https
。之后,请确保在输出之前对其进行编码(请参见OWASP链接)。基本上,您完全可以像对待任何html属性编码一样进行操作,但您还需要注意恶意方案
注意事项:javascript:alert(1)代码>(验证方案),https://example.com?xss=“onclick=alert(1);//
(转义输出)
见:
至于问题的第二部分,一旦用户单击链接并转到新站点,它就不再是您站点上的XSS。允许用户添加任何URL仍然可能是危险的,即使它不是XSS漏洞。他们仍然可以链接到恶意站点、非法内容等。对于这些,您可能可以针对这不是绝对可靠的。要回答您的问题,作为System.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;
}
私有静态只读字符串[]acceptedSchemes={Uri.UriSchemeHttp,Uri.UriSchemeHttps,Uri.urischemeEmailTo,Uri.UriSchemeFile};
私有静态只读字符[]禁止HREFChars={'''','\'''''',(char)10,(char)13};
私有静态只读字符[]禁止BeforeQueryString={':','&','\\'};//冒号可能看起来很奇怪,但是如果我们处理冒号,我们期望它能解析为URI
///
///如果指定的字符串被视为XSS安全href属性值,则返回true。
///
公共静态bool IsSafeHref(字符串输入)
{
if(input.Any(c=>forbiddenHrefChars.Contains(c)))
返回false;
//不接受任何实体
string href=WebUtility.HtmlDecode(输入);
如果(href!=输入)
返回false;
//检查方案是否有效(如果指定)
bool-isUri=Uri.TryCreate(输入,UriKind.Absolute,out-Uri);
if(uri!=null)
返回acceptedSchemes.Contains(uri.Scheme???);
int qsIdx=href.IndexOf('?');
字符串partBeforeQueryString=qsIdx<0?href:href.Substring(0,qsIdx);
if(禁止BeforeQueryString.Any(c=>partBeforeQueryString.Contains(c)))
返回false;
返回true;
}
我认为它不应该允许任何方式将URL的上下文切换为javascript执行。如果你想办法打破它,请告诉我