search_path 하이재킹: 들어본 적 없는 PostgreSQL 공격
발행: (2026년 1월 3일 오전 04:49 GMT+9)
4 min read
원문: Dev.to
Source: Dev.to
대부분의 개발자는 SQL 인젝션에 대해 알고 있습니다. 하지만 search_path 하이재킹에 대해서는 거의 모릅니다.
위험성은 똑같습니다.
search_path란?
PostgreSQL의 search_path는 스키마를 지정하지 않은 테이블 이름을 참조할 때 어느 스키마를 검색할지 결정합니다.
-- 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'); // 이제 공격자의 스키마를 조회함
동작 방식
- 공격자는 악성
users테이블을 가진 스키마를 생성합니다. - 공격자는
search_path를 자신의 스키마로 설정합니다. - 여러분의 쿼리는 가짜 데이터를 반환합니다.
왜 중요한가?
| 공격 종류 | 영향 |
|---|---|
| 데이터 탈취 | 가짜 데이터를 반환하고 입력을 수집함 |
| 권한 상승 | 보안 함수를 교체함 |
| 코드 실행 | 악성 트리거·함수를 실행함 |
올바른 패턴
// ✅ 정적인 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'); // 스키마를 명시
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 {
// 사용자 입력이 아닌 신뢰할 수 있는 소스에서 스키마 이름을 가져옴
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];
공격자가 여러분의 쿼리를 하이재킹하지 못하도록 하세요.