Base64编码无法防御SQL注入,因其仅为可逆字符转换,解码后恶意载荷原样恢复;必须将解码结果通过参数化查询绑定执行,而非字符串拼接,否则仍会触发注入。

Base64编码本身不防注入,解码后必须走参数化
Base64不是安全机制,只是字符转换。服务端收到 YW5kIDE9MQ==,base64_decode() 后得到 and 1=1,如果直接拼进 "WHERE id = '$id'",攻击就成功了。关键不在“有没有编码”,而在“解码后的值是否被当成数据而非代码处理”。
必须把解码结果作为绑定参数传给预编译语句,而不是字符串拼接:
- PHP + PDO:
$stmt->execute([$decoded_id]),绝不能写"WHERE id = '$decoded_id'" - Python + psycopg2:
cursor.execute("SELECT * FROM users WHERE name = %s", (decoded_name,)) - Node.js + mysql2:
connection.execute("SELECT * FROM users WHERE id = ?", [decoded_id])
警惕解码时机与上下文错配
很多漏洞出在“解码早、过滤晚、拼接更晚”这个时间差上。比如:
- 前端传
{"name": "a' OR 1=1 -- "}→ Base64 编码 → 后端先解码,再json_decode()→ 此时 SQL 拼接发生在 JSON 解析之后,过滤器根本没机会看到原始 payload - WAF 只检查原始请求体,放行了
b2IgMQoxPTE=(换行绕过),后端解码后才暴露ob 1\n1=1 - MySQL 连接字符集设为
latin1,但传输 UTF-8 字节流,%C0%BC可能被解释成单引号,绕过基于 UTF-8 的校验
别信任何“解码后关键词过滤”方案
用 preg_match('/(union|select|;)/i', base64_decode($input)) 检查解码后内容,看似严谨,实则脆弱:
- 大小写混淆:
UnIoN SeLeCt能绕过简单正则 - Unicode/全角字符:
union不匹配 ASCII 关键字表 - 空字节截断:
admin\x00' OR 1=1 --编码后,旧版base64_decode()遇\x00提前终止,只解出admin,过滤器误判“安全” - 性能陷阱:高并发下对每个 Base64 参数都跑一遍正则,CPU 瞬间拉满
自动化测试时要启用 tamper 插件,但别依赖它绕过防御
sqlmap 的 --tamper base64encode.py 确实能帮你快速验证 Base64 注入点,命令形如:
sqlmap -u "http://target.com/api?id=MTIz" --tamper base64encode.py -v 3 --batch
但它只是探测手段,不是修复依据。真实防御必须落在代码层:
- 所有用户输入,无论是否 Base64 编码,只要进 SQL,一律走 prepare/bind
- 整型参数必须强转:
(int)base64_decode($input)或intval(),避免1 OR 1=1逃逸到无引号上下文 - ORM 调用
.raw()或.extra()时,等同于放弃参数化,必须人工确保内部无拼接
最危险的不是 Base64,而是开发看到“已编码”就放松警惕,把 base64_decode() 的输出当“可信数据”直接拼接——这等于给攻击者多套了一层免检外衣。

















