Fortify:跨站脚本:反映

时间:2019-05-28 06:28:13

标签: c# fortify

我正在开发一个Web服务解决方案,并且我有以下代码来构造我的Web服务调用:

// Body portion
string postData = JsonConvert.SerializeObject(Body));
byte[] byteArray = Encoding.UTF8.GetBytes(postData);

// Send the query
webRequest.ContentLength = byteArray.Length;
Stream dataStream = webRequest.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();

所以Body将是一个JSON对象,我打算对其进行序列化,以便可以将其表示为要发送到Web服务器的字符串。 但是在使用Fortify进行扫描时,它抱怨

行中的Cross-Site Scripting: Reflected的原因
dataStream.Write(byteArray, 0, byteArray.Length);

对于建议,目前尚不清楚解决方法

  

建议:

     

XSS的解决方案是确保验证在正确的位置进行并检查正确的属性。

     

由于XSS漏洞是在应用程序的输出中包含恶意数据时发生的,因此一种逻辑方法是在数据离开应用程序之前立即对其进行验证。但是,由于Web应用程序通常具有用于生成动态内容的复杂且复杂的代码,因此此方法易于遗漏错误(缺少验证)。减轻这种风险的有效方法是还对XSS执行输入验证。

     

Web应用程序必须验证其输入以防止其他漏洞(例如SQL注入),因此增强应用程序现有的输入验证机制以包括对XSS的检查通常相对容易。尽管有其价值,但XSS的输入验证并不能代替严格的输出验证。应用程序可以接受通过共享数据存储或其他受信任源的输入,并且该数据存储可以接受来自未执行适当输入验证的源的输入。因此,应用程序不能隐式依赖此数据或任何其他数据的安全性。这意味着防止XSS漏洞的最佳方法是验证所有进入应用程序并将应用程序留给用户的东西。

     

对XSS进行验证的最安全方法是创建安全字符白名单,允许其出现在HTTP内容中,并接受仅由批准集中的字符组成的输入。例如,有效的用户名可能仅包含字母数字字符,或者电话号码可能仅包含数字0-9。但是,此解决方案在Web应用程序中通常不可行,因为许多对浏览器具有特殊意义的字符在进行编码后仍应视为有效输入,例如必须接受用户HTML片段的Web设计公告板。

     

一种更灵活但安全性较低的方法被称为黑名单,它可以在使用输入之前有选择地拒绝或转义潜在危险的字符。为了形成这样的列表,您首先需要了解对Web浏览器具有特殊含义的字符集。尽管HTML标准定义了哪些字符具有特殊含义,但是许多Web浏览器会尝试纠正HTML中的常见错误,并且在某些情况下可能会将其他字符视为特殊字符,因此我们不鼓励使用黑名单来阻止XSS。卡内基梅隆大学软件工程学院的CERT(R)协调中心提供了以下有关各种情况下特殊字符的详细信息[1]:

     

在块级元素的内容中(在文本段落的中间):

     
      
  • “ <”之所以特别,是因为它引入了标签。

  •   
  • “&”之所以特别,是因为它引入了字符实体。

  •   
  • “>”之所以特殊,是因为某些浏览器将其视为特殊信息,并假定页面的作者打算包含一个开头“ <”,但错误地省略了它。

  •   
     

以下原则适用于属性值:

     
      
  • 在用双引号引起来的属性值中,双引号是特殊的,因为它们标记了属性值的结尾。

  •   
  • 在用单引号引起来的属性值中,单引号是特殊的,因为它们标记了属性值的结尾。

  •   
  • 在没有任何引号的属性值中,空格字符(例如空格和制表符)是特殊的。

  •   
  • “&”与某些属性一起使用时会很特殊,因为它会引入字符实体。

  •   
     

例如,在URL中,搜索引擎可能会在结果页面中提供一个链接,用户可以单击该链接来重新运行搜索。这可以通过对URL中的搜索查询进行编码来实现,其中引入了其他特殊字符:

     
      
  • 空格,制表符和换行符是特殊的,因为它们标记了URL的结尾。

  •   
  • “&”很特殊,因为它引入了字符实体或分隔了CGI参数。

  •   
  • URL中不允许使用非ASCII字符(即ISO-8859-1编码中大于128的所有字符),因此在这种情况下它们被认为是特殊的。

  •   
  • 在服务器端代码对使用HTTP转义序列编码的参数进行解码的任何地方,都必须从输入中过滤掉“%”符号。例如,如果诸如“%68%65%6C%6C%6F”之类的输入出现在相关网页上时变成“你好”,则必须过滤“%”。

  •   
     

在一个主体内:

     
      
  • 在可以将文本直接插入到预先存在的脚本标记中的情况下,应滤除分号,括号,花括号和换行符。
  •   
     

服务器端脚本:

     
      
  • 将输入中的任何感叹号(!)转换为输出中的双引号字符(“)的服务器端脚本,可能需要进行其他过滤。
  •   
     

其他可能性:

     
      
  • 如果攻击者使用UTF-7提交请求,则特殊字符“ <”显示为“ + ADw-”,并且可能绕过过滤。如果输出包含在未明确指定编码格式的页面中,则某些浏览器会尝试根据内容(在本例中为UTF-7)智能识别编码。
  •   
     

在确定了要对XSS攻击执行验证的应用程序中的正确点以及验证应考虑哪些特殊字符之后,下一个挑战是确定验证如何处理特殊字符。如果特殊字符不被认为是应用程序的有效输入,那么您可以拒绝任何包含特殊字符的输入为无效。在这种情况下的第二种选择是通过过滤删除特殊字符。但是,过滤具有更改过滤内容的任何视觉表示的副作用,并且在必须保留输入的完整性以供显示的情况下可能是不可接受的。

     

如果必须正确接受并显示包含特殊字符的输入,则验证必须对任何特殊字符进行编码以消除其重要性。正式HTML规范[2]的一部分提供了特殊字符的ISO 8859-1编码值的完整列表。

     

许多应用服务器试图通过提供负责设置某些特定HTTP响应内容的功能的实现来限制应用程序对跨站点脚本漏洞的暴露,这些特定HTTP响应内容对跨站点脚本攻击所必需的字符进行验证。不要依靠运行您的应用程序的服务器来确保它的安全。开发应用程序时,无法保证其在生命周期中将在哪些应用程序服务器上运行。随着标准和已知漏洞的发展,无法保证应用程序服务器也将保持同步。

我尝试放入HttpUtility.HtmlEncode,但这会弄乱字符串,因此不起作用。

有人知道如何解决吗?

1 个答案:

答案 0 :(得分:0)

能够通过使用 JSanitizer nuget package 方法满足 Fortify“跨站点脚本:反射”消息。包支持.NET Core 3.1。

    using JSanitizer;

    string serializedObj = JsonConvert.SerializeObject(myDynamic);
    documentResult.Content = serializedObj.SanitizeXmlValue();