跳转到主内容
websoft网络软件专家 - 深耕网络技术,打造实用软件!

为什么数据库连接字符串也需要防止SQL注入_避免连接串拼接用户输入

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

相关文章