漏洞说明:

跨站脚本攻击(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. 如何找到并使用makecert.exe

    如果安装visual studio 后,visual studio command  仍然无法识别 makecert.exe 命令. 则需要手动安装 Windows Software Developm ...

  2. 基础篇二:Linux常用系统命令

    Linux常用系统命令 pwd 打印当前目录 cd /目录 切换目录 cd ..   切换上一级目录 ls 显示目录 ls -a  包括隐藏文件 ls -l 以长格式列出 alias 当前系统所有别名 ...

  3. Mysql压缩版安装

    1.官网去下载压缩版本(https://dev.mysql.com/downloads/) 这里下载Community版(因为免费<-_->   它功能和Enterprise版功能差不多) ...

  4. 01.数据库基础、JDBC

    一.数据库 数据库:用于存储和管理数据的仓库. 数据库的特点 持久化储存数据,数据库就是一个文件系统. 方便储存和管理数据. 使用了统一的方式操作数据库--SQL. 配置 Mysql 服务启动 手动 ...

  5. go写文件常用方法

    注意:打开文件,一定记得关闭 file, err := os.OpenFile(name, flag, perm) defer file.Close() 一.打开文件|创建 1.os.OpenFile ...

  6. Python之常用数据类型详解

    tuple 元组 1 # 定义 2 temp = (2, ) # 规范定义,单个元素的元组 3 tem = 2, # 可行,但不规范定义 4 tep = () # 空元组 5 6 tp = (1, ' ...

  7. Ubuntu 中tab键不能自动补全解决方法

    1.打开文件vim /etc/bash.bashrc(root下操作)2.找到下面几行 3.去掉前面的#号 4.最后source /etc/bash.bashrc即可

  8. Python项目案例开发从入门到实战-1.5Python文件的使用

    Python对文件的操作通常按照三个步骤进行: un 使用open()函数打开(或建立)文件,并返回一个file对象. deux 使用file对象的读写方法对文件进行读写操作. trois 使用fil ...

  9. SpringBoot之基于idea搭建ssm(maven)

    此次目标为搭建一个简单的基于springboot的ssm(spring + springmvc + mybatis)的maven项目,使用的数据库为mysql. 最终项目目录结构 创建过程 1.项目创 ...

  10. Linux下apache日志(按日期存放)分析与状态查看方法

    转载网址: https://blog.csdn.net/weixin_42272246/article/details/125602258