2021年11月20日 星期六

[研究]Eval與一些HtmlEncode、HtmlSanitizer與Fortify SCA的XSS (Cross-Site Scripting)檢測

[研究]Eval與一些HtmlEncode、HtmlSanitizer與Fortify SCA的XSS (Cross-Site Scripting)檢測

2021-11-20
2024-02-26更新

環境:Visual Studio 2022 + ASP.NET + WebForm + Web Application + C# + SQL Server 2019 + SQL Server Management Studio (SSMS) 19

********************************************************************************

某些程式寫法

<a href="####" onclick="window.open('MyGroupForm.aspx?MyGroupID=<%# Eval("MyGroupID") %>', '', 'scrollbars=yes,resizable=yes,width=800,height=700,left=10,top=10');">編輯</a>

<a href="MyGroupDelete.aspx?MyGroupID=<%#Eval("MyGroupID")%>&p=<%=p%>" onclick="return confirm('確定要刪除嗎?');" >刪除</a>

<asp:Label ID="lb_MyGroupName" runat="server" Text='<%# Eval("MyGroupName") %>' />

Fortify SCA 檢查會出現 Cross-Site Scripting 問題。

Default.aspx


<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication4.Default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <asp:Label ID="Label0" runat="server"></asp:Label><br />
            <asp:Label ID="Label1" runat="server"></asp:Label><br />
            <asp:Label ID="Label2" runat="server"></asp:Label><br />
            <asp:Label ID="Label3" runat="server"></asp:Label><br />
            <asp:Label ID="Label4" runat="server"></asp:Label><br />
            <asp:Label ID="Label5" runat="server"></asp:Label><br />
            <asp:Label ID="Label6" runat="server"></asp:Label><br />
            <asp:Label ID="Label7" runat="server"></asp:Label><br />
            <asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />
        </div>
    </form>
</body>
</html>


Default.aspx.cs


using Ganss.XSS;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace WebApplication4
{
    public partial class Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected void Button1_Click(object sender, EventArgs e)
        {
            // NuGet 要安裝 AntiXSS 4.3.0
            string testString = "<b>Test</b><script>alert(1);</script>123'" + Request.QueryString["XSS"];
            Label0.Text = testString;
            Label1.Text = Microsoft.Security.Application.Encoder.HtmlEncode(testString); 
            Label2.Text = Server.HtmlEncode(testString);
            Label3.Text = System.Web.Security.AntiXss.AntiXssEncoder.HtmlEncode(testString, true);
            Label4.Text = System.Web.Security.AntiXss.AntiXssEncoder.HtmlEncode(testString, false);
            Label5.Text = HttpUtility.HtmlEncode(testString);
            Label6.Text = System.Net.WebUtility.HtmlEncode(testString);
            
            // NuGet 要安裝 HtmlSanitizer
            var sanitizer = new HtmlSanitizer();
            Label7.Text = sanitizer.Sanitize(testString);
        }
    }
}

(下圖) testString 有 XSS 問題,Label0 沒有處理就輸出,彈出了視窗,Fortify SCA也掃出有問題。




********************************************************************************

測試 含空白字串、日期資料

Default.aspx


<%@ Page Language="C#" AutoEventWireup="true" 
    CodeBehind="Default.aspx.cs" Inherits="WebApplication1.Default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" /><br />
        <asp:Literal ID="Literal1" runat="server"></asp:Literal><br />
        <asp:Literal ID="Literal2" runat="server"></asp:Literal><br />
        <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label><br />
        <asp:Label ID="Label2" runat="server" Text="Label"></asp:Label><br />
    </form>
</body>
</html>

注意,HtmlSanitizer 8.x 使用的是 using Ganss.Xss; 不是 using Ganss.XSS;  (大小寫差異)

Default.aspx.cs

using Ganss.Xss;
using System;
namespace WebApplication1
{
    public partial class Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected void Button1_Click(object sender, EventArgs e)
        {
            //string testString = "<b>Test</b><script>alert(1);</script>123'" + Request.QueryString["XSS"];
            string testString = "<b>Test</b>   " + DateTime.Now.ToString();

            // NuGet 要安裝 HtmlSanitizer
            var sanitizer = new HtmlSanitizer();
            Literal1.Text = testString;
            Literal1.Text = sanitizer.Sanitize(testString);
            Label1.Text = testString;
            Label2.Text = sanitizer.Sanitize(testString);
        }
    }
}

********************************************************************************

APS.NET WebForm 程式<asp:Label ID="lb_GroupName" runat="server" Text='<%# Eval("GroupName") %>' /> 如何用using Ganss.Xss; 和sanitizer.Sanitize 改寫,避免 XSS 問題?

ChatGPT

首先,請確保您已將 Ganss.Xss 庫新增至您的專案。 您可以透過 NuGet 套件管理器來安裝該程式庫。

Default.aspx

<asp:Label ID="lb_GroupName" runat="server" Text='<%# Sanitizer_Sanitize(Eval("GroupName").ToString()) %>' />

Default.aspx.cs

using Ganss.Xss;

protected string Sanitizer_Sanitize(string input)  
{ var sanitizer = new HtmlSanitizer(); return sanitizer.Sanitize(input); }

Common.cs

public static string MyAntiXssFilter(object inputObject)
{
    // 注意,MyAntiXssFilter 參數若為網址,& 會變成 &amp;  ,無法傳1個以上參數,改成

    string inputStr = "";
    if (inputObject != null)
    {
        inputStr = inputObject.ToString();
    }
    var sanitizer = new HtmlSanitizer();
    sanitizer.AllowedAttributes.Add("class");
    sanitizer.AllowedAttributes.Add("id");
    
    // 允許 <a href="mailto:"
    sanitizer.AllowedSchemes.Add("mailto"); 
    
    // 沒用; 若處理網址, & 會變成 &amp;
    //sanitizer.AllowedAttributes.Add("&"); 

    var sanitized = sanitizer.Sanitize(inputStr);
    sanitized = sanitized.Replace("&amp;", "&");
    return sanitized;
}

Default.aspx

<asp:Label ID="lb_GroupName" runat="server" Text='<%# Common.MyAntiXssFilter(Eval("GroupName").ToString()) %>' />

注意 Eval("GroupName") 改成 Common.MyAntiXssFilter(Eval("GroupName")),後面兩個括弧若少了一個,Compile 時不會有錯誤或警告,除非目前在 .aspx 網頁上,才會有一點警告
因為 MyAntiXssFilter 傳入是 object,傳出已經是 string,所以可以不用 ToString()。
********************************************************************************
2024-02-27
boxList.DataSource = En.Sys.Where(s => s.Id == id && s.Level == "A")
.Select(t => new { v1 = HttpUtility.HtmlEncode(t.Name), v2 = HttpUtility.HtmlEncode(t.Id) })
.ToList();
使用 HttpUtility.HtmlEncode 失敗


********************************************************************************

結論

  • HtmlEncode 把 HTML Tag 全部都編碼了,HtmlSanitizer 保留部分安全的 HTML Tag不做編碼,避免 XSS 問題。
  • 如果 testString 你確認沒有 HTML Tag,兩者都可用。
  • 如果 testString 不應該有 HTML Tag,用 HtmlEncode。(更好做法是把 HTML Tag移除,例如 HTML Agility Pack,https://www.nuget.org/packages/HtmlAgilityPack/
  • 如果 testString 有 HTML Tag,只是要處理有 XSS 問題的,用 HtmlSanitizer。

(完)

相關

探討 .NET HtmlEncode 解決方案之間的比較
https://www.thinkinmd.com/post/2020/07/25/discuss-dotnet-htmlencode-solutions-and-compare/#-htmlencode

【HTML】AntiXss.HtmlEncode vs AntiXss.GetSafeHtmlFragment
https://www.796t.com/post/MXliOWs=.html

沒有留言:

張貼留言