SQL 注入防护怎么做

一、新手友好版(通俗易操作,核心抓重点)

  1. 别直接拼用户输入到 SQL 里
     
    比如别写 SELECT * FROM user WHERE id='${用户输入的id}',这种写法黑客改输入内容就能篡改 SQL 逻辑;改用「参数化查询」(也叫预编译语句),把输入当 “参数” 而非 SQL 代码的一部分,比如 MySQL 用 PREPARE 语句、Java 用 PreparedStatement,Python 用 cursor.execute(sql, (参数,)),从根源杜绝拼接风险。
  2. 给输入 “设规矩”
     
    比如手机号只允许填 11 位数字、邮箱按邮箱格式校验,用正则表达式过滤非法字符(单引号、分号、OR 1=1 这类),就算黑客想输恶意代码,也会被直接拦截。
  3. 装个 WAF “守门”
     
    不管是云 WAF(阿里云 / 腾讯云 WAF)还是服务器端 WAF,能自动识别含恶意 SQL 片段的请求(比如带 UNION SELECTDROP TABLE 的请求),直接拦在外面,不用自己写复杂规则。
  4. 数据库账号 “少给权限”
     
    应用连接数据库的账号,只给必要权限:比如查数据只给SELECT、加数据只给INSERT,坚决不给DROP(删表)、ALTER(改表)权限,就算被注入,黑客也没法删库。

二、专业落地版(按优先级排序,覆盖全场景)

🔥 优先级最高(根源防护)

  • 强制使用参数化查询 / 预编译语句
     
    所有涉及用户输入的 SQL 操作,必须通过参数化方式执行,禁止任何动态拼接 SQL 的写法(包括拼接后再预编译)。
     
    示例(Python):
    python
     
    运行
     
    # 错误写法(易注入)
    sql = f"SELECT * FROM user WHERE id='{user_input}'"
    cursor.execute(sql)
    
    # 正确写法(参数化)
    sql = "SELECT * FROM user WHERE id=%s"
    cursor.execute(sql, (user_input,))
     
     
  • 使用 ORM 框架
     
    MyBatis、Hibernate、Django ORM 等框架会自动做参数化处理,避免手写 SQL 的注入风险;注意 MyBatis 中别用${}(直接拼接),改用#{}(参数化)。

🛡️ 第二层防护(拦截 + 加固)

  • 部署 Web 应用防火墙(WAF)
     
    配置 WAF 的 SQL 注入规则库,拦截含恶意 SQL 特征的请求;同时开启日志审计,及时发现攻击行为。
  • 输入验证与转义
     
    对用户输入做 “白名单校验”(仅允许指定字符 / 格式),而非 “黑名单过滤”(难覆盖所有绕过方式);特殊场景下对输入的特殊字符(如单引号)做转义(辅助手段,不能替代参数化)。
  • 数据库权限最小化
     
    应用账号仅授予业务必需的权限,禁止使用 root/SA 等超级账号连接数据库;生产库禁止外网直连,通过内网 IP + 白名单限制访问。

📌 补充防护(兜底 + 监控)

  • 错误信息脱敏
     
    前端 / 接口返回的错误提示仅展示 “请求失败” 等通用信息,禁止泄露表名、字段名、SQL 语句等细节(避免黑客利用报错信息构造注入语句)。
  • 实时监控与审计
     
    监控数据库慢查询、异常访问日志(如批量查询用户表、高频执行UNION语句),定期做渗透测试,模拟攻击发现漏洞。
  • 禁用数据库危险功能
     
    关闭 SQL Server 的xp_cmdshell、MySQL 的FILE系列函数(如load_fileinto outfile),减少注入后的提权 / 破坏风险。

三、避坑提醒

❌ 别只靠 “过滤特殊字符” 防注入:黑客可通过编码、大小写混合(如UnIoN SeLeCt)绕过过滤,仅能作为辅助;❌ 别依赖 “前端校验”:前端校验可被轻易绕过,必须在后端重复校验;✅ 核心原则:把用户输入当 “数据”,而非 “代码”,始终隔离 SQL 语句与用户输入。
posted @ 2025-12-27 16:55  Python也不过如此  阅读(21)  评论(0)    收藏  举报