什么可能使已注销的用户能够绕过 Firebase 默认存储规则并访问存储桶?
Posted
技术标签:
【中文标题】什么可能使已注销的用户能够绕过 Firebase 默认存储规则并访问存储桶?【英文标题】:What might enable a logged-out user to bypass Firebase default Storage rules and access a Storage bucket? 【发布时间】:2021-12-31 07:49:27 【问题描述】:我一直在尝试使用 Firebase 代码在我的 Windows 11 电脑和我的 Firebase 存储桶之间上传/下载文件。一旦我得到它的工作,我意识到代码不包括登录。由于我使用的是默认 Cloud Storage 规则,因此我预计我的上传/下载调用会被退回。
rules_version = '2';
service firebase.storage
match /b/bucket/o
match /allPaths=**
allow read, write: if request.auth != null;
我清除了浏览器缓存并退出了 Google 和 Firebase 控制台,看看这是否解决了问题。它没有,也没有重新启动。但是当我发现代码在完全独立的机器上运行时出现了预期错误,我松了一口气。在这种情况下运行我的代码(现在部署到网络上)会产生预期的错误:
“糟糕 - 上传失败:错误 = FirebaseError:Firebase 存储:用户无权访问 'some-child'。(存储/未经授权)”。
但问题仍然存在于我的开发 PC 上,所以我的问题是,有什么可能将 Firebase 置于绕过云存储规则的状态,即使没有登录也允许存储桶访问?
这是我正在使用的 (firebase v9) 代码(它允许我将 PC 上的选定文件上传到存储桶中名为“some-child”的文件中,然后将其下载到名为 demo. txt 在我的下载文件夹中)。 :
import initializeApp from 'https://www.gstatic.com/firebasejs/9.4.0/firebase-app.js';
import getAuth, GoogleAuthProvider, signInWithPopup from 'https://www.gstatic.com/firebasejs/9.4.0/firebase-auth.js';
import getStorage, ref, uploadBytes, getDownloadURL from 'https://www.gstatic.com/firebasejs/9.4.0/firebase-storage.js';
const firebaseConfig =
...
;
const firebaseApp = initializeApp(firebaseConfig);
const provider = new GoogleAuthProvider();
const auth = getAuth();
const storage = getStorage();
const storageRef = ref(storage, 'some-child');
window.onload = function ()
document.getElementById('fileitem').onchange = function () uploadFile() ;
document.getElementById('downloadbutton').onclick = function () downloadFile() ;
function uploadFile()
var file = document.getElementById('fileitem').files[0];
uploadBytes(storageRef, file)
.then((snapshot) =>
alert('Successful upload');
)
.catch((error) =>
alert('Oops - upload failed : error = ' + error);
);
function downloadFile()
var file = getDownloadURL(ref(storage, 'some-child'))
.then((url) =>
// `url` is the download URL for 'some-child' and can be downloaded directly:
const xhr = new XMLHttpRequest();
xhr.responseType = 'text';
xhr.onload = (event) =>
const blob = xhr.response;
const a = document.getElementById('downloadanchor');
a.href = window.URL.createObjectURL(new Blob([blob], type: "text/plain" ));
a.download = "demo.txt";
a.click();
alert('Successful download');
;
xhr.open('GET', url);
xhr.send();
)
.catch((error) =>
alert('Oops - download failed : error = ' + error);
);
当然有一个 html 前端。其内容如下:
<input id="fileitem" type="file"><br></br>
<button id="downloadbutton">Download</button>
<a id="downloadanchor" href="" download></a>
【问题讨论】:
为了验证用户未登录,我建议您在尝试上传文件之前登录auth.currentUser.uid
。
有趣。在“问题项目”中,auth.currentUser.uid;报告为真实值。我为相同的源代码创建了另一个项目,这个项目说 auth.currentUser 为 null 并且出现了预期的错误。
【参考方案1】:
听起来您只登录了一个用户,但从未将其注销。 Firebase 保留用户凭据并在重新加载页面时恢复它们,然后将其与对数据库的调用一起发送。这通常正是您想要的,但在这里它似乎妨碍了您。
如果您不想使用身份验证,可以通过一次性调用 signOut 来sign the user out:
import getAuth, ... from "firebase/auth";
const auth = getAuth();
signOut(auth).then(() =>
// Sign-out successful.
).catch((error) =>
// An error happened.
);
【讨论】:
以上是关于什么可能使已注销的用户能够绕过 Firebase 默认存储规则并访问存储桶?的主要内容,如果未能解决你的问题,请参考以下文章
为啥从 firebase 控制台发送的通知能够绕过 android 后台任务限制? - 反应原生火力基地 -
用于 uid 列表的 Firebase 存储自定义元数据安全规则