对于字符串谓词,我应该采取什么样的安全措施?

What kind of security measures should I take for string predicate?

提问人:nikki 提问时间:8/14/2023 最后编辑:nikki 更新时间:8/14/2023 访问量:62

问:

我正在使用动态 linq 核心库将筛选器作为字符串获取。在这里,我向apiye发送一个字符串表达式。我正在使用 apide 动态 linq 核心库将我的字符串表达式解析为表达式。为了安全起见,我应该遵循什么路径?例如,我在下面创建了一个名为 ValidatePredicate 的方法。你对此有什么建议吗?

public class ValidatePredicate
{
    private static readonly Dictionary<Type, string[]> AllowedFieldsByType = new Dictionary<Type, string[]>
    {
        { typeof(OrganisationItem), new[] { nameof(OrganisationItem.ItemType), nameof(OrganisationItem.OrganisationItemName), nameof(OrganisationItem.isActive), nameof(OrganisationItem.UpdatedDate) } },
        // The fields that will be allowed for other entities should be written.        };
    public bool ValidatePredicateString<TEntity>(string predicate)
    {
        // entity'nin izin verilen alanlarini aliriz
        if (!AllowedFieldsByType.TryGetValue(typeof(TEntity), out var allowedFields))
        {
            return false; // returns false if it is a disallowed round          }

        // Allowed operators
        var allowedOperators = new[] { "==", "<=", ">=", "!=", "<", ">", ".Contains" };

        // 
        var parts = Regex.Split(predicate, @"&&|\|\|"); //'$$' to '||' in the predicate expression removes expressions

        foreach (var part in parts)
        {
            var trimmedPart = part.Trim(); //removes spaces in part
            bool validPart = false;

            //we control each operator.
            foreach (var op in allowedOperators)
            {
                if (op == ".Contains")
                {
                    var match = Regex.Match(trimmedPart, @"(\w+)\.Contains\(");
                    if (match.Success && allowedFields.Contains(match.Groups[1].Value)) //We get the name before the .contains statement.
                    {
                        validPart = true;
                        break;
                    }
                }
                else
                {
                    var segments = trimmedPart.Split(new[] { op }, StringSplitOptions.None);
                    var leftSegment = segments[0].Trim(); //The name to the left of the operator in the relevant expression is taken

                    if (allowedFields.Contains(leftSegment)) //check if the left side matches the allowed fields
                    {
                        validPart = true;
                        break;
                    }
                }
            }

            if (!validPart)
            {
                return false; // Returns false if a disallowed entity property name is found
            }
        }


        //check allowed operators
        //foreach (var op in allowedOperators)
        //{
        //  if (predicate.Contains(op))
        //  {
        //      continue;
        //  }

        //  return false; // Returns false if operator is not allowed
        //}

        //';' in expression returns false if
        if (predicate.Contains(";"))
        {
            return false;
        }

        return true;
    }

}
C# .NET 字符串 安全性 SQL 注入

评论

0赞 Zohar Peled 8/14/2023
正确解析字符串是相当困难的,即使你事先知道所有细节。我建议不要这样做。相反,您可能应该探索使用 Linq 表达式。这样可以更容易地避免字符串解析的许多潜在陷阱。
0赞 nikki 8/14/2023
我需要进行动态过滤和排序。这就是我使用字符串表达式的原因。如何在 linq 表达式中执行此操作?
0赞 Zohar Peled 8/14/2023
您使用的是某种 ORM,还是只是普通的旧 ADO.Net?
0赞 nikki 8/14/2023
我正在使用 ef core。我正在使用动态 linq 核心库进行动态筛选和排序。在客户端,我将谓词语句创建为字符串,并在 api 控制器中以 dto 形式提供它。其中谓词是我正在解析。predicate = DynamicExpressionParser.ParseLambda<OrganisationItem, bool>(ParsingConfig.Default, false,pageRequest.Predicate);
0赞 Your Common Sense 8/14/2023
这回答了你的问题吗?如何将用户提供的输入添加到 SQL 语句中?

答:

0赞 Guru Stron 8/14/2023 #1

这仍然允许在服务器上执行相当多的任意SQL(例如信息泄露,即如果您对客户恶意进行了预定义的过滤器,那么用户可以这样做)。where customerId = companyId and /*required dynamic filters*/ or 1 = 1

如果你想要受控的动态过滤并防止注入 - 创建相应的 DSL(例如类似于规范模式的东西),解析它并使用查询参数化重新构建它,这样就会被解析、验证只有允许的字段用于比较,并转换为 和 值并添加为参数。field1 = 1 or field2 = 'foo'field1 = @param1 or field2 = @param21'foo'

此外,您的代码绝不会强制执行声称的“// 如果找到不允许的属性,则返回 false”,它实际上只是检查所有项目是否存在,这同样适用于 .allowedFields// Return false if a disallowed operator is found

另请参阅:

评论

0赞 nikki 8/14/2023
我编写了当前版本的代码,这是一种有效的方法还是我应该寻找另一种解决方案?我将在我的列表页面上的人事管理系统中使用它。