数据库加密挡不住sql注入,因为注入发生在查询执行阶段,攻击者直接获取明文结果;tde或aes_encrypt等仅保护静态数据,运行时数据库自动解密,返回的仍是明文字段。

加密存储对SQL注入几乎没用——攻击者拿到的是明文数据,根本不需要解密。
为什么数据库加密挡不住SQL注入
SQL注入发生在查询执行阶段,攻击者通过构造恶意输入,让数据库直接返回原始字段内容。比如执行 SELECT credit_card FROM users WHERE id = 1 OR 1=1,结果集里 credit_card 字段如果是明文存储,就原样吐出来;哪怕你用了 AES_ENCRYPT() 或 TDE,只要该字段没在应用层加密,攻击者照样能 SELECT 出来——数据库引擎解密是自动的,他连密钥都不用碰。
常见误解包括:
- 以为开启 MySQL 的
TDE就能防注入——TDE 加密的是磁盘文件,运行时数据全是明文 - 在 SQL 层用
AES_ENCRYPT()但把密钥写死在查询里——密钥可能进慢日志、代理日志或审计表 - 用 ORM 却调用
.extra(where=["... %s" % user_input])——参数化失效,加密白做
真正该加密的字段必须在应用层处理
只有当敏感字段(如手机号、身份证号)在写入数据库前,由应用代码用 AES-GCM 等标准算法加密,且密钥由 KMS 动态获取,才可能增加一层防护。此时即使注入成功,返回的也只是密文。
实操要点:
-
IV必须每次随机生成,并和密文一起存(例如新增phone_iv字段),不能复用 - 密文建议 Base64 编码后存
TEXT,避免VARBINARY与字符集转换冲突 - 解密逻辑只在必要业务路径触发,禁止全量缓存解密结果
- 若需按加密字段查询(如手机号前缀),应拆出明文前缀字段 + 加密剩余部分,而非对密文做
LIKE
SQL Server 里 ENCRYPTBYKEY 容易踩的坑
在 SQL Server 存储过程中调用 ENCRYPTBYKEY,最常遇到返回 NULL,不是函数写错,而是密钥没打开或类型不匹配。
关键检查点:
- 必须显式执行
OPEN SYMMETRIC KEY your_key DECRYPTION BY CERTIFICATE your_cert,不能依赖“密钥存在”就自动可用 - 目标列类型必须是
VARBINARY(8000),写进NVARCHAR会静默损坏 -
DECRYPTBYKEY要求执行用户有VIEW DEFINITION(证书)和REFERENCES(密钥)权限,EXECUTE AS OWNER不自动继承 - 密钥打开后仅限当前会话有效,长事务或异常分支后可能已关闭,需重复检查
加密解决的是硬盘被盗、备份泄露这类离线场景;而 SQL 注入是在线实时攻击。把精力花在参数化查询、最小权限账号、禁用高危函数上,比堆砌加密更直接有效。应用层加密只是补丁,不是盾牌——它只在你已经漏掉前几道防线时,多拖住攻击者一两秒。











