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

Fortify SCA标记C#存储过程调用代码存在SQL注入问题咨询

SQL注入风险分析与修复方案

被Fortify标记的原因

  • 错误的输入清理方式:代码里用Sanitizer.GetSafeHtmlFragment()处理存储过程名,这是用来清理HTML标签的工具,对数据库对象名的安全校验完全没用。攻击者传个带恶意构造的存储过程名,这个方法根本拦不住。
  • 用户可控的存储过程名未做有效校验:虽然设置了CommandType.StoredProcedure,但如果存储过程名是用户能随便传的,攻击者可以构造类似合法存储过程名; DROP TABLE 敏感表--的字符串,照样能触发SQL注入(某些数据库环境下,即使指定存储过程类型,恶意名称也可能被解析成多条执行语句)。
  • Fortify规则触发逻辑:工具识别到用户输入直接用于生成SqlCommand的存储过程名,且使用了完全不匹配的清理手段,直接判定为SQL注入风险点。

修复方案

1. 用白名单机制校验存储过程名(最安全)

提前维护系统里所有合法的存储过程名列表,只有传入的名称在列表里才允许执行,否则直接报错。示例代码:

// 提前定义合法存储过程白名单
private static readonly HashSet<string> AllowedStoredProcs = new HashSet<string>
{
    "GetUserInfo",
    "FetchOrderRecords",
    // 补充其他系统用到的存储过程名
};

public DataSet GetTableByStoredProc(string strProcName, ArrayList alParams)
{
    // 先做白名单校验
    if (!AllowedStoredProcs.Contains(strProcName))
    {
        throw new ArgumentException("无效的存储过程名称");
    }

    DataSet dataSet = new DataSet();
    // 后续逻辑直接用strProcName,不需要HTML清理
    // ...原有代码逻辑
}

2. 移除无效的HTML清理代码

删掉string SPname1 = Sanitizer.GetSafeHtmlFragment(strProcName);这行,它不仅防不住注入,还可能把合法的存储过程名搞坏(比如带下划线、特殊后缀的名称)。

3. 优化资源释放逻辑

原有代码finally块里的objConn.Dispose()和objCmd.Dispose()是多余的,因为objCmd已经在using里自动释放,objConn也应该用using包裹,避免资源泄漏:

try
{
    using (SqlConnection objConn = new SqlConnection())
    {
        GetConnection(ref objConn); // 假设这个方法负责设置连接串并打开连接
        using (SqlCommand objCmd = new SqlCommand(strProcName, objConn))
        {
            objCmd.CommandType = CommandType.StoredProcedure;
            objCmd.CommandTimeout = 7200;

            if (alParams.Count > 0) // 注意:这里应该用Count而不是Capacity,Capacity是容量不是实际元素数
            {
                objCmd.Parameters.AddRange(AddDBParameter(ref alParams).ToArray());
            }

            using (SqlDataAdapter objDataAdapter = new SqlDataAdapter(objCmd))
            {
                objDataAdapter.Fill(SanitizeDataTable(dataSet));
                GetDBParameterValuesSpecific(objCmd, ref alParams);
            }
        }
    }
    return dataSet;
}
catch (Exception ex)
{
    throw ex;
}
// 不需要finally块,using会自动释放连接和命令对象

注意:原代码里用alParams.Capacity > 0判断是否有参数是错误的,Capacity是集合的容量,不是实际元素数量,应该改成alParams.Count > 0。

4. 替换ArrayList为强类型集合

ArrayList是非泛型集合,类型不安全,建议改用List<SqlParameter>或者自定义的参数实体类,减少参数处理中的潜在问题。

内容的提问来源于stack exchange,提问作者Jatin D

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 08:47:24