mcpField
S
supabase-audit-rls

supabase-audit-rls

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

关于 supabase-audit-rls

supabase-audit-rls 是用于审查 Supabase Row Level Security(RLS)策略的安全审计技能,适合验证访问控制和排查常见绕过风险。它检查匿名及认证访问等场景,并要求逐步记录发现、测试结果和证据。

主要功能

  1. 01检查 RLS 是否启用及策略配置
  2. 02测试匿名与跨用户访问
  3. 03检查过滤器、关联查询和 RPC 绕过
  4. 04提供漏洞影响与 SQL 修复建议
  5. 05逐步保存审计上下文、日志和证据

适用场景

  1. 01审查 Supabase 项目表的 RLS
  2. 02验证用户只能访问获准的数据
  3. 03调查关联表或 RPC 的访问绕过
  4. 04生成可追溯的安全审计记录

安装

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

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

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

详细介绍

RLS 策略审计

🔴 严重:必须逐步更新文件

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

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

此要求不可跳过。未能逐步写入属于严重错误。

此技能用于测试行级安全性(RLS)策略中的常见漏洞和配置错误。

何时使用此技能

  • 在发现表中的数据暴露后
  • 验证 RLS 策略是否正确实施
  • 测试常见的 RLS 绕过技术
  • 作为全面安全审计的一部分

前提条件

  • 已列出表
  • 已获取 Anon 密钥
  • 最好也使用经过身份验证的用户令牌进行测试

了解 RLS

Supabase/PostgreSQL 中的行级安全性:

-- Enable RLS on a table
ALTER TABLE posts ENABLE ROW LEVEL SECURITY;

-- Create a policy
CREATE POLICY "Users see own posts"
  ON posts FOR SELECT
  USING (auth.uid() = author_id);

如果启用了 RLS,但没有任何策略,则所有访问都会被阻止。

常见 RLS 问题

问题说明严重性
未启用 RLS表没有 RLS 保护P0
缺少策略已启用 RLS,但没有 SELECT 策略可变
权限过于宽松策略允许过多访问P0-P1
缺少操作有 SELECT 策略,但没有 INSERT/UPDATE/DELETE 策略P1
USING 与 WITH CHECK允许读取,但写入规则不一致P1

测试向量

此技能会测试以下常见绕过场景:

1. 未经身份验证的访问
GET /rest/v1/users?select=*
# No Authorization header or with anon key only
2. 跨用户访问
# As user A, try to access user B's data
GET /rest/v1/orders?user_id=eq.[user-b-id]
Authorization: Bearer [user-a-token]
3. 绕过筛选条件
# Try to bypass filters with OR conditions
GET /rest/v1/posts?or=(published.eq.true,published.eq.false)
4. Join 漏洞利用
# Try to access data through related tables
GET /rest/v1/comments?select=*,posts(*)
5. RPC 绕过
# Check if RPC functions bypass RLS
POST /rest/v1/rpc/get_all_users

用法

基本 RLS 审计
Audit RLS policies on my Supabase project
指定表
Test RLS on the users table
使用经过身份验证的用户
Test RLS policies using this user token: eyJ...

输出格式

═══════════════════════════════════════════════════════════
 RLS POLICY AUDIT
═══════════════════════════════════════════════════════════

 Project: abc123def.supabase.co
 Tables Audited: 8

 ─────────────────────────────────────────────────────────
 RLS Status by Table
 ─────────────────────────────────────────────────────────

 1. users
    RLS Enabled: ❌ NO
    Status: 🔴 P0 - NO RLS PROTECTION

    All operations allowed without restriction!
    Test Results:
    ├── Anon SELECT: ✓ Returns all 1,247 rows
    ├── Anon INSERT: ✓ Succeeds (tested with rollback)
    ├── Anon UPDATE: ✓ Would succeed
    └── Anon DELETE: ✓ Would succeed

    Immediate Fix:
    ```sql
    ALTER TABLE users ENABLE ROW LEVEL SECURITY;

    CREATE POLICY "Users see own data"
      ON users FOR ALL
      USING (auth.uid() = id);
    ```

 2. posts
    RLS Enabled: ✅ YES
    Policies Found: 2
    Status: ✅ PROPERLY CONFIGURED

    Policies:
    ├── "Public sees published" (SELECT)
    │   └── USING: (published = true)
    └── "Authors manage own" (ALL)
        └── USING: (auth.uid() = author_id)

    Test Results:
    ├── Anon SELECT: Only published posts (correct)
    ├── Anon INSERT: ❌ Blocked (correct)
    ├── Cross-user access: ❌ Blocked (correct)
    └── Filter bypass: ❌ Blocked (correct)

 3. orders
    RLS Enabled: ✅ YES
    Policies Found: 1
    Status: 🟠 P1 - PARTIAL ISSUE

    Policies:
    └── "Users see own orders" (SELECT)
        └── USING: (auth.uid() = user_id)

    Issue Found:
    ├── No INSERT policy - users can't create orders via API
    ├── No UPDATE policy - users can't modify their orders
    └── This may be intentional (orders via Edge Functions)

    Recommendation: Document if intentional, or add policies:
    ```sql
    CREATE POLICY "Users insert own orders"
      ON orders FOR INSERT
      WITH CHECK (auth.uid() = user_id);
    ```

 4. comments
    RLS Enabled: ✅ YES
    Policies Found: 2
    Status: 🟠 P1 - BYPASS POSSIBLE

    Policies:
    ├── "Anyone can read" (SELECT)
    │   └── USING: (true)  ← Too permissive
    └── "Users comment on posts" (INSERT)
        └── WITH CHECK: (auth.uid() = user_id)

    Issue Found:
    └── SELECT policy allows reading all comments
        including user_id, enabling user correlation

    Recommendation:
    ```sql
    -- Use a view to hide user_id
    CREATE VIEW public.comments_public AS
      SELECT id, post_id, content, created_at FROM comments;
    ```

 5. settings
    RLS Enabled: ❌ NO
    Status: 🔴 P0 - NO RLS PROTECTION

    Contains sensitive configuration!
    Immediate action required.

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

 RLS Disabled: 2 tables (users, settings) ← CRITICAL
 RLS Enabled: 6 tables
   ├── Properly Configured: 3
   ├── Partial Issues: 2
   └── Major Issues: 1

 Bypass Tests:
 ├── Unauthenticated access: 2 tables vulnerable
 ├── Cross-user access: 0 tables vulnerable
 ├── Filter bypass: 0 tables vulnerable
 └── Join exploitation: 1 table allows data leakage

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

上下文输出

{
  "rls_audit": {
    "timestamp": "2025-01-31T10:45:00Z",
    "tables_audited": 8,
    "summary": {
      "rls_disabled": 2,
      "rls_enabled": 6,
      "properly_configured": 3,
      "partial_issues": 2,
      "major_issues": 1
    },
    "findings": [
      {
        "table": "users",
        "rls_enabled": false,
        "severity": "P0",
        "issue": "No RLS protection",
        "operations_exposed": ["SELECT", "INSERT", "UPDATE", "DELETE"]
      },
      {
        "table": "comments",
        "rls_enabled": true,
        "severity": "P1",
        "issue": "Overly permissive SELECT policy",
        "detail": "user_id exposed enabling correlation"
      }
    ]
  }
}

常见 RLS 模式

良好:用户拥有自己的数据
CREATE POLICY "Users own their data"
  ON user_data FOR ALL
  USING (auth.uid() = user_id)
  WITH CHECK (auth.uid() = user_id);
良好:公开读取,经过身份验证后写入
-- Anyone can read
CREATE POLICY "Public read" ON posts
  FOR SELECT USING (published = true);

-- Only authors can write
CREATE POLICY "Author write" ON posts
  FOR INSERT WITH CHECK (auth.uid() = author_id);

CREATE POLICY "Author update" ON posts
  FOR UPDATE USING (auth.uid() = author_id);
不良:使用 (true)
-- ❌ Too permissive
CREATE POLICY "Anyone" ON secrets
  FOR SELECT USING (true);
不良:忘记 WITH CHECK
-- ❌ Users can INSERT any user_id
CREATE POLICY "Insert" ON posts
  FOR INSERT WITH CHECK (true);  -- Should check user_id!

RLS 绕过说明

对于发现的每种绕过方式,此技能都会提供:

  1. 漏洞的说明
  2. 概念验证查询
  3. 影响评估
  4. 包含 SQL 代码的修复方案
  5. 文档链接

强制要求:逐步更新上下文文件

⚠️ 此技能必须在执行过程中逐步更新跟踪文件,而不是只在最后更新。

关键规则:随执行进度写入

不要等到最后才一次性写入。请按以下步骤操作:

  1. 测试每张表之前 → 将操作记录到 .sb-pentest-audit.log
  2. 发现每项 RLS 问题后 → 立即更新 .sb-pentest-context.json
  3. 每项测试完成后 → 将结果记录到 .sb-pentest-audit.log

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

必需操作(逐步执行)
  1. 使用结果更新 .sb-pentest-context.json:

    {
      "rls_audit": {
        "timestamp": "...",
        "tables_audited": 8,
        "summary": { "rls_disabled": 2, ... },
        "findings": [ ... ]
      }
    }
    
  2. 记录到 .sb-pentest-audit.log:

    [TIMESTAMP] [supabase-audit-rls] [START] Auditing RLS policies
    [TIMESTAMP] [supabase-audit-rls] [FINDING] P0: users table has no RLS
    [TIMESTAMP] [supabase-audit-rls] [CONTEXT_UPDATED] .sb-pentest-context.json updated
    
  3. 如果文件不存在,请先创建再写入。

未能更新上下文文件不可接受。

强制要求:收集证据

📁 证据目录: .sb-pentest-evidence/03-api-audit/rls-tests/

需要创建的证据文件
文件内容
rls-tests/[table]-anon.json匿名访问测试结果
rls-tests/[table]-auth.json经过身份验证的访问测试结果
rls-tests/cross-user-test.json跨用户访问尝试
证据格式(RLS 绕过)
{
  "evidence_id": "RLS-001",
  "timestamp": "2025-01-31T10:25:00Z",
  "category": "api-audit",
  "type": "rls_test",
  "severity": "P0",

  "table": "users",
  "rls_enabled": false,

  "tests": [
    {
      "test_name": "anon_select",
      "description": "Anonymous user SELECT access",
      "request": {
        "curl_command": "curl -s '$URL/rest/v1/users?select=*&limit=5' -H 'apikey: $ANON_KEY'"
      },
      "response": {
        "status": 200,
        "rows_returned": 5,
        "total_accessible": 1247
      },
      "result": "VULNERABLE",
      "impact": "All user data accessible without authentication"
    },
    {
      "test_name": "anon_insert",
      "description": "Anonymous user INSERT access",
      "request": {
        "curl_command": "curl -X POST '$URL/rest/v1/users' -H 'apikey: $ANON_KEY' -d '{...}'"
      },
      "response": {
        "status": 201
      },
      "result": "VULNERABLE",
      "impact": "Can create arbitrary user records"
    }
  ],

  "remediation_sql": "ALTER TABLE users ENABLE ROW LEVEL SECURITY;\nCREATE POLICY \"Users see own data\" ON users FOR SELECT USING (auth.uid() = id);"
}
添加到 curl-commands.sh
# === RLS BYPASS TESTS ===
# Test anon access to users table
curl -s "$SUPABASE_URL/rest/v1/users?select=*&limit=5" \
  -H "apikey: $ANON_KEY" -H "Authorization: Bearer $ANON_KEY"

# Test filter bypass
curl -s "$SUPABASE_URL/rest/v1/posts?or=(published.eq.true,published.eq.false)" \
  -H "apikey: $ANON_KEY"

相关技能

  • supabase-audit-tables-list — 先列出表
  • supabase-audit-tables-read — 查看实际数据暴露情况
  • supabase-audit-rpc — RPC 函数可能绕过 RLS
  • supabase-report — 完整安全报告

评论

支持 Markdown