search_path 劫持:你从未听说过的 PostgreSQL 攻击

发布: (2026年1月3日 GMT+8 03:49)
3 min read
原文: Dev.to

Source: Dev.to

大多数开发者都了解 SQL 注入,少有人知晓 search_path 劫持。

它同样危险。

什么是 search_path

PostgreSQL 的 search_path 决定在引用未限定表名时查找哪个 schema。

-- 当 search_path = public 时,这两条语句等价:
SELECT * FROM users;
SELECT * FROM public.users;

攻击方式

如果攻击者能够控制 search_path,就可以把你的查询重定向到恶意表:

// ❌ 动态 search_path 来自用户输入
const schema = req.query.tenant; // 攻击者可以控制此值
await client.query(`SET search_path TO ${schema}`);
await client.query('SELECT * FROM users'); // 现在查询的是攻击者的 schema

工作原理

  1. 攻击者创建一个包含恶意 users 表的 schema。
  2. 攻击者将 search_path 设置为自己的 schema。
  3. 你的查询返回伪造的数据。

为什么这很重要

攻击类型影响
数据窃取返回伪造数据,捕获输入
权限提升替换安全函数
代码执行恶意触发器、函数

正确的写法

// ✅ 静态 search_path
await client.query(`SET search_path TO tenant_${tenantId}`);

// ✅ 对照白名单进行校验
const ALLOWED_SCHEMAS = ['tenant_1', 'tenant_2', 'tenant_3'];
if (!ALLOWED_SCHEMAS.includes(schema)) {
  throw new Error('Invalid schema');
}
await client.query(`SET search_path TO ${schema}`);

// ✅ 使用全限定表名
await client.query('SELECT * FROM public.users'); // 明确指定 schema

用 ESLint 捕获此问题

npm install --save-dev eslint-plugin-pg
import pg from 'eslint-plugin-pg';
export default [pg.configs.recommended];

动态 search_path 会被检测到:

src/tenants.ts
  8:15  error  🔒 CWE-426 | Dynamic search_path detected
               Fix: Use static schema name or validate against allowlist

多租户模式

// ✅ 通过校验的安全多租户实现
async function queryTenant(tenantId, sql, params) {
  // 校验租户是否存在
  const tenant = await getTenant(tenantId);
  if (!tenant) throw new Error('Unknown tenant');

  const client = await pool.connect();
  try {
    // 从可信来源获取 schema 名称,而非用户输入
    await client.query(`SET search_path TO tenant_${tenant.id}`);
    return await client.query(sql, params);
  } finally {
    // 重置 search_path
    await client.query('SET search_path TO public');
    client.release();
  }
}

快速安装

npm install --save-dev eslint-plugin-pg
import pg from 'eslint-plugin-pg';
export default [pg.configs.recommended];

别让攻击者劫持你的查询。

Back to Blog

相关文章

阅读更多 »

入门 eslint-plugin-pg

快速安装 bash npm install --save-dev eslint-plugin-pg Flat Config js // eslint.config.js import pg from 'eslint-plugin-pg'; export default pg.configs.reco...