漏洞说明:

跨站脚本攻击(Cross Site Scripting),为了不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS。恶意攻击者往Web页面里插入恶意Web脚本代码(html、javascript、css等),当用户浏览该页面时,嵌入其中的Web脚本代码会被执行,从而达到恶意攻击用户的特殊目的。

测试步骤

访问系统网站,点击基础报告库进行编辑,使用Burp抓包并重新构造数据包

重新访问,成功触发了XSS弹窗

解决方法:

将危险内容过滤去除,用HTML转义字符串(Escape Sequence)表达的则保留

添加脚本过滤类

    /// <summary>
/// Html 脚本过滤
/// </summary>
public class NHtmlFilter
{
protected static readonly RegexOptions REGEX_FLAGS_SI = RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Compiled; private static string P_COMMENTS = "<!--(.*?)-->";
private static Regex P_COMMENT = new Regex("^!--(.*)--$", REGEX_FLAGS_SI);
private static string P_TAGS = "<(.*?)>";
private static Regex P_END_TAG = new Regex("^/([a-z0-9]+)", REGEX_FLAGS_SI);
private static Regex P_START_TAG = new Regex("^([a-z0-9]+)(.*?)(/?)$", REGEX_FLAGS_SI);
private static Regex P_QUOTED_ATTRIBUTES = new Regex("([a-z0-9|(a-z0-9\\-a-z0-9)]+)=([\"'])(.*?)\\2", REGEX_FLAGS_SI);
private static Regex P_UNQUOTED_ATTRIBUTES = new Regex("([a-z0-9]+)(=)([^\"\\s']+)", REGEX_FLAGS_SI);
private static Regex P_PROTOCOL = new Regex("^([^:]+):", REGEX_FLAGS_SI);
private static Regex P_ENTITY = new Regex("&#(\\d+);?");
private static Regex P_ENTITY_UNICODE = new Regex("&#x([0-9a-f]+);?");
private static Regex P_ENCODE = new Regex("%([0-9a-f]{2});?");
private static Regex P_VALID_ENTITIES = new Regex("&([^&;]*)(?=(;|&|$))");
private static Regex P_VALID_QUOTES = new Regex("(>|^)([^<]+?)(<|$)", RegexOptions.Singleline | RegexOptions.Compiled);
private static string P_END_ARROW = "^>";
private static string P_BODY_TO_END = "<([^>]*?)(?=<|$)";
private static string P_XML_CONTENT = "(^|>)([^<]*?)(?=>)";
private static string P_STRAY_LEFT_ARROW = "<([^>]*?)(?=<|$)";
private static string P_STRAY_RIGHT_ARROW = "(^|>)([^<]*?)(?=>)";
private static string P_AMP = "&";
private static string P_QUOTE = "\"";
private static string P_LEFT_ARROW = "<";
private static string P_RIGHT_ARROW = ">";
private static string P_BOTH_ARROWS = "<>"; // @xxx could grow large... maybe use sesat's ReferenceMap
private static Dictionary<string, string> P_REMOVE_PAIR_BLANKS = new Dictionary<string, string>();
private static Dictionary<string, string> P_REMOVE_SELF_BLANKS = new Dictionary<string, string>();
/**
* flag determining whether to try to make tags when presented with "unbalanced"
* angle brackets (e.g. "<b text </b>" becomes "<b> text </b>"). If set to false,
* unbalanced angle brackets will be html escaped.
*/
protected static bool alwaysMakeTags = true; /**
* flag determing whether comments are allowed in input String.
*/
protected static bool stripComment = true; /// <summary>
/// 不允许
/// </summary>
private string[] vDisallowed { get; set; }
/// <summary>
/// 允许
/// </summary>
protected Dictionary<string, List<string>> vAllowed { get; set; } /** counts of open tags for each (allowable) html element **/
protected Dictionary<string, int> vTagCounts; /** html elements which must always be self-closing (e.g. "<img />") **/
protected string[] vSelfClosingTags; /** html elements which must always have separate opening and closing tags (e.g. "<b></b>") **/
protected string[] vNeedClosingTags; /** attributes which should be checked for valid protocols **/
protected string[] vProtocolAtts; /** allowed protocols **/
protected string[] vAllowedProtocols; /** tags which should be removed if they contain no content (e.g. "<b></b>" or "<b />") **/
protected string[] vRemoveBlanks; /** entities allowed within html markup **/
protected string[] vAllowedEntities; /// <summary>
/// 是否为调试
/// </summary>
protected bool vDebug; public NHtmlFilter() : this(false) { } public NHtmlFilter(bool debug)
{
//List<Item> vAllowed = new List<Item>();
vAllowed = new Dictionary<string, List<string>>();
#region 允许通过数组 vAllowed.Add("a", new List<string>() { "target", "href", "title", "class", "style" });
vAllowed.Add("addr", new List<string>() { "title", "class", "style" });
vAllowed.Add("address", new List<string>() { "class", "style" });
vAllowed.Add("area", new List<string>() { "shape", "coords", "href", "alt" });
vAllowed.Add("article", new List<string>() { });
vAllowed.Add("aside", new List<string>() { });
vAllowed.Add("audio", new List<string>() { "autoplay", "controls", "loop", "preload", "src", "class", "style" });
vAllowed.Add("b", new List<string>() { "class", "style" });
vAllowed.Add("bdi", new List<string>() { "dir" });
vAllowed.Add("bdo", new List<string>() { "dir" });
vAllowed.Add("big", new List<string>() { });
vAllowed.Add("blockquote", new List<string>() { "cite", "class", "style" });
vAllowed.Add("br", new List<string>() { });
vAllowed.Add("caption", new List<string>() { "class", "style" });
vAllowed.Add("center", new List<string>() { });
vAllowed.Add("cite", new List<string>() { });
vAllowed.Add("code", new List<string>() { "class", "style" });
vAllowed.Add("col", new List<string>() { "align", "valign", "span", "width", "class", "style" });
vAllowed.Add("colgroup", new List<string>() { "align", "valign", "span", "width", "class", "style" });
vAllowed.Add("dd", new List<string>() { "class", "style" });
vAllowed.Add("del", new List<string>() { "datetime" });
vAllowed.Add("details", new List<string>() { "open" });
vAllowed.Add("div", new List<string>() { "class", "style" });
vAllowed.Add("dl", new List<string>() { "class", "style" });
vAllowed.Add("dt", new List<string>() { "class", "style" });
vAllowed.Add("em", new List<string>() { "class", "style" });
vAllowed.Add("font", new List<string>() { "color", "size", "face" });
vAllowed.Add("footer", new List<string>() { });
vAllowed.Add("h1", new List<string>() { "class", "style" });
vAllowed.Add("h2", new List<string>() { "class", "style" });
vAllowed.Add("h3", new List<string>() { "class", "style" });
vAllowed.Add("h4", new List<string>() { "class", "style" });
vAllowed.Add("h5", new List<string>() { "class", "style" });
vAllowed.Add("h6", new List<string>() { "class", "style" });
vAllowed.Add("header", new List<string>() { });
vAllowed.Add("hr", new List<string>() { });
vAllowed.Add("i", new List<string>() { "class", "style" });
vAllowed.Add("img", new List<string>() { "src", "alt", "title", "style", "width", "height", "id", "_src", "loadingclass", "class", "data-latex", "data-id", "data-type", "data-s" });
vAllowed.Add("ins", new List<string>() { "datetime" });
vAllowed.Add("li", new List<string>() { "class", "style" });
vAllowed.Add("mark", new List<string>() { });
vAllowed.Add("nav", new List<string>() { });
vAllowed.Add("ol", new List<string>() { "class", "style" });
vAllowed.Add("p", new List<string>() { "class", "style" });
vAllowed.Add("pre", new List<string>() { "class", "style" });
vAllowed.Add("s", new List<string>() { });
vAllowed.Add("section", new List<string>() { });
vAllowed.Add("small", new List<string>() { });
vAllowed.Add("span", new List<string>() { "class", "style" });
vAllowed.Add("sub", new List<string>() { "class", "style" });
vAllowed.Add("sup", new List<string>() { "class", "style" });
vAllowed.Add("strong", new List<string>() { "class", "style" });
vAllowed.Add("table", new List<string>() { "width", "border", "align", "valign", "class", "style" });
vAllowed.Add("tbody", new List<string>() { "align", "valign", "class", "style" });
vAllowed.Add("td", new List<string>() { "width", "rowspan", "colspan", "align", "valign", "class", "style" });
vAllowed.Add("tfoot", new List<string>() { "align", "valign", "class", "style" });
vAllowed.Add("th", new List<string>() { "width", "rowspan", "colspan", "align", "valign", "class", "style" });
vAllowed.Add("thead", new List<string>() { "align", "valign", "class", "style" });
vAllowed.Add("tr", new List<string>() { "rowspan", "align", "valign", "class", "style" });
vAllowed.Add("tt", new List<string>() { });
vAllowed.Add("u", new List<string>() { });
vAllowed.Add("ul", new List<string>() { "class", "style" });
vAllowed.Add("video", new List<string>() { "autoplay", "controls", "loop", "preload", "src", "height", "width", "class", "style" });
#endregion vDebug = debug;
vTagCounts = new Dictionary<string, int>(); vSelfClosingTags = new string[] { "img" };
vNeedClosingTags = new string[] { "a", "b", "strong", "i", "em" };
vDisallowed = new string[] { "script" };
vAllowedProtocols = new string[] { "http", "mailto" }; // no ftp.
vProtocolAtts = new string[] { "src", "href" };
vRemoveBlanks = new string[] { "a", "b", "strong", "i", "em" };
vAllowedEntities = new string[] { "amp", "gt", "lt", "quot" };
stripComment = true;
alwaysMakeTags = true;
} protected void reset()
{
vTagCounts = new Dictionary<string, int>();
} protected void debug(string msg)
{
if (vDebug)
System.Diagnostics.Debug.WriteLine(msg);
} //---------------------------------------------------------------
// my versions of some PHP library functions public static string chr(int dec)
{
return "" + (char)dec;
} /// <summary>
/// 转换成实体字符
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
public static string htmlSpecialChars(string str)
{
str = str.Replace(P_QUOTE, "\""); str = str.Replace(P_LEFT_ARROW, "<");
str = str.Replace(P_RIGHT_ARROW, ">");
str = str.Replace("\n", "<br>");
return str;
} //--------------------------------------------------------------- /**
* given a user submitted input String, filter out any invalid or restricted
* html.
*
* @param input text (i.e. submitted by a user) than may contain html
* @return "clean" version of input, with only valid, whitelisted html elements allowed
*/
public string filter(string input)
{
reset();
string s = input; debug("************************************************");
debug(" INPUT: " + input); s = escapeComments(s);
debug(" escapeComments: " + s); s = balanceHTML(s);
debug(" balanceHTML: " + s); s = checkTags(s);
debug(" checkTags: " + s); s = processRemoveBlanks(s);
debug("processRemoveBlanks: " + s); s = validateEntities(s);
debug(" validateEntites: " + s); debug("************************************************\n\n");
return s;
} protected string escapeComments(string s)
{
return Regex.Replace(s, P_COMMENTS, new MatchEvaluator(ConverMatchComments), RegexOptions.Singleline);
} protected string regexReplace(string regex_pattern, string replacement, string s)
{
return Regex.Replace(s, regex_pattern, replacement);
} protected string balanceHTML(string s)
{
if (alwaysMakeTags)
{
//
// try and form html
//
s = regexReplace(P_END_ARROW, "", s);
s = regexReplace(P_BODY_TO_END, "<$1>", s);
s = regexReplace(P_XML_CONTENT, "$1<$2", s); }
else
{
//
// escape stray brackets
//
s = regexReplace(P_STRAY_LEFT_ARROW, "<$1", s);
s = regexReplace(P_STRAY_RIGHT_ARROW, "$1$2><", s); //
// the last regexp causes '<>' entities to appear
// (we need to do a lookahead assertion so that the last bracket can
// be used in the next pass of the regexp)
//
s = s.Replace(P_BOTH_ARROWS, "");
}
return s;
} protected string checkTags(string s)
{
//替换不允许标签
foreach (var item in vDisallowed)
{
s = Regex.Replace(s, string.Format(@"<{0}\b(.)*?>(.)+?</{0}>", item), "");
}
s = Regex.Replace(s, P_TAGS, new MatchEvaluator(ConverMatchTags), RegexOptions.Singleline); // these get tallied in processTag
// (remember to reset before subsequent calls to filter method)
foreach (string key in vTagCounts.Keys)
{
for (int ii = 0; ii < vTagCounts[key]; ii++)
{
s += "</" + key + ">";
}
} return s;
} protected string processRemoveBlanks(string s)
{
foreach (string tag in vRemoveBlanks)
{
s = regexReplace("<" + tag + "(\\s[^>]*)?></" + tag + ">", "", s);
s = regexReplace("<" + tag + "(\\s[^>]*)?/>", "", s);
}
return s;
} private string processTag(string s)
{
// ending tags
Match m = P_END_TAG.Match(s);
if (m.Success)
{
string name = m.Groups[1].Value.ToLower();
if (allowed(name))
{
if (!inArray(name, vSelfClosingTags))
{
if (vTagCounts.ContainsKey(name))
{
vTagCounts[name] = vTagCounts[name] - 1;
return "</" + name + ">";
}
}
}
} // starting tags
m = P_START_TAG.Match(s);
if (m.Success)
{
string name = m.Groups[1].Value.ToLower();
string body = m.Groups[2].Value;
string ending = m.Groups[3].Value; //debug( "in a starting tag, name='" + name + "'; body='" + body + "'; ending='" + ending + "'" );
if (allowed(name))
{
string params1 = ""; MatchCollection m2 = P_QUOTED_ATTRIBUTES.Matches(body);
MatchCollection m3 = P_UNQUOTED_ATTRIBUTES.Matches(body);
List<string> paramNames = new List<string>();
List<string> paramValues = new List<string>();
foreach (Match match in m2)
{
paramNames.Add(match.Groups[1].Value); //([a-z0-9]+)
paramValues.Add(match.Groups[3].Value); //(.*?)
}
foreach (Match match in m3)
{
paramNames.Add(match.Groups[1].Value); //([a-z0-9]+)
paramValues.Add(match.Groups[3].Value); //([^\"\\s']+)
} string paramName, paramValue;
for (int ii = 0; ii < paramNames.Count; ii++)
{
paramName = paramNames[ii].ToLower();
paramValue = paramValues[ii]; if (allowedAttribute(name, paramName))
{
if (inArray(paramName, vProtocolAtts))
{
paramValue = processParamProtocol(paramValue);
}
params1 += " " + paramName + "=\"" + paramValue + "\"";
}
} if (inArray(name, vSelfClosingTags))
{
ending = " /";
} if (inArray(name, vNeedClosingTags))
{
ending = "";
} if (ending == null || ending.Length < 1)
{
if (vTagCounts.ContainsKey(name))
{
vTagCounts[name] = vTagCounts[name] + 1;
}
else
{
vTagCounts.Add(name, 1);
}
}
else
{
ending = " /";
}
return "<" + name + params1 + ending + ">";
}
else
{
return "";
}
} // comments
m = P_COMMENT.Match(s);
if (!stripComment && m.Success)
{
return "<" + m.Value + ">";
} return "";
} private string processParamProtocol(string s)
{
s = decodeEntities(s);
Match m = P_PROTOCOL.Match(s);
if (m.Success)
{
string protocol = m.Groups[1].Value;
if (!inArray(protocol, vAllowedProtocols))
{
// bad protocol, turn into local anchor link instead
s = "#" + s.Substring(protocol.Length + 1, s.Length - protocol.Length - 1);
if (s.StartsWith("#//"))
{
s = "#" + s.Substring(3, s.Length - 3);
}
}
}
return s;
} private string decodeEntities(string s)
{ s = P_ENTITY.Replace(s, new MatchEvaluator(ConverMatchEntity)); s = P_ENTITY_UNICODE.Replace(s, new MatchEvaluator(ConverMatchEntityUnicode)); s = P_ENCODE.Replace(s, new MatchEvaluator(ConverMatchEntityUnicode)); s = validateEntities(s);
return s;
} private string validateEntities(string s)
{
s = P_VALID_ENTITIES.Replace(s, new MatchEvaluator(ConverMatchValidEntities));
s = P_VALID_QUOTES.Replace(s, new MatchEvaluator(ConverMatchValidQuotes));
return s;
} private static bool inArray(string s, string[] array)
{
foreach (string item in array)
{
if (item != null && item.Equals(s))
{
return true;
}
}
return false;
} private bool allowed(string name)
{
return (vAllowed.Count == 0 || vAllowed.ContainsKey(name)) && !inArray(name, vDisallowed);
} private bool allowedAttribute(string name, string paramName)
{
return allowed(name) && (vAllowed.Count == 0 || vAllowed[name].Contains(paramName));
} private string checkEntity(string preamble, string term)
{ return ";".Equals(term) && isValidEntity(preamble)
? '&' + preamble
: "&" + preamble;
}
private bool isValidEntity(string entity)
{
return inArray(entity, vAllowedEntities);
}
private static string ConverMatchComments(Match match)
{
string matchValue = "<!--" + htmlSpecialChars(match.Groups[1].Value) + "-->";
return matchValue;
} private string ConverMatchTags(Match match)
{
string matchValue = processTag(match.Groups[1].Value);
return matchValue;
} private string ConverMatchEntity(Match match)
{
string v = match.Groups[1].Value;
int decimal1 = int.Parse(v);
return chr(decimal1);
} private string ConverMatchEntityUnicode(Match match)
{
string v = match.Groups[1].Value;
int decimal1 = Convert.ToInt32("0x" + v, 16);
return chr(decimal1);
} private string ConverMatchValidEntities(Match match)
{
string one = match.Groups[1].Value; //([^&;]*)
string two = match.Groups[2].Value; //(?=(;|&|$))
return checkEntity(one, two);
}
private string ConverMatchValidQuotes(Match match)
{
string one = match.Groups[1].Value; //(>|^)
string two = match.Groups[2].Value; //([^<]+?)
string three = match.Groups[3].Value;//(<|$)
return one + regexReplace(P_QUOTE, "\"", two) + three;
} public bool isAlwaysMakeTags()
{
return alwaysMakeTags;
} public bool isStripComments()
{
return stripComment;
} class Item
{
public string name { get; set; }
public List<string> parameter { get; set; }
} }

源代码出自:https://www.cnblogs.com/OleRookie/p/5970167.html

在请求时对参数的内容进行过滤:

var nHtmlFilter = new NHtmlFilter(false);
surveyPayload.PayloadContent = nHtmlFilter.filter(surveyPayload.PayloadContent);

再次请求时,已将危险代码转成HTML转义字符串的形式了

[Asp.Net Core] 网站中的XSS跨站脚本攻击和防范的更多相关文章

  1. web应用程序安全攻防---sql注入和xss跨站脚本攻击

    kali视频学习请看 http://www.cnblogs.com/lidong20179210/p/8909569.html 博文主要内容包括两种常见的web攻击 sql注入 XSS跨站脚本攻击 代 ...

  2. Web攻防系列教程之跨站脚本攻击和防范技巧详解

    摘要:XSS跨站脚本攻击一直都被认为是客户端Web安全中最主流的攻击方式.因为Web环境的复杂性以及XSS跨站脚本攻击的多变性,使得该类型攻击很 难彻底解决.那么,XSS跨站脚本攻击具体攻击行为是什么 ...

  3. ASP.NET Core 网站在Docker中运行

    Docker作为新一代的虚拟化方式,未来肯定会得到广泛的应用,传统虚拟机的部署方式要保证开发环境.测试环境.UAT环境.生产环境的依赖一致性,需要大量的运维人力,使用Docker我们可以实现一次部署, ...

  4. ASP.NET Core 网站发布到Linux服务器

    长期以来,使用.NET开发的应用只能运行在Windows平台上面,而目前国内蓬勃发展的互联网公司由于成本的考虑,大量使用免费的Linux平台,这就使得.NET空有一身绝技但无法得到广大的施展空间,.N ...

  5. docker 初识之二(简单发布ASP.NET Core 网站)

    在发布ASP.NET Core网站以前,先介绍一下DaoCloud 一个免费的docker云容器服务平台.登陆官方网站,创建一台docker主机,这台主机有120分钟的使用时间,对于鄙人学习使用正好合 ...

  6. ASP.NET Core 网站发布到Linux服务器(转)

    出处;ASP.NET Core 网站发布到Linux服务器 长期以来,使用.NET开发的应用只能运行在Windows平台上面,而目前国内蓬勃发展的互联网公司由于成本的考虑,大量使用免费的Linux平台 ...

  7. ASP.NET Core MVC中构建Web API

    在ASP.NET CORE MVC中,Web API是其中一个功能子集,可以直接使用MVC的特性及路由等功能. 在成功构建 ASP.NET CORE MVC项目之后,选中解决方案,先填加一个API的文 ...

  8. ASP.NET Core WebAPI中的分析工具MiniProfiler

    介绍 作为一个开发人员,你知道如何分析自己开发的Api性能么? 在Visual Studio和Azure中, 我们可以使用Application Insight来监控项目.除此之外我们还可以使用一个免 ...

  9. asp.net core mvc中如何把二级域名绑定到特定的控制器上

    由于公司的工作安排,一直在研究其他技术,所以一直没时间更新博客,今天终于可以停下手头的事情,写一些新内容了. 应用场景:企业门户网站会根据内容不同,设置不同的板块,如新浪有体育,娱乐频道,等等.有的情 ...

  10. 在 ASP.NET Core 项目中使用 MediatR 实现中介者模式

    一.前言  最近有在看 DDD 的相关资料以及微软的 eShopOnContainers 这个项目中基于 DDD 的架构设计,在 Ordering 这个示例服务中,可以看到各层之间的代码调用与我们之前 ...

随机推荐

  1. web后端之过滤器

    1直接java搞定 2把@WebFilter()去掉,配置web.xml文件.

  2. pytorch卷积模块

    nn.Conv2d() 常用的参数有in_channels,out_channels,kernel_size,stride,padding; 除此之外还有参数dilation,groups,bias ...

  3. 3Des加密解密,java c#通用。

    1.需要实现对其他系统的单点登陆,我们实现的方法很简单,就是将当前系统的账号通过加密去获取 需要直接登陆上的系统的token,然后访问需直接登陆的系统就带着token,就相当于登陆了. 2.然后呢,我 ...

  4. 使用SecureCRT通过SSH连接远程Linux设备

    Ubuntu安装和配置ssh教程 https://blog.csdn.net/future_ai/article/details/81701744 以SecureCRT为例: 把电脑和设备连接在同一个 ...

  5. vue 项目页面刷新router-view控制

    vue项目开发过程中,需要在页面提交表单信息之后清空还原,即恢复页面初始状态,第一想法就是对当前页面刷新,重新加载. 想起location.reload()方式和this.$router.go(0)方 ...

  6. js 遍历对象属性

    function* objectEntries(obj) { let propKeys = Reflect.ownKeys(obj); for (let propKey of propKeys) { ...

  7. nhrhrhr

    每名学生按规定时间进行答辩,答辩总时间控制在12分钟,其中包括学生报告7分钟.提问以及回答问题5分钟. 1.答辩开始前由答辩委员会组长宣布答辩程序:学生的答辩顺序由教师确定,前一名学生答辩时,下一名答 ...

  8. CSS3之伸缩布局

    一 主轴方向 在伸缩布局中, 默认伸缩项是从左至右的排版的 主轴的排版的方向默认就是row, 默认就是从左至右 1.默认情况下主轴是水平方向的, 但是也可以修改为垂直方向.只要看到flex-direc ...

  9. filebeat+elasticsearch+kibana

    一.到elasticsearch官网下载 filebeat+elasticsearch+kibana http://www.elasticsearch.cn/ 二.安装filebeat tar -xz ...

  10. Linux基础——操作系统

    1. 操作系统(Operation System,OS) 操作系统作为接口的示意图 如果想在裸机上运行自己所编写的程序,就必须用机器语言书写程序如果计算机上安装了操作系统,就可以在操作系统上安装支持的 ...