数据库连接字符串拼接用户输入会触发连接劫持而非SQL语法错误,攻击者可篡改host、port、user、password等参数,导致应用连错库、泄露凭证甚至写入恶意数据库。
数据库连接字符串拼接用户输入会触发什么错误
它不会报
,也不会在执行查询时被拦截——因为连接阶段根本还没走到 SQL 解析器。但攻击者可以借此完成更底层的劫持:比如把
改成
,直接让应用连错库、写错表、甚至把凭证暴露给恶意服务器。
哪些地方容易误以为“连接串不执行SQL,所以安全”
常见误判场景包括:
登录页允许用户填写自定义数据库地址(如内网调试工具、多租户管理后台)
命令行脚本用
或
拼接连接参数后传给
(Python)或
(Java)
配置中心动态注入连接信息,但未校验
、
字段是否含分号、反斜杠、URL 编码绕过字符
这些位置一旦放开拼接,就等于把数据库的“门锁钥匙”交到用户手上——而门锁本身(如 MySQL 的
或 PostgreSQL 的
配置)可能早已被绕过。
和
URL 中哪些字符必须严格过滤
URL 格式本身支持特殊字符,但解析器对它们的处理并不统一。以下字符在连接串中极易引发意外交互:
防SQL注入的php类库
防SQL注入的php类库
下载
:用于分隔用户密码与 host,若用户输入
,部分驱动会取第一个
前为 credential,第二个
后为 host,导致连接目标偏移
:某些 JDBC 驱动(如旧版 MySQL Connector/J)会将分号后内容当作额外参数,可能开启
等危险选项
:URL 编码字符,如
(分号)、
(/),可绕过前端简单正则过滤
:Windows 路径中若混入双反斜杠,可能干扰本地 socket 连接路径解析(如
)
不要依赖“只允许字母数字”的粗暴过滤——
是合法 host,
是合法 database 名,但
就不是。
真正安全的连接串构造方式
核心原则:连接参数 ≠ 用户输入。所有来自用户的值,必须经过白名单校验或强制类型转换,再填入预定义模板:
host 必须通过
或 DNS 解析验证可达性,且仅接受 IPv4/IPv6 地址或明确授权的域名(如
)
port 必须是整数且在 1–65535 范围内,拒绝字符串形式的端口(如
)
database 名需匹配
,且不能是
、
、
等系统库名
绝不在任何环节使用
这类拼接,改用标准 URL 构建库(如 Python 的
)并禁用自由参数注入
最常被忽略的一点:连接串里出现的
和
,哪怕只是用于测试,也绝不能从 HTTP 请求体、Query 参数或 Cookie 中直接读取——它们属于最高敏感级凭据,应走独立凭证服务或环境变量注入,并启用连接池级别的凭据轮换机制。
SQL syntax errorhost=localhost;port=3306;user=admin;password=123456host=evil.com;port=3307;user=attacker;password=;database=stolen_dbos.environsys.argvcreate_engine()DriverManager.getConnection()hostdatabaseskip-grant-tablespg_hba.confmysql://postgresql://@admin:pass@evil.com@localhost@@;allowUrlInLocalInfile=true%%3B%2F\socket=/var/run/mysqld/mysqld.sock\localhost:3306my-db-123my-db-123%3Bdrop+table+userssocket.gethostbyname()^db-[0-9]+.prod.example.com$"3306;SELECT 1"^[a-zA-Z_][a-zA-Z0-9_]{0,63}$information_schemamysqlperformance_schema"mysql://" + user_host + ":" + user_port + "/" + user_dburllib.parse.urlunparseuserpassword