mirror of
https://github.com/labring/laf.git
synced 2026-01-25 16:07:45 +00:00
3.6 KiB
3.6 KiB
Query 安全性考虑
规则为数组时
query: ["id", "status"]
query { $or: [...] } // 这种情况可绕过数组限制 @TODO
query { "id": 0, $or: [...] } // 这种情况可绕过数组限制 @TODO
如果不用数组,是否可限定指定字段
query: {
id: "$uid == query.id", // 此种情况下,如果客户端不传 id,则无效,需指定 required = true
status: {
required: true, // 此种情况下,可强制开启
condition: "$value==1"
}
}
结论: 如果不用数组,可通过 required 强制启用指定字段,但是仍然可通过 opeartor 指定。 数组需要单独处理,如果需要数组限定范围,可禁用 operator。 或者,递归遍历所有操作符内的字段,继续使用数组限定范围。 【已按此实现】
Query 规则场景
场景1: 用户数据简单查询
使用 contidion 验证器,严格验证,指定权限下限,可确定数据安全。
condition: "$uid==query.uid"
使用 query 字段约束, 非严格验证,用户若不传 uid 则不会触发该约束
query: {
uid: "$value == $uid"
}
使用 query 验证多条件
以下规则并不是「强制」的,只有用户传了某字段,才会触发该字段验证,如需强制验证需设置 required: true
- 其中,如果用户不传 uid 则不会触发 uid 的约束条件。
- 此 query 原定是可以限定用户只能用 uid 和 status 查询,但现在存在 operator 绕过的漏洞。【已修复:递归枚举所有输入查询字段,实现了字段的限定】
query: {
uid: "$value == $uid",
status: { in: ['saved', 'published'], required: true},
}
使用 query 验证是否可绕过?
query: {
created_by: {
required: true,
cond: "$value == $uid"
}
}
// 问:如果用户使用 $or: [ created_by: 1, status: true] 是否能绕过以上 cond 验证,从而以 status 为依据?
// 答:不能,query 验证器是以规则中配置的 fields 为依据判定和取值的,以上规则 query.created_by 表达式是取不到值的。
// 即,query 验证器中显式定义约束的字段,如果出现在操作符内,其值是 undefined,无法通过约束,所以约束有效。
场景2:存在逻辑删除数据的查询
若有专用字段存储删除状态时:
默认查询未删除的数据,此写法有要求数据有 del_flag 字段且值为 0 的 data 约束,如果该文档中没有此字段,则查询不到。 且该约束并不强制用户只能访问 未删除数据,只是缺省查询未删除。 如果用户指定 del_flag 为其它值,也是可以查询的。
query: {
del_flag: { default: 0 }
}
如果要禁止用户访问已逻辑删除的数据:
// 此方法禁止查询删除的数据,且前端必须传此字段
query: {
del_flag: {
condition: "$value != 1",
required: true
}
}
//
query: {
del_flag: { override: 1 }
}
逻辑删除更新
// 用户可删除或恢复自己创建的数据,如果用户不修改 del_flag,则不传即可,不影响修改其它字段
update: {
data: {
del_flag: {
cond: "$uid == query.created_by",
in: [0,1]
},
otherfield: {...}
}
}
// 禁止用户删除数据,即禁止修改 del_flag,但可修改其它字段
// 只要不配置 del_field 字段的约束即可,缺省禁止更新
update: {
data: {
otherfield: {...}
},
// 或者
data: ["otherfield1", "otherfield2"]
}
// 补充说明,若缺省 data 规则,则用户可修改所有字段
update: {
condition: true
}