PostgreSQL中不直接写明表名能否访问pg_tables等系统表?
结论
有,PostgreSQL中存在多种不需要明确写出pg_tables完整字符串即可访问该系统表的方法,你当前基于关键词匹配的拦截方案完全不可靠。
常见绕过方式
- 动态SQL拼接:PostgreSQL支持执行动态构造的查询字符串,完全可以拆分关键词绕过匹配
-- 示例:拆分拼接访问pg_tables EXECUTE 'SELECT * FROM ' || 'pg_' || 'tables'; - 函数转换间接引用:通过字符串处理函数构造表名,再转换为表标识符访问
-- 示例:通过正则替换构造表名 SELECT * FROM regexp_replace('pg_xxxxxx', 'xxxxxx', 'tables')::regclass; - 大小写/转义符绕过:PostgreSQL默认标识符不区分大小写,还可以通过引号插入无关字符拆分关键词,也能绕过简单的字符串匹配
- 间接查询等效信息:就算完全不碰
pg_tables关键词,也可以通过information_schema.tables、pg_class等其他系统视图/表拿到完全一致的表元数据信息。
正确解决方案
你完全不需要在应用层做不可靠的关键词拦截,直接通过PostgreSQL原生权限体系即可从根源限制用户访问系统表:
- 先回收目标角色对系统目录和公共schema的默认访问权限
REVOKE ALL ON SCHEMA public, information_schema, pg_catalog FROM my_user_role; - 仅授予该角色访问必要资源的最小权限:
-- 允许访问视图所在的schema GRANT USAGE ON SCHEMA public TO my_user_role; -- 仅允许查询指定视图 GRANT SELECT ON my_view TO my_user_role;
配置完成后,即使用户传入查询系统表的语句,数据库会直接返回权限不足错误,远比应用层字符串匹配可靠。
内容的提问来源于stack exchange,提问作者Pangolin
相关产品推荐
相关产品推荐

