使用AddInParameter仍被Checkmarx检测SQL注入:是否为代码问题?
问题分析与解决方案
这不是扫描误报,你的代码确实存在SQL注入风险,必须修改。
风险根源
你虽然对@s_row_insrt、@localdate等参数用了AddInParameter做了参数化,但处理account_group_id列表时犯了关键错误:
- 你把
accountGroupList转成CSV字符串后,直接用Replace把@i_account_group_id_list替换成这个字符串,这属于直接将不可信输入拼接进SQL语句,完全绕过了参数化保护。 - 如果
accountGroupList来自用户可控的输入(比如前端请求传递),攻击者可以构造类似1'); DROP TABLE YourTable;--的恶意ID,替换后会直接执行破坏数据库的SQL语句。
修复方案
必须对IN子句的列表也做参数化处理,推荐两种靠谱的方式:
- 使用表值参数(TVP)
- 先在SQL Server中创建用户定义表类型:
CREATE TYPE dbo.AccountGroupIdList AS TABLE (Id INT); - 代码中把
accountGroupList转成DataTable,作为参数传入:DataTable idTable = new DataTable(); idTable.Columns.Add("Id", typeof(int)); foreach (var item in accountGroupList) { idTable.Rows.Add(item.i_account_group_id); } // 构建SQL时用WHERE i_account_group_id IN (SELECT Id FROM @i_account_group_id_list) database.AddInParameter(dbCommand, "@i_account_group_id_list", SqlDbType.Structured, idTable);
- 先在SQL Server中创建用户定义表类型:
- 动态生成参数并添加
- 为每个ID生成独立参数(比如
@id0、@id1),然后添加到命令中:List<string> paramNames = new List<string>(); for (int i = 0; i < accountGroupList.Count; i++) { string paramName = $"@id{i}"; paramNames.Add(paramName); database.AddInParameter(dbCommand, paramName, DbType.Int32, accountGroupList[i].i_account_group_id); } // 替换IN子句为参数列表 sqlQuery = sqlQuery.Replace("@i_account_group_id_list", string.Join(", ", paramNames));
- 为每个ID生成独立参数(比如
额外提示
另外代码中替换testSchemaName为配置文件的SchemaName,虽然配置文件相对安全,但如果存在配置篡改风险,也建议避免直接字符串替换,可考虑用存储过程或者预定义的合法Schema列表做校验。
内容的提问来源于stack exchange,提问作者jpatel
相关产品推荐
相关产品推荐

