You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复Checkmarx报告中的“Reflected XSS All Clients”问题?

修复Checkmarx检测出的"Reflected XSS All Clients"高风险问题

问题背景

代码被Checkmarx检测出151个高风险的“Reflected XSS All Clients”问题,所有问题模式一致:以dtIn为源对象,最终流向SerializeObject输出。

代码示例(/DEBT/DEBT/Controllers/DEBT440Controller.cs):

176. public string GetHistory(DataTableIn dtIn)
....
184. model = JsonConvert.DeserializeObject<DEBTM440Model>(dtIn.findJson);
....
189. var data = _service.Use(t => t.GetHistory(model));

Checkmarx报告指出:_service.Use方法在DEBT047Controller.cs第175行通过GetPage将不可信数据嵌入输出,未经过滤编码,攻击者可篡改dtIn输入发起反射型跨站脚本(XSS)攻击。

尝试修改DataTableIn类,添加SanitizeAndEncode和EncodeJsonValue方法进行HTML编码处理,同时在控制器反序列化前调用该方法,但方案完全无效,需有效修复方法。

已尝试的无效代码

DataTableIn类修改代码:

using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Web;

namespace ABT.Entity
{
    public class DataTableIn
    {
        public int draw { get; set; }
        public int start { get; set; }
        public int length { get; set; }
        public int recordsFiltered { get; set; }
        public string findJson { get; set; }
        public DataTableSearchIn search { get; set; }
        public List<DataTableOrderIn> order { get; set; }

        public DataTableIn SanitizeAndEncode()
        {
            DataTableIn sanitizedData = new DataTableIn();
            // Sanitize and encode "findJson"
            JObject jsonObject = JObject.Parse(findJson);

            // Iterate through the fields in the JSON object
            foreach (var field in jsonObject)
            {
                // Encode the field's value
                string fieldName = field.Key;
                string fieldValue = field.Value.ToString();
                string encodedFieldValue = EncodeJsonValue(fieldValue);
                jsonObject[fieldName] = encodedFieldValue;
            }
            findJson = jsonObject.ToString();

            // Sanitize and encode search terms
            if (search != null)
            {
                search.value = HttpUtility.HtmlEncode(search.value);
            }
            if (order != null)
            {
                foreach (DataTableOrderIn order in order)
                {
                    order.column = Math.Min(order.column, 0);
                }
            }
            sanitizedData.findJson = findJson;
            sanitizedData.search = search;
            sanitizedData.order = order;
            sanitizedData.draw = Math.Max(draw, 0);
            sanitizedData.start = Math.Max(start, 0);
            sanitizedData.length = Math.Max(length, 0);
            sanitizedData.recordsFiltered = Math.Max(recordsFiltered, 0);

            return sanitizedData;
        }
        public string EncodeJsonValue(string value)
        {
            // Encode special characters in the value
            string encodedValue = value
                .Replace("\\", "\\\\")  // Escape backslashes
                .Replace("\"", "\\\"")  // Escape double quotes
                .Replace("\n", "\\n")   // Escape newlines
                .Replace("\r", "\\r")   // Escape carriage returns
                .Replace("\t", "\\t");  // Escape tabs

            // Apply HTML encoding to the encoded value
            string htmlEncodedValue = HttpUtility.HtmlEncode(encodedValue);

            return htmlEncodedValue;
        }

    }
    public class DataTableOrderIn
    {
        public int column { get; set; }
        public EnumOrderType dir { get; set; }
    }

    public class DataTableSearchIn
    {
        //search value
        public string value { get; set; }
        public bool regex { get; set; }
    }

    public enum EnumOrderType
    {
        Asc,
        Desc
    }
}

控制器修改代码:

....
189. public string GetHistory(DataTableIn dtIn)
....
209. dtIn = dtIn.SanitizeAndEncode();
....
214. model = JsonConvert.DeserializeObject<DEBTM575Model>(dtIn.findJson);

有效修复方案

1. 调整编码时机:输出阶段编码而非输入阶段

之前的核心错误是在输入反序列化前做HTML编码,导致业务逻辑处理的是编码后的数据,既可能破坏业务数据准确性,还可能引发双重编码问题。正确逻辑是:

  • 输入阶段仅做数据验证(校验字段类型、长度、合法范围),保留原始可信数据
  • 在最终序列化输出到客户端的阶段,对所有包含用户输入的字段做对应场景的编码

2. 针对DataTables场景的输出编码实现

假设服务最终将数据序列化为JSON返回给前端,需确保所有来自用户输入的字段在序列化前完成HTML编码:

var data = _service.Use(t => t.GetHistory(model));
// 遍历结果集,对所有用户输入来源的字段编码
foreach (var item in data.Items)
{
    item.UserInputField1 = HttpUtility.HtmlEncode(item.UserInputField1);
    item.UserInputField2 = HttpUtility.HtmlEncode(item.UserInputField2);
    // 其他涉及用户输入的字段同理
}
// 序列化输出
return JsonConvert.SerializeObject(data);

3. 利用序列化工具的安全配置自动编码

使用Newtonsoft.Json时,可配置全局自动HTML编码字符串字段,避免手动编码遗漏:

var jsonSettings = new JsonSerializerSettings
{
    StringEscapeHandling = StringEscapeHandling.EscapeHtml
};
return JsonConvert.SerializeObject(data, jsonSettings);

4. 增强输入验证(非编码,仅做安全校验)

输入阶段需严格校验数据合法性,过滤危险内容:

if (dtIn.search != null && !string.IsNullOrEmpty(dtIn.search.value))
{
    // 过滤HTML标签
    dtIn.search.value = Regex.Replace(dtIn.search.value, @"<[^>]+>", string.Empty);
    // 限制输入长度
    if (dtIn.search.value.Length > 200)
        dtIn.search.value = dtIn.search.value.Substring(0, 200);
}
// 校验findJson中的字段类型,比如数字字段必须为数字
JObject findObj = JObject.Parse(dtIn.findJson);
foreach (var prop in findObj.Properties())
{
    if (prop.Value.Type == JTokenType.String && prop.Name.Contains("Id"))
    {
        if (!int.TryParse(prop.Value.ToString(), out _))
            throw new ArgumentException("非法的ID格式");
    }
}

内容的提问来源于stack exchange,提问作者Wei Chung Shih

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 21:07:12