Firestore认证用户文档写入规则:缺失校验的风险与改进咨询
问题分析与解决方案
你的现有Firestore规则确实存在安全漏洞,攻击者完全可以通过CLI、自定义脚本等非应用渠道利用合法用户凭证执行恶意操作,以下是具体说明:
具体攻击示例
写入不符合业务预期的文档结构
假设你的React应用仅允许用户写入displayName、email、avatarUrl三类字段,但现有规则未做任何结构校验。攻击者可通过Firebase CLI执行命令,写入恶意字段(比如用于提权的isAdmin: true):firebase firestore:set users/{目标用户UID} '{"isAdmin": true, "displayName": "Hacker"}' --auth {获取到的用户ID令牌}由于规则仅校验UID匹配,不会拦截这类违规字段写入。若后续业务逻辑信任
isAdmin字段,将直接导致权限绕过风险。无限制更新/删除用户文档
你的规则仅定义了allow create权限,未限制update和delete操作。攻击者可随意删除自己的用户文档,或修改任意字段:# 删除用户文档 firebase firestore:delete users/{目标用户UID} --auth {用户ID令牌} # 恶意修改字段 firebase firestore:update users/{目标用户UID} '{"displayName": "恶意名称", "customMaliciousField": "垃圾数据"}' --auth {用户ID令牌}写入超大恶意数据
未限制文档大小或字段长度时,攻击者可写入几MB级的垃圾数据,占用Firestore存储空间,直接导致成本飙升。
规则安全改进建议
1. 强制文档模式验证
明确规定users文档允许的字段、类型和必填项,拒绝不符合结构的请求:
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { function isAuthenticated() { return request.auth != null; } function isUserOwner(uid) { return isAuthenticated() && uid == request.auth.uid; } // 定义合法的用户文档结构 function isValidUserDocument() { return request.resource.data.keys().hasOnly(['displayName', 'email', 'avatarUrl', 'createdAt']) && request.resource.data.displayName is string && request.resource.data.email is string && request.resource.data.avatarUrl is string && request.resource.data.createdAt is timestamp; } // 限制字段内容长度 function isValidFieldLengths() { return request.resource.data.displayName.size() <= 50 && request.resource.data.avatarUrl.size() <= 200; } match /users/{uid} { // 创建时需满足:用户是文档所有者、结构合法、字段长度合规 allow create: if isUserOwner(uid) && isValidUserDocument() && isValidFieldLengths(); // 更新时仅允许修改指定字段,禁止修改敏感字段(如email、createdAt) allow update: if isUserOwner(uid) && request.resource.data.keys().hasOnly(['displayName', 'avatarUrl']) && request.resource.data.email == resource.data.email && request.resource.data.createdAt == resource.data.createdAt && isValidFieldLengths(); // 仅允许用户自身删除文档(若业务不需要删除可直接移除这条规则) allow delete: if isUserOwner(uid); } } }
2. 添加请求时间校验(防范重放攻击)
若业务对请求时效性有要求,可添加request.time校验,限制请求仅在当前时间前后5分钟内有效:
function isRequestRecent() { return request.time > now - duration.value(5, 'm') && request.time < now + duration.value(5, 'm'); } // 将校验加入create和update规则中 allow create: if isUserOwner(uid) && isValidUserDocument() && isValidFieldLengths() && isRequestRecent(); allow update: if isUserOwner(uid) && ... && isRequestRecent();
3. 限制文档大小
Firestore单文档最大支持1MB,你可根据业务需求进一步缩小限制:
function isValidDocumentSize() { return request.resource.size() < 10000; // 限制为10KB } // 加入到create和update规则中
内容的提问来源于stack exchange,提问作者user16560218
相关产品推荐
相关产品推荐

