mcpField
S
supabase-audit-buckets-read

supabase-audit-buckets-read

github.com/yoanbernabeu安全71481 次安装39 周前更新
代码仓库

关于 supabase-audit-buckets-read

用于 Supabase 安全审计的技能,通过测试存储桶中的文件访问来验证权限。它会检查文件列表、元数据、样本下载和公开 URL,并逐步记录发现与证据。

主要功能

  1. 01测试文件列表和元数据访问
  2. 02下载样本并检查内容类型
  3. 03检查公开 URL 可访问性
  4. 04识别敏感文件与内容
  5. 05逐步记录发现和证据

适用场景

  1. 01验证存储桶的 RLS 权限
  2. 02查找公开暴露的敏感文件
  3. 03记录可访问文件及审计证据

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/yoanbernabeu/supabase-pentest-skills --skill supabase-audit-buckets-read

安装后在 Claude Code 中输入/supabase-audit-buckets-read确认已加载。

详细介绍

存储桶文件访问测试

🔴 严重:必须渐进式更新文件

你必须随进度写入上下文文件,而不是只在最后写入。

  • 每测试完一个存储桶后,立即写入 .sb-pentest-context.json
  • 每次文件访问测试之前和之后,都要记录到 .sb-pentest-audit.log
  • 不要等到技能执行完毕才更新文件
  • 如果技能崩溃或中断,之前的所有发现都必须已经保存

此要求不可协商。不渐进式写入属于严重错误。

此技能会测试存储桶中的实际文件访问情况,以验证权限。

何时使用此技能

  • 列出存储桶后,用于验证实际访问权限
  • 测试存储 RLS 策略的有效性
  • 检查是否暴露了敏感文件
  • 记录哪些文件可以访问

前提条件

  • 已列出存储桶(如有需要会自动调用)
  • 有可用的 anon key

工作原理

此技能会尝试:

  1. 列出文件:列出每个存储桶中的文件
  2. 读取文件元数据
  3. 下载示例文件(用于验证内容类型)
  4. 检查公共 URL 的访问情况

重要: 此操作为只读操作,不会修改或删除任何文件。

测试方法

存储桶类型执行的测试
公共直接 URL 访问、列表、元数据
私有使用 anon key 通过 API 列表查询、验证已认证访问

用法

基本读取测试
Test read access on storage buckets
指定存储桶
Test file access on the documents bucket
仅列出文件(不下载)
List accessible files without downloading content

输出格式

═══════════════════════════════════════════════════════════
 BUCKET FILE ACCESS TEST
═══════════════════════════════════════════════════════════

 Project: abc123def.supabase.co
 Buckets Tested: 5

 ─────────────────────────────────────────────────────────
 avatars (Public Bucket)
 ─────────────────────────────────────────────────────────

 Status: ✅ Expected Access
 Files Found: 1,247

 Sample Files:
 ├── user-550e8400.jpg (45KB) - Public URL works
 ├── user-6ba7b810.png (32KB) - Public URL works
 └── default.png (12KB) - Public URL works

 Access Methods:
 ├── Public URL: ✅ Accessible
 ├── API Listing: ✅ Works
 └── Metadata: ✅ Visible

 Assessment: Expected behavior for avatar storage.

 ─────────────────────────────────────────────────────────
 documents (Private Bucket)
 ─────────────────────────────────────────────────────────

 Status: ✅ PROPERLY PROTECTED
 Files Found: 0 (via anon key)

 Access Methods:
 ├── Public URL: ❌ 403 Forbidden (correct)
 ├── API Listing: ❌ Empty result (RLS working)
 └── Metadata: ❌ Not accessible (correct)

 Assessment: RLS policies working correctly.

 ─────────────────────────────────────────────────────────
 uploads (Public Bucket)
 ─────────────────────────────────────────────────────────

 Status: 🟠 P1 - SENSITIVE FILES EXPOSED
 Files Found: 3,891

 Sensitive Files Detected:
 ├── 🔴 invoice-2025-001.pdf - Contains financial data
 ├── 🔴 contract-signed.pdf - Legal document
 ├── 🔴 id-verification.jpg - Personal ID photo!
 ├── ⚠️ database-export.csv - Possible data export
 └── ⚠️ config.json - Configuration file

 File Types Distribution:
 ├── PDF: 1,234 (31%)
 ├── Images: 2,100 (54%)
 ├── Documents: 450 (12%)
 └── Other: 107 (3%)

 Assessment: Bucket contains sensitive files that should not be public!

 ─────────────────────────────────────────────────────────
 backups (Public - CRITICAL)
 ─────────────────────────────────────────────────────────

 Status: 🔴 P0 - CRITICAL DATA EXPOSURE
 Files Found: 45

 Exposed Files:
 ├── 🔴 db-backup-2025-01-30.sql (125MB) - DATABASE BACKUP!
 ├── 🔴 db-backup-2025-01-29.sql (124MB) - DATABASE BACKUP!
 ├── 🔴 users-export.csv (2.3MB) - USER DATA EXPORT!
 ├── 🔴 secrets.env (1KB) - ENVIRONMENT SECRETS!
 └── 🔴 .env.production (1KB) - PRODUCTION SECRETS!

 Sample Content (secrets.env):
 ┌─────────────────────────────────────────────────────────┐
 │ STRIPE_SECRET_KEY=sk_live_xxxxxxxxxxxx                 │
 │ DATABASE_URL=postgresql://postgres:xxx@...             │
 │ JWT_SECRET=super-secret-jwt-key                        │
 └─────────────────────────────────────────────────────────┘

 ⚠️ IMMEDIATE ACTION REQUIRED:
 1. Make bucket private NOW
 2. Rotate ALL exposed secrets
 3. Delete backup files from public access
 4. Audit for unauthorized access in logs

 ─────────────────────────────────────────────────────────
 temp (Private Bucket)
 ─────────────────────────────────────────────────────────

 Status: ✅ PROPERLY PROTECTED
 Files Found: 0 (via anon key)
 Assessment: Access correctly restricted.

 ─────────────────────────────────────────────────────────
 Summary
 ─────────────────────────────────────────────────────────

 P0 Critical: 1 bucket (backups - DB dumps & secrets exposed)
 P1 High: 1 bucket (uploads - sensitive documents in public bucket)
 Protected: 2 buckets (documents, temp)
 Expected: 1 bucket (avatars)

 Total Files Accessible: 5,183
 Sensitive Files Exposed: 52
 Secret Files Exposed: 3

 Immediate Actions:
 1. 🔴 DELETE or make private 'backups' bucket
 2. 🔴 Rotate Stripe key, DB password, JWT secret
 3. 🟠 Move sensitive files from 'uploads' to private bucket
 4. Review all 52 sensitive files for exposure impact

═══════════════════════════════════════════════════════════

敏感文件检测

此技能通过以下方式识别敏感文件:

文件名模式
模式风险类型
*.sql, backup*P0数据库转储
.env*, *secrets*P0密钥文件
*password*, *credential*P0凭据
*invoice*, *payment*P1财务
*contract*, *agreement*P1法律
*id*, *passport*, *license*P1身份信息
*export*, *dump*P1数据导出
内容检测

对于可访问的文件,此技能会抽样检查内容中的:

  • API 密钥(例如 sk_live_、pk_test_ 等模式)
  • 数据库凭据
  • JWT 密钥
  • 个人信息模式

上下文输出

{
  "storage_access": {
    "timestamp": "2025-01-31T11:30:00Z",
    "buckets_tested": 5,
    "findings": [
      {
        "bucket": "backups",
        "severity": "P0",
        "public": true,
        "files_exposed": 45,
        "sensitive_files": [
          {
            "path": "db-backup-2025-01-30.sql",
            "size": 131072000,
            "type": "database_backup",
            "risk": "Full database accessible"
          },
          {
            "path": "secrets.env",
            "size": 1024,
            "type": "secrets",
            "exposed_secrets": ["STRIPE_SECRET_KEY", "DATABASE_URL", "JWT_SECRET"]
          }
        ]
      }
    ],
    "summary": {
      "total_files_accessible": 5183,
      "sensitive_files": 52,
      "secret_files": 3
    }
  }
}

修复步骤

针对暴露的密钥
# 1. Rotate Stripe keys
# Stripe Dashboard → Developers → API Keys → Roll Keys

# 2. Change database password
# Supabase Dashboard → Settings → Database → Reset Password

# 3. Regenerate JWT secret
# Supabase Dashboard → Settings → API → Regenerate JWT Secret

# 4. Update application environment variables
# Redeploy with new secrets
修复公共存储桶
-- Make bucket private
UPDATE storage.buckets
SET public = false
WHERE name = 'backups';

-- Delete sensitive files or move to secure location
DELETE FROM storage.objects
WHERE bucket_id = 'backups';
针对上传存储桶
-- Add RLS to restrict access
CREATE POLICY "Users access own uploads"
  ON storage.objects FOR ALL
  USING (
    bucket_id = 'uploads'
    AND auth.uid()::text = (storage.foldername(name))[1]
  );

常见问题

❌ 问题: 无法列出私有存储桶中的文件 ✅ 解决方案: 这是正确的行为,说明 RLS 正在生效。

❌ 问题: 要扫描的文件数量过多 ✅ 解决方案: 对大型存储桶使用抽样模式。

❌ 问题: 文件下载失败 ✅ 解决方案: 可能是 RLS 限制或网络问题。

强制要求:渐进式更新上下文文件

⚠️ 此技能必须在执行过程中渐进式更新跟踪文件,不能只在最后更新。

关键规则:随进度写入

不要把所有写入操作都留到最后。请按以下步骤操作:

  1. 测试每个存储桶之前 → 将操作记录到 .sb-pentest-audit.log
  2. 发现每个敏感文件之后 → 立即更新 .sb-pentest-context.json
  3. 完成每个存储桶之后 → 记录摘要

这样可以确保即使技能被中断、崩溃或超时,到那时为止的所有发现都能得到保留。

必须执行的操作(渐进式)
  1. 更新 .sb-pentest-context.json,写入测试结果:

    {
      "storage_access": {
        "timestamp": "...",
        "buckets_tested": 5,
        "findings": [ ... ],
        "summary": { "total_files_accessible": 5183, ... }
      }
    }
    
  2. 记录到 .sb-pentest-audit.log:

    [TIMESTAMP] [supabase-audit-buckets-read] [START] Testing bucket file access
    [TIMESTAMP] [supabase-audit-buckets-read] [FINDING] P0: backups bucket has exposed secrets
    [TIMESTAMP] [supabase-audit-buckets-read] [CONTEXT_UPDATED] .sb-pentest-context.json updated
    
  3. 如果文件不存在,请先创建文件再写入。

不更新上下文文件是不可接受的。

强制要求:收集证据

📁 证据目录: .sb-pentest-evidence/04-storage-audit/buckets/

需要创建的证据文件
文件内容
buckets/[name]/file-list.json在存储桶中找到的文件
buckets/[name]/sensitive-files.json检测到的敏感文件
buckets/[name]/sample-contents/已编辑的内容样本
暴露敏感文件时的证据格式
{
  "evidence_id": "STG-READ-001",
  "timestamp": "2025-01-31T10:40:00Z",
  "category": "storage-audit",
  "type": "file_access",
  "severity": "P0",

  "bucket": "backups",
  "public": true,

  "files_found": 45,
  "sensitive_files": [
    {
      "path": "db-backup-2025-01-30.sql",
      "size": 131072000,
      "type": "database_backup",
      "public_url": "https://abc123def.supabase.co/storage/v1/object/public/backups/db-backup-2025-01-30.sql",
      "curl_command": "curl -o backup.sql 'https://abc123def.supabase.co/storage/v1/object/public/backups/db-backup-2025-01-30.sql'"
    },
    {
      "path": "secrets.env",
      "size": 1024,
      "type": "secrets_file",
      "content_sample": "STRIPE_SECRET_KEY=sk_live_[REDACTED]\nDATABASE_URL=postgresql://[REDACTED]",
      "exposed_secrets": ["STRIPE_SECRET_KEY", "DATABASE_URL", "JWT_SECRET"]
    }
  ],

  "impact": {
    "data_breach": true,
    "secrets_exposed": true,
    "affected_records": "All database records",
    "credentials_to_rotate": ["Stripe API key", "Database password", "JWT secret"]
  }
}
添加到 curl-commands.sh
# === STORAGE FILE ACCESS TESTS ===
# List files in backups bucket
curl -s "$SUPABASE_URL/storage/v1/object/list/backups" \
  -H "apikey: $ANON_KEY"

# Direct access to public file (P0 if accessible)
curl -I "https://abc123def.supabase.co/storage/v1/object/public/backups/secrets.env"

# Download exposed backup (for evidence - be careful with size)
# curl -o evidence-backup-sample.sql "https://abc123def.supabase.co/storage/v1/object/public/backups/db-backup-2025-01-30.sql" | head -1000

相关技能

  • supabase-audit-buckets-list — 先列出存储桶
  • supabase-audit-buckets-public — 聚焦公开访问问题
  • supabase-report — 生成完整报告

评论

支持 Markdown