名称: supabase-audit-tables-list 描述: 通过 Supabase PostgREST API 列出所有暴露的表以识别攻击面。
列出暴露的表
🔴 关键: 需要渐进式文件更新
您必须逐步写入上下文文件,而不仅仅是在结束时。
- 每次发现后立即写入
.sb-pentest-context.json- 每次操作前后记录到
.sb-pentest-audit.log- 不要等待技能完成再更新文件
- 如果技能崩溃或中断,所有先前发现必须已保存
这不是可选的。未逐步写入是关键错误。
此技能发现通过 Supabase PostgREST API 暴露的所有数据库表。
何时使用此技能
- 理解 API 攻击面
- 测试 RLS 策略前
- 清点暴露的数据模型
- 作为全面安全审计的一部分
先决条件
- 提取的 Supabase URL(如果需要,自动调用)
- 提取的 Anon 密钥(如果需要,自动调用)
工作原理
Supabase 通过 PostgREST 暴露表:
https://[项目引用].supabase.co/rest/v1/
技能使用 OpenAPI 模式端点枚举表:
https://[项目引用].supabase.co/rest/v1/?apikey=[anon-key]
暴露内容
默认情况下,Supabase 暴露 public 模式中的表。表在以下情况下暴露:
- 它们存在于暴露的模式中(默认:
public) - 未执行显式
REVOKE - PostgREST 可以看见它们
用法
基本表列表
列出我的 Supabase 项目上暴露的表
带模式信息
列出所有暴露的表及其列详细信息
输出格式
═══════════════════════════════════════════════════════════
暴露的表
═══════════════════════════════════════════════════════════
项目: abc123def.supabase.co
模式: public
发现表数: 8
─────────────────────────────────────────────────────────
表清点
─────────────────────────────────────────────────────────
1. users
├── 列: id, email, name, avatar_url, created_at
├── 主键: id (uuid)
├── RLS 状态: 未知(使用 supabase-audit-rls 测试)
└── 风险: ⚠️ 包含用户 PII
2. profiles
├── 列: id, user_id, bio, website, social_links
├── 主键: id (uuid)
├── 外键: user_id → auth.users
└── 风险: ⚠️ 包含用户 PII
3. posts
├── 列: id, author_id, title, content, published, created_at
├── 主键: id (uuid)
└── 风险: ℹ️ 内容数据
4. comments
├── 列: id, post_id, user_id, content, created_at
├── 主键: id (uuid)
└── 风险: ℹ️ 内容数据
5. orders
├── 列: id, user_id, total, status, items, created_at
├── 主键: id (uuid)
└── 风险: 🔴 包含财务/交易数据
6. products
├── 列: id, name, description, price, stock, image_url
├── 主键: id (uuid)
└── 风险: ℹ️ 公共目录数据
7. settings
├── 列: id, key, value, updated_at
├── 主键: id (uuid)
└── 风险: ⚠️ 可能包含敏感配置
8. api_keys
├── 列: id, user_id, key_hash, name, last_used
├── 主键: id (uuid)
└── 风险: 🔴 包含机密
─────────────────────────────────────────────────────────
摘要
─────────────────────────────────────────────────────────
总表数: 8
高风险: 2 (orders, api_keys)
中风险: 3 (users, profiles, settings)
低风险: 3 (posts, comments, products)
后续步骤:
├── 运行 supabase-audit-tables-read 测试实际数据访问
├── 运行 supabase-audit-rls 验证 RLS 策略
└── 首先审查高风险表
═══════════════════════════════════════════════════════════
风险分类
表根据可能内容分类:
| 风险 | 表模式 | 示例 |
|---|---|---|
| 🔴 高 | 财务、机密、认证 | orders, payments, api_keys, secrets |
| ⚠️ 中 | 用户 PII、配置 | users, profiles, settings, preferences |
| ℹ️ 低 | 公共内容 | posts, products, categories, tags |
上下文输出
{
"tables": {
"count": 8,
"list": [
{
"name": "users",
"schema": "public",
"columns": ["id", "email", "name", "avatar_url", "created_at"],
"primary_key": "id",
"risk_level": "medium",
"risk_reason": "包含用户 PII"
},
{
"name": "orders",
"schema": "public",
"columns": ["id", "user_id", "total", "status", "items", "created_at"],
"primary_key": "id",
"risk_level": "high",
"risk_reason": "包含财务数据"
}
],
"by_risk": {
"high": ["orders", "api_keys"],
"medium": ["users", "profiles", "settings"],
"low": ["posts", "comments", "products"]
}
}
}
隐藏表
某些表可能未出现在 OpenAPI 模式中:
═══════════════════════════════════════════════════════════
额外发现
═══════════════════════════════════════════════════════════
模式中常见的未列出表(测试存在性):
├── _prisma_migrations: ❌ 未找到
├── schema_migrations: ❌ 未找到
├── audit_log: ✅ 存在但不在 OpenAPI 中
└── internal_config: ❌ 未找到
注意: 'audit_log' 存在但可能访问受限。
使用 supabase-audit-tables-read 测试。
═══════════════════════════════════════════════════════════
模式分析
技能还检查非公共模式:
模式暴露检查:
├── public: ✅ 暴露 (8 表)
├── auth: ❌ 未直接暴露(预期)
├── storage: ❌ 未直接暴露(预期)
├── extensions: ❌ 未暴露(好)
└── custom_schema: ⚠️ 暴露 (3 表) - 审查是否故意
常见问题
❌ 问题: 未找到表 ✅ 解决方案:
- 检查 anon 密钥是否有效
- 验证项目 URL 正确
- API 可能在项目设置中禁用
❌ 问题: 列出太多表 ✅ 解决方案: 这可能表示模式暴露过于宽松。考虑:
-- 限制暴露的模式
ALTER ROLE anon SET search_path TO public;
❌ 问题: 敏感表暴露 ✅ 解决方案: 要么从公共模式中移除,要么实施严格的 RLS。
按表类型推荐
用户表
-- 确保启用 RLS
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
-- 用户只能查看自己的数据
CREATE POLICY "用户查看自己数据" ON users
FOR SELECT USING (auth.uid() = id);
订单/支付表
-- 对财务数据实施严格 RLS
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
CREATE POLICY "用户查看自己订单" ON orders
FOR SELECT USING (auth.uid() = user_id);
-- 即使管理员也禁止通过 API 公共访问
-- 使用 Edge Functions 进行管理操作
机密表
-- 考虑完全不暴露
REVOKE ALL ON TABLE api_keys FROM anon, authenticated;
-- 或使用隐藏敏感列的视图
CREATE VIEW public.api_keys_safe AS
SELECT id, name, last_used FROM api_keys;
强制: 渐进式上下文文件更新
⚠️ 此技能必须在执行期间渐进式更新跟踪文件,而不仅仅在结束时。
关键规则: 逐步写入
不要在结束时批量写入所有内容。而是:
- 开始任何操作前 → 记录操作到
.sb-pentest-audit.log - 每次发现表后 → 立即更新
.sb-pentest-context.json - 每次重要步骤后 → 记录完成到
.sb-pentest-audit.log
这确保如果技能中断、崩溃或超时,所有先前发现都已保存。
所需操作(渐进式)
-
更新
.sb-pentest-context.json包含结果:{ "tables": { "count": 8, "list": [ ... ], "by_risk": { "high": [], "medium": [], "low": [] } } } -
记录到
.sb-pentest-audit.log:[时间戳] [supabase-audit-tables-list] [开始] 列出暴露的表 [时间戳] [supabase-audit-tables-list] [成功] 发现 8 表 [时间戳] [supabase-audit-tables-list] [上下文已更新] .sb-pentest-context.json 已更新 -
如果文件不存在,写入前创建。
未更新上下文文件是不可接受的。
强制: 证据收集
📁 证据目录: .sb-pentest-evidence/03-api-audit/tables/
要创建的证据文件
| 文件 | 内容 |
|---|---|
tables-list.json |
暴露表的完整列表 |
tables-metadata.json |
每表的列详细信息和类型 |
openapi-schema.json |
原始 OpenAPI/PostgREST 模式 |
证据格式
{
"evidence_id": "API-TBL-001",
"timestamp": "2025-01-31T10:15:00Z",
"category": "api-audit",
"type": "table_enumeration",
"request": {
"method": "GET",
"url": "https://abc123def.supabase.co/rest/v1/",
"headers": {
"apikey": "[已隐藏]"
},
"curl_command": "curl -s 'https://abc123def.supabase.co/rest/v1/' -H 'apikey: $ANON_KEY'"
},
"tables_found": [
{
"name": "users",
"schema": "public",
"columns": ["id", "email", "name", "created_at"],
"primary_key": "id",
"risk_level": "high",
"risk_reason": "包含 PII"
},
{
"name": "orders",
"schema": "public",
"columns": ["id", "user_id", "total", "status"],
"primary_key": "id",
"risk_level": "high",
"risk_reason": "财务数据"
}
],
"summary": {
"total_tables": 8,
"high_risk": 2,
"medium_risk": 3,
"low_risk": 3
}
}
添加到 curl-commands.sh
# === 表枚举 ===
# 通过 OpenAPI 模式列出所有暴露的表
curl -s "$SUPABASE_URL/rest/v1/" -H "apikey: $ANON_KEY"
相关技能
supabase-audit-tables-read— 测试实际数据访问supabase-audit-rls— 验证 RLS 策略supabase-audit-rpc— 检查暴露的函数