mysql如何防止SQL注入_mysql权限与安全设计

6次阅读

应使用预处理语句替代sql拼接,严格遵循最小权限原则,清理默认危险配置,并在应用层增加输入白名单与类型强校验。

mysql如何防止SQL注入_mysql权限与安全设计

用预处理语句(Prepared Statements)代替拼接SQL

直接拼接用户输入到 selectINSERT 等语句中,是 SQL 注入最常见入口。mysql 本身不校验字符串内容,只按语法执行——只要注入的 SQL 片段语法合法,就会被执行。

正确做法是使用客户端驱动层的预处理机制,让 MySQL Server 分离「SQL 结构」和「数据值」:

  • PHP 中用 pdo::prepare() + bindValue(),不是 mysql_query()(已废弃)
  • Python 中用 cursor.execute("SELECT * FROM user WHERE id = %s", [user_id]),不用 f"WHERE id = {user_id}"
  • Java 中用 PreparedStatement,参数用 ? 占位,调用 setString() 等方法赋值

注意:仅用 mysqli_real_escape_string() 或正则过滤是靠不住的——它无法覆盖所有上下文(比如数字上下文、json 字段、ORDER BY 子句),且容易漏掉多字节编码绕过场景。

最小权限原则:给应用账号配专属数据库用户

别让 Web 应用连的是 root@localhost。一个典型误操作是建库后直接 GRANT ALL ON *.* TO 'app'@'%',这等于把整套实例权限交出去。

应按实际需求限制:

  • 只读接口 → 只授 SELECT 权限,且限定到具体库表,如 GRANT SELECT ON myapp.users TO 'web_ro'@'10.0.1.%'
  • 写操作分离 → 写账号禁用 DROPALTERCREATE,甚至禁用 delete(用软删字段替代)
  • 禁止跨库访问 → 不用 myapp.*,而用 myapp.user_profilemyapp.order_log 明确授权
  • 连接来源限制 → 把 '%' 换成内网 IP 段,如 '172.16.20.%',避免暴露到公网

权限变更后务必执行 FLUSH PRIVILEGES,否则新规则不生效。

关闭危险配置与默认高危账户

MySQL 默认安装常带安全隐患,需手动清理:

  • 删除匿名用户:DROP USER ''@'localhost'
  • 禁用 LOAD DATA INFILESELECT ... intO OUTFILE:在 my.cnf 中设 secure_file_priv = "" 或指向空目录,防止文件读写类注入利用
  • 关闭旧协议认证:default_authentication_plugin = caching_sha2_password(5.7.21+ / 8.0+),避免 mysql_native_password 的弱协商风险
  • 禁用远程 root 登录:DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1'),再 FLUSH PRIVILEGES

这些配置改完要重启 mysqld 或执行 SET GLOBAL(部分可动态生效),但 secure_file_priv 必须重启才生效。

应用层加一道校验:输入白名单 + 类型强约束

数据库权限和预处理是底线,但不能全依赖它们。比如 ID 参数本该是正整数,就应在 PHP/Python 中先做 is_int()int(user_input) 转换;枚举字段如 status,应查表或硬编码白名单,而非直接代入 SQL。

常见疏漏点:

  • ORDER BY 子句无法用预处理参数(MySQL 不允许占位符用于列名/关键字),必须用白名单映射:$allowed_sort = ['created_at', 'score']; $sort = in_array($_GET['sort'], $allowed_sort) ? $_GET['sort'] : 'created_at';
  • LIKE 模糊查询中的通配符 %_ 需转义,用 ESCAPE 子句或客户端函数(如 Python 的 re.escape() 后替换)
  • JSON 字段内容若含用户输入,需先 JSON 解码再校验结构,不能直接拼进 JSON_EXTRACT() 表达式

真正难防的从来不是复杂注入手法,而是开发时觉得“这里就一个数字ID,肯定安全”,结果忘了类型转换或边界检查。

text=ZqhQzanResources