提问人:nikki 提问时间:8/14/2023 最后编辑:nikki 更新时间:8/14/2023 访问量:62
对于字符串谓词,我应该采取什么样的安全措施?
What kind of security measures should I take for string predicate?
问:
我正在使用动态 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;
}
}
答:
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 = @param2
1
'foo'
此外,您的代码绝不会强制执行声称的“// 如果找到不允许的属性,则返回 false”,它实际上只是检查所有项目是否存在,这同样适用于 .allowedFields
// Return false if a disallowed operator is found
另请参阅:
评论
0赞
nikki
8/14/2023
我编写了当前版本的代码,这是一种有效的方法还是我应该寻找另一种解决方案?我将在我的列表页面上的人事管理系统中使用它。
评论
predicate = DynamicExpressionParser.ParseLambda<OrganisationItem, bool>(ParsingConfig.Default, false,pageRequest.Predicate);