Supabase数据库连接字符串检测Skill supabase-extract-db-string

此技能用于检测客户端代码中是否意外暴露了PostgreSQL数据库连接字符串,特别针对Supabase平台。它是一个关键的安全审计工具,帮助防止直接数据库访问漏洞,确保数据安全。关键词:安全审计、数据库安全、Supabase、连接字符串检测、客户端代码、渗透测试。

安全审计 0 次安装 0 次浏览 更新于 3/18/2026

name: supabase-extract-db-string description: 关键 - 检测客户端代码中暴露的PostgreSQL数据库连接字符串。直接数据库访问是一个P0问题。

数据库连接字符串检测

🔴 关键:需要逐步文件更新

您必须逐步写入上下文文件,而不仅仅是在结束时。

  • 每次发现后立即写入 .sb-pentest-context.json
  • 每次操作前后记录到 .sb-pentest-audit.log
  • 不要等到技能完成才更新文件
  • 如果技能崩溃或中断,所有之前的发现必须已经保存

这不是可选的。未能逐步写入是关键错误。

此技能检测PostgreSQL数据库连接字符串是否意外暴露在客户端代码中。

何时使用此技能

  • 作为每次安全审计的一部分
  • 在生产前审查代码时
  • 当怀疑Supabase数据库访问时

为什么这很关键

暴露的数据库连接字符串允许:

影响 描述
🔴 直接数据库访问 绕过API,直接连接到PostgreSQL
🔴 完全数据访问 在没有RLS的情况下读写所有数据
🔴 模式访问 查看和修改数据库结构
🔴 用户枚举 直接访问auth.users表

这是一个需要立即行动的P0(关键)发现。

连接字符串模式

Supabase数据库URL

postgresql://postgres:[password]@db.[project-ref].supabase.co:5432/postgres

连接字符串组件

组件 示例 敏感度
主机 db.abc123.supabase.co 中等
端口 5432
数据库 postgres
用户名 postgres 中等
密码 [your-password] 🔴 关键

连接池(Supavisor)

postgresql://postgres.[project-ref]:[password]@aws-0-us-east-1.pooler.supabase.com:6543/postgres

检测模式

1. 完整连接字符串

// ❌ 关键 - 完整连接字符串
const dbUrl = 'postgresql://postgres:MySecretPass123@db.abc123.supabase.co:5432/postgres'

2. 环境变量泄露

// ❌ 在客户端包中暴露
process.env.DATABASE_URL
process.env.POSTGRES_URL
process.env.SUPABASE_DB_URL

3. 部分暴露

// ⚠️ 密码单独暴露
const DB_PASSWORD = 'MySecretPass123'
const DB_HOST = 'db.abc123.supabase.co'

4. ORM配置

// ❌ 客户端代码中的数据库配置
const prisma = new PrismaClient({
  datasources: {
    db: {
      url: 'postgresql://postgres:pass@db.abc123.supabase.co:5432/postgres'
    }
  }
})

使用方式

基本检查

在 https://myapp.example.com 上检查数据库连接字符串

深度扫描

在 https://myapp.example.com 上深度扫描数据库凭证

输出格式

未找到连接字符串(良好)

═══════════════════════════════════════════════════════════
 数据库连接字符串检查
═══════════════════════════════════════════════════════════

 状态:✅ 未检测到数据库连接字符串

 扫描内容:
 ├── JavaScript包:5个文件分析
 ├── PostgreSQL模式:未找到
 ├── 连接字符串:未找到
 └── 密码模式:未找到

 结果:通过 - 无直接数据库凭证暴露
═══════════════════════════════════════════════════════════

找到连接字符串(关键)

═══════════════════════════════════════════════════════════
 🔴 关键:数据库连接字符串暴露
═══════════════════════════════════════════════════════════

 严重性:P0 - 关键
 状态:❌ PostgreSQL连接字符串在客户端代码中找到!

 ⚠️  需要立即行动 ⚠️

 连接字符串:
 postgresql://postgres:MySecr***@db.abc123def.supabase.co:5432/postgres
 (密码在显示中部分隐藏,完整值在上下文文件中)

 解析组件:
 ├── 主机:db.abc123def.supabase.co
 ├── 端口:5432
 ├── 数据库:postgres
 ├── 用户名:postgres
 └── 密码:[暴露] ← 关键

 位置:
 └── /static/js/api.chunk.js (第234行)
     const DATABASE_URL = 'postgresql://postgres:...'

 影响评估:
 ├── 🔴 可直接访问PostgreSQL
 ├── 🔴 所有RLS策略被绕过
 ├── 🔴 可访问auth.users表
 ├── 🔴 可修改数据库模式
 └── 🔴 可能完全数据外泄

 ═══════════════════════════════════════════════════════════
 立即修复步骤
 ═══════════════════════════════════════════════════════════

 1. 立即更改数据库密码
    → Supabase控制台 > 设置 > 数据库 > 重置数据库密码

 2. 从客户端代码中移除
    → 从源代码中删除连接字符串
    → 确保DATABASE_URL不在NEXT_PUBLIC_*或VITE_*环境变量中
    → 重新部署应用程序

 3. 审计滥用情况
    → 检查Supabase日志中的直接PostgreSQL连接
    → 审查未经授权的数据访问或修改

 4. 使用正确架构
    → 客户端应仅使用Supabase客户端库(REST API)
    → 直接数据库访问应仅来自:
      - 边缘函数
      - 服务器端代码
      - 迁移工具

 文档:
 → https://supabase.com/docs/guides/database/connecting-to-postgres
 → https://supabase.com/docs/guides/functions

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

上下文输出

{
  "findings": [
    {
      "id": "DB_CONNECTION_STRING_EXPOSED",
      "severity": "P0",
      "title": "PostgreSQL连接字符串暴露",
      "description": "在客户端代码中找到带有密码的数据库连接字符串",
      "location": {
        "file": "/static/js/api.chunk.js",
        "line": 234
      },
      "evidence": {
        "host": "db.abc123def.supabase.co",
        "port": 5432,
        "database": "postgres",
        "username": "postgres",
        "password_exposed": true
      },
      "remediation": {
        "immediate": "在Supabase控制台中重置数据库密码",
        "long_term": "将数据库操作移至边缘函数",
        "docs": "https://supabase.com/docs/guides/database/connecting-to-postgres"
      }
    }
  ],
  "supabase": {
    "db_string_exposed": true,
    "db_host": "db.abc123def.supabase.co"
  }
}

部分暴露

即使部分暴露也令人担忧:

═══════════════════════════════════════════════════════════
 ⚠️ 部分数据库凭证找到
═══════════════════════════════════════════════════════════

 严重性:P1 - 高

 找到:
 ├── 数据库主机:db.abc123def.supabase.co (第45行)
 ├── 数据库密码:[16字符字符串] (第89行)
 └── 可能被组合以获取访问权限

 建议:
 → 作为预防措施,轮换数据库密码
 → 从客户端代码中移除所有数据库相关值
═══════════════════════════════════════════════════════════

常见原因

原因 解决方案
错误的环境变量前缀 永远不要使用 NEXT_PUBLIC_DATABASE_URL
SSR代码在客户端中 确保服务器端代码仅保留在服务器端
打包器配置错误 检查webpack/vite配置以暴露环境变量
复制粘贴错误 双重检查您提交的内容

架构指导

错误(客户端中直接数据库)

// ❌ 永远不要在客户端代码中
import { Pool } from 'pg'
const pool = new Pool({
  connectionString: process.env.DATABASE_URL  // ❌
})

正确(API或边缘函数)

// ✅ 客户端使用Supabase客户端
const { data } = await supabase
  .from('products')
  .select('*')

// 或调用边缘函数进行复杂查询
const { data } = await supabase.functions.invoke('complex-query')

边缘函数(服务器端)

// supabase/functions/complex-query/index.ts
import { createClient } from '@supabase/supabase-js'

Deno.serve(async (req) => {
  // ✅ 仅在服务器上进行直接数据库访问
  const supabase = createClient(
    Deno.env.get('SUPABASE_URL'),
    Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')
  )

  // 无法通过REST完成的复杂查询
  const { data } = await supabase.rpc('complex_function')
  return new Response(JSON.stringify(data))
})

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

⚠️ 此技能必须在执行过程中逐步更新跟踪文件,而不仅仅是在结束时。

关键规则:逐步写入

不要在结束时批量写入所有内容。相反:

  1. 在开始任何操作前 → 将操作记录到 .sb-pentest-audit.log
  2. 每次发现后 → 立即更新 .sb-pentest-context.json
  3. 每个重要步骤后 → 将完成记录到 .sb-pentest-audit.log

这确保如果技能被中断、崩溃或超时,所有到该点的发现都被保留。

必需操作(逐步)

  1. 用发现更新 .sb-pentest-context.json

    {
      "supabase": {
        "db_string_exposed": true/false,
        "db_host": "db.[ref].supabase.co"
      },
      "findings": [
        {
          "id": "DB_CONNECTION_STRING_EXPOSED",
          "severity": "P0",
          ...
        }
      ]
    }
    
  2. 记录到 .sb-pentest-audit.log

    [时间戳] [supabase-extract-db-string] [开始] 检查数据库连接字符串
    [时间戳] [supabase-extract-db-string] [关键] 连接字符串暴露
    [时间戳] [supabase-extract-db-string] [上下文更新] .sb-pentest-context.json 已更新
    
  3. 如果文件不存在,在写入前创建它们。

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

强制:证据收集

📁 证据目录: .sb-pentest-evidence/02-extraction/db-string-exposure/

要创建的证据文件(如果找到数据库字符串)

文件 内容
db-string-exposure/connection-details.json 解析的连接字符串(密码隐藏)
db-string-exposure/location.txt 文件路径和行号

证据格式(P0发现)

{
  "evidence_id": "EXT-DB-001",
  "timestamp": "2025-01-31T10:12:00Z",
  "category": "extraction",
  "type": "db_connection_string",
  "severity": "P0",
  "finding_id": "P0-002",

  "connection_string": {
    "pattern": "postgresql://postgres:[REDACTED]@db.abc123def.supabase.co:5432/postgres",
    "host": "db.abc123def.supabase.co",
    "port": 5432,
    "database": "postgres",
    "username": "postgres",
    "password_exposed": true,
    "password_length": 24
  },

  "location": {
    "file": "/static/js/api.chunk.js",
    "line": 234,
    "context": "const DATABASE_URL = 'postgresql://postgres:...' // [REDACTED]"
  },

  "impact": {
    "direct_db_access": true,
    "rls_bypass": true,
    "schema_access": true,
    "auth_users_access": true
  },

  "remediation": {
    "immediate": "在Supabase控制台中重置数据库密码",
    "remove_from_code": "从客户端代码中删除DATABASE_URL",
    "verify_env_vars": "确保不使用NEXT_PUBLIC_DATABASE_URL或类似"
  }
}

添加到timeline.md(P0)

## [时间戳] - 🔴 P0 关键:数据库连接字符串暴露
- PostgreSQL连接字符串带有密码在客户端代码中找到
- 位置:[文件]:[行]
- 影响:直接数据库访问,完全RLS绕过
- 证据:`02-extraction/db-string-exposure/`
- **需要立即密码轮换**

相关技能

  • supabase-extract-service-key — 检查服务密钥暴露
  • supabase-audit-tables-read — 通过API测试数据访问
  • supabase-report — 生成全面报告