权限、加密与注入防护

数据库往往是攻击者的最终目标。安全不是单一功能,而是网络、账号、加密、审计的多层防御。

最小权限原则

为每个应用创建独立账号,只授予必需的最小权限:

CREATE USER 'order_svc'@'10.0.0.%' IDENTIFIED BY 'strong-password';
GRANT SELECT, INSERT, UPDATE ON shop.orders TO 'order_svc'@'10.0.0.%';
-- 不给 DROP、ALTER、GRANT,尤其不给全库 *.* 权限
CREATE ROLE order_svc LOGIN PASSWORD 'strong-password';
GRANT CONNECT ON DATABASE shop TO order_svc;
GRANT USAGE ON SCHEMA app TO order_svc;
GRANT SELECT, INSERT, UPDATE ON app.orders TO order_svc;

要点:

  • 禁止应用使用 root / superuser
  • 禁止 GRANT ALL、禁止 *.*
  • 读账号与写账号分离;只读业务用只读账号。
  • 限制来源 IP('user'@'10.0.0.%'),不要用 % 全网段。

网络隔离

  • 数据库绝不暴露公网,只在内网/私有子网可达。
  • 用安全组/防火墙把访问限制在应用服务器。
  • 端口不对外;管理入口走跳板机/VPN。
  • 云环境使用私有网络 + 数据库代理。
Warning

「公网 + 弱密码」是数据泄露事故的经典成因。哪怕临时开启公网调试,也必须立即关闭并轮换口令。默认数据库端口(3306/5432/27017/6379)暴露在公网会在数小时内被扫描并尝试爆破。

SQL 注入防护

唯一正确做法:参数化查询(预处理语句)。永远不要拼接用户输入。

// 正确:占位符由驱动安全处理
row := db.QueryRow("SELECT id, name FROM users WHERE email = ?", email)

// 多值的 IN 也要用参数占位,动态生成占位符个数
query := "SELECT * FROM orders WHERE id IN (" + placeholders(len(ids)) + ")"
db.Query(query, ids...)

func placeholders(n int) string {
    if n == 0 {
        return "NULL"
    }
    return strings.TrimSuffix(strings.Repeat("?,", n), ",")
}
// 危险:字符串拼接,可被注入
q := fmt.Sprintf("SELECT * FROM users WHERE name = '%s'", name) // 绝不这样做

其他加固:

  • 输入校验与长度限制;对排序字段用白名单映射,而非直接拼列名。
  • 数据库账号只读权限可限制注入的破坏范围。
  • 使用 ORM 时也避免 Raw 拼接用户输入。

传输与存储加密

场景措施
传输强制 TLS(MySQL require_secure_transport、PG sslmode=verify-full、MongoDB tls=true、Redis TLS)
存储云盘加密、表空间加密(InnoDB TDE)
密钥用 KMS/密钥管理服务,不落盘到代码
备份备份文件加密,异地存储也加密
# PostgreSQL
postgres://user:pass@host:5432/db?sslmode=verify-full

# MongoDB
mongodb://user:pass@host:27017/?tls=true&tlsCAFile=/etc/ssl/ca.pem
Tip

sslmode=disable / tls=false 只应用于本地开发。生产必须 verify-full(校验证书链与主机名),否则 TLS 可被中间人降级攻击绕过。

敏感数据保护

  • 脱敏:日志、导出、测试环境中的手机号、身份证、银行卡需脱敏或假数据。
  • 加密存储:口令用 bcrypt/argon2 加盐哈希(不可逆);身份证等敏感字段可应用层加密。
  • 字段级加密:对极敏感列加密,密钥独立管理。
  • 最小暴露:查询只取必要字段,避免 SELECT * 泄露敏感列。
// 数据库中只存哈希,绝不存明文口令
hash, _ := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
// 校验
err := bcrypt.CompareHashAndPassword(hash, []byte(input))

审计与变更管控

  • 开启数据库审计日志,记录敏感操作(DDL、权限变更、大批量删除)。
  • 生产变更走工单 + 审核,高危语句(DROPTRUNCATE、无 WHEREUPDATE/DELETE)二次确认。
  • 定期轮换口令与密钥。
  • 监控异常行为:非工作时间的批量导出、异常来源 IP。
Warning

应用日志里常见「打印整条 SQL 与参数」,这可能把手机号、口令写进日志系统。开启 SQL 日志前必须做参数脱敏,并限制日志访问权限。

小结

  • 最小权限:独立账号、按需授权、限制来源 IP、禁用 superuser。
  • 网络隔离:数据库不暴露公网。
  • 注入防护的核心是参数化查询,排序/表名用白名单。
  • 传输与存储加密、敏感数据脱敏、口令哈希、审计与变更管控,构成完整防线。