375 字
2 分钟
记一次Google赏金VRP漏洞挖掘
记一次Google赏金VRP漏洞挖掘
资产是google/ground-platform: Ground hosted components: Web console, Cloud Functions, db config
在其中的Firebase Storage Security Rules文件中找到了鉴权的接口
service firebase.storage { match /b/{bucket}/o {
/** * Returns true iff the user is signed in. */ function isSignedIn() { return request.auth != null; }并且下方对于media共享文件存在
match /user-media/{allPaths=**} { allow create, read, write: if isSignedIn(); }上方发放auth是无限制的,也就是简单越权。
有所有权检查(request.auth.uid == owner),没有调查成员检查,也没有路径绑定检查。
也就是说,任何用户都可以访问此文件
简单附一个POC
/* eslint-disable no-console */const fs = require('fs');const path = require('path');
const rulesPath = process.argv[2] || 'D:\\CTF\\work\\ground-platform-master\\storage\\storage.rules';const outPath = process.argv[3] || 'C:\\Users\\zwz-o\\audit_tmp\\gp_poc\\offline_poc_result.json';
function mustMatch(input, regex, name) { if (!regex.test(input)) { throw new Error(`rules check failed: ${name}`); }}
function canAccess(requestAuth) { // Mirrors: function isSignedIn() { return request.auth != null; } return requestAuth !== null;}
function main() { const rules = fs.readFileSync(rulesPath, 'utf8');
// Prove exact vulnerable rule exists in target file. mustMatch( rules, /function\s+isSignedIn\s*\(\)\s*{[\s\S]*?request\.auth\s*!=\s*null[\s\S]*?}/m, 'isSignedIn uses request.auth != null' ); mustMatch( rules, /match\s*\/user-media\/\{allPaths=\*\*\}\s*{[\s\S]*?allow\s+create,\s*read,\s*write\s*:\s*if\s*isSignedIn\(\)\s*;[\s\S]*?}/m, 'user-media allows create/read/write for all signed-in users' );
const unauth = null;
const targetPath = 'user-media/survey-001/alice_private_note.jpg';
const result = { rulesPath, targetPath, checks: { unauth_create_allowed: canAccess(unauth), alice_create_allowed: canAccess(alice), bob_read_allowed: canAccess(bob), bob_write_allowed: canAccess(bob), }, exploit_chain: [ 'alice uploads file to user-media/**', 'bob reads alice file from same path (allowed)', 'bob overwrites/deletes alice file (allowed)', ], };
result.vulnerable = result.checks.unauth_create_allowed === false && result.checks.alice_create_allowed === true && result.checks.bob_read_allowed === true && result.checks.bob_write_allowed === true;
fs.mkdirSync(path.dirname(outPath), { recursive: true }); fs.writeFileSync(outPath, JSON.stringify(result, null, 2), 'utf8'); console.log(JSON.stringify(result, null, 2));
if (!result.vulnerable) { process.exit(2); }}
main();当然,这符合披露规则,评级达到了S2/P2。也是简单记录一下
部分信息可能已经过时





