数据库权限基线要求:禁用root@%等高危账号,最小化授权,禁用危险扩展如dblink,启用sql_mode严格模式,限制information_schema访问。

查 mysql 用户权限是否过度开放
数据库账号权限过大是基线失守最常见原因,尤其 root@% 或任意主机可连的高权账号。别只看有没有密码,重点看 Host 字段和 Privileges 列表。
实操建议:
- 用
SELECT User, Host, authentication_string FROM mysql.user;查所有账号,重点关注Host为%或非内网 IP 的记录 - 用
SHOW GRANTS FOR 'xxx'@'yyy';看具体权限,警惕含GRANT OPTION、FILE、PROCESS的授权 - 生产环境禁止
GRANT ALL PRIVILEGES ON *.*,应按最小权限原则限定库/表级权限 -
mysql_native_password插件在 8.0+ 默认禁用,若强制启用需确认未暴露明文密码传输风险
检查 postgresql 是否禁用 pg_stat_statements 外的危险扩展
PostgreSQL 扩展机制灵活,但像 dblink、postgres_fdw、file_fdw 这类能跨库/读文件的扩展,一旦被注入或误用,极易导致数据越权或 RCE。
实操建议:
- 运行
SELECT * FROM pg_extension;查已安装扩展,对照业务需求判断是否冗余 - 禁用非必要扩展:用
DROP EXTENSION dblink;(注意依赖关系,先查pg_depend) -
pg_stat_statements是安全基线推荐开启的,用于审计慢查询,但它本身不带执行能力,无需担心 - 检查
shared_preload_libraries配置项,确保没加载未经验证的自定义 .so
验证 sql_mode 是否启用严格模式(MySQL / MariaDB)
默认 sql_mode 宽松会导致隐式类型转换、截断插入、零日期接受等行为,掩盖应用层数据校验缺陷,也增加 SQL 注入利用面。
实操建议:
- 查当前值:
SELECT @@GLOBAL.sql_mode;或SELECT @@SESSION.sql_mode; - 基线要求至少包含
STRICT_TRANS_TABLES(InnoDB 表)或STRICT_ALL_TABLES(全表),禁用NO_ZERO_DATE、ALLOW_INVALID_DATES等宽松项 - 修改方式:在
my.cnf的[mysqld]段加sql_mode = "STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION" - 注意:变更后需测试应用,部分老代码依赖隐式转换(如字符串转数字时截断),会直接报错
识别 information_schema 是否被未授权用户遍历
很多扫描工具和攻击者第一件事就是查 information_schema.tables、columns,如果低权账号也能读,等于把数据库结构白送。
实操建议:
- 用普通账号执行
SELECT COUNT(*) FROM information_schema.tables;,若返回非零结果,说明未限制 - MySQL 8.0+ 可通过
REVOKE SELECT ON information_schema.* FROM 'user'@'host';收回(但需确保应用不依赖该查询) - MariaDB 10.6+ 支持
system_versioning和更细粒度的INFORMATION_SCHEMA权限控制,旧版本只能靠账号隔离 - PostgreSQL 中对应的是
pg_catalog和information_schemaschema,默认普通用户可读元数据,需用REVOKE USAGE ON SCHEMA information_schema FROM PUBLIC;控制
真正难的是权限收敛后的兼容性验证——业务代码里藏着多少 SELECT * FROM information_schema.columns WHERE table_name = ? 这种“便利写法”,不跑一遍真实流量根本发现不了。

















