什么可能使已注销的用户绕过 Firebase 默认存储规则并访问存储桶?
What might enable a logged-out user to bypass Firebase default Storage rules and access a Storage bucket?
我一直在尝试使用 Firebase 代码在我的 Windows 11 PC 和我的 Firebase 存储桶之间生成 upload/download 文件。一旦我让它工作,我意识到代码不包括登录。由于我使用的是默认的云存储规则,我本以为我的 upload/download 呼叫会被退回。
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'。(storage/unauthorized)”。
但问题仍然存在于我的开发 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>
听起来您好像只让一个用户登录过一次,就再也没有退出过。 Firebase 保留用户凭据并在重新加载页面时恢复它们,然后将其与对数据库的调用一起发送。这通常正是您想要的,但在这里它似乎妨碍了您。
如果您不想使用身份验证,您可以 sign the user out 通过一次性调用 signOut`:
import { getAuth, ... } from "firebase/auth";
const auth = getAuth();
signOut(auth).then(() => {
// Sign-out successful.
}).catch((error) => {
// An error happened.
});
我一直在尝试使用 Firebase 代码在我的 Windows 11 PC 和我的 Firebase 存储桶之间生成 upload/download 文件。一旦我让它工作,我意识到代码不包括登录。由于我使用的是默认的云存储规则,我本以为我的 upload/download 呼叫会被退回。
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'。(storage/unauthorized)”。
但问题仍然存在于我的开发 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>
听起来您好像只让一个用户登录过一次,就再也没有退出过。 Firebase 保留用户凭据并在重新加载页面时恢复它们,然后将其与对数据库的调用一起发送。这通常正是您想要的,但在这里它似乎妨碍了您。
如果您不想使用身份验证,您可以 sign the user out 通过一次性调用 signOut`:
import { getAuth, ... } from "firebase/auth";
const auth = getAuth();
signOut(auth).then(() => {
// Sign-out successful.
}).catch((error) => {
// An error happened.
});